зеркало из https://github.com/mozilla/gecko-dev.git
Bug 526178. Fix constructor firing order to match Gecko 1.9.1 again. r=roc
This commit is contained in:
Родитель
161cfad092
Коммит
9283a8626e
|
@ -70,6 +70,7 @@ _TEST_FILES = \
|
|||
test_bug481558.html \
|
||||
file_bug481558css.sjs \
|
||||
file_bug481558.xbl \
|
||||
test_bug526178.xhtml \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -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>
|
|
@ -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)) {
|
||||
|
@ -2414,6 +2489,9 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -2516,11 +2594,12 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
|
|||
// 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.
|
||||
|
@ -2539,11 +2618,13 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
|
|||
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();
|
||||
|
@ -2575,8 +2656,9 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
|
|||
|
||||
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);
|
||||
|
@ -3071,7 +3153,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 +3168,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 +3265,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 +3279,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 +3317,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 +3340,7 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
|
|||
nsIFrame* aParentFrame,
|
||||
nsStyleContext* aStyleContext,
|
||||
PRBool aBuildCombobox,
|
||||
PendingBinding* aPendingBinding,
|
||||
nsFrameItems& aFrameItems)
|
||||
{
|
||||
const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
|
||||
|
@ -3316,7 +3404,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 +3467,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 +3948,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 +4020,7 @@ nsresult
|
|||
nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
|
||||
nsIContent* aParent,
|
||||
nsIFrame* aParentFrame,
|
||||
PendingBinding* aPendingBinding,
|
||||
nsFrameItems& aChildItems)
|
||||
{
|
||||
nsAutoTArray<nsIContent*, 4> newAnonymousItems;
|
||||
|
@ -3942,6 +4032,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 +4397,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 +4632,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 +4669,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 +5099,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 +5139,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 +5233,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 +5244,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 +5382,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 +8273,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 +9516,8 @@ nsCSSFrameConstructor::CreateNeededTablePseudos(FrameConstructionItemList& aItem
|
|||
// match the old behavior
|
||||
iter.item().mNameSpaceID,
|
||||
-1,
|
||||
// no pending binding
|
||||
nsnull,
|
||||
wrapperStyle.forget());
|
||||
|
||||
if (!newItem) {
|
||||
|
@ -9467,14 +9582,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 +9589,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 +9615,9 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
|
|||
aState.PushFloatContainingBlock(aFrame, floatSaveState);
|
||||
}
|
||||
|
||||
nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
|
||||
aPendingBinding);
|
||||
|
||||
FrameConstructionItemList itemsToConstruct;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -10547,7 +10658,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 +10723,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 +10960,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 +11840,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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче