diff options
Diffstat (limited to 'layout')
-rw-r--r-- | layout/base/nsCSSFrameConstructor.cpp | 119 | ||||
-rw-r--r-- | layout/base/nsCSSFrameConstructor.h | 17 | ||||
-rw-r--r-- | layout/style/nsRuleProcessorData.h | 9 |
3 files changed, 112 insertions, 33 deletions
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 1545e1d331..8293e5198c 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -788,21 +788,23 @@ public: nsCOMArray<nsIContent> mGeneratedTextNodesWithInitializer; - TreeMatchContext mTreeMatchContext; + TreeMatchContext& mTreeMatchContext; // Constructor // Use the passed-in history state. nsFrameConstructorState( nsIPresShell* aPresShell, + TreeMatchContext& aTreeMatchContext, nsContainerFrame* aFixedContainingBlock, nsContainerFrame* aAbsoluteContainingBlock, nsContainerFrame* aFloatContainingBlock, already_AddRefed<nsILayoutHistoryState> aHistoryState); // Get the history state from the pres context's pres shell. - nsFrameConstructorState(nsIPresShell* aPresShell, - nsContainerFrame* aFixedContainingBlock, - nsContainerFrame* aAbsoluteContainingBlock, - nsContainerFrame* aFloatContainingBlock); + nsFrameConstructorState(nsIPresShell* aPresShell, + TreeMatchContext& aTreeMatchContext, + nsContainerFrame* aFixedContainingBlock, + nsContainerFrame* aAbsoluteContainingBlock, + nsContainerFrame* aFloatContainingBlock); ~nsFrameConstructorState(); @@ -955,6 +957,7 @@ protected: nsFrameConstructorState::nsFrameConstructorState( nsIPresShell* aPresShell, + TreeMatchContext& aTreeMatchContext, nsContainerFrame* aFixedContainingBlock, nsContainerFrame* aAbsoluteContainingBlock, nsContainerFrame* aFloatContainingBlock, @@ -979,8 +982,7 @@ nsFrameConstructorState::nsFrameConstructorState( mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock), mHavePendingPopupgroup(false), mCreatingExtraFrames(false), - mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited, - aPresShell->GetDocument()), + mTreeMatchContext(aTreeMatchContext), mCurrentPendingBindingInsertionPoint(nullptr) { nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell); @@ -991,10 +993,13 @@ nsFrameConstructorState::nsFrameConstructorState( } nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell, + TreeMatchContext& aTreeMatchContext, nsContainerFrame* aFixedContainingBlock, nsContainerFrame* aAbsoluteContainingBlock, nsContainerFrame* aFloatContainingBlock) - : nsFrameConstructorState(aPresShell, aFixedContainingBlock, + : nsFrameConstructorState(aPresShell, + aTreeMatchContext, + aFixedContainingBlock, aAbsoluteContainingBlock, aFloatContainingBlock, aPresShell->GetDocument()->GetLayoutHistoryState()) @@ -2396,13 +2401,15 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now"); + TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction); + // Initialize the ancestor filter with null for now; we'll push + // aDocElement once we finish resolving style for it. + matchContext.InitAncestors(nullptr); nsFrameConstructorState state(mPresShell, + matchContext, GetAbsoluteContainingBlock(mDocElementContainingBlock, FIXED_POS), nullptr, nullptr, do_AddRef(aFrameState)); - // Initialize the ancestor filter with null for now; we'll push - // aDocElement once we finish resolving style for it. - state.mTreeMatchContext.InitAncestors(nullptr); // XXXbz why, exactly? if (!mTempFrameTreeState) @@ -2831,7 +2838,8 @@ nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement) RefPtr<nsStyleContext> rootPseudoStyle; // we must create a state because if the scrollbars are GFX it needs the // state to build the scrollbar frames. - nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr); + TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction); + nsFrameConstructorState state(mPresShell, matchContext, nullptr, nullptr, nullptr); // Start off with the viewport as parent; we'll adjust it as needed. nsContainerFrame* parentFrame = viewportFrame; @@ -6978,12 +6986,16 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation, } void -nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent) +nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent, + TreeMatchContext& aTreeMatchContext) { NS_ASSERTION(!aContent->HasFlag(NODE_NEEDS_FRAME), "shouldn't get here with a content node that has needs frame bit set"); NS_ASSERTION(aContent->HasFlag(NODE_DESCENDANTS_NEED_FRAMES), "should only get here with a content node that has descendants needing frames"); + NS_ASSERTION(aTreeMatchContext.mAncestorFilter.HasFilter(), + "The whole point of having the tree match context is optimizing " + "the ancestor filter usage!"); aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES); @@ -7019,19 +7031,31 @@ nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent) inRun = false; // generate a ContentRangeInserted for [startOfRun,i) ContentRangeInserted(aContent, firstChildInRun, child, nullptr, - false); + false, &aTreeMatchContext); } } } if (inRun) { - ContentAppended(aContent, firstChildInRun, false); + ContentAppended(aContent, firstChildInRun, false, &aTreeMatchContext); } // Now descend. FlattenedChildIterator iter(aContent); for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { if (child->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) { - CreateNeededFrames(child); + TreeMatchContext::AutoAncestorPusher insertionPointPusher( + aTreeMatchContext); + + // Handle stuff like xbl:children. + if (child->GetParent() != aContent && child->GetParent()->IsElement()) { + insertionPointPusher.PushAncestorAndStyleScope( + child->GetParent()->AsElement()); + } + + TreeMatchContext::AutoAncestorPusher pusher(aTreeMatchContext); + pusher.PushAncestorAndStyleScope(child); + + CreateNeededFrames(child, aTreeMatchContext); } } } @@ -7046,7 +7070,9 @@ void nsCSSFrameConstructor::CreateNeededFrames() "root element should not have frame created lazily"); if (rootElement && rootElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) { BeginUpdate(); - CreateNeededFrames(rootElement); + TreeMatchContext treeMatchContext(mDocument, TreeMatchContext::ForFrameConstruction); + treeMatchContext.InitAncestors(rootElement); + CreateNeededFrames(rootElement, treeMatchContext); EndUpdate(); } } @@ -7160,10 +7186,13 @@ nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame, } void -nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, - nsIContent* aFirstNewContent, - bool aAllowLazyConstruction) +nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, + nsIContent* aFirstNewContent, + bool aAllowLazyConstruction, + TreeMatchContext* aProvidedTreeMatchContext) { + MOZ_ASSERT_IF(aProvidedTreeMatchContext, !aAllowLazyConstruction); + AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC); NS_PRECONDITION(mUpdateCount != 0, "Should be in an update while creating frames"); @@ -7341,13 +7370,23 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, } // Create some new frames + // + // We use the provided tree match context, or create a new one on the fly + // otherwise. + Maybe<TreeMatchContext> matchContext; + if (!aProvidedTreeMatchContext) { + matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction); + // We use GetParentElementCrossingShadowRoot to handle the case where + // aContainer is a ShadowRoot. + matchContext->InitAncestors(aFirstNewContent->GetParentElementCrossingShadowRoot()); + } nsFrameConstructorState state(mPresShell, + aProvidedTreeMatchContext + ? *aProvidedTreeMatchContext + : *matchContext, GetAbsoluteContainingBlock(parentFrame, FIXED_POS), GetAbsoluteContainingBlock(parentFrame, ABS_POS), containingBlock); - // We use GetParentElementCrossingShadowRoot to handle the case where - // aContainer is a ShadowRoot. - state.mTreeMatchContext.InitAncestors(aFirstNewContent->GetParentElementCrossingShadowRoot()); nsIAtom* frameType = parentFrame->GetType(); @@ -7553,7 +7592,8 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, nsIContent* aStartChild, nsIContent* aEndChild, nsILayoutHistoryState* aFrameState, - bool aAllowLazyConstruction) + bool aAllowLazyConstruction, + TreeMatchContext* aProvidedTreeMatchContext) { AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC); NS_PRECONDITION(mUpdateCount != 0, @@ -7784,14 +7824,21 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, return; } + Maybe<TreeMatchContext> matchContext; + if (!aProvidedTreeMatchContext) { + matchContext.emplace(mDocument, TreeMatchContext::ForFrameConstruction); + // We use GetParentElementCrossingShadowRoot to handle the case where + // aContainer is a ShadowRoot. + matchContext->InitAncestors(aStartChild->GetParentElementCrossingShadowRoot()); + } nsFrameConstructorState state(mPresShell, + aProvidedTreeMatchContext + ? *aProvidedTreeMatchContext + : *matchContext, GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS), GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS), GetFloatContainingBlock(insertion.mParentFrame), do_AddRef(aFrameState)); - // We use GetParentElementCrossingShadowRoot to handle the case where - // aContainer is a ShadowRoot. - state.mTreeMatchContext.InitAncestors(aStartChild->GetParentElementCrossingShadowRoot()); // Recover state for the containing block - we need to know if // it has :first-letter or :first-line style applied to it. The @@ -8637,7 +8684,9 @@ nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell, // Replicate the header/footer frame. nsTableRowGroupFrame* headerFooterFrame; nsFrameItems childItems; + TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction); nsFrameConstructorState state(mPresShell, + matchContext, GetAbsoluteContainingBlock(newFrame, FIXED_POS), GetAbsoluteContainingBlock(newFrame, ABS_POS), nullptr); @@ -8909,7 +8958,10 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame) // This should not normally be possible (because fixed-pos elements should // be absolute containers) but fixed-pos tables currently aren't abs-pos // containers. - nsFrameConstructorState state(mPresShell, aParentFrame, + TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction); + nsFrameConstructorState state(mPresShell, + matchContext, + aParentFrame, nullptr, mRootElementFrame); state.mCreatingExtraFrames = true; @@ -11047,7 +11099,10 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame, NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame), "Containing block is confused"); + TreeMatchContext matchContext(mDocument, + TreeMatchContext::ForFrameConstruction); nsFrameConstructorState state(mPresShell, + matchContext, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS), GetAbsoluteContainingBlock(aParentFrame, ABS_POS), aBlockContinuation); @@ -11422,7 +11477,10 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame, // Construct a new frame if (nullptr != aParentFrame) { nsFrameItems frameItems; - nsFrameConstructorState state(mPresShell, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS), + TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction); + nsFrameConstructorState state(mPresShell, + matchContext, + GetAbsoluteContainingBlock(aParentFrame, FIXED_POS), GetAbsoluteContainingBlock(aParentFrame, ABS_POS), GetFloatContainingBlock(aParentFrame), do_AddRef(mTempFrameTreeState.get())); @@ -12312,7 +12370,8 @@ nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame) BeginUpdate(); nsFrameItems childItems; - nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr); + TreeMatchContext matchContext(mDocument, TreeMatchContext::ForFrameConstruction); + nsFrameConstructorState state(mPresShell, matchContext, nullptr, nullptr, nullptr); // 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. diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index c4f94ceccd..c01d6ad7a0 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -87,7 +87,8 @@ public: void CreateNeededFrames(); private: - void CreateNeededFrames(nsIContent* aContent); + void CreateNeededFrames(nsIContent* aContent, + TreeMatchContext& aTreeMatchContext); enum Operation { CONTENTAPPEND, @@ -202,9 +203,15 @@ public: // If aAllowLazyConstruction is true then frame construction of the new // children can be done lazily. + // + // When constructing frames lazily, we can keep the tree match context in a + // much easier way than nsFrameConstructorState, and thus, we're allowed to + // provide a TreeMatchContext to avoid calling InitAncestors repeatedly deep + // in the DOM. void ContentAppended(nsIContent* aContainer, nsIContent* aFirstNewContent, - bool aAllowLazyConstruction); + bool aAllowLazyConstruction, + TreeMatchContext* aProvidedTreeMatchContext = nullptr); // If aAllowLazyConstruction is true then frame construction of the new child // can be done lazily. @@ -219,11 +226,15 @@ public: // aStartChild. If aAllowLazyConstruction is true then frame construction of // the new children can be done lazily. It is only allowed to be true when // inserting a single node. + // + // See ContentAppended to see why we allow passing an already initialized + // TreeMatchContext. void ContentRangeInserted(nsIContent* aContainer, nsIContent* aStartChild, nsIContent* aEndChild, nsILayoutHistoryState* aFrameState, - bool aAllowLazyConstruction); + bool aAllowLazyConstruction, + TreeMatchContext* aProvidedTreeMatchContext = nullptr); public: // FIXME(emilio): How important is it to keep the frame tree state around for diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h index f6d9771001..938c2f9d35 100644 --- a/layout/style/nsRuleProcessorData.h +++ b/layout/style/nsRuleProcessorData.h @@ -444,6 +444,15 @@ struct MOZ_STACK_CLASS TreeMatchContext { } } } + + enum ForFrameConstructionTag { ForFrameConstruction }; + + TreeMatchContext(nsIDocument* aDocument, + ForFrameConstructionTag) + : TreeMatchContext(true, + nsRuleWalker::eRelevantLinkUnvisited, + aDocument) + {} }; struct MOZ_STACK_CLASS RuleProcessorData { |