Fix the parent pointer for ::first-letter child frame next-in-flows. b=401042 r+sr=roc
authorMats Palmgren <mats.palmgren@bredband.net>
Sun, 07 Dec 2008 19:21:40 +0100
changeset 22469 18ae5e6af525ef3c81ae11f6a69f27f5896e24bc
parent 22468 f7c410f03d0e5ce4dcc07ae7aa5da92249dff0c4
child 22470 23c07da38629a69b1f8935b3c80ecea71bf5b3f4
push idunknown
push userunknown
push dateunknown
bugs401042
milestone1.9.2a1pre
Fix the parent pointer for ::first-letter child frame next-in-flows. b=401042 r+sr=roc
layout/generic/nsInlineFrame.cpp
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -454,27 +454,56 @@ nsInlineFrame::ReflowFrames(nsPresContex
         ReparentFloatsForInlineChild(irs.mLineContainer, frame, PR_FALSE);
       }
       frame->SetParent(this);
       // We also need to check if frame has a next-in-flow. If it does, then set
       // its parent frame pointer, too. Otherwise, if we reflow frame and it's
       // complete we'll fail when deleting its next-in-flow which is no longer
       // needed. This scenario doesn't happen often, but it can happen
       nsIFrame* nextInFlow = frame->GetNextInFlow();
-      while (nextInFlow) {
+      for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
         // Since we only do lazy setting of parent pointers for the frame's
         // initial reflow, this frame can't have a next-in-flow. That means
         // the continuing child frame must be in our child list as well. If
         // not, then something is wrong
         NS_ASSERTION(mFrames.ContainsFrame(nextInFlow), "unexpected flow");
         if (havePrevBlock) {
           ReparentFloatsForInlineChild(irs.mLineContainer, nextInFlow, PR_FALSE);
         }
         nextInFlow->SetParent(this);
-        nextInFlow = nextInFlow->GetNextInFlow();
+      }
+
+      // Fix the parent pointer for ::first-letter child frame next-in-flows,
+      // so nsFirstLetterFrame::Reflow can destroy them safely (bug 401042).
+      nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(frame);
+      if (realFrame->GetType() == nsGkAtoms::letterFrame) {
+        nsIFrame* child = realFrame->GetFirstChild(nsnull);
+        if (child) {
+          NS_ASSERTION(child->GetType() == nsGkAtoms::textFrame,
+                       "unexpected frame type");
+          nsIFrame* nextInFlow = child->GetNextInFlow();
+          for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
+            NS_ASSERTION(nextInFlow->GetType() == nsGkAtoms::textFrame,
+                         "unexpected frame type");
+            if (mFrames.ContainsFrame(nextInFlow)) {
+              nextInFlow->SetParent(this);
+            }
+            else {
+#ifdef DEBUG              
+              // Once we find a next-in-flow that isn't ours none of the
+              // remaining next-in-flows should be either.
+              for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
+                NS_ASSERTION(!mFrames.ContainsFrame(nextInFlow),
+                             "unexpected letter frame flow");
+              }
+#endif
+              break;
+            }
+          }
+        }
       }
     }
     rv = ReflowInlineFrame(aPresContext, aReflowState, irs, frame, aStatus);
     if (NS_FAILED(rv)) {
       done = PR_TRUE;
       break;
     }
     if (NS_INLINE_IS_BREAK(aStatus) ||