Report incomplete reflow status as appropriate when frame tree is too deep. (Bug 619021) r=roc a2.0=blocking
authorL. David Baron <dbaron@dbaron.org>
Tue, 11 Jan 2011 17:09:22 -0800
changeset 60343 e2f7319148ce0e58cdca35e963b8ba27d47bcf46
parent 60342 67cfc95b4b9096008e98e90489ae649d287d61d7
child 60344 51573b855c1bf787b3c6b34ae3b2424d9ef09aff
push id17944
push userdbaron@mozilla.com
push dateWed, 12 Jan 2011 01:09:43 +0000
treeherdermozilla-central@e2f7319148ce [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs619021
milestone2.0b10pre
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
Report incomplete reflow status as appropriate when frame tree is too deep. (Bug 619021) r=roc a2.0=blocking
layout/generic/nsBlockFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsInlineFrame.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -988,18 +988,17 @@ nsBlockFrame::Reflow(nsPresContext*     
     autoFloatManager.CreateFloatManager(aPresContext);
 
   // OK, some lines may be reflowed. Blow away any saved line cursor
   // because we may invalidate the nondecreasing
   // overflowArea.VisualOverflow().y/yMost invariant, and we may even
   // delete the line with the line cursor.
   ClearLineCursor();
 
-  if (IsFrameTreeTooDeep(aReflowState, aMetrics)) {
-    aStatus = NS_FRAME_COMPLETE;
+  if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
     return NS_OK;
   }
 
   PRBool marginRoot = BlockIsMarginRoot(this);
   nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
                            marginRoot, marginRoot, needFloatManager);
 
 #ifdef IBMBIDI
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4546,27 +4546,38 @@ nsIFrame::CheckInvalidateSizeChange(cons
 
 // Define the MAX_FRAME_DEPTH to be the ContentSink's MAX_REFLOW_DEPTH plus
 // 4 for the frames above the document's frames: 
 //  the Viewport, GFXScroll, ScrollPort, and Canvas
 #define MAX_FRAME_DEPTH (MAX_REFLOW_DEPTH+4)
 
 PRBool
 nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
-                            nsHTMLReflowMetrics& aMetrics)
+                            nsHTMLReflowMetrics& aMetrics,
+                            nsReflowStatus& aStatus)
 {
   if (aReflowState.mReflowDepth >  MAX_FRAME_DEPTH) {
     NS_WARNING("frame tree too deep; setting zero size and returning");
     mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
     ClearOverflowRects();
     aMetrics.width = 0;
     aMetrics.height = 0;
     aMetrics.ascent = 0;
     aMetrics.mCarriedOutBottomMargin.Zero();
     aMetrics.mOverflowAreas.Clear();
+
+    if (GetNextInFlow()) {
+      // Reflow depth might vary between reflows, so we might have
+      // successfully reflowed and split this frame before.  If so, we
+      // shouldn't delete its continuations.
+      aStatus = NS_FRAME_NOT_COMPLETE;
+    } else {
+      aStatus = NS_FRAME_COMPLETE;
+    }
+
     return PR_TRUE;
   }
   mState &= ~NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
   return PR_FALSE;
 }
 
 /* virtual */ PRBool nsFrame::IsContainingBlock() const
 {
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -381,23 +381,24 @@ public:
    * desired size indicates that the size has changed (specifically border,
    * background and outline).
    * We assume that the difference between the old frame area and the new
    * frame area is invalidated by some other means.
    * @param aDesiredSize the new size of the frame
    */
   void CheckInvalidateSizeChange(nsHTMLReflowMetrics&     aNewDesiredSize);
 
-  // Helper function that tests if the frame tree is too deep; if it
-  // is it marks the frame as "unflowable" and zeros out the metrics
-  // and returns PR_TRUE. Otherwise, the frame is unmarked
-  // "unflowable" and the metrics are not touched and PR_FALSE is
-  // returned.
+  // Helper function that tests if the frame tree is too deep; if it is
+  // it marks the frame as "unflowable", zeroes out the metrics, sets
+  // the reflow status, and returns PR_TRUE. Otherwise, the frame is
+  // unmarked "unflowable" and the metrics and reflow status are not
+  // touched and PR_FALSE is returned.
   PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
-                            nsHTMLReflowMetrics& aMetrics);
+                            nsHTMLReflowMetrics& aMetrics,
+                            nsReflowStatus& aStatus);
 
   // Do the work for getting the parent style context frame so that
   // other frame's |GetParentStyleContextFrame| methods can call this
   // method on *another* frame.  (This function handles out-of-flow
   // frames by using the frame manager's placeholder map and it also
   // handles block-within-inline and generated content wrappers.)
   nsresult DoGetParentStyleContextFrame(nsPresContext* aPresContext,
                                         nsIFrame**      aProviderFrame,
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -387,18 +387,17 @@ nsInlineFrame::Reflow(nsPresContext*    
 
       // Because we lazily set the parent pointer of child frames we get from
       // our prev-in-flow's overflow list, it's possible that we have not set
       // the parent pointer for these frames.
       mFrames.AppendFrames(this, *overflowFrames);
     }
   }
 
-  if (IsFrameTreeTooDeep(aReflowState, aMetrics)) {
-    aStatus = NS_FRAME_COMPLETE;
+  if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
     return NS_OK;
   }
 
   // Set our own reflow state (additional state above and beyond
   // aReflowState)
   InlineReflowState irs;
   irs.mPrevFrame = nsnull;
   irs.mLineContainer = lineContainer;