Bug 847208 - Make RemoveFloat() check the PushedFloatsList too. r=dbaron
authorMats Palmgren <matspal@gmail.com>
Fri, 15 Mar 2013 23:32:35 +0100
changeset 135381 3761f1b7df28397541b631a6eeb8a61d3dd3ae70
parent 135380 fa0ee26e949cb0fea011a8fbed7d0252ad996c32
child 135382 a6355247c934a7c1aff49a0c4e2d7e3b1caaf36f
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs847208
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 847208 - Make RemoveFloat() check the PushedFloatsList too. r=dbaron
layout/base/nsLayoutUtils.cpp
layout/generic/crashtests/847208.html
layout/generic/crashtests/crashtests.list
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -616,18 +616,17 @@ nsLayoutUtils::GetChildListNameFor(nsIFr
 
       // XXX FIXME: Bug 350740
       // Return here, because the postcondition for this function actually
       // fails for this case, since the popups are not in a "real" frame list
       // in the popup set.
       return nsIFrame::kPopupList;
 #endif // MOZ_XUL
     } else {
-      NS_ASSERTION(aChildFrame->IsFloating(),
-                   "not a floated frame");
+      NS_ASSERTION(aChildFrame->IsFloating(), "not a floated frame");
       id = nsIFrame::kFloatList;
     }
 
   } else {
     nsIAtom* childType = aChildFrame->GetType();
     if (nsGkAtoms::menuPopupFrame == childType) {
       nsIFrame* parent = aChildFrame->GetParent();
       nsIFrame* firstPopup = (parent)
@@ -655,16 +654,20 @@ nsLayoutUtils::GetChildListNameFor(nsIFr
   if (!found) {
     if (!(aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
       found = parent->GetChildList(nsIFrame::kOverflowList)
                 .ContainsFrame(aChildFrame);
     }
     else if (aChildFrame->IsFloating()) {
       found = parent->GetChildList(nsIFrame::kOverflowOutOfFlowList)
                 .ContainsFrame(aChildFrame);
+      if (!found) {
+        found = parent->GetChildList(nsIFrame::kPushedFloatsList)
+                  .ContainsFrame(aChildFrame);
+      }
     }
     // else it's positioned and should have been on the 'id' child list.
     NS_POSTCONDITION(found, "not in child list");
   }
 #endif
 
   return id;
 }
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/847208.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.f:first-letter {
+  float: left;
+}
+.f {
+  page-break-inside: avoid; float: left;
+}
+</style>
+</head>
+<body onload="document.getElementById('p').className = '';">
+<p id="p" class="f">text</p>
+</body>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -445,8 +445,9 @@ load 840818.html
 test-pref(layout.css.flexbox.enabled,true) load 812822-1.html
 asserts(1) test-pref(layout.css.flexbox.enabled,true) load 824297-1.html # bug 399262
 asserts(1) test-pref(layout.css.flexbox.enabled,true) load 826532-1.html # bug 399262
 test-pref(layout.css.flexbox.enabled,true) load 827168-1.html
 load 836895.html
 load 842132-1.html
 test-pref(layout.css.flexbox.enabled,true) load 844529-1.html
 load 847130.xhtml
+load 847208.html
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -4949,47 +4949,65 @@ nsBlockFrame::AddFrames(nsFrameList& aFr
 
 #ifdef DEBUG
   VerifyLines(true);
 #endif
   return NS_OK;
 }
 
 void
-nsBlockFrame::RemoveFloat(nsIFrame* aFloat)
-{
-#ifdef DEBUG
-  if (!mFloats.ContainsFrame(aFloat)) {
-    MOZ_ASSERT(GetOverflowOutOfFlows() &&
-               GetOverflowOutOfFlows()->ContainsFrame(aFloat),
-               "aFloat is not our child or on an unexpected frame list");
-  }
-#endif
-
+nsBlockFrame::RemoveFloatFromFloatCache(nsIFrame* aFloat)
+{
   // Find which line contains the float, so we can update
   // the float cache.
   line_iterator line = begin_lines(), line_end = end_lines();
   for ( ; line != line_end; ++line) {
     if (line->IsInline() && line->RemoveFloat(aFloat)) {
       break;
     }
   }
+}
+
+void
+nsBlockFrame::RemoveFloat(nsIFrame* aFloat)
+{
+#ifdef DEBUG
+  // Floats live in mFloats, or in the PushedFloat or OverflowOutOfFlows
+  // frame list properties.
+  if (!mFloats.ContainsFrame(aFloat)) {
+    MOZ_ASSERT((GetOverflowOutOfFlows() &&
+                GetOverflowOutOfFlows()->ContainsFrame(aFloat)) ||
+               (GetPushedFloats() &&
+                GetPushedFloats()->ContainsFrame(aFloat)),
+               "aFloat is not our child or on an unexpected frame list");
+  }
+#endif
 
   if (mFloats.StartRemoveFrame(aFloat)) {
     return;
   }
 
+  nsFrameList* list = GetPushedFloats();
+  if (list && list->ContinueRemoveFrame(aFloat)) {
+#if 0
+    // XXXmats not yet - need to investigate nsBlockReflowState::mPushedFloats
+    // first so we don't leave it pointing to a deleted list.
+    if (list->IsEmpty()) {
+      delete RemovePushedFloats();
+    }
+#endif
+    return;
+  }
+
   {
     nsAutoOOFFrameList oofs(this);
     if (oofs.mList.ContinueRemoveFrame(aFloat)) {
       return;
     }
   }
-
-  MOZ_ASSERT(false, "float child frame not found");
 }
 
 static void MarkSameFloatManagerLinesDirty(nsBlockFrame* aBlock)
 {
   nsBlockFrame* blockWithFloatMgr = aBlock;
   while (!(blockWithFloatMgr->GetStateBits() & NS_BLOCK_FLOAT_MGR)) {
     nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(blockWithFloatMgr->GetParent());
     if (!bf) {
@@ -5098,16 +5116,17 @@ nsBlockFrame::DoRemoveOutOfFlowFrame(nsI
   else {
     // First remove aFrame's next-in-flows.
     nsIFrame* nif = aFrame->GetNextInFlow();
     if (nif) {
       static_cast<nsContainerFrame*>(nif->GetParent())
         ->DeleteNextInFlowChild(aFrame->PresContext(), nif, false);
     }
     // Now remove aFrame from its child list and Destroy it.
+    block->RemoveFloatFromFloatCache(aFrame);
     block->RemoveFloat(aFrame);
     aFrame->Destroy();
   }
 }
 
 /**
  * This helps us iterate over the list of all normal + overflow lines
  */
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -513,20 +513,23 @@ protected:
                               nsOverflowAreas&    aOverflowAreas,
                               nsReflowStatus&     aStatus);
 
   /** Find any trailing BR clear from the last line of the block (or its PIFs)
    */
   uint8_t FindTrailingClear();
 
   /**
-    * Remove a float from our float list and also the float cache
-    * for the line its placeholder is on.
-    */
+   * Remove a float from our float list.
+   */
   void RemoveFloat(nsIFrame* aFloat);
+  /**
+   * Remove a float from the float cache for the line its placeholder is on.
+   */
+  void RemoveFloatFromFloatCache(nsIFrame* aFloat);
 
   void CollectFloats(nsIFrame* aFrame, nsFrameList& aList,
                      bool aCollectFromSiblings) {
     if (MaybeHasFloats()) {
       DoCollectFloats(aFrame, aList, aCollectFromSiblings);
     }
   }
   void DoCollectFloats(nsIFrame* aFrame, nsFrameList& aList,