summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
Diffstat (limited to 'layout')
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp119
-rw-r--r--layout/base/nsCSSFrameConstructor.h17
-rw-r--r--layout/style/nsRuleProcessorData.h9
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 {