commit 7cd59a61c6a01fdd88254a2d880191ebcd3865ab
parent e53645f574d4cccad40a679ab9cb3cf0fbbcf110
Author: Timothy Nikkel <tnikkel@gmail.com>
Date: Wed, 26 Nov 2025 13:04:52 +0000
Bug 1988030. Allow passing a limit ancestor to DisplayPortUtils::OneStepInASRChain that we don't walk past. r=hiro,layout-reviewers
With CSS anchor pos we know that the anchor is in the containing block of the anchored content. We use that to limit a walk up the frame tree in subsequent patches and make the computation simpler. So we need OneStepInASRChain to obey that limit too.
Differential Revision: https://phabricator.services.mozilla.com/D271804
Diffstat:
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/layout/base/DisplayPortUtils.cpp b/layout/base/DisplayPortUtils.cpp
@@ -856,7 +856,8 @@ nsIFrame* DisplayPortUtils::OneStepInAsyncScrollableAncestorChain(
return nsLayoutUtils::GetCrossDocParentFrameInProcess(aFrame);
}
-nsIFrame* DisplayPortUtils::OneStepInASRChain(nsIFrame* aFrame) {
+nsIFrame* DisplayPortUtils::OneStepInASRChain(
+ nsIFrame* aFrame, nsIFrame* aLimitAncestor /* = nullptr */) {
// This mirrors one iteration of GetNearestScrollableOrOverflowClipFrame in
// nsLayoutUtils.cpp as called by nsLayoutUtils::GetASRAncestorFrame. They
// should be kept in sync. See that function for comments about the structure
@@ -867,9 +868,18 @@ nsIFrame* DisplayPortUtils::OneStepInASRChain(nsIFrame* aFrame) {
nsIFrame* anchor = nullptr;
while ((anchor =
AnchorPositioningUtils::GetAnchorThatFrameScrollsWith(aFrame))) {
+ MOZ_ASSERT_IF(aLimitAncestor,
+ nsLayoutUtils::IsProperAncestorFrameConsideringContinuations(
+ aLimitAncestor, anchor));
aFrame = anchor;
}
- return nsLayoutUtils::GetCrossDocParentFrameInProcess(aFrame);
+ nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrameInProcess(aFrame);
+ if (aLimitAncestor && parent &&
+ (parent == aLimitAncestor ||
+ parent->FirstContinuation() == aLimitAncestor->FirstContinuation())) {
+ return nullptr;
+ }
+ return parent;
}
void DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
diff --git a/layout/base/DisplayPortUtils.h b/layout/base/DisplayPortUtils.h
@@ -294,9 +294,11 @@ class DisplayPortUtils {
* ASR frame to the next. Rather this walks all frame types, taking only one
* ancestor step per call. Note that a frame returned from this function could
* generate two ASRs: an inner one corresponding to an activated scroll frame,
- * and an outer one corresponding to sticky pos.
+ * and an outer one corresponding to sticky pos. Returns null if we hit
+ * aLimitAncestor.
*/
- static nsIFrame* OneStepInASRChain(nsIFrame* aFrame);
+ static nsIFrame* OneStepInASRChain(nsIFrame* aFrame,
+ nsIFrame* aLimitAncestor = nullptr);
/**
* Sets a zero margin display port on all proper ancestors of aFrame that