diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:50 +0000 |
commit | def92d1b8e9d373e2f6f27c366d578d97d8960c6 (patch) | |
tree | 2ef34b9ad8bb9a9220e05d60352558b15f513894 /layout/base/RestyleManager.cpp | |
parent | Adding debian version 125.0.3-1. (diff) | |
download | firefox-def92d1b8e9d373e2f6f27c366d578d97d8960c6.tar.xz firefox-def92d1b8e9d373e2f6f27c366d578d97d8960c6.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/base/RestyleManager.cpp')
-rw-r--r-- | layout/base/RestyleManager.cpp | 96 |
1 files changed, 76 insertions, 20 deletions
diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 8c07512093..81ffebf89a 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -2087,6 +2087,28 @@ void RestyleManager::AnimationsWithDestroyedFrame ::StopAnimationsWithoutFrame( } } +// When using handled hints by an ancestor, we need to make sure that our +// ancestor in the DOM tree is actually our ancestor in the flat tree. +// Otherwise, we can't guarantee that e.g. a repaint from an ancestor in the DOM +// will really end up repainting us. +static bool CanUseHandledHintsFromAncestors(const nsIFrame* aFrame) { + if (aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) { + // An out of flow can be parented in other part of the tree. + return false; + } + if (aFrame->IsColumnSpanInMulticolSubtree()) { + // Any column-spanner's parent frame is not its DOM parent's primary frame. + return false; + } + if (aFrame->IsTableCaption()) { + // This one is more subtle. captions are in-flow children of the table + // frame. But they are parented to the table wrapper. So hints handled for + // the inner table might not be applicable to us. + return false; + } + return true; +} + #ifdef DEBUG static bool IsAnonBox(const nsIFrame* aFrame) { return aFrame->Style()->IsAnonBox(); @@ -2185,8 +2207,7 @@ static bool IsInReplicatedFixedPosTree(const nsIFrame* aFrame) { void ServoRestyleState::AssertOwner(const ServoRestyleState& aParent) const { MOZ_ASSERT(mOwner); - MOZ_ASSERT(!mOwner->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)); - MOZ_ASSERT(!mOwner->IsColumnSpanInMulticolSubtree()); + MOZ_ASSERT(CanUseHandledHintsFromAncestors(mOwner)); // We allow aParent.mOwner to be null, for cases when we're not starting at // the root of the tree. We also allow aParent.mOwner to be somewhere up our // expected owner chain not our immediate owner, which allows us creating long @@ -2309,7 +2330,7 @@ size_t ServoRestyleState::ProcessMaybeNestedWrapperRestyle(nsIFrame* aParent, nsLayoutUtils::FirstContinuationOrIBSplitSibling(parent); if (parentForRestyle != aParent) { parentRestyleState.emplace(*parentForRestyle, *this, nsChangeHint_Empty, - Type::InFlow); + CanUseHandledHints::Yes); } ServoRestyleState& curRestyleState = parentRestyleState ? *parentRestyleState : *this; @@ -2332,7 +2353,7 @@ size_t ServoRestyleState::ProcessMaybeNestedWrapperRestyle(nsIFrame* aParent, // the other hand, presumably our mChangesHandled already has the bits // we really want here so in practice it doesn't matter. ServoRestyleState childState(*cur, curRestyleState, nsChangeHint_Empty, - Type::InFlow, + CanUseHandledHints::Yes, /* aAssertWrapperRestyleLength = */ false); numProcessed += childState.ProcessMaybeNestedWrapperRestyle(cur, aIndex + 1); @@ -2652,8 +2673,7 @@ static void UpdateOneAdditionalComputedStyle(nsIFrame* aFrame, uint32_t aIndex, uint32_t equalStructs; // Not used, actually. nsChangeHint childHint = aOldContext.CalcStyleDifference(*newStyle, &equalStructs); - if (!aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) && - !aFrame->IsColumnSpanInMulticolSubtree()) { + if (CanUseHandledHintsFromAncestors(aFrame)) { childHint = NS_RemoveSubsumedHints(childHint, aRestyleState.ChangesHandledFor(aFrame)); } @@ -2812,11 +2832,8 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement, const bool isOutOfFlow = primaryFrame && primaryFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW); - // We need this because any column-spanner's parent frame is not its DOM - // parent's primary frame. We need some special check similar to out-of-flow - // frames. - const bool isColumnSpan = - primaryFrame && primaryFrame->IsColumnSpanInMulticolSubtree(); + const bool canUseHandledHints = + primaryFrame && CanUseHandledHintsFromAncestors(primaryFrame); // Grab the change hint from Servo. bool wasRestyled = false; @@ -2848,11 +2865,12 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement, maybeAnonBoxChild = primaryFrame->GetPlaceholderFrame(); } else { maybeAnonBoxChild = primaryFrame; - // Do not subsume change hints for the column-spanner. - if (!isColumnSpan) { - changeHint = NS_RemoveSubsumedHints( - changeHint, aRestyleState.ChangesHandledFor(styleFrame)); - } + } + + // Do not subsume change hints for the column-spanner. + if (canUseHandledHints) { + changeHint = NS_RemoveSubsumedHints( + changeHint, aRestyleState.ChangesHandledFor(styleFrame)); } // If the parent wasn't restyled, the styles of our anon box parents won't @@ -2944,10 +2962,9 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement, Maybe<ServoRestyleState> thisFrameRestyleState; if (styleFrame) { - auto type = isOutOfFlow || isColumnSpan ? ServoRestyleState::Type::OutOfFlow - : ServoRestyleState::Type::InFlow; - - thisFrameRestyleState.emplace(*styleFrame, aRestyleState, changeHint, type); + thisFrameRestyleState.emplace( + *styleFrame, aRestyleState, changeHint, + ServoRestyleState::CanUseHandledHints(canUseHandledHints)); } // We can't really assume as used changes from display: contents elements (or @@ -3435,6 +3452,45 @@ void RestyleManager::ElementStateChanged(Element* aElement, MaybeRestyleForRelativeSelectorState(styleSet, aElement, aChangedBits); } +void RestyleManager::CustomStatesWillChange(Element& aElement) { + MOZ_DIAGNOSTIC_ASSERT(!mInStyleRefresh); + + IncrementUndisplayedRestyleGeneration(); + + // Relative selector invalidation travels ancestor and earlier sibling + // direction, so it's very possible that it invalidates a styled element. + if (!aElement.HasServoData() && + !(aElement.GetSelectorFlags() & + NodeSelectorFlags::RelativeSelectorSearchDirectionAncestorSibling)) { + return; + } + + ServoElementSnapshot& snapshot = SnapshotFor(aElement); + snapshot.AddCustomStates(aElement); +} + +void RestyleManager::CustomStateChanged(Element& aElement, nsAtom* aState) { + ServoStyleSet& styleSet = *StyleSet(); + MaybeRestyleForNthOfCustomState(styleSet, aElement, aState); + styleSet.MaybeInvalidateRelativeSelectorCustomStateDependency( + aElement, aState, Snapshots()); +} + +void RestyleManager::MaybeRestyleForNthOfCustomState(ServoStyleSet& aStyleSet, + Element& aChild, + nsAtom* aState) { + const auto* parentNode = aChild.GetParentNode(); + MOZ_ASSERT(parentNode); + const auto parentFlags = parentNode->GetSelectorFlags(); + if (!(parentFlags & NodeSelectorFlags::HasSlowSelectorNthOf)) { + return; + } + + if (aStyleSet.HasNthOfCustomStateDependency(aChild, aState)) { + RestyleSiblingsForNthOf(&aChild, parentFlags); + } +} + void RestyleManager::MaybeRestyleForNthOfState(ServoStyleSet& aStyleSet, Element* aChild, ElementState aChangedBits) { |