Bug 386266: Crash [@ nsFrameManager::UnregisterPlaceholderFrame] or assertions with -moz-column and float. r+sr=bzbarsky, a=blocking1.9+
authorsharparrow1@yahoo.com
Thu, 02 Aug 2007 10:20:45 -0700
changeset 4162 b8826017d10fed69ed94e593dd25ac9381ac38fb
parent 4161 098987b9eb4db65da3cc093cfbe14ce93addf881
child 4163 49ae8a12c5fb58b9b4430a371c69b856a21b1b35
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblocking1.9
bugs386266
milestone1.9a7pre
Bug 386266: Crash [@ nsFrameManager::UnregisterPlaceholderFrame] or assertions with -moz-column and float. r+sr=bzbarsky, a=blocking1.9+
layout/base/nsCSSFrameConstructor.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -9431,16 +9431,27 @@ nsCSSFrameConstructor::RemoveMappingsFor
   }
 
   // Save the frame tree's state before deleting it
   CaptureStateFor(aRemovedFrame, mTempFrameTreeState);
 
   return ::DeletingFrameSubtree(mPresShell->FrameManager(), aRemovedFrame);
 }
 
+static void UnregisterPlaceholderChain(nsFrameManager* frameManager,
+                                       nsPlaceholderFrame* placeholderFrame)
+{
+  // Remove the mapping from the frame to its placeholder
+  nsPlaceholderFrame* curFrame = placeholderFrame;
+  do {
+    frameManager->UnregisterPlaceholderFrame(curFrame);
+    curFrame = static_cast<nsPlaceholderFrame*>(curFrame->GetNextContinuation());
+  } while (curFrame);
+}
+
 nsresult
 nsCSSFrameConstructor::ContentRemoved(nsIContent*     aContainer,
                                       nsIContent*     aChild,
                                       PRInt32         aIndexInContainer,
                                       PRBool          aInReinsertContent)
 {
   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
   // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
@@ -9568,19 +9579,18 @@ nsCSSFrameConstructor::ContentRemoved(ns
     // remove the mapping from content objects to frames
     ::DeletingFrameSubtree(frameManager, childFrame);
 
     // See if the child frame is an out-of-flow
     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
       nsPlaceholderFrame* placeholderFrame =
         frameManager->GetPlaceholderFrameFor(childFrame);
       NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
-      
-      // Remove the mapping from the frame to its placeholder
-      frameManager->UnregisterPlaceholderFrame(placeholderFrame);
+
+      UnregisterPlaceholderChain(frameManager, placeholderFrame);
 
       // Now we remove the out-of-flow frame
       // XXX has to be done first for now: for floats, the block's line list
       // contains an array of pointers to the placeholder - we have to
       // remove the float first (which gets rid of the lines
       // reference to the placeholder and float) and then remove the
       // placeholder
       rv = frameManager->RemoveFrame(parentFrame,
@@ -12100,26 +12110,26 @@ nsCSSFrameConstructor::RemoveFloatingFir
                "Placeholder not in parent's principal child list?");
   nsIFrame* prevSibling = siblingList.GetPrevSiblingFor(placeholderFrame);
 
   // Now that everything is set...
 #ifdef NOISY_FIRST_LETTER
   printf("RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p newTextFrame=%p\n",
          textContent.get(), textFrame, newTextFrame);
 #endif
-  // Should we call DeletingFrameSubtree on the placeholder instead
-  // and skip this call?
-  aFrameManager->UnregisterPlaceholderFrame(placeholderFrame);
+
+  UnregisterPlaceholderChain(aFrameManager, placeholderFrame);
 
   // Remove the float frame
   ::DeletingFrameSubtree(aFrameManager, floatFrame);
   aFrameManager->RemoveFrame(aBlockFrame, nsGkAtoms::floatList,
                              floatFrame);
 
   // Remove placeholder frame
+  ::DeletingFrameSubtree(aFrameManager, placeholderFrame);
   aFrameManager->RemoveFrame(parentFrame, nsnull, placeholderFrame);
 
   // Insert text frame in its place
   aFrameManager->InsertFrames(parentFrame, nsnull,
                               prevSibling, newTextFrame);
 
   return NS_OK;
 }
@@ -12857,24 +12867,23 @@ nsresult nsCSSFrameConstructor::RemoveFi
 
   if (mFixedContainingBlock) {
     nsIFrame *fixedChild = nsnull;
     do {
       fixedChild = mFixedContainingBlock->GetFirstChild(nsGkAtoms::fixedList);
       if (fixedChild) {
         // Remove the placeholder so it doesn't end up sitting about pointing
         // to the removed fixed frame.
-        nsIFrame *placeholderFrame;
-        mPresShell->GetPlaceholderFrameFor(fixedChild, &placeholderFrame);
+        nsPlaceholderFrame *placeholderFrame =
+          aState.mFrameManager->GetPlaceholderFrameFor(fixedChild);
         NS_ASSERTION(placeholderFrame, "no placeholder for fixed-pos frame");
         NS_ASSERTION(placeholderFrame->GetType() ==
                      nsGkAtoms::placeholderFrame,
                      "Wrong type");
-        aState.mFrameManager->UnregisterPlaceholderFrame(
-          static_cast<nsPlaceholderFrame*>(placeholderFrame));
+        UnregisterPlaceholderChain(aState.mFrameManager, placeholderFrame);
         nsIFrame* placeholderParent = placeholderFrame->GetParent();
         ::DeletingFrameSubtree(aState.mFrameManager, placeholderFrame);
         rv = aState.mFrameManager->RemoveFrame(placeholderParent, nsnull,
                                                placeholderFrame);
         if (NS_FAILED(rv)) {
           NS_WARNING("Error removing placeholder for fixed frame in RemoveFixedItems");
           break;
         }