Bug 1366721: Restyle additional style contexts in ServoRestyleManager. r?heycam
I was about to assert that other non-primary frames don't have additional style
contexts everywhere, but that wouldn't make much sense, given they don't
correspond to an element we could selector-match against.
MozReview-Commit-ID: EtAQbSg6nP6
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -418,16 +418,68 @@ UpdateFirstLetterIfNeeded(nsIFrame* aFra
while (!block->IsFrameOfType(nsIFrame::eBlockFrame)) {
block = block->GetParent();
}
static_cast<nsBlockFrame*>(block->FirstContinuation())->
UpdateFirstLetterStyle(aRestyleState);
}
static void
+UpdateOneAdditionalStyleContext(nsIFrame* aFrame,
+ uint32_t aIndex,
+ ServoStyleContext& aOldContext,
+ ServoRestyleState& aRestyleState)
+{
+ auto pseudoType = aOldContext.GetPseudoType();
+ MOZ_ASSERT(pseudoType != CSSPseudoElementType::NotPseudo);
+ MOZ_ASSERT(
+ !nsCSSPseudoElements::PseudoElementSupportsUserActionState(pseudoType));
+
+ RefPtr<ServoStyleContext> newContext =
+ aRestyleState.StyleSet().ResolvePseudoElementStyle(
+ aFrame->GetContent()->AsElement(),
+ pseudoType,
+ aFrame->StyleContext()->AsServo(),
+ /* aPseudoElement = */ nullptr);
+
+ uint32_t equalStructs, samePointerStructs; // Not used, actually.
+ nsChangeHint childHint = aOldContext.CalcStyleDifference(
+ newContext,
+ &equalStructs,
+ &samePointerStructs);
+ if (!aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
+ childHint = NS_RemoveSubsumedHints(
+ childHint, aRestyleState.ChangesHandledFor(*aFrame));
+ }
+
+ if (childHint) {
+ aRestyleState.ChangeList().AppendChange(
+ aFrame, aFrame->GetContent(), childHint);
+ }
+
+ aFrame->SetAdditionalStyleContext(aIndex, newContext);
+}
+
+static void
+UpdateAdditionalStyleContexts(nsIFrame* aFrame,
+ ServoRestyleState& aRestyleState)
+{
+ MOZ_ASSERT(aFrame);
+ MOZ_ASSERT(aFrame->GetContent() && aFrame->GetContent()->IsElement());
+
+ // FIXME(emilio): Consider adding a bit or something to avoid the initial
+ // virtual call?
+ uint32_t index = 0;
+ while (auto* oldContext = aFrame->GetAdditionalStyleContext(index)) {
+ UpdateOneAdditionalStyleContext(
+ aFrame, index++, *oldContext->AsServo(), aRestyleState);
+ }
+}
+
+static void
UpdateFramePseudoElementStyles(nsIFrame* aFrame,
ServoRestyleState& aRestyleState)
{
// first-letter needs to be updated before first-line, because first-line can
// change the style of the first-letter.
UpdateFirstLetterIfNeeded(aFrame, aRestyleState);
if (aFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
@@ -566,25 +618,27 @@ ServoRestyleManager::ProcessPostTraversa
// styles). But in that case, newContext is the right context for the
// _later_ continuations anyway (the ones not affected by ::first-line), not
// the earlier ones, so there is no point stopping right at the point when
// we'd actually be setting the right style context.
//
// This does mean that we may be setting the wrong style context on our
// initial continuations; ::first-line fixes that up after the fact.
for (nsIFrame* f = styleFrame; f; f = f->GetNextContinuation()) {
+ MOZ_ASSERT_IF(f != styleFrame, !f->GetAdditionalStyleContext(0));
f->SetStyleContext(newContext);
}
if (MOZ_UNLIKELY(displayContentsNode)) {
MOZ_ASSERT(!styleFrame);
displayContentsNode->mStyle = newContext;
}
if (styleFrame) {
+ UpdateAdditionalStyleContexts(styleFrame, aRestyleState);
styleFrame->UpdateStyleOfOwnedAnonBoxes(childrenRestyleState);
}
if (!aElement->GetParent()) {
// This is the root. Update styles on the viewport as needed.
ViewportFrame* viewport =
do_QueryFrame(mPresContext->PresShell()->GetRootFrame());
if (viewport) {
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10252,16 +10252,19 @@ nsIFrame::UpdateStyleOfChildAnonBox(nsIF
/* static */ nsChangeHint
nsIFrame::UpdateStyleOfOwnedChildFrame(
nsIFrame* aChildFrame,
nsStyleContext* aNewStyleContext,
ServoRestyleState& aRestyleState,
const Maybe<nsStyleContext*>& aContinuationStyleContext)
{
+ MOZ_ASSERT(!aChildFrame->GetAdditionalStyleContext(0),
+ "We don't handle additional style contexts here");
+
// Figure out whether we have an actual change. It's important that we do
// this, for several reasons:
//
// 1) Even if all the child's changes are due to properties it inherits from
// us, it's possible that no one ever asked us for those style structs and
// hence changes to them aren't reflected in the changes handled at all.
//
// 2) Content can change stylesheets that change the styles of pseudos, and
@@ -10299,16 +10302,17 @@ nsIFrame::UpdateStyleOfOwnedChildFrame(
}
aChildFrame->SetStyleContext(aNewStyleContext);
nsStyleContext* continuationStyle =
aContinuationStyleContext ? *aContinuationStyleContext : aNewStyleContext;
for (nsIFrame* kid = aChildFrame->GetNextContinuation();
kid;
kid = kid->GetNextContinuation()) {
+ MOZ_ASSERT(!kid->GetAdditionalStyleContext(0));
kid->SetStyleContext(continuationStyle);
}
return childHint;
}
/* static */ void
nsIFrame::AddInPopupStateBitToDescendants(nsIFrame* aFrame)