summaryrefslogtreecommitdiffstats
path: root/layout/base/RestyleManager.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:50 +0000
commitdef92d1b8e9d373e2f6f27c366d578d97d8960c6 (patch)
tree2ef34b9ad8bb9a9220e05d60352558b15f513894 /layout/base/RestyleManager.cpp
parentAdding debian version 125.0.3-1. (diff)
downloadfirefox-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.cpp96
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) {