Bug 1108104 part 4 - Don't use the current next-sibling as a reference point where to continue the loop, since that frame may be pushed if it's also the next-in-flow. Instead, use the frame from the last iteration (the prev-sibling) and query its (potentially new) next-sibling. r=roc
Bug 1108104 part 4 - Don't use the current next-sibling as a reference point where to continue the loop, since that frame may be pushed if it's also the next-in-flow. Instead, use the frame from the last iteration (the prev-sibling) and query its (potentially new) next-sibling. r=roc
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6013,23 +6013,20 @@ nsBlockFrame::FindTrailingClear()
void
nsBlockFrame::ReflowPushedFloats(nsBlockReflowState& aState,
nsOverflowAreas& aOverflowAreas,
nsReflowStatus& aStatus)
{
// Pushed floats live at the start of our float list; see comment
// above nsBlockFrame::DrainPushedFloats.
- for (nsIFrame* f = mFloats.FirstChild(), *next;
- f && (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT);
- f = next) {
- // save next sibling now, since reflowing could push the entire
- // float, changing its siblings
- next = f->GetNextSibling();
-
+ nsIFrame* f = mFloats.FirstChild();
+ nsIFrame* prev = nullptr;
+ while (f && (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT)) {
+ MOZ_ASSERT(prev == f->GetPrevSibling());
// When we push a first-continuation float in a non-initial reflow,
// it's possible that we end up with two continuations with the same
// parent. This happens if, on the previous reflow of the block or
// a previous reflow of the line containing the block, the float was
// split between continuations A and B of the parent, but on the
// current reflow, none of the float can fit in A.
//
// When this happens, we might even have the two continuations
@@ -6056,24 +6053,32 @@ nsBlockFrame::ReflowPushedFloats(nsBlock
// continuation of a float gets moved across more than one
// continuation of the containing block. In this case we'd manage
// to push the second continuation without this check, but not the
// third and later.
nsIFrame *prevContinuation = f->GetPrevContinuation();
if (prevContinuation && prevContinuation->GetParent() == f->GetParent()) {
mFloats.RemoveFrame(f);
aState.AppendPushedFloat(f);
+ f = !prev ? mFloats.FirstChild() : prev->GetNextSibling();
continue;
}
// Always call FlowAndPlaceFloat; we might need to place this float
// if didn't belong to this block the last time it was reflowed.
aState.FlowAndPlaceFloat(f);
-
ConsiderChildOverflow(aOverflowAreas, f);
+
+ nsIFrame* next = !prev ? mFloats.FirstChild() : prev->GetNextSibling();
+ if (next == f) {
+ // We didn't push |f| so its next-sibling is next.
+ next = f->GetNextSibling();
+ prev = f;
+ } // else: we did push |f| so |prev|'s new next-sibling is next.
+ f = next;
}
// If there are continued floats, then we may need to continue BR clearance
if (0 != aState.ClearFloats(0, NS_STYLE_CLEAR_BOTH)) {
aState.mFloatBreakType = static_cast<nsBlockFrame*>(GetPrevInFlow())
->FindTrailingClear();
}
}