Bug 359371. Don't leak overflowing frames if a bug occurs and we still have overflowing frames in an unconstrained reflow situation. r+sr=dbaron

This commit is contained in:
roc+%cs.cmu.edu 2006-12-12 01:06:23 +00:00
parent aacd1b5247
commit c3cd4e8b4b
3 changed files with 35 additions and 14 deletions

View File

@ -872,6 +872,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// overflow lines hanging around; block reflow depends on the
// overflow line lists being cleared out between reflow passes.
DrainOverflowLines(state);
state.SetupOverflowPlaceholdersProperty();
// If we're not dirty (which means we'll mark everything dirty later)
// and our width has changed, mark the lines dirty that we need to
@ -891,9 +892,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// allows subsequent lines on the page to be impacted by floats. If the
// block is incomplete or there is no ancestor using the same space manager,
// put continued floats at the beginning of the first overflow line.
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) &&
state.mOverflowPlaceholders.NotEmpty()) {
PRBool gaveToAncestor = PR_FALSE;
if (state.mOverflowPlaceholders.NotEmpty()) {
NS_ASSERTION(aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE,
"Somehow we failed to fit all content, even though we have unlimited space!");
if (NS_FRAME_IS_COMPLETE(state.mReflowStatus)) {
// find the nearest block ancestor that uses the same space manager
for (const nsHTMLReflowState* ancestorRS = aReflowState.parentReflowState;
@ -924,13 +925,13 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// don't keep their out of flows in a child frame list.
}
ancestorPlace->AppendFrames(nsnull, state.mOverflowPlaceholders.FirstChild());
gaveToAncestor = PR_TRUE;
state.mOverflowPlaceholders.SetFrames(nsnull);
break;
}
}
}
}
if (!gaveToAncestor) {
if (!state.mOverflowPlaceholders.IsEmpty()) {
state.mOverflowPlaceholders.SortByContentOrder();
PRInt32 numOverflowPlace = state.mOverflowPlaceholders.GetLength();
nsLineBox* newLine =
@ -971,6 +972,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine);
}
state.mOverflowPlaceholders.SetFrames(nsnull);
}
state.mReflowStatus |= NS_FRAME_NOT_COMPLETE | NS_FRAME_REFLOW_NEXTINFLOW;
}

View File

@ -77,12 +77,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
const nsMargin& borderPadding = BorderPadding();
if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
mBlock->SetProperty(nsLayoutAtoms::overflowPlaceholdersProperty,
&mOverflowPlaceholders, nsnull);
mBlock->AddStateBits(NS_BLOCK_HAS_OVERFLOW_PLACEHOLDERS);
}
if (aTopMarginRoot || 0 != aReflowState.mComputedBorderPadding.top) {
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
}
@ -144,8 +138,22 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
aReflowState.frame);
}
void
nsBlockReflowState::SetupOverflowPlaceholdersProperty()
{
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE ||
!mOverflowPlaceholders.IsEmpty()) {
mBlock->SetProperty(nsLayoutAtoms::overflowPlaceholdersProperty,
&mOverflowPlaceholders, nsnull);
mBlock->AddStateBits(NS_BLOCK_HAS_OVERFLOW_PLACEHOLDERS);
}
}
nsBlockReflowState::~nsBlockReflowState()
{
NS_ASSERTION(mOverflowPlaceholders.IsEmpty(),
"Leaking overflow placeholder frames");
// Restore the coordinate system, unless the space manager is null,
// which means it was just destroyed.
if (mSpaceManager) {
@ -153,7 +161,7 @@ nsBlockReflowState::~nsBlockReflowState()
mSpaceManager->Translate(-borderPadding.left, -borderPadding.top);
}
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
if (mBlock->GetStateBits() & NS_BLOCK_HAS_OVERFLOW_PLACEHOLDERS) {
mBlock->UnsetProperty(nsLayoutAtoms::overflowPlaceholdersProperty);
mBlock->RemoveStateBits(NS_BLOCK_HAS_OVERFLOW_PLACEHOLDERS);
}
@ -560,11 +568,15 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
// This float will be placed after the line is done (it is a
// below-current-line float).
mBelowCurrentLineFloats.Append(fc);
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE ||
aPlaceholder->GetNextInFlow()) {
// If the float might not be complete, mark it incomplete now to
// prevent the placeholders being torn down. We will destroy any
// placeholders later if PlaceBelowCurrentLineFloats finds the
// float is complete.
// Note that we could have unconstrained height and yet have
// a next-in-flow placeholder --- for example columns can switch
// from constrained height to unconstrained height.
nsSplittableType splitType;
aPlaceholder->IsSplittable(splitType);
if (splitType == NS_FRAME_NOT_SPLITTABLE) {

View File

@ -69,6 +69,13 @@ public:
~nsBlockReflowState();
// Set up a property on the block that points to our temporary mOverflowPlaceholders
// list, if that list is or could become non-empty during this reflow. Must be
// called after the block has done DrainOverflowLines because DrainOverflowLines
// can setup mOverflowPlaceholders even if the block is in unconstrained height
// reflow (it may have previously been reflowed with constrained height).
void SetupOverflowPlaceholdersProperty();
/**
* Get the available reflow space for the current y coordinate. The
* available space is relative to our coordinate system (0,0) is our