From 4dcbca8b3c26b451e1376cd1b7c88ab984a45b39 Mon Sep 17 00:00:00 2001
From: Mats Palmgren <mats@mozilla.com>
Date: Tue, 14 Apr 2015 22:12:39 -0400
Subject: [PATCH] Bug 1143299 - Make frame insertion methods deal with
 aPrevFrame being on an overflow list. r=roc, a=bkerensa

---
 layout/generic/nsBlockFrame.cpp        | 18 ++++++++++++---
 layout/generic/nsBlockFrame.h          | 14 ++++++++----
 layout/generic/nsContainerFrame.cpp    | 41 +++++++++++++++++++---------------
 layout/tables/nsTableFrame.cpp         |  2 ++
 layout/tables/nsTableRowFrame.cpp      |  2 ++
 layout/tables/nsTableRowGroupFrame.cpp |  2 ++
 6 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp
index a011bcf..70d5297 100644
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1049,7 +1049,7 @@ nsBlockFrame::Reflow(nsPresContext*           aPresContext,
   state.mOverflowTracker = &tracker;
 
   // Drain & handle pushed floats
-  DrainPushedFloats(state);
+  DrainPushedFloats();
   nsOverflowAreas fcBounds;
   nsReflowStatus fcStatus = NS_FRAME_COMPLETE;
   ReflowPushedFloats(state, fcBounds, fcStatus);
@@ -4438,9 +4438,13 @@ nsBlockFrame::DrainSelfOverflowList()
  * might push some of them on).  Floats with placeholders in this block
  * are reflowed by (nsBlockReflowState/nsLineLayout)::AddFloat, which
  * also maintains these invariants.
+ *
+ * DrainSelfPushedFloats moves any pushed floats from this block's own
+ * PushedFloats list back into mFloats.  DrainPushedFloats additionally
+ * moves frames from its prev-in-flow's PushedFloats list into mFloats.
  */
 void
-nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState)
+nsBlockFrame::DrainSelfPushedFloats()
 {
 #ifdef DEBUG
   // Between when we drain pushed floats and when we complete reflow,
@@ -4503,12 +4507,18 @@ nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState)
       RemovePushedFloats()->Delete(presContext->PresShell());
     }
   }
+}
+
+void
+nsBlockFrame::DrainPushedFloats()
+{
+  DrainSelfPushedFloats();
 
   // After our prev-in-flow has completed reflow, it may have a pushed
   // floats list, containing floats that we need to own.  Take these.
   nsBlockFrame* prevBlock = static_cast<nsBlockFrame*>(GetPrevInFlow());
   if (prevBlock) {
-    AutoFrameListPtr list(presContext, prevBlock->RemovePushedFloats());
+    AutoFrameListPtr list(PresContext(), prevBlock->RemovePushedFloats());
     if (list && list->NotEmpty()) {
       mFloats.InsertFrames(this, nullptr, *list);
     }
@@ -4711,6 +4721,7 @@ nsBlockFrame::AppendFrames(ChildListID  aListID,
       return nsContainerFrame::AppendFrames(aListID, aFrameList);
     }
     else if (kFloatList == aListID) {
+      DrainSelfPushedFloats(); // ensure the last frame is in mFloats
       mFloats.AppendFrames(nullptr, aFrameList);
       return NS_OK;
     }
@@ -4757,6 +4768,7 @@ nsBlockFrame::InsertFrames(ChildListID aListID,
       return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
     }
     else if (kFloatList == aListID) {
+      DrainSelfPushedFloats(); // ensure aPrevFrame is in mFloats
       mFloats.InsertFrames(this, aPrevFrame, aFrameList);
       return NS_OK;
     }
diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h
index 1a6bb1e..07f7508 100644
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -533,10 +533,16 @@ protected:
     return GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS;
   }
 
-  /** grab pushed floats from this block's prevInFlow, and splice
-    * them into this block's mFloats list.
-    */
-  void DrainPushedFloats(nsBlockReflowState& aState);
+  /**
+   * Moves frames from our PushedFloats list back into our mFloats list.
+   */
+  void DrainSelfPushedFloats();
+
+  /**
+   * First calls DrainSelfPushedFloats() then grabs pushed floats from this
+   * block's prev-in-flow, and splice them into this block's mFloats list too.
+   */
+  void DrainPushedFloats();
 
   /** Load all our floats into the float manager (without reflowing them).
    *  Assumes float manager is in our own coordinate system.
diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
index 76f0748..3ffcba7 100644
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -102,16 +102,18 @@ nsContainerFrame::AppendFrames(ChildListID  aListID,
       return NS_ERROR_INVALID_ARG;
     }
   }
-  if (aFrameList.NotEmpty()) {
-    mFrames.AppendFrames(this, aFrameList);
 
-    // Ask the parent frame to reflow me.
-    if (aListID == kPrincipalList)
-    {
-      PresContext()->PresShell()->
-        FrameNeedsReflow(this, nsIPresShell::eTreeChange,
-                         NS_FRAME_HAS_DIRTY_CHILDREN);
-    }
+  if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
+    return NS_OK;
+  }
+
+  DrainSelfOverflowList(); // ensure the last frame is in mFrames
+  mFrames.AppendFrames(this, aFrameList);
+
+  if (aListID != kNoReflowPrincipalList) {
+    PresContext()->PresShell()->
+      FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+                       NS_FRAME_HAS_DIRTY_CHILDREN);
   }
   return NS_OK;
 }
@@ -131,16 +133,19 @@ nsContainerFrame::InsertFrames(ChildListID aListID,
       return NS_ERROR_INVALID_ARG;
     }
   }
-  if (aFrameList.NotEmpty()) {
-    // Insert frames after aPrevFrame
-    mFrames.InsertFrames(this, aPrevFrame, aFrameList);
 
-    if (aListID == kPrincipalList)
-    {
-      PresContext()->PresShell()->
-        FrameNeedsReflow(this, nsIPresShell::eTreeChange,
-                         NS_FRAME_HAS_DIRTY_CHILDREN);
-    }
+  if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
+    return NS_OK;
+  }
+
+  DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
+  mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+
+  if (aListID != kNoReflowPrincipalList) {
+    PresContext()->PresShell()->
+      FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+                       NS_FRAME_HAS_DIRTY_CHILDREN);
+
   }
   return NS_OK;
 }
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 60613ba..44088da 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -2232,6 +2232,7 @@ nsTableFrame::AppendFrames(ChildListID     aListID,
       InsertColGroups(startColIndex,
                       nsFrameList::Slice(mColGroups, f, f->GetNextSibling()));
     } else if (IsRowGroup(display->mDisplay)) {
+      DrainSelfOverflowList(); // ensure the last frame is in mFrames
       // Append the new row group frame to the sibling chain
       mFrames.AppendFrame(nullptr, f);
 
@@ -2404,6 +2405,7 @@ nsTableFrame::HomogenousInsertFrames(ChildListID     aListID,
     InsertColGroups(startColIndex, newColgroups);
   } else if (IsRowGroup(display->mDisplay)) {
     NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+    DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
     // Insert the frames in the sibling chain
     const nsFrameList::Slice& newRowGroups =
       mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
index d1c493b..2351de3 100644
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -182,6 +182,7 @@ nsTableRowFrame::AppendFrames(ChildListID     aListID,
 {
   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
 
+  DrainSelfOverflowList(); // ensure the last frame is in mFrames
   const nsFrameList::Slice& newCells = mFrames.AppendFrames(nullptr, aFrameList);
 
   // Add the new cell frames to the table
@@ -208,6 +209,7 @@ nsTableRowFrame::InsertFrames(ChildListID     aListID,
   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
+  DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
   //Insert Frames in the frame list
   const nsFrameList::Slice& newCells = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
 
diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp
index 34aaf02..40b349b 100644
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1389,6 +1389,7 @@ nsTableRowGroupFrame::AppendFrames(ChildListID     aListID,
 {
   NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
 
+  DrainSelfOverflowList(); // ensure the last frame is in mFrames
   ClearRowCursor();
 
   // collect the new row frames in an array
@@ -1430,6 +1431,7 @@ nsTableRowGroupFrame::InsertFrames(ChildListID     aListID,
   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
                "inserting after sibling frame with different parent");
 
+  DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
   ClearRowCursor();
 
   // collect the new row frames in an array
-- 
2.2.1

