fix incorrect loop test condition for skipping irrelevant frames; update code to deal properly with skipped frames; b=404213 r+sr=roc
authorfantasai.cvs@inkedblade.net
Sat, 01 Dec 2007 19:13:23 -0800
changeset 8531 073fbded6c1593b0f10b70bdb2aeee44af11b9b7
parent 8530 824fc97d50acc1d2678d4d772b09413005fc54ac
child 8532 36bef573498d5fbfa287631cf105b160886d2a79
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherderautoland@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs404213
milestone1.9b2pre
fix incorrect loop test condition for skipping irrelevant frames; update code to deal properly with skipped frames; b=404213 r+sr=roc
layout/generic/nsContainerFrame.cpp
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1304,17 +1304,18 @@ nsOverflowContinuationTracker::SetUpList
   if (mOverflowContList) {
     nsIFrame* cur = mOverflowContList->FirstChild();
     if (mSkipOverflowContainerChildren) {
       while (cur && (cur->GetPrevInFlow()->GetStateBits()
                      & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
         mPrevOverflowCont = cur;
         cur = cur->GetNextSibling();
       }
-      while (cur && (mWalkOOFFrames == cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
+      while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
+                     == mWalkOOFFrames)) {
         mPrevOverflowCont = cur;
         cur = cur->GetNextSibling();
       }
     }
     if (cur) {
       mSentry = cur->GetPrevInFlow();
     }
   }
@@ -1337,33 +1338,37 @@ nsOverflowContinuationTracker::StepForwa
   }
   else {
     mPrevOverflowCont = mOverflowContList->FirstChild();
   }
 
   // Skip over oof or non-oof frames as appropriate
   if (mSkipOverflowContainerChildren) {
     nsIFrame* cur = mPrevOverflowCont->GetNextSibling();
-    while (cur && (mWalkOOFFrames == cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
+    while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
+                   == mWalkOOFFrames)) {
       mPrevOverflowCont = cur;
       cur = cur->GetNextSibling();
     }
   }
 
   // Set up the sentry
   mSentry = (mPrevOverflowCont->GetNextSibling())
             ? mPrevOverflowCont->GetNextSibling()->GetPrevInFlow()
             : nsnull;
 }
 
 nsresult
 nsOverflowContinuationTracker::Insert(nsIFrame*       aOverflowCont,
                                       nsReflowStatus& aReflowStatus)
 {
   NS_PRECONDITION(aOverflowCont, "null frame pointer");
+  NS_PRECONDITION(!mSkipOverflowContainerChildren || mWalkOOFFrames ==
+                  !!(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
+                  "shouldn't insert frame that doesn't match walker type");
   NS_PRECONDITION(aOverflowCont->GetPrevInFlow(),
                   "overflow containers must have a prev-in-flow");
   nsresult rv = NS_OK;
   if (!mSentry || aOverflowCont != mSentry->GetNextInFlow()) {
     // Not in our list, so we need to add it
     nsPresContext* presContext = aOverflowCont->PresContext();
     if (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
       // aOverflowCont is in some other overflow container list,
@@ -1395,18 +1400,21 @@ nsOverflowContinuationTracker::Insert(ns
   }
 
   // If we need to reflow it, mark it dirty
   if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW)
     aOverflowCont->AddStateBits(NS_FRAME_IS_DIRTY);
 
   // It's in our list, just step forward
   StepForward();
-  NS_ASSERTION(mPrevOverflowCont == aOverflowCont,
-              "OverflowContTracker logic error");
+  NS_ASSERTION(mPrevOverflowCont == aOverflowCont ||
+               (mSkipOverflowContainerChildren &&
+                (mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
+                (aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
+              "OverflowContTracker in unexpected state");
   return rv;
 }
 
 void
 nsOverflowContinuationTracker::Finish(nsIFrame* aChild)
 {
   NS_PRECONDITION(aChild, "null ptr");
   NS_PRECONDITION(aChild->GetNextInFlow(),
@@ -1417,21 +1425,24 @@ nsOverflowContinuationTracker::Finish(ns
     if (mOverflowContList->FirstChild() == aChild->GetNextInFlow()
         && !aChild->GetNextInFlow()->GetNextSibling()) {
       mOverflowContList = nsnull;
       mPrevOverflowCont = nsnull;
       mSentry = nsnull;
       mParent = static_cast<nsContainerFrame*>(aChild->GetParent());
     }
     else {
-      // Don't move the mPrevOverflowCont, but shift the sentry
-      // The intervening overflow continuation will be deleted by our caller
+      // Step past aChild
       nsIFrame* prevOverflowCont = mPrevOverflowCont;
       StepForward();
-      mPrevOverflowCont = prevOverflowCont;
+      if (mPrevOverflowCont == aChild) {
+        // Pull mPrevOverflowChild back to aChild's prevSibling:
+        // aChild will be removed from our list by our caller
+        mPrevOverflowCont = prevOverflowCont;
+      }
     }
   }
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Debugging
 
 #ifdef NS_DEBUG