From 821b4127c4916015fc987536602f0b084166243a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 20 Jul 2017 18:29:14 +0200 Subject: [PATCH] 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 --HG-- extra : rebase_source : e9e10c53b7a69506750bd3c7c985946f7027dc30 --- layout/base/ServoRestyleManager.cpp | 54 +++++++++++++++++++++++++++++ layout/generic/nsFrame.cpp | 4 +++ 2 files changed, 58 insertions(+) diff --git a/layout/base/ServoRestyleManager.cpp b/layout/base/ServoRestyleManager.cpp index 976ef5902aa6..2a65ba7471e0 100644 --- a/layout/base/ServoRestyleManager.cpp +++ b/layout/base/ServoRestyleManager.cpp @@ -422,6 +422,58 @@ UpdateFirstLetterIfNeeded(nsIFrame* aFrame, ServoRestyleState& aRestyleState) 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 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) @@ -571,6 +623,7 @@ ServoRestyleManager::ProcessPostTraversal( // 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); } @@ -580,6 +633,7 @@ ServoRestyleManager::ProcessPostTraversal( } if (styleFrame) { + UpdateAdditionalStyleContexts(styleFrame, aRestyleState); styleFrame->UpdateStyleOfOwnedAnonBoxes(childrenRestyleState); } diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 6869ba4fdd04..42f5cd5647b0 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -10257,6 +10257,9 @@ nsIFrame::UpdateStyleOfOwnedChildFrame( ServoRestyleState& aRestyleState, const Maybe& 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: // @@ -10304,6 +10307,7 @@ nsIFrame::UpdateStyleOfOwnedChildFrame( for (nsIFrame* kid = aChildFrame->GetNextContinuation(); kid; kid = kid->GetNextContinuation()) { + MOZ_ASSERT(!kid->GetAdditionalStyleContext(0)); kid->SetStyleContext(continuationStyle); }