Bug 526178. Fix constructor firing order to match Gecko 1.9.1 again. r=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 04 Nov 2009 17:58:13 -0500
changeset 34614 77512fa7701e7bf4a534fa226704608c27076c77
parent 34613 da1ba2b10d8d3bffd589a73f54ae9ebc11208c78
child 34615 c724ba56c88c1b6124720854cebda9123a01a256
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs526178
milestone1.9.3a1pre
Bug 526178. Fix constructor firing order to match Gecko 1.9.1 again. r=roc
content/xbl/test/Makefile.in
content/xbl/test/test_bug526178.xhtml
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/content/xbl/test/Makefile.in
+++ b/content/xbl/test/Makefile.in
@@ -65,12 +65,13 @@ include $(topsrcdir)/config/rules.mk
 		test_bug379959.html \
 		file_bug379959_data.html \
 		file_bug379959_cross.html \
 		file_bug379959_xbl.xml \
 		test_bug468210.xhtml \
 		test_bug481558.html \
 		file_bug481558css.sjs \
 		file_bug481558.xbl \
+		test_bug526178.xhtml \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/xbl/test/test_bug526178.xhtml
@@ -0,0 +1,80 @@
+<html xmlns="http://www.w3.org/1999/xhtml" style="display: none">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=526178
+-->
+<head>
+  <title>Test for Bug 526178</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style id="sheet">
+    #content * {
+      display: block;
+      -moz-binding: url("#binding");
+    }
+  </style>
+  <bindings xmlns="http://www.mozilla.org/xbl">
+    <binding id="binding">
+      <implementation>
+        <constructor>
+          window.logString += this.localName;
+          window.bindingDone();
+        </constructor>
+      </implementation>
+    </binding>
+  </bindings>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=526178">Mozilla Bug 526178</a>
+<div id="content">
+  <a>
+    <b>
+      <c/>
+    </b>
+    <d/>
+    <e style="display: inline">
+      <f style="display: inline">
+        <g style="display: inline"/>
+        <h style="display: none"/>
+        <i style="display: inline"/>
+      </f>
+      <j style="display: none"/>
+      <k style="display: inline">
+        <l style="display: inline"/>
+        <m/>
+        <n style="display: inline"/>
+      </k>
+    </e>
+    <o style="display: none"/>
+    <p/>
+  </a>
+</div>
+<p id="display">
+</p>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 526178 **/
+var logString = "";
+// Add one for the root
+var pendingBindings = $("content").getElementsByTagName("*").length + 1;
+function bindingDone() {
+  if (--pendingBindings == 0) {
+    is(logString, "apoeknmljfihgdbchtml");
+    SimpleTest.finish();
+  }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// Have to add the rule for the root dynamically so the binding doesn't try
+//  to load before bindingDone() is defined.
+$("sheet").sheet.insertRule(':root { -moz-binding: url("#binding"); }', 0);
+document.documentElement.style.display = "";
+
+]]>
+</script>
+</pre>
+</body>
+</html>
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -762,16 +762,33 @@ private:
 
   // The name of the child list in which our frames would belong
   nsIAtom* mChildListName;
   nsFrameConstructorState* mState;
 
   friend class nsFrameConstructorState;
 };
 
+// Structure used to keep track of a list of bindings we need to call
+// AddToAttachedQueue on.  These should be in post-order depth-first
+// flattened tree traversal order.
+struct PendingBinding : public PRCList
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+  PendingBinding() {
+    MOZ_COUNT_CTOR(PendingBinding);
+  }
+  ~PendingBinding() {
+    MOZ_COUNT_DTOR(PendingBinding);
+  }
+#endif
+
+  nsRefPtr<nsXBLBinding> mBinding;
+};
+
 // Structure used for maintaining state information during the
 // frame construction process
 class NS_STACK_CLASS nsFrameConstructorState {
 public:
   nsPresContext            *mPresContext;
   nsIPresShell             *mPresShell;
   nsFrameManager           *mFrameManager;
 
@@ -885,25 +902,69 @@ public:
   {
     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
   }
   const nsAbsoluteItems& GetFixedItems() const
   {
     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
   }
 
+
+  /**
+   * class to automatically push and pop a pending binding in the frame
+   * constructor state.  See nsCSSFrameConstructor::FrameConstructionItem
+   * mPendingBinding documentation.
+   */
+  class PendingBindingAutoPusher;
+  friend class PendingBindingAutoPusher;
+  class NS_STACK_CLASS PendingBindingAutoPusher {
+  public:
+    PendingBindingAutoPusher(nsFrameConstructorState& aState,
+                             PendingBinding* aPendingBinding) :
+      mState(aState),
+      mPendingBinding(aState.mCurrentPendingBindingInsertionPoint)
+        {
+          NS_PRECONDITION(mPendingBinding, "how did that happen?");
+          if (aPendingBinding) {
+            aState.mCurrentPendingBindingInsertionPoint = aPendingBinding;
+          }
+        }
+
+    ~PendingBindingAutoPusher()
+      {
+        mState.mCurrentPendingBindingInsertionPoint = mPendingBinding;
+      }
+
+  private:
+    nsFrameConstructorState& mState;
+    PRCList* mPendingBinding;
+  };
+
+  /**
+   * Add a new pending binding to the list
+   */
+  void AddPendingBinding(PendingBinding* aPendingBinding) {
+    PR_INSERT_BEFORE(aPendingBinding, mCurrentPendingBindingInsertionPoint);
+  }
+
 protected:
   friend class nsFrameConstructorSaveState;
 
   /**
    * ProcessFrameInsertions takes the frames in aFrameItems and adds them as
    * kids to the aChildListName child list of |aFrameItems.containingBlock|.
    */
   void ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
                               nsIAtom* aChildListName);
+
+  // Our list of all pending bindings.  When we're done, we need to call
+  // AddToAttachedQueue on all of them, in order.
+  PRCList mPendingBindings;
+
+  PRCList* mCurrentPendingBindingInsertionPoint;
 };
 
 nsFrameConstructorState::nsFrameConstructorState(nsIPresShell*          aPresShell,
                                                  nsIFrame*              aFixedContainingBlock,
                                                  nsIFrame*              aAbsoluteContainingBlock,
                                                  nsIFrame*              aFloatContainingBlock,
                                                  nsILayoutHistoryState* aHistoryState)
   : mPresContext(aPresShell->GetPresContext()),
@@ -916,25 +977,27 @@ nsFrameConstructorState::nsFrameConstruc
     mAbsoluteItems(aAbsoluteContainingBlock),
     mFloatedItems(aFloatContainingBlock),
     // See PushAbsoluteContaningBlock below
     mFrameState(aHistoryState),
     mAdditionalStateBits(0),
     mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
                       aAbsoluteContainingBlock->GetStyleDisplay()->
                         HasTransform()),
-    mHavePendingPopupgroup(PR_FALSE)
+    mHavePendingPopupgroup(PR_FALSE),
+    mCurrentPendingBindingInsertionPoint(&mPendingBindings)
 {
 #ifdef MOZ_XUL
   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
   if (rootBox) {
     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
   }
 #endif
   MOZ_COUNT_CTOR(nsFrameConstructorState);
+  PR_INIT_CLIST(&mPendingBindings);
 }
 
 nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
                                                  nsIFrame*     aFixedContainingBlock,
                                                  nsIFrame*     aAbsoluteContainingBlock,
                                                  nsIFrame*     aFloatContainingBlock)
   : mPresContext(aPresShell->GetPresContext()),
     mPresShell(aPresShell),
@@ -945,26 +1008,28 @@ nsFrameConstructorState::nsFrameConstruc
     mFixedItems(aFixedContainingBlock),
     mAbsoluteItems(aAbsoluteContainingBlock),
     mFloatedItems(aFloatContainingBlock),
     // See PushAbsoluteContaningBlock below
     mAdditionalStateBits(0),
     mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
                       aAbsoluteContainingBlock->GetStyleDisplay()->
                         HasTransform()),
-    mHavePendingPopupgroup(PR_FALSE)
+    mHavePendingPopupgroup(PR_FALSE),
+    mCurrentPendingBindingInsertionPoint(&mPendingBindings)
 {
 #ifdef MOZ_XUL
   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
   if (rootBox) {
     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
   }
 #endif
   MOZ_COUNT_CTOR(nsFrameConstructorState);
   mFrameState = aPresShell->GetDocument()->GetLayoutHistoryState();
+  PR_INIT_CLIST(&mPendingBindings);
 }
 
 nsFrameConstructorState::~nsFrameConstructorState()
 {
   // Frame order comparison functions only work properly when the placeholders
   // have been inserted into the frame tree. So for example if we have a new float
   // containing the placeholder for a new abs-pos frame, and we process the abs-pos
   // insertion first, then we won't be able to find the right place to insert in
@@ -978,16 +1043,26 @@ nsFrameConstructorState::~nsFrameConstru
   ProcessFrameInsertions(mFixedItems, nsGkAtoms::fixedList);
 #ifdef MOZ_XUL
   ProcessFrameInsertions(mPopupItems, nsGkAtoms::popupList);
 #endif
   for (PRInt32 i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
     mGeneratedTextNodesWithInitializer[i]->
       DeleteProperty(nsGkAtoms::genConInitializerProperty);
   }
+  if (!PR_CLIST_IS_EMPTY(&mPendingBindings)) {
+    nsBindingManager* bindingManager = mPresShell->GetDocument()->BindingManager();
+    do {
+      PendingBinding* pendingBinding =
+        static_cast<PendingBinding*>(PR_NEXT_LINK(&mPendingBindings));
+      PR_REMOVE_LINK(pendingBinding);
+      bindingManager->AddToAttachedQueue(pendingBinding->mBinding);
+      delete pendingBinding;
+    } while (!PR_CLIST_IS_EMPTY(&mPendingBindings));
+  }
 }
 
 static nsIFrame*
 AdjustAbsoluteContainingBlock(nsIFrame* aContainingBlockIn)
 {
   if (!aContainingBlockIn) {
     return nsnull;
   }
@@ -2021,17 +2096,17 @@ nsCSSFrameConstructor::ConstructTable(ns
   }
 
   nsFrameItems childItems;
   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
     rv = ConstructFramesFromItemList(aState, aItem.mChildItems,
                                      innerFrame, childItems);
   } else {
     rv = ProcessChildren(aState, content, styleContext, innerFrame,
-                         PR_TRUE, childItems, PR_FALSE);
+                         PR_TRUE, childItems, PR_FALSE, aItem.mPendingBinding);
   }
   // XXXbz what about cleaning up?
   if (NS_FAILED(rv)) return rv;
 
   nsFrameItems captionItems;
   PullOutCaptionFrames(childItems, captionItems);
 
   // Set the inner table frame's initial primary list 
@@ -2076,17 +2151,17 @@ nsCSSFrameConstructor::ConstructTableRow
 
   nsFrameItems childItems;
   nsresult rv;
   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
     rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
                                      childItems);
   } else {
     rv = ProcessChildren(aState, content, styleContext, newFrame,
-                         PR_TRUE, childItems, PR_FALSE);
+                         PR_TRUE, childItems, PR_FALSE, aItem.mPendingBinding);
   }
   if (NS_FAILED(rv)) return rv;
 
   newFrame->SetInitialChildList(nsnull, childItems);
   aFrameItems.AddChild(newFrame);
   *aNewFrame = newFrame;
 
   return NS_OK;
@@ -2216,17 +2291,17 @@ nsCSSFrameConstructor::ConstructTableCel
       aState.PushFloatContainingBlock(cellInnerFrame, floatSaveState);
     }
 
     rv = ConstructFramesFromItemList(aState, aItem.mChildItems, cellInnerFrame,
                                      childItems);
   } else {
     // Process the child content
     rv = ProcessChildren(aState, content, styleContext, cellInnerFrame,
-                         PR_TRUE, childItems, isBlock);
+                         PR_TRUE, childItems, isBlock, aItem.mPendingBinding);
   }
   
   if (NS_FAILED(rv)) {
     // Clean up
     // XXXbz kids of this stuff need to be cleaned up too!
     cellInnerFrame->Destroy();
     newFrame->Destroy();
     return rv;
@@ -2409,16 +2484,19 @@ nsCSSFrameConstructor::ConstructDocEleme
     rv = xblService->LoadBindings(aDocElement, display->mBinding->mURI,
                                   display->mBinding->mOriginPrincipal,
                                   PR_FALSE, getter_AddRefs(binding),
                                   &resolveStyle);
     if (NS_FAILED(rv))
       return NS_OK; // Binding will load asynchronously.
 
     if (binding) {
+      // For backwards compat, keep firing the root's constructor
+      // after all of its kids' constructors.  So tell the binding
+      // manager about it right now.
       mDocument->BindingManager()->AddToAttachedQueue(binding);
     }
 
     if (resolveStyle) {
       styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
                                                              nsnull);
       display = styleContext->GetStyleDisplay();
     }
@@ -2511,21 +2589,22 @@ nsCSSFrameConstructor::ConstructDocEleme
     if (docElemIsTable) {
       // We're going to call the right function ourselves, so no need to give a
       // function to this FrameConstructionData.
 
       // XXXbz on the other hand, if we converted this whole function to
       // FrameConstructionData/Item, then we'd need the right function
       // here... but would probably be able to get away with less code in this
       // function in general.
+      // Use a null PendingBinding, since our binding is not in fact pending.
       static const FrameConstructionData rootTableData = FCDATA_DECL(0, nsnull);
       nsRefPtr<nsStyleContext> extraRef(styleContext);
       FrameConstructionItem item(&rootTableData, aDocElement,
                                  aDocElement->Tag(), kNameSpaceID_None,
-                                 -1, extraRef.forget());
+                                 -1, nsnull, extraRef.forget());
 
       nsFrameItems frameItems;
       // if the document is a table then just populate it.
       rv = ConstructTable(state, item, mDocElementContainingBlock,
                           styleContext->GetStyleDisplay(),
                           frameItems, &contentFrame);
       if (NS_FAILED(rv))
         return rv;
@@ -2534,21 +2613,23 @@ nsCSSFrameConstructor::ConstructDocEleme
       *aNewFrame = frameItems.FirstChild();
       NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
     } else {
       contentFrame = NS_NewBlockFrame(mPresShell, styleContext,
         NS_BLOCK_FLOAT_MGR|NS_BLOCK_MARGIN_ROOT);
       if (!contentFrame)
         return NS_ERROR_OUT_OF_MEMORY;
       nsFrameItems frameItems;
+      // Use a null PendingBinding, since our binding is not in fact pending.
       rv = ConstructBlock(state, display, aDocElement,
                           state.GetGeometricParent(display,
                                                    mDocElementContainingBlock),
                           mDocElementContainingBlock, styleContext,
-                          &contentFrame, frameItems, display->IsPositioned());
+                          &contentFrame, frameItems, display->IsPositioned(),
+                          nsnull);
       if (NS_FAILED(rv) || frameItems.IsEmpty())
         return rv;
       *aNewFrame = frameItems.FirstChild();
       NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
     }
   }
 
   // set the primary frame
@@ -2570,18 +2651,19 @@ nsCSSFrameConstructor::ConstructDocEleme
   }
 
   if (processChildren) {
     // Still need to process the child content
     nsFrameItems childItems;
 
     NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame),
                  "Only XUL and SVG frames should reach here");
+    // Use a null PendingBinding, since our binding is not in fact pending.
     ProcessChildren(state, aDocElement, styleContext, contentFrame, PR_TRUE,
-                    childItems, PR_FALSE);
+                    childItems, PR_FALSE, nsnull);
 
     // Set the initial child lists
     contentFrame->SetInitialChildList(nsnull, childItems);
   }
 
   SetInitialSingleChild(mDocElementContainingBlock, *aNewFrame);
 
   return NS_OK;
@@ -3066,31 +3148,33 @@ nsCSSFrameConstructor::ConstructButtonFr
 
 #ifdef DEBUG
     // Make sure that anonymous child creation will have no effect in this case
     nsIAnonymousContentCreator* creator = do_QueryFrame(blockFrame);
     NS_ASSERTION(!creator, "Shouldn't be an anonymous content creator!");
 #endif
 
     rv = ProcessChildren(aState, content, styleContext, blockFrame, PR_TRUE,
-                         childItems, aStyleDisplay->IsBlockInside());
+                         childItems, aStyleDisplay->IsBlockInside(),
+                         aItem.mPendingBinding);
     if (NS_FAILED(rv)) return rv;
   
     // Set the areas frame's initial child lists
     blockFrame->SetInitialChildList(nsnull, childItems);
   }
 
   SetInitialSingleChild(buttonFrame, blockFrame);
 
   if (isLeaf) {
     nsFrameItems  anonymousChildItems;
     // if there are any anonymous children create frames for them.  Note that
     // we're doing this using a different parent frame from the one we pass to
     // ProcessChildren!
-    CreateAnonymousFrames(aState, content, buttonFrame, anonymousChildItems);
+    CreateAnonymousFrames(aState, content, buttonFrame, aItem.mPendingBinding,
+                          anonymousChildItems);
     if (anonymousChildItems.NotEmpty()) {
       // the anonymous content is already parented to the area frame
       aState.mFrameManager->AppendFrames(blockFrame, nsnull,
                                          anonymousChildItems);
     }
   }
 
   // our new button frame returned is the top frame. 
@@ -3176,30 +3260,32 @@ nsCSSFrameConstructor::ConstructSelectFr
       NS_ASSERTION(!listStyle->GetStyleDisplay()->IsFloating(),
                    "Ended up with floating dropdown list somehow.");
       
       // Initialize the scroll frame positioned. Note that it is NOT
       // initialized as absolutely positioned.
       nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(mPresShell, styleContext, flags);
 
       InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
-                            comboboxFrame, listStyle, PR_TRUE, aFrameItems);
+                            comboboxFrame, listStyle, PR_TRUE,
+                            aItem.mPendingBinding, aFrameItems);
 
         // Set flag so the events go to the listFrame not child frames.
         // XXX: We should replace this with a real widget manager similar
         // to how the nsFormControlFrame works. Re-directing events is a temporary Kludge.
       NS_ASSERTION(listFrame->GetView(), "ListFrame's view is nsnull");
       //listFrame->GetView()->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN);
 
       // Create display and button frames from the combobox's anonymous content.
       // The anonymous content is appended to existing anonymous content for this
       // element (the scrollbars).
 
       nsFrameItems childItems;
-      CreateAnonymousFrames(aState, content, comboboxFrame, childItems);
+      CreateAnonymousFrames(aState, content, comboboxFrame,
+                            aItem.mPendingBinding, childItems);
   
       comboboxFrame->SetInitialChildList(nsnull, childItems);
 
       // Initialize the additional popup child list which contains the
       // dropdown list frame.
       nsFrameItems popupItems;
       popupItems.AddChild(listFrame);
       comboboxFrame->SetInitialChildList(nsGkAtoms::selectPopupList,
@@ -3226,17 +3312,18 @@ nsCSSFrameConstructor::ConstructSelectFr
 
       nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(
         mPresShell, styleContext, NS_BLOCK_FLOAT_MGR);
 
       // ******* this code stolen from Initialze ScrollFrame ********
       // please adjust this code to use BuildScrollFrame.
 
       InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
-                            aParentFrame, styleContext, PR_FALSE, aFrameItems);
+                            aParentFrame, styleContext, PR_FALSE,
+                            aItem.mPendingBinding, aFrameItems);
 
       *aNewFrame = listFrame;
     }
   }
   return rv;
 
 }
 
@@ -3248,16 +3335,17 @@ nsCSSFrameConstructor::ConstructSelectFr
 nsresult
 nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
                                              nsIFrame*                scrollFrame,
                                              nsIFrame*                scrolledFrame,
                                              nsIContent*              aContent,
                                              nsIFrame*                aParentFrame,
                                              nsStyleContext*          aStyleContext,
                                              PRBool                   aBuildCombobox,
+                                             PendingBinding*          aPendingBinding,
                                              nsFrameItems&            aFrameItems)
 {
   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
 
   // Initialize it
   nsIFrame* geometricParent = aState.GetGeometricParent(display, aParentFrame);
     
   // We don't call InitAndRestoreFrame for scrollFrame because we can only
@@ -3311,17 +3399,17 @@ nsCSSFrameConstructor::InitializeSelectF
 
   if (display->IsPositioned()) {
     // The area frame becomes a container for child frames that are
     // absolutely positioned
     aState.PushAbsoluteContainingBlock(scrolledFrame, absoluteSaveState);
   }
 
   ProcessChildren(aState, aContent, aStyleContext, scrolledFrame, PR_FALSE,
-                  childItems, PR_TRUE);
+                  childItems, PR_TRUE, aPendingBinding);
 
   // Set the scrolled frame's initial child lists
   scrolledFrame->SetInitialChildList(nsnull, childItems);
   return NS_OK;
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
@@ -3374,17 +3462,17 @@ nsCSSFrameConstructor::ConstructFieldSet
     // The area frame becomes a container for child frames that are
     // absolutely positioned
     // XXXbz this is probably wrong, and once arbitrary frames can be absolute
     // containing blocks we should fix this..
     aState.PushAbsoluteContainingBlock(blockFrame, absoluteSaveState);
   }
 
   ProcessChildren(aState, content, styleContext, blockFrame, PR_TRUE,
-                  childItems, PR_TRUE);
+                  childItems, PR_TRUE, aItem.mPendingBinding);
 
   nsFrameItems fieldsetKids;
   fieldsetKids.AddChild(blockFrame);
 
   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
     nsLegendFrame* legendFrame = do_QueryFrame(e.get());
     if (legendFrame) {
       // We want the legend to be the first frame in the fieldset child list.
@@ -3855,17 +3943,18 @@ nsCSSFrameConstructor::ConstructFrameFro
     if (bits & FCDATA_USE_CHILD_ITEMS) {
       rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
                                        childItems);
     } else {
       // Process the child frames.
       rv = ProcessChildren(aState, content, styleContext, newFrame,
                            !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
                            childItems,
-                           (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0);
+                           (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0,
+                           aItem.mPendingBinding);
     }
 
 #ifdef MOZ_XUL
     // More icky XUL stuff
     if (aItem.mNameSpaceID == kNameSpaceID_XUL &&
         (aItem.mTag == nsGkAtoms::treechildren || // trees always need titletips
          content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
          content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
@@ -3926,27 +4015,31 @@ nsCSSFrameConstructor::ConstructFrameFro
 }
 
 // after the node has been constructed and initialized create any
 // anonymous content a node needs.
 nsresult
 nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
                                              nsIContent*              aParent,
                                              nsIFrame*                aParentFrame,
+                                             PendingBinding*          aPendingBinding,
                                              nsFrameItems&            aChildItems)
 {
   nsAutoTArray<nsIContent*, 4> newAnonymousItems;
   nsresult rv = GetAnonymousContent(aParent, aParentFrame, newAnonymousItems);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRUint32 count = newAnonymousItems.Length();
   if (count == 0) {
     return NS_OK;
   }
 
+  nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
+                                                           aPendingBinding);
+
   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
   NS_ASSERTION(creator,
                "How can that happen if we have nodes to construct frames for?");
 
   for (PRUint32 i=0; i < count; i++) {
     nsIContent* content = newAnonymousItems[i];
     NS_ASSERTION(content, "null anonymous content?");
 
@@ -4299,17 +4392,21 @@ nsCSSFrameConstructor::BeginBuildingScro
     InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, gfxScrollFrame);
 
     // Create a view
     nsHTMLContainerFrame::CreateViewForFrame(gfxScrollFrame, PR_FALSE);
   }
 
   // if there are any anonymous children for the scroll frame, create
   // frames for them.
-  CreateAnonymousFrames(aState, aContent, gfxScrollFrame, anonymousItems);
+  // Pass a null pending binding: we don't care how constructors for any of
+  // this anonymous content order with anything else.  It's never been
+  // consistent anyway.
+  CreateAnonymousFrames(aState, aContent, gfxScrollFrame, nsnull,
+                        anonymousItems);
 
   aNewFrame = gfxScrollFrame;
 
   // we used the style that was passed in. So resolve another one.
   nsStyleSet *styleSet = mPresShell->StyleSet();
   nsStyleContext* aScrolledChildStyle = styleSet->ResolvePseudoStyleFor(aContent,
                                                                         aScrolledPseudo,
                                                                         contentStyle).get();
@@ -4530,17 +4627,18 @@ nsCSSFrameConstructor::ConstructScrollab
   // pass a temporary stylecontext, the correct one will be set later
   nsIFrame* scrolledFrame =
     NS_NewBlockFormattingContext(mPresShell, styleContext);
 
   nsFrameItems blockItem;
   nsresult rv = ConstructBlock(aState,
                                scrolledContentStyle->GetStyleDisplay(), content,
                                *aNewFrame, *aNewFrame, scrolledContentStyle,
-                               &scrolledFrame, blockItem, aDisplay->IsPositioned());
+                               &scrolledFrame, blockItem, aDisplay->IsPositioned(),
+                               aItem.mPendingBinding);
   if (NS_UNLIKELY(NS_FAILED(rv))) {
     // XXXbz any cleanup needed here?
     return rv;
   }
 
   NS_ASSERTION(blockItem.FirstChild() == scrolledFrame,
                "Scrollframe's frameItems should be exactly the scrolled frame");
   FinishBuildingScrollFrame(*aNewFrame, scrolledFrame);
@@ -4566,17 +4664,18 @@ nsCSSFrameConstructor::ConstructNonScrol
     *aNewFrame = NS_NewBlockFormattingContext(mPresShell, styleContext);
   } else {
     *aNewFrame = NS_NewBlockFrame(mPresShell, styleContext);
   }
 
   return ConstructBlock(aState, aDisplay, aItem.mContent,
                         aState.GetGeometricParent(aDisplay, aParentFrame),
                         aParentFrame, styleContext, aNewFrame,
-                        aFrameItems, aDisplay->IsPositioned());
+                        aFrameItems, aDisplay->IsPositioned(),
+                        aItem.mPendingBinding);
 }
 
 
 nsresult 
 nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
                                            nsIContent*              aContent,
                                            nsIFrame*                aParentFrame,
                                            nsIFrame*                aPrevInFlow,
@@ -4995,17 +5094,18 @@ nsCSSFrameConstructor::ConstructSVGForei
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsFrameItems childItems;
   // Claim to be relatively positioned so that we end up being the
   // absolute containing block.
   rv = ConstructBlock(aState, innerPseudoStyle->GetStyleDisplay(), content,
                       newFrame, newFrame, innerPseudoStyle,
-                      &blockFrame, childItems, PR_TRUE);
+                      &blockFrame, childItems, PR_TRUE,
+                      aItem.mPendingBinding);
 
   // Give the blockFrame a view so that GetOffsetTo works for descendants
   // of blockFrame with views...
   nsHTMLContainerFrame::CreateViewForFrame(blockFrame, PR_TRUE);
 
   newFrame->SetInitialChildList(nsnull, childItems);
 
   *aNewFrame = newFrame;
@@ -5034,17 +5134,17 @@ nsCSSFrameConstructor::AddPageBreakItem(
                  NS_STYLE_DISPLAY_BLOCK, "Unexpected display");
 
   static const FrameConstructionData sPageBreakData =
     FCDATA_DECL(FCDATA_SKIP_FRAMEMAP, NS_NewPageBreakFrame);
 
   // Lie about the tag and namespace so we don't trigger anything
   // interesting during frame construction.
   aItems.AppendItem(&sPageBreakData, aContent, nsCSSAnonBoxes::pageBreak,
-                    kNameSpaceID_None, -1, pseudoStyle.forget());
+                    kNameSpaceID_None, -1, nsnull, pseudoStyle.forget());
 }
 
 nsresult
 nsCSSFrameConstructor::ConstructFrame(nsFrameConstructorState& aState,
                                       nsIContent*              aContent,
                                       nsIFrame*                aParentFrame,
                                       nsFrameItems&            aFrameItems)
 
@@ -5128,35 +5228,45 @@ nsCSSFrameConstructor::AddFrameConstruct
                aContent->GetParent()->GetChildAt(aContentIndex) == aContent,
                "aContentIndex isn't the right content index");
 
   // The following code allows the user to specify the base tag
   // of an element using XBL.  XUL and HTML objects (like boxes, menus, etc.)
   // can then be extended arbitrarily.
   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
   nsRefPtr<nsStyleContext> styleContext(aStyleContext);
-  nsAutoEnqueueBinding binding(mDocument);
+  PendingBinding* pendingBinding = nsnull;
   if ((aFlags & ITEM_ALLOW_XBL_BASE) && display->mBinding)
   {
     // Ensure that our XBL bindings are installed.
 
     nsIXBLService * xblService = GetXBLService();
     if (!xblService)
       return;
 
     PRBool resolveStyle;
 
+    nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
+    if (!newPendingBinding) {
+      return;
+    }
     nsresult rv = xblService->LoadBindings(aContent, display->mBinding->mURI,
                                            display->mBinding->mOriginPrincipal,
                                            PR_FALSE,
-                                           getter_AddRefs(binding.mBinding),
+                                           getter_AddRefs(newPendingBinding->mBinding),
                                            &resolveStyle);
     if (NS_FAILED(rv))
       return;
 
+    if (newPendingBinding->mBinding) {
+      pendingBinding = newPendingBinding;
+      // aState takes over owning newPendingBinding
+      aState.AddPendingBinding(newPendingBinding.forget());
+    }
+
     if (resolveStyle) {
       styleContext = ResolveStyleContext(styleContext->GetParent(), aContent);
       display = styleContext->GetStyleDisplay();
       aStyleContext = styleContext;
     }
 
     aTag = mDocument->BindingManager()->ResolveTag(aContent, &aNameSpaceID);
   }
@@ -5267,17 +5377,17 @@ nsCSSFrameConstructor::AddFrameConstruct
     !(bits & FCDATA_IS_TABLE_PART);
 
   if (canHavePageBreak && display->mBreakBefore) {
     AddPageBreakItem(aContent, aStyleContext, aItems);
   }
 
   FrameConstructionItem* item =
     aItems.AppendItem(data, aContent, aTag, aNameSpaceID, aContentIndex,
-                      styleContext.forget());
+                      pendingBinding, styleContext.forget());
   if (!item) {
     if (isGeneratedContent) {
       aContent->UnbindFromTree();
     }
     return;
   }
 
   item->mIsText = isText;
@@ -8158,18 +8268,21 @@ nsCSSFrameConstructor::CreateContinuingT
           nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
                                         GetAbsoluteContainingBlock(newFrame),
                                         nsnull);
 
           headerFooterFrame = static_cast<nsTableRowGroupFrame*>
                                          (NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
           nsIContent* headerFooter = rowGroupFrame->GetContent();
           headerFooterFrame->Init(headerFooter, newFrame, nsnull);
+          // No ancestor bindings to worry about ordering with, so null pending
+          // binding is ok.
           ProcessChildren(state, headerFooter, rowGroupFrame->GetStyleContext(),
-                          headerFooterFrame, PR_TRUE, childItems, PR_FALSE);
+                          headerFooterFrame, PR_TRUE, childItems, PR_FALSE,
+                          nsnull);
           NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
           headerFooterFrame->SetInitialChildList(nsnull, childItems);
           headerFooterFrame->SetRepeatable(PR_TRUE);
 
           // Table specific initialization
           headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
 
           // XXX Deal with absolute and fixed frames...
@@ -9398,16 +9511,18 @@ nsCSSFrameConstructor::CreateNeededTable
                                 parentContent,
                                 // Lie about the tag; it doesn't matter anyway
                                 pseudoType,
                                 // The namespace does matter, however; it needs
                                 // to match that of our first child item to
                                 // match the old behavior
                                 iter.item().mNameSpaceID,
                                 -1,
+                                // no pending binding
+                                nsnull,
                                 wrapperStyle.forget());
 
     if (!newItem) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // Here we're cheating a tad... technically, table-internal items should be
     // inline if aParentFrame is inline, but they'll get wrapped in an
@@ -9462,32 +9577,25 @@ nsCSSFrameConstructor::ConstructFramesFr
   }
 
   NS_ASSERTION(!aState.mHavePendingPopupgroup,
                "Should have proccessed it by now");
 
   return NS_OK;
 }
 
-/**
- * Request to process the child content elements and create frames.
- *
- * @param   aContent the content object whose child elements to process
- * @param   aFrame the frame associated with aContent. This will be the
- *            parent frame (both content and geometric) for the flowed
- *            child frames
- */
 nsresult
 nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
                                        nsIContent*              aContent,
                                        nsStyleContext*          aStyleContext,
                                        nsIFrame*                aFrame,
                                        const PRBool             aCanHaveGeneratedContent,
                                        nsFrameItems&            aFrameItems,
-                                       const PRBool             aAllowBlockStyles)
+                                       const PRBool             aAllowBlockStyles,
+                                       PendingBinding*          aPendingBinding)
 {
   NS_PRECONDITION(aFrame, "Must have parent frame here");
   NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
                   "Parent frame in ProcessChildren should be its own "
                   "content insertion frame");
 
   // XXXbz ideally, this would do all the pushing of various
   // containing blocks as needed, so callers don't have to do it...
@@ -9502,16 +9610,19 @@ nsCSSFrameConstructor::ProcessChildren(n
   nsFrameConstructorSaveState floatSaveState;
   if (aFrame->IsFrameOfType(nsIFrame::eMathML) ||
       aFrame->IsBoxFrame()) {
     aState.PushFloatContainingBlock(nsnull, floatSaveState);
   } else if (aFrame->IsFloatContainingBlock()) {
     aState.PushFloatContainingBlock(aFrame, floatSaveState);
   }
 
+  nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
+                                                           aPendingBinding);
+
   FrameConstructionItemList itemsToConstruct;
   nsresult rv = NS_OK;
 
   // If we have first-letter or first-line style then frames can get
   // moved around so don't set these flags.
   if (aAllowBlockStyles && !haveFirstLetterStyle && !haveFirstLineStyle) {
     itemsToConstruct.SetLineBoundaryAtStart(PR_TRUE);
     itemsToConstruct.SetLineBoundaryAtEnd(PR_TRUE);
@@ -10542,17 +10653,18 @@ nsresult
 nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
                                       const nsStyleDisplay*    aDisplay,
                                       nsIContent*              aContent,
                                       nsIFrame*                aParentFrame,
                                       nsIFrame*                aContentParentFrame,
                                       nsStyleContext*          aStyleContext,
                                       nsIFrame**               aNewFrame,
                                       nsFrameItems&            aFrameItems,
-                                      PRBool                   aAbsPosContainer)
+                                      PRBool                   aAbsPosContainer,
+                                      PendingBinding*          aPendingBinding)
 {
   // Create column wrapper if necessary
   nsIFrame* blockFrame = *aNewFrame;
   nsIFrame* parent = aParentFrame;
   nsRefPtr<nsStyleContext> blockStyle = aStyleContext;
   const nsStyleColumn* columns = aStyleContext->GetStyleColumn();
 
   if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
@@ -10606,17 +10718,17 @@ nsCSSFrameConstructor::ConstructBlock(ns
   if (aAbsPosContainer) {
     //    NS_ASSERTION(aRelPos, "should have made area frame for this");
     aState.PushAbsoluteContainingBlock(blockFrame, absoluteSaveState);
   }
 
   // Process the child content
   nsFrameItems childItems;
   rv = ProcessChildren(aState, aContent, aStyleContext, blockFrame, PR_TRUE,
-                       childItems, PR_TRUE);
+                       childItems, PR_TRUE, aPendingBinding);
 
   // Set the frame's initial child list
   blockFrame->SetInitialChildList(nsnull, childItems);
 
   return rv;
 }
 
 nsresult
@@ -10843,16 +10955,18 @@ nsCSSFrameConstructor::CreateIBSiblings(
 }
 
 void
 nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
                                              FrameConstructionItem& aParentItem)
 {
   // XXXbz should we preallocate aParentItem.mChildItems to some sane
   // length?  Maybe even to parentContent->GetChildCount()?
+  nsFrameConstructorState::PendingBindingAutoPusher
+    pusher(aState, aParentItem.mPendingBinding);
 
   // Probe for generated content before
   nsStyleContext* const parentStyleContext = aParentItem.mStyleContext;
   nsIContent* const parentContent = aParentItem.mContent;
   CreateGeneratedContentItem(aState, nsnull, parentContent,
                              parentStyleContext, nsCSSPseudoElements::before,
                              aParentItem.mChildItems);
 
@@ -11721,18 +11835,22 @@ nsCSSFrameConstructor::LazyGenerateChild
 
    {
       nsAutoScriptBlocker scriptBlocker;
       nsCSSFrameConstructor* fc = mPresShell->FrameConstructor();
       fc->BeginUpdate();
 
       nsFrameItems childItems;
       nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull);
+      // We don't have a parent frame with a pending binding constructor here,
+      // so no need to worry about ordering of the kids' constructors with it.
+      // Pass null for the PendingBinding.
       nsresult rv = fc->ProcessChildren(state, mContent, frame->GetStyleContext(),
-                                        frame, PR_FALSE, childItems, PR_FALSE);
+                                        frame, PR_FALSE, childItems, PR_FALSE,
+                                        nsnull);
       if (NS_FAILED(rv)) {
         fc->EndUpdate();
         return rv;
       }
 
       frame->SetInitialChildList(nsnull, childItems);
 
       fc->EndUpdate();
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -64,16 +64,17 @@ class nsFrameManager;
 class nsIDOMHTMLSelectElement;
 class nsPresContext;
 class nsStyleChangeList;
 class nsIFrame;
 struct nsGenConInitializer;
 class ChildIterator;
 class nsICSSAnonBoxPseudo;
 class nsPageContentFrame;
+struct PendingBinding;
 
 struct nsFindFrameHint
 {
   nsIFrame *mPrimaryFrameForPrevSibling;  // weak ref to the primary frame for the content for which we need a frame
   nsFindFrameHint() : mPrimaryFrameForPrevSibling(nsnull) { }
 };
 
 typedef void (nsLazyFrameConstructionCallback)
@@ -762,21 +763,22 @@ private:
     // aContentIndex is the index of aContent in its parent's child list,
     // or -1 if aContent is not in its parent's child list, or the index
     // is not known.
     FrameConstructionItem* AppendItem(const FrameConstructionData* aFCData,
                                       nsIContent* aContent,
                                       nsIAtom* aTag,
                                       PRInt32 aNameSpaceID,
                                       PRInt32 aContentIndex,
+                                      PendingBinding* aPendingBinding,
                                       already_AddRefed<nsStyleContext> aStyleContext)
     {
       FrameConstructionItem* item =
         new FrameConstructionItem(aFCData, aContent, aTag, aNameSpaceID,
-                                  aContentIndex, aStyleContext);
+                                  aContentIndex, aPendingBinding, aStyleContext);
       if (item) {
         PR_APPEND_LINK(item, &mItems);
         ++mItemCount;
         ++mDesiredParentCounts[item->DesiredParentType()];
       } else {
         // Clean up the style context
         nsRefPtr<nsStyleContext> sc(aStyleContext);
       }
@@ -918,20 +920,21 @@ private:
   struct FrameConstructionItem : public PRCList {
     // No need to PR_INIT_CLIST in the constructor because the only
     // place that creates us immediately appends us.
     FrameConstructionItem(const FrameConstructionData* aFCData,
                           nsIContent* aContent,
                           nsIAtom* aTag,
                           PRInt32 aNameSpaceID,
                           PRInt32 aContentIndex,
+                          PendingBinding* aPendingBinding,
                           already_AddRefed<nsStyleContext> aStyleContext) :
       mFCData(aFCData), mContent(aContent), mTag(aTag),
       mNameSpaceID(aNameSpaceID), mContentIndex(aContentIndex),
-      mStyleContext(aStyleContext),
+      mPendingBinding(aPendingBinding), mStyleContext(aStyleContext),
       mIsText(PR_FALSE), mIsGeneratedContent(PR_FALSE),
       mIsRootPopupgroup(PR_FALSE), mIsAllInline(PR_FALSE), mIsBlock(PR_FALSE),
       mHasInlineEnds(PR_FALSE), mIsPopup(PR_FALSE),
       mIsLineParticipant(PR_FALSE)
     {}
     ~FrameConstructionItem() {
       if (mIsGeneratedContent) {
         mContent->UnbindFromTree();
@@ -958,16 +961,25 @@ private:
     nsIContent* mContent;
     // The XBL-resolved tag name to use for frame construction.
     nsIAtom* mTag;
     // The XBL-resolved namespace to use for frame construction.
     PRInt32 mNameSpaceID;
     // The index of mContent in its parent's child list, or -1 if it's
     // not in the parent's child list or not known.
     PRInt32 mContentIndex;
+    // The PendingBinding for this frame construction item, if any.  May be
+    // null.  We maintain a list of PendingBindings in the frame construction
+    // state in the order in which AddToAttachedQueue should be called on them:
+    // depth-first, post-order traversal order.  Since we actually traverse the
+    // DOM in a mix of breadth-first and depth-first, it is the responsibility
+    // of whoever constructs FrameConstructionItem kids of a given
+    // FrameConstructionItem to push its mPendingBinding as the current
+    // insertion point before doing so and pop it afterward.
+    PendingBinding* mPendingBinding;
     // The style context to use for creating the new frame.
     nsRefPtr<nsStyleContext> mStyleContext;
     // Whether this is a text content item.
     PRPackedBool mIsText;
     // Whether this is a generated content container.
     // If it is, mContent is a strong pointer.
     PRPackedBool mIsGeneratedContent;
     // Whether this is an item for the root popupgroup.
@@ -1160,16 +1172,17 @@ private:
                                    FCItemIterator& aItem,
                                    nsIFrame* aParentFrame,
                                    nsFrameItems& aFrameItems);
   static PRBool AtLineBoundary(FCItemIterator& aIter);
 
   nsresult CreateAnonymousFrames(nsFrameConstructorState& aState,
                                  nsIContent*              aParent,
                                  nsIFrame*                aParentFrame,
+                                 PendingBinding  *        aPendingBinding,
                                  nsFrameItems&            aChildItems);
 
   nsresult GetAnonymousContent(nsIContent* aParent,
                                nsIFrame* aParentFrame,
                                nsTArray<nsIContent*>& aAnonContent);
 
 //MathML Mod - RBS
 #ifdef MOZ_MATHML
@@ -1290,27 +1303,27 @@ private:
    *        pushed as the float containing block, as needed.  aFrame is also
    *        used to find the parent style context for the kids' style contexts
    *        (not necessary aFrame's style context).
    * @param aCanHaveGeneratedContent Whether to allow :before and
    *        :after styles on the parent.
    * @param aFrameItems the list in which we should place the in-flow children
    * @param aAllowBlockStyles Whether to allow first-letter and first-line
    *        styles on the parent.
-   * @param aTableCreator if non-null, will just make this method call
-   *        TableProcessChildren between constructing the ::before and ::after
-   *        content instead of doing whatever it would normally do.
+   * @param aPendingBinding Make sure to push this into aState before doing any
+   *        child item construction.
    */
   nsresult ProcessChildren(nsFrameConstructorState& aState,
                            nsIContent*              aContent,
                            nsStyleContext*          aStyleContext,
                            nsIFrame*                aFrame,
                            const PRBool             aCanHaveGeneratedContent,
                            nsFrameItems&            aFrameItems,
-                           const PRBool             aAllowBlockStyles);
+                           const PRBool             aAllowBlockStyles,
+                           PendingBinding*          aPendingBinding);
 
   nsIFrame* GetFrameFor(nsIContent* aContent);
 
   /**
    * These two functions are used when we start frame creation from a non-root
    * element. They should recreate the same state that we would have
    * arrived at if we had built frames from the root frame to aFrame.
    * Therefore, any calls to PushFloatContainingBlock and
@@ -1357,16 +1370,17 @@ private:
   nsresult
   InitializeSelectFrame(nsFrameConstructorState& aState,
                         nsIFrame*                scrollFrame,
                         nsIFrame*                scrolledFrame,
                         nsIContent*              aContent,
                         nsIFrame*                aParentFrame,
                         nsStyleContext*          aStyleContext,
                         PRBool                   aBuildCombobox,
+                        PendingBinding*          aPendingBinding,
                         nsFrameItems&            aFrameItems);
 
   nsresult MaybeRecreateFramesForContent(nsIContent* aContent);
 
   // If aAsyncInsert is true then a restyle event will be posted to handle the
   // required ContentInserted call instead of doing it immediately.
   nsresult RecreateFramesForContent(nsIContent* aContent, PRBool aAsyncInsert);
 
@@ -1430,25 +1444,28 @@ private:
   // @param aNewFrame an in/out parameter. On input it is the block to be
   // constructed. On output it is reset to the outermost
   // frame constructed (e.g. if we need to wrap the block in an
   // nsColumnSetFrame.
   // @param aParentFrame is the desired parent for the (possibly wrapped)
   // block
   // @param aContentParent is the parent the block would have if it
   // were in-flow
+  // @param aPendingBinding the pending binding  from this block's frame
+  // construction item.
   nsresult ConstructBlock(nsFrameConstructorState& aState,
                           const nsStyleDisplay*    aDisplay,
                           nsIContent*              aContent,
                           nsIFrame*                aParentFrame,
                           nsIFrame*                aContentParentFrame,
                           nsStyleContext*          aStyleContext,
                           nsIFrame**               aNewFrame,
                           nsFrameItems&            aFrameItems,
-                          PRBool                   aAbsPosContainer);
+                          PRBool                   aAbsPosContainer,
+                          PendingBinding*          aPendingBinding);
 
   nsresult ConstructInline(nsFrameConstructorState& aState,
                            FrameConstructionItem&   aItem,
                            nsIFrame*                aParentFrame,
                            const nsStyleDisplay*    aDisplay,
                            nsFrameItems&            aFrameItems,
                            nsIFrame**               aNewFrame);