commit 330ab66d10425ffea1a5145f8e454c83f52205e4
parent bb13e903d533c70ff7a4dd58328e614ed950503d
Author: Cristina Horotan <chorotan@mozilla.com>
Date: Thu, 18 Dec 2025 01:50:13 +0200
Revert "Bug 2006002: Ensure that positioned elements with implicit anchors get scroll compensated. r=layout-anchor-positioning-reviewers,firefox-style-system-reviewers,layout-reviewers,emilio" for causing bc failures on browser_retainedResultsOnFocus.js
This reverts commit 7b0c7c8034392fdb8cd13f220973f47927c4bfc4.
Diffstat:
5 files changed, 29 insertions(+), 162 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -11571,26 +11571,17 @@ struct AffectedAnchorGroup {
nsTArray<AffectedAnchor> mFrames;
};
-static const nsIFrame* NearestScrollContainerOfAffectedAnchor(
- const nsIFrame* aAnchor, const ScrollContainerFrame* aScrollContainer) {
- const auto* scrollContainer =
- AnchorPositioningUtils::GetNearestScrollFrame(aAnchor).mScrollContainer;
- if (!scrollContainer) {
- // Fixed-pos anchor, likely
- return nullptr;
- }
- // Does this scroll container match a anchor's nearest scroll container,
- // or contain it?
- if (scrollContainer == aScrollContainer ||
- nsLayoutUtils::IsProperAncestorFrame(aScrollContainer, scrollContainer)) {
- return scrollContainer;
- }
- return nullptr;
-}
-
static nsTArray<AffectedAnchorGroup> FindAnchorsAffectedByScroll(
const nsTHashMap<RefPtr<const nsAtom>, nsTArray<nsIFrame*>>& aAnchors,
const ScrollContainerFrame* aScrollContainer) {
+ const auto AffectedByScrollContainer =
+ [](const nsIFrame* aFrame, const ScrollContainerFrame* aScrollContainer) {
+ MOZ_ASSERT(aFrame);
+ MOZ_ASSERT(aScrollContainer);
+ return aFrame == aScrollContainer ||
+ nsLayoutUtils::IsProperAncestorFrame(aScrollContainer, aFrame);
+ };
+
nsTArray<AffectedAnchorGroup> affectedAnchors;
// We keep only referenced anchors' name in positioned frames to avoid dealing
// with lifetime issues associated with it. Now we need to re-establish that
@@ -11600,8 +11591,14 @@ static nsTArray<AffectedAnchorGroup> FindAnchorsAffectedByScroll(
Maybe<nsTArray<AffectedAnchor>> affected;
for (const auto& frame : anchorFrames) {
const auto* scrollContainer =
- NearestScrollContainerOfAffectedAnchor(frame, aScrollContainer);
+ AnchorPositioningUtils::GetNearestScrollFrame(frame).mScrollContainer;
if (!scrollContainer) {
+ // Fixed-pos anchor, likely
+ continue;
+ }
+ // Does this scroll container match a anchor's nearest scroll container,
+ // or contain it?
+ if (!AffectedByScrollContainer(scrollContainer, aScrollContainer)) {
continue;
}
if (affected.isNothing()) {
@@ -11619,9 +11616,8 @@ static nsTArray<AffectedAnchorGroup> FindAnchorsAffectedByScroll(
// Given a list of anchors affected by scrolling, find one that the given
// positioned frame need to compensate scroll for.
-static Maybe<AffectedAnchor> FindScrollCompensatedAnchor(
+static Maybe<const AffectedAnchor&> FindScrollCompensatedAnchor(
const PresShell* aPresShell,
- const ScrollContainerFrame* aScrolledScrollContainer,
const nsTArray<AffectedAnchorGroup>& aAffectedAnchors,
const nsIFrame* aPositioned, const AnchorPosReferenceData& aReferenceData,
const nsIFrame** aResolvedDefaultAnchor) {
@@ -11654,22 +11650,6 @@ static Maybe<AffectedAnchor> FindScrollCompensatedAnchor(
return Nothing{};
}
- if (defaultAnchorName == nsGkAtoms::AnchorPosImplicitAnchor) {
- // We're not going to find this in `aAffectedAnchors`, which works off of
- // `PresShell::mAnchorPosAnchors`, which doesn't store implicit anchors.
- const auto* anchor =
- AnchorPositioningUtils::GetAnchorPosImplicitAnchor(aPositioned);
- if (!anchor) {
- return Nothing{};
- }
- const auto* scrollContainer = NearestScrollContainerOfAffectedAnchor(
- anchor, aScrolledScrollContainer);
- if (!scrollContainer) {
- return Nothing{};
- }
- return Some(AffectedAnchor{anchor, scrollContainer});
- }
-
struct Comparator {
bool Equals(const AffectedAnchor& aEntry, const nsIFrame* aFrame) const {
return aEntry.mAnchor == aFrame;
@@ -11692,7 +11672,7 @@ static Maybe<AffectedAnchor> FindScrollCompensatedAnchor(
break;
}
const auto& info = anchors.ElementAt(idx);
- return Some(info);
+ return SomeRef(info);
}
return Nothing{};
@@ -11746,7 +11726,7 @@ static bool AnchorIsStickyOrChainedToScrollCompensatedAnchor(
// https://drafts.csswg.org/css-anchor-position-1/#default-scroll-shift
void PresShell::UpdateAnchorPosForScroll(
const ScrollContainerFrame* aScrollContainer) {
- if (mAnchorPosAnchors.IsEmpty() && mAnchorPosPositioned.IsEmpty()) {
+ if (mAnchorPosAnchors.IsEmpty()) {
return;
}
@@ -11757,7 +11737,10 @@ void PresShell::UpdateAnchorPosForScroll(
// can.
nsTArray<AffectedAnchorGroup> affectedAnchors =
FindAnchorsAffectedByScroll(mAnchorPosAnchors, aScrollContainer);
- // Affected anchors may be empty, an implicit anchor may have scrolled.
+
+ if (affectedAnchors.IsEmpty()) {
+ return;
+ }
// Now, update all affected positioned elements' scroll offsets.
for (auto* positioned : mAnchorPosPositioned) {
@@ -11767,9 +11750,8 @@ void PresShell::UpdateAnchorPosForScroll(
continue;
}
const nsIFrame* defaultAnchor = nullptr;
- const auto scrollDependency =
- FindScrollCompensatedAnchor(this, aScrollContainer, affectedAnchors,
- positioned, *referenceData, &defaultAnchor);
+ const auto scrollDependency = FindScrollCompensatedAnchor(
+ this, affectedAnchors, positioned, *referenceData, &defaultAnchor);
const bool offsetChanged = [&]() {
if (!scrollDependency) {
return false;
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
@@ -3261,9 +3261,6 @@ class PresShell final : public nsStubDocumentObserver,
// cannot be determined.
nsTArray<AnchorPosAnchorChange> mLazyAnchorPosAnchorChanges;
- // Note: Does not store implicit anchors, since many elements can be
- // potential implicit anchors (e.g. pseudo-elements' implicit anchor
- // is its originating element).
nsTHashMap<RefPtr<const nsAtom>, nsTArray<nsIFrame*>> mAnchorPosAnchors;
nsTArray<nsIFrame*> mAnchorPosPositioned;
diff --git a/layout/style/ComputedStyle.cpp b/layout/style/ComputedStyle.cpp
@@ -432,10 +432,11 @@ void ComputedStyle::DumpMatchedRules() const {
bool ComputedStyle::HasAnchorPosReference() const {
const auto* pos = StylePosition();
- if (pos->mPositionAnchor.IsIdent() || pos->mPositionAnchor.IsAuto()) {
- // Short circuit if there's a default anchor defined (Or an implicit one),
- // even if it may not end up being referenced. If this early return is
- // removed, we'll need to handle mPositionArea explicitly.
+ if (pos->mPositionAnchor.IsIdent()) {
+ // Short circuit if there's a default anchor defined, even if
+ // it may not end up being referenced.
+ // If this early return is removed, we'll need to handle mPositionArea
+ // explicitly.
return true;
}
diff --git a/testing/web-platform/tests/css/css-anchor-position/anchor-scroll-implicit-001.html b/testing/web-platform/tests/css/css-anchor-position/anchor-scroll-implicit-001.html
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<html class=reftest-wait>
-<title>Tests that scroll adjustments of implicitly anchored elements are applied correctly</title>
-<link rel="author" href="mailto:dshin@mozilla.com">
-<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/">
-<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
-<style>
-.positioned {
- position: fixed;
- width: 100px;
- height: 50px;
- left: anchor(left);
- top: anchor(bottom);
- background: green;
- border: none;
- padding: 0;
- margin: 0;
-}
-
-.container {
- position: relative;
- width: 100px;
- height: 100px;
- background: red;
- overflow: hidden;
-}
-
-.filler {
- width: 1px;
- height: 50px;
-}
-
-.anchor {
- width: 100px;
- height: 50px;
- background: green;
- border: none;
- padding: 0;
-}
-</style>
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
-<div class=positioned popover id="popover"></div>
-<div id=s class=container>
- <div class=filler></div>
- <button id=b class=anchor popovertarget="popover"></button>
- <div class=filler></div>
-</div>
-<script>
-b.click();
-s.scrollTop = 50;
-document.documentElement.classList.remove('reftest-wait');
-</script>
-</html>
diff --git a/testing/web-platform/tests/css/css-anchor-position/anchor-scroll-implicit-002.html b/testing/web-platform/tests/css/css-anchor-position/anchor-scroll-implicit-002.html
@@ -1,60 +0,0 @@
-<!DOCTYPE html>
-<html class=reftest-wait>
-<title>Tests that scroll adjustments of implicitly anchored elements are applied correctly</title>
-<link rel="author" href="mailto:dshin@mozilla.com">
-<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/">
-<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
-<style>
-.positioned {
- position: absolute;
- width: 100px;
- height: 50px;
- left: anchor(left);
- top: anchor(bottom);
- background: green;
- border: none;
- padding: 0;
- margin: 0;
-}
-
-.container {
- position: relative;
- width: 100px;
- height: 100px;
- background: red;
-}
-
-.scroller {
- width: 100%;
- height: 100%;
- overflow: hidden;
-}
-
-.filler {
- width: 1px;
- height: 50px;
-}
-
-.anchor {
- width: 100px;
- height: 50px;
- background: green;
- border: none;
- padding: 0;
-}
-</style>
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
-<div class=container>
- <div id=s class=scroller>
- <div class=filler></div>
- <button id=b class=anchor popovertarget="popover"></button>
- <div class=filler></div>
- </div>
- <div class=positioned popover id="popover"></div>
-</div>
-<script>
-b.click();
-s.scrollTop = 50;
-document.documentElement.classList.remove('reftest-wait');
-</script>
-</html>