Bug 526178. Fix constructor firing order to match Gecko 1.9.1 again. r=roc

This commit is contained in:
Boris Zbarsky 2009-11-04 17:58:13 -05:00
parent acb9c8f8e4
commit 482ee7e084
4 changed files with 260 additions and 48 deletions

View File

@ -70,6 +70,7 @@ _TEST_FILES = \
test_bug481558.html \
file_bug481558css.sjs \
file_bug481558.xbl \
test_bug526178.xhtml \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,75 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
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>
#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" style="display: none">
<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 = "";
var pendingBindings = $("content").getElementsByTagName("*").length;
function bindingDone() {
if (--pendingBindings == 0) {
is(logString, "apoeknmljfihgdbc");
SimpleTest.finish();
}
}
SimpleTest.waitForExplicitFinish();
$("content").style.display = "";
]]>
</script>
</pre>
</body>
</html>

View File

@ -767,6 +767,23 @@ private:
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 {
@ -890,6 +907,44 @@ public:
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;
@ -899,6 +954,12 @@ protected:
*/
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,
@ -921,7 +982,8 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShe
mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
aAbsoluteContainingBlock->GetStyleDisplay()->
HasTransform()),
mHavePendingPopupgroup(PR_FALSE)
mHavePendingPopupgroup(PR_FALSE),
mCurrentPendingBindingInsertionPoint(&mPendingBindings)
{
#ifdef MOZ_XUL
nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
@ -930,6 +992,7 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShe
}
#endif
MOZ_COUNT_CTOR(nsFrameConstructorState);
PR_INIT_CLIST(&mPendingBindings);
}
nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
@ -950,7 +1013,8 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
aAbsoluteContainingBlock->GetStyleDisplay()->
HasTransform()),
mHavePendingPopupgroup(PR_FALSE)
mHavePendingPopupgroup(PR_FALSE),
mCurrentPendingBindingInsertionPoint(&mPendingBindings)
{
#ifdef MOZ_XUL
nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
@ -960,6 +1024,7 @@ nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
#endif
MOZ_COUNT_CTOR(nsFrameConstructorState);
mFrameState = aPresShell->GetDocument()->GetLayoutHistoryState();
PR_INIT_CLIST(&mPendingBindings);
}
nsFrameConstructorState::~nsFrameConstructorState()
@ -983,6 +1048,16 @@ nsFrameConstructorState::~nsFrameConstructorState()
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*
@ -2026,7 +2101,7 @@ nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
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;
@ -2081,7 +2156,7 @@ nsCSSFrameConstructor::ConstructTableRow(nsFrameConstructorState& aState,
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;
@ -2221,7 +2296,7 @@ nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
} 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)) {
@ -2395,6 +2470,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
const nsStyleDisplay* display = styleContext->GetStyleDisplay();
PendingBinding* pendingBinding = nsnull;
// Ensure that our XBL bindings are installed.
if (display->mBinding) {
// Get the XBL loader.
@ -2405,16 +2481,22 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
if (!xblService)
return NS_ERROR_FAILURE;
nsRefPtr<nsXBLBinding> binding;
nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
if (!newPendingBinding) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = xblService->LoadBindings(aDocElement, display->mBinding->mURI,
display->mBinding->mOriginPrincipal,
PR_FALSE, getter_AddRefs(binding),
PR_FALSE,
getter_AddRefs(newPendingBinding->mBinding),
&resolveStyle);
if (NS_FAILED(rv))
return NS_OK; // Binding will load asynchronously.
if (binding) {
mDocument->BindingManager()->AddToAttachedQueue(binding);
if (newPendingBinding->mBinding) {
pendingBinding = newPendingBinding;
// state takes over owning newPendingBinding
state.AddPendingBinding(newPendingBinding.forget());
}
if (resolveStyle) {
@ -2520,7 +2602,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
nsRefPtr<nsStyleContext> extraRef(styleContext);
FrameConstructionItem item(&rootTableData, aDocElement,
aDocElement->Tag(), kNameSpaceID_None,
-1, extraRef.forget());
-1, pendingBinding, extraRef.forget());
nsFrameItems frameItems;
// if the document is a table then just populate it.
@ -2543,7 +2625,8 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
state.GetGeometricParent(display,
mDocElementContainingBlock),
mDocElementContainingBlock, styleContext,
&contentFrame, frameItems, display->IsPositioned());
&contentFrame, frameItems, display->IsPositioned(),
pendingBinding);
if (NS_FAILED(rv) || frameItems.IsEmpty())
return rv;
*aNewFrame = frameItems.FirstChild();
@ -2576,7 +2659,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame),
"Only XUL and SVG frames should reach here");
ProcessChildren(state, aDocElement, styleContext, contentFrame, PR_TRUE,
childItems, PR_FALSE);
childItems, PR_FALSE, pendingBinding);
// Set the initial child lists
contentFrame->SetInitialChildList(nsnull, childItems);
@ -3071,7 +3154,8 @@ nsCSSFrameConstructor::ConstructButtonFrame(nsFrameConstructorState& aState,
#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
@ -3085,7 +3169,8 @@ nsCSSFrameConstructor::ConstructButtonFrame(nsFrameConstructorState& aState,
// 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,
@ -3181,7 +3266,8 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
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
@ -3194,7 +3280,8 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
// element (the scrollbars).
nsFrameItems childItems;
CreateAnonymousFrames(aState, content, comboboxFrame, childItems);
CreateAnonymousFrames(aState, content, comboboxFrame,
aItem.mPendingBinding, childItems);
comboboxFrame->SetInitialChildList(nsnull, childItems);
@ -3231,7 +3318,8 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
// 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;
}
@ -3253,6 +3341,7 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
nsIFrame* aParentFrame,
nsStyleContext* aStyleContext,
PRBool aBuildCombobox,
PendingBinding* aPendingBinding,
nsFrameItems& aFrameItems)
{
const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
@ -3316,7 +3405,7 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
}
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);
@ -3379,7 +3468,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
}
ProcessChildren(aState, content, styleContext, blockFrame, PR_TRUE,
childItems, PR_TRUE);
childItems, PR_TRUE, aItem.mPendingBinding);
nsFrameItems fieldsetKids;
fieldsetKids.AddChild(blockFrame);
@ -3860,7 +3949,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
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
@ -3931,6 +4021,7 @@ nsresult
nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
nsIContent* aParent,
nsIFrame* aParentFrame,
PendingBinding* aPendingBinding,
nsFrameItems& aChildItems)
{
nsAutoTArray<nsIContent*, 4> newAnonymousItems;
@ -3942,6 +4033,9 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
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?");
@ -4304,7 +4398,11 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
// 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;
@ -4535,7 +4633,8 @@ nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
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;
@ -4571,7 +4670,8 @@ nsCSSFrameConstructor::ConstructNonScrollableBlock(nsFrameConstructorState& aSta
return ConstructBlock(aState, aDisplay, aItem.mContent,
aState.GetGeometricParent(aDisplay, aParentFrame),
aParentFrame, styleContext, aNewFrame,
aFrameItems, aDisplay->IsPositioned());
aFrameItems, aDisplay->IsPositioned(),
aItem.mPendingBinding);
}
@ -5000,7 +5100,8 @@ nsCSSFrameConstructor::ConstructSVGForeignObjectFrame(nsFrameConstructorState& a
// 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...
@ -5039,7 +5140,7 @@ nsCSSFrameConstructor::AddPageBreakItem(nsIContent* aContent,
// 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
@ -5133,7 +5234,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
// 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.
@ -5144,14 +5245,24 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
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();
@ -5272,7 +5383,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
FrameConstructionItem* item =
aItems.AppendItem(data, aContent, aTag, aNameSpaceID, aContentIndex,
styleContext.forget());
pendingBinding, styleContext.forget());
if (!item) {
if (isGeneratedContent) {
aContent->UnbindFromTree();
@ -8163,8 +8274,11 @@ nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell,
(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);
@ -9403,6 +9517,8 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(FrameConstructionItemList& aItem
// match the old behavior
iter.item().mNameSpaceID,
-1,
// no pending binding
nsnull,
wrapperStyle.forget());
if (!newItem) {
@ -9467,14 +9583,6 @@ nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aSta
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,
@ -9482,7 +9590,8 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
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,
@ -9507,6 +9616,9 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
aState.PushFloatContainingBlock(aFrame, floatSaveState);
}
nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
aPendingBinding);
FrameConstructionItemList itemsToConstruct;
nsresult rv = NS_OK;
@ -10547,7 +10659,8 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
nsStyleContext* aStyleContext,
nsIFrame** aNewFrame,
nsFrameItems& aFrameItems,
PRBool aAbsPosContainer)
PRBool aAbsPosContainer,
PendingBinding* aPendingBinding)
{
// Create column wrapper if necessary
nsIFrame* blockFrame = *aNewFrame;
@ -10611,7 +10724,7 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
// 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);
@ -10848,6 +10961,8 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
{
// 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;
@ -11726,8 +11841,12 @@ nsCSSFrameConstructor::LazyGenerateChildrenEvent::Run()
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;

View File

@ -69,6 +69,7 @@ struct nsGenConInitializer;
class ChildIterator;
class nsICSSAnonBoxPseudo;
class nsPageContentFrame;
struct PendingBinding;
struct nsFindFrameHint
{
@ -767,11 +768,12 @@ private:
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;
@ -923,10 +925,11 @@ private:
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),
@ -963,6 +966,15 @@ private:
// 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.
@ -1165,6 +1177,7 @@ private:
nsresult CreateAnonymousFrames(nsFrameConstructorState& aState,
nsIContent* aParent,
nsIFrame* aParentFrame,
PendingBinding * aPendingBinding,
nsFrameItems& aChildItems);
nsresult GetAnonymousContent(nsIContent* aParent,
@ -1295,9 +1308,8 @@ private:
* @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,
@ -1305,7 +1317,8 @@ private:
nsIFrame* aFrame,
const PRBool aCanHaveGeneratedContent,
nsFrameItems& aFrameItems,
const PRBool aAllowBlockStyles);
const PRBool aAllowBlockStyles,
PendingBinding* aPendingBinding);
nsIFrame* GetFrameFor(nsIContent* aContent);
@ -1362,6 +1375,7 @@ private:
nsIFrame* aParentFrame,
nsStyleContext* aStyleContext,
PRBool aBuildCombobox,
PendingBinding* aPendingBinding,
nsFrameItems& aFrameItems);
nsresult MaybeRecreateFramesForContent(nsIContent* aContent);
@ -1435,6 +1449,8 @@ private:
// 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,
@ -1443,7 +1459,8 @@ private:
nsStyleContext* aStyleContext,
nsIFrame** aNewFrame,
nsFrameItems& aFrameItems,
PRBool aAbsPosContainer);
PRBool aAbsPosContainer,
PendingBinding* aPendingBinding);
nsresult ConstructInline(nsFrameConstructorState& aState,
FrameConstructionItem& aItem,