commit 1d3aea82862601fd5f5b9cf533c6e06d04b1595e
parent 5b42ac4317bfd8b4753c6b2b012a5c8c21d67376
Author: Timothy Nikkel <tnikkel@gmail.com>
Date: Wed, 26 Nov 2025 13:55:41 +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
@@ -857,7 +857,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
@@ -868,9 +869,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