tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit b75b0abc10eaa46764969a84a71342aa02dfefdc
parent e68671efd8c8e76073e6a9e5c61afad383b62ce1
Author: Alexandru Marc <amarc@mozilla.com>
Date:   Wed, 26 Nov 2025 15:39:03 +0200

Revert (Bug 1988032, Bug 1988030) for causing build bustages @ DisplayPortUtils.cpp

This reverts commit 8244ecad8b53e9475d89f635869d12b714c62208.

Revert "Bug 1988032. Disable RDL if are there active CSS anchor pos. r=layout-reviewers,emilio"

This reverts commit 9063b3c208f7f5cc99cf105a6df4d9911fb7d4f7.

Revert "Bug 1988032. Don't async scroll with anchors if there is an active view transition. r=layout-reviewers,emilio"

This reverts commit 472901d51347a44527c2ed4166b55f3b728fb52d.

Revert "Bug 1988030. Detect and reject an anchor that is outside of the positioned frame's containing block. r=layout-reviewers,emilio"

This reverts commit 237e8563f6569f547c6c7fe47ce6997726c0d38b.

Revert "Bug 1988032. Add a pref to control async scroll of CSS anchor positioned content. r=layout-reviewers,hiro"

This reverts commit 98d14e2dc81960e63ae50bceab379450f0b0c5d9.

Revert "Bug 1988032. Add some basic anchor pos plus async scroll reftests. r=hiro,layout-reviewers"

This reverts commit 7165d46e3b2405fcbe87188998e20af6b3c56b7d.

Revert "Bug 1988032. Assign the ASR of the anchor to the anchored content. r=hiro,layout-reviewers,layout-anchor-positioning-reviewers,emilio"

This reverts commit cb45424f429d3618455071440543c3b5423190b4.

Revert "Bug 1988030. Create a function that activates and creates ASRs for scrollframes of the anchor of anchored content. r=hiro,layout-reviewers,layout-anchor-positioning-reviewers,botond,emilio"

This reverts commit 1816a3d49caa602d49af77c9a99b2c0325c31521.

Revert "Bug 1988030. Allow passing a limit ancestor to DisplayPortUtils::OneStepInASRChain that we don't walk past. r=hiro,layout-reviewers"

This reverts commit 7cd59a61c6a01fdd88254a2d880191ebcd3865ab.

Revert "Bug 1988030. Create nsLayoutUtils::GetASRAncestorFrame and OneStepInASRChain that walks only scroll frames that are currently async scrollable in the ASR order. r=botond,hiro,layout-reviewers,layout-anchor-positioning-reviewers,emilio"

This reverts commit e53645f574d4cccad40a679ab9cb3cf0fbbcf110.

Revert "Bug 1988030. Adjust DisplayPortUtils::OneStepInAsyncScrollableAncestorChain to be CSS anchor pos aware. r=hiro,layout-reviewers,layout-anchor-positioning-reviewers,emilio"

This reverts commit e7619a7efccc6f2ca258a9f3cdf4cc1d8741ede4.

Revert "Bug 1988030. Adjust nsLayoutUtils::GetAsyncScrollableAncestorFrame to be CSS anchor pos aware. r=layout-reviewers,layout-anchor-positioning-reviewers,hiro,emilio"

This reverts commit 537725a5c4aaa5e36df125f308024c54b1eb6fda.

Diffstat:
Mlayout/base/AnchorPositioningUtils.cpp | 30------------------------------
Mlayout/base/AnchorPositioningUtils.h | 6------
Mlayout/base/DisplayPortUtils.cpp | 175-------------------------------------------------------------------------------
Mlayout/base/DisplayPortUtils.h | 35-----------------------------------
Mlayout/base/nsLayoutUtils.cpp | 76+---------------------------------------------------------------------------
Mlayout/base/nsLayoutUtils.h | 39+--------------------------------------
Mlayout/generic/ScrollContainerFrame.cpp | 34+++++++++++++---------------------
Mlayout/generic/ScrollContainerFrame.h | 10----------
Mlayout/generic/nsIFrame.cpp | 71++---------------------------------------------------------------------
Dlayout/reftests/async-scrolling/anchor-pos-1-ref.html | 14--------------
Dlayout/reftests/async-scrolling/anchor-pos-1.html | 47-----------------------------------------------
Dlayout/reftests/async-scrolling/anchor-pos-2-ref.html | 23-----------------------
Dlayout/reftests/async-scrolling/anchor-pos-2.html | 64----------------------------------------------------------------
Dlayout/reftests/async-scrolling/anchor-pos-sticky-1-ref.html | 22----------------------
Dlayout/reftests/async-scrolling/anchor-pos-sticky-1.html | 52----------------------------------------------------
Dlayout/reftests/async-scrolling/anchor-pos-sticky-2-ref.html | 22----------------------
Dlayout/reftests/async-scrolling/anchor-pos-sticky-2.html | 52----------------------------------------------------
Mlayout/reftests/async-scrolling/reftest.list | 5-----
Mmodules/libpref/init/StaticPrefList.yaml | 6------
Dtesting/web-platform/tests/css/css-anchor-position/anchor-loop-crash.html | 70----------------------------------------------------------------------
20 files changed, 17 insertions(+), 836 deletions(-)

diff --git a/layout/base/AnchorPositioningUtils.cpp b/layout/base/AnchorPositioningUtils.cpp @@ -9,7 +9,6 @@ #include "ScrollContainerFrame.h" #include "mozilla/Maybe.h" #include "mozilla/PresShell.h" -#include "mozilla/StaticPrefs_apz.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/Element.h" #include "nsCanvasFrame.h" @@ -875,33 +874,4 @@ bool AnchorPositioningUtils::FitsInContainingBlock( .Contains(rect); } -nsIFrame* AnchorPositioningUtils::GetAnchorThatFrameScrollsWith( - nsIFrame* aFrame) { - if (!StaticPrefs::apz_async_scroll_css_anchor_pos_AtStartup()) { - return nullptr; - } - mozilla::PhysicalAxes axes = aFrame->GetAnchorPosCompensatingForScroll(); - // TODO for now we return the anchor if we are compensating in either axis. - // This is not fully spec compliant, bug 1988034 tracks this. - if (axes.isEmpty()) { - return nullptr; - } - - const auto* pos = aFrame->StylePosition(); - if (!pos->mPositionAnchor.IsIdent()) { - return nullptr; - } - - const nsAtom* defaultAnchorName = pos->mPositionAnchor.AsIdent().AsAtom(); - nsIFrame* anchor = const_cast<nsIFrame*>( - aFrame->PresShell()->GetAnchorPosAnchor(defaultAnchorName, aFrame)); - // TODO Bug 1997026 We need to update the anchor finding code so this can't - // happen. For now we just detect it and reject it. - if (anchor && !nsLayoutUtils::IsProperAncestorFrameConsideringContinuations( - aFrame->GetParent(), anchor)) { - return nullptr; - } - return anchor; -} - } // namespace mozilla diff --git a/layout/base/AnchorPositioningUtils.h b/layout/base/AnchorPositioningUtils.h @@ -309,12 +309,6 @@ struct AnchorPositioningUtils { const ContainingBlockInfo& aContainingBlockInfo, const nsIFrame* aPositioned, const AnchorPosReferenceData* aReferenceData); - - /** - * If aFrame is positioned using CSS anchor positioning, and it scrolls with - * its anchor this function returns the anchor. Otherwise null. - */ - static nsIFrame* GetAnchorThatFrameScrollsWith(nsIFrame* aFrame); }; } // namespace mozilla diff --git a/layout/base/DisplayPortUtils.cpp b/layout/base/DisplayPortUtils.cpp @@ -10,7 +10,6 @@ #include "FrameMetrics.h" #include "RetainedDisplayListBuilder.h" -#include "StickyScrollContainer.h" #include "WindowRenderer.h" #include "mozilla/PresShell.h" #include "mozilla/ScrollContainerFrame.h" @@ -734,22 +733,6 @@ void DisplayPortUtils::RemoveDisplayPort(nsIContent* aContent) { aContent->RemoveProperty(nsGkAtoms::DisplayPortMargins); } -void DisplayPortUtils::SetMinimalDisplayPortDuringPainting( - nsIContent* aContent, PresShell* aPresShell) { - // SetDisplayPortMargins calls TriggerDisplayPortExpiration which starts a - // display port expiry timer for display ports that do expire. However - // minimal display ports do not expire, so the display port has to be - // marked before the SetDisplayPortMargins call so the expiry timer - // doesn't get started. - aContent->SetProperty(nsGkAtoms::MinimalDisplayPort, - reinterpret_cast<void*>(true)); - - DisplayPortUtils::SetDisplayPortMargins( - aContent, aPresShell, DisplayPortMargins::Empty(aContent), - DisplayPortUtils::ClearMinimalDisplayPortProperty::No, 0, - DisplayPortUtils::RepaintMode::DoNotRepaint); -} - bool DisplayPortUtils::ViewportHasDisplayPort(nsPresContext* aPresContext) { nsIFrame* rootScrollContainerFrame = aPresContext->PresShell()->GetRootScrollContainerFrame(); @@ -851,18 +834,9 @@ bool DisplayPortUtils::MaybeCreateDisplayPort( nsIFrame* DisplayPortUtils::OneStepInAsyncScrollableAncestorChain( nsIFrame* aFrame) { - // This mirrors one iteration of GetNearestScrollableOrOverflowClipFrame in - // nsLayoutUtils.cpp as called by - // nsLayoutUtils::GetAsyncScrollableAncestorFrame. They should be kept in - // sync. See that function for comments about the structure of this code. if (aFrame->IsMenuPopupFrame()) { return nullptr; } - nsIFrame* anchor = nullptr; - while ((anchor = - AnchorPositioningUtils::GetAnchorThatFrameScrollsWith(aFrame))) { - aFrame = anchor; - } if (aFrame->StyleDisplay()->mPosition == StylePositionProperty::Fixed && nsLayoutUtils::IsReallyFixedPos(aFrame)) { if (nsIFrame* root = aFrame->PresShell()->GetRootScrollContainerFrame()) { @@ -872,32 +846,6 @@ nsIFrame* DisplayPortUtils::OneStepInAsyncScrollableAncestorChain( return nsLayoutUtils::GetCrossDocParentFrameInProcess(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 - // of this code. - if (aFrame->IsMenuPopupFrame()) { - return nullptr; - } - nsIFrame* anchor = nullptr; - while ((anchor = - AnchorPositioningUtils::GetAnchorThatFrameScrollsWith(aFrame))) { - MOZ_ASSERT_IF(aLimitAncestor, - nsLayoutUtils::IsProperAncestorFrameConsideringContinuations( - aLimitAncestor, anchor)); - aFrame = anchor; - } - nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrameInProcess(aFrame); - if (aLimitAncestor && parent && - (parent == aLimitAncestor || - parent->FirstContinuation() == aLimitAncestor->FirstContinuation())) { - return nullptr; - } - return parent; -} - void DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors( nsIFrame* aFrame) { nsIFrame* frame = aFrame; @@ -1062,127 +1010,4 @@ bool DisplayPortUtils::WillUseEmptyDisplayPortMargins(nsIContent* aContent) { nsLayoutUtils::ShouldDisableApzForElement(aContent); } -// This first checks if aFrame is a scroll frame, if so it then tries to -// activate it. Then this function returns true if aFrame generates a scroll ASR -// (ie its an active scroll frame). -static bool ActivatePotentialScrollASR(nsIFrame* aFrame, - nsDisplayListBuilder* aBuilder) { - ScrollContainerFrame* scrollContainerFrame = do_QueryFrame(aFrame); - if (!scrollContainerFrame) { - return false; - } - return scrollContainerFrame->DecideScrollableLayerEnsureDisplayport(aBuilder); -} - -// This first checks if aFrame is sticky pos, if so it then tries to activate -// the associate scroll frame. Then this function returns true if aFrame -// generates a sticky ASR (ie its sticky pos and its associated scroll frame is -// active). -static bool ActivatePotentialStickyASR(nsIFrame* aFrame, - nsDisplayListBuilder* aBuilder) { - if (aFrame->StyleDisplay()->mPosition != StylePositionProperty::Sticky) { - return false; - } - auto* ssc = StickyScrollContainer::GetOrCreateForFrame(aFrame); - if (!ssc) { - return false; - } - return ssc->ScrollContainer()->DecideScrollableLayerEnsureDisplayport( - aBuilder); -} - -struct FrameAndASRKind { - nsIFrame* mFrame; - ActiveScrolledRoot::ASRKind mASRKind; -}; - -const ActiveScrolledRoot* DisplayPortUtils::ActivateDisplayportOnASRAncestors( - nsIFrame* aAnchor, nsIFrame* aLimitAncestor, - const ActiveScrolledRoot* aASRofLimitAncestor, - nsDisplayListBuilder* aBuilder) { - MOZ_ASSERT(ScrollContainerFrame::ShouldActivateAllScrollFrames( - aBuilder, aLimitAncestor)); - - MOZ_ASSERT((aASRofLimitAncestor ? aASRofLimitAncestor->mFrame : nullptr) == - nsLayoutUtils::GetASRAncestorFrame(aLimitAncestor, aBuilder)); - - MOZ_ASSERT(nsLayoutUtils::IsProperAncestorFrameConsideringContinuations( - aLimitAncestor, aAnchor)); - - AutoTArray<FrameAndASRKind, 4> ASRframes; - nsIFrame* frame = aAnchor; - - // The passed in frame is the anchor, if it is a scroll frame we do not scroll - // with that scroll frame (we are "outside" of it) but if it is sticky pos - // then we do move with the sticky ASR. - if (ActivatePotentialStickyASR(frame, aBuilder)) { - ASRframes.EmplaceBack(frame, ActiveScrolledRoot::ASRKind::Sticky); - } - frame = OneStepInASRChain(frame, aLimitAncestor); - while (frame && frame != aLimitAncestor && - (!aLimitAncestor || - frame->FirstContinuation() != aLimitAncestor->FirstContinuation())) { - // We check if each frame encountered generates an ASR. It can either - // generate a scroll asr or a sticky asr, or both! If it generates both then - // the sticky asr is the outer (parent) asr. So we check for scroll ASRs - // first. - - // We intentionally call this on all scroll frames encountered, not just the - // ones that WantAsyncScroll. This is because scroll frames with - // WantAsyncScroll == false can have a display port (say if they had - // non-zero scroll range and had a display port but then their scroll range - // shrank to zero then the displayport would still stick around), hence - // mWillBuildScrollableLayer would be true on them and we need to make sure - // mWillBuildScrollableLayer is up to date (if the scroll frame was - // temporarily inside a view transition mWillBuildScrollableLayer would - // temporarily get set to false). - - // In this loop we are looking for any scroll frame that will generate an - // ASR. This corresponds to scroll frames with mWillBuildScrollableLayer == - // true. This is different from scroll frames that return true from - // WantAsyncScroll (both because of what was explained above and because not - // every scroll frame that WantAsyncScroll will have a displayport), and - // hence it's also different from what GetAsyncScrollableAncestorFrame will - // return. - if (ActivatePotentialScrollASR(frame, aBuilder)) { - ASRframes.EmplaceBack(frame, ActiveScrolledRoot::ASRKind::Scroll); - } - - // Then check if it's a sticky ASR. - if (ActivatePotentialStickyASR(frame, aBuilder)) { - ASRframes.EmplaceBack(frame, ActiveScrolledRoot::ASRKind::Sticky); - } - - frame = OneStepInASRChain(frame, aLimitAncestor); - } - - const ActiveScrolledRoot* asr = aASRofLimitAncestor; - - // Iterate array in reverse order (top down in the frame/asr tree) creating - // the asr structs. - for (auto asrFrame : Reversed(ASRframes)) { - MOZ_ASSERT(nsLayoutUtils::IsProperAncestorFrameConsideringContinuations( - aLimitAncestor, asrFrame.mFrame)); - -#ifdef DEBUG - if (asr && (asr->mFrame == asrFrame.mFrame)) { - MOZ_ASSERT(asr->mKind == ActiveScrolledRoot::ASRKind::Sticky); - MOZ_ASSERT(asrFrame.mASRKind == ActiveScrolledRoot::ASRKind::Scroll); - } else { - MOZ_ASSERT((asr ? asr->mFrame : nullptr) == - nsLayoutUtils::GetASRAncestorFrame( - OneStepInASRChain(asrFrame.mFrame), aBuilder)); - } -#endif - - asr = (asrFrame.mASRKind == ActiveScrolledRoot::ASRKind::Scroll) - ? aBuilder->GetOrCreateActiveScrolledRoot( - asr, static_cast<ScrollContainerFrame*>( - do_QueryFrame(asrFrame.mFrame))) - : aBuilder->GetOrCreateActiveScrolledRootForSticky( - asr, asrFrame.mFrame); - } - return asr; -} - } // namespace mozilla diff --git a/layout/base/DisplayPortUtils.h b/layout/base/DisplayPortUtils.h @@ -238,12 +238,6 @@ class DisplayPortUtils { static void RemoveDisplayPort(nsIContent* aContent); /** - * Set minimal display port margins during painting. - */ - static void SetMinimalDisplayPortDuringPainting(nsIContent* aContent, - PresShell* aPresShell); - - /** * Return true if aPresContext's viewport has a displayport. */ static bool ViewportHasDisplayPort(nsPresContext* aPresContext); @@ -295,18 +289,6 @@ class DisplayPortUtils { static nsIFrame* OneStepInAsyncScrollableAncestorChain(nsIFrame* aFrame); /** - * Step up one frame in the ASR chain, to be used in conjunction with - * GetASRAncestorFrame to walk the ASR chain. Note this doesn't go from one - * 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. Returns null if we hit - * aLimitAncestor. - */ - static nsIFrame* OneStepInASRChain(nsIFrame* aFrame, - nsIFrame* aLimitAncestor = nullptr); - - /** * Sets a zero margin display port on all proper ancestors of aFrame that * are async scrollable. */ @@ -338,23 +320,6 @@ class DisplayPortUtils { * of displayports. */ static bool WillUseEmptyDisplayPortMargins(nsIContent* aContent); - - /** - * Calls DecideScrollableLayerEnsureDisplayport on all proper ancestors of - * aAnchor that are async scrollable up to but not including aLimitAncestor - * (this creates a minimal display port on all async scrollable ancestors if - * they don't have a display port) and makes sure that there is an ASR struct - * created for all such async scrollable ancestors. - * Returns the ASR of aAnchor. - * This is a very specific function for anchor positioning and likely not - * what you want. In that context, aAnchor is the anchor of an abspos frame f - * (not passed to this function because it is not needed) and aLimitAncestor - * is the parent/containing block of f. - */ - static const ActiveScrolledRoot* ActivateDisplayportOnASRAncestors( - nsIFrame* aAnchor, nsIFrame* aLimitAncestor, - const ActiveScrolledRoot* aASRofLimitAncestor, - nsDisplayListBuilder* aBuilder); }; } // namespace mozilla diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp @@ -10,7 +10,6 @@ #include <limits> #include "ActiveLayerTracker.h" -#include "AnchorPositioningUtils.h" #include "DisplayItemClip.h" #include "ImageContainer.h" #include "ImageOps.h" @@ -1318,11 +1317,6 @@ static nsIFrame* GetNearestScrollableOrOverflowClipFrame( MOZ_ASSERT( aFrame, "GetNearestScrollableOrOverflowClipFrame expects a non-null frame"); - // Only one of these two flags can be set at a time. - MOZ_ASSERT_IF(aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE, - !(aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASRS)); - MOZ_ASSERT_IF(aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASRS, - !(aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE)); auto GetNextFrame = [aFlags](const nsIFrame* aFrame) -> nsIFrame* { return (aFlags & nsLayoutUtils::SCROLLABLE_SAME_DOC) @@ -1330,9 +1324,6 @@ static nsIFrame* GetNearestScrollableOrOverflowClipFrame( : nsLayoutUtils::GetCrossDocParentFrameInProcess(aFrame); }; - // This should be kept in sync with - // DisplayPortUtils::OneStepInAsyncScrollableAncestorChain and - // DisplayPortUtils::OneStepInASRChain. for (nsIFrame* f = aFrame; f; f = GetNextFrame(f)) { if (aClipFrameCheck && aClipFrameCheck(f)) { return f; @@ -1344,8 +1335,7 @@ static nsIFrame* GetNearestScrollableOrOverflowClipFrame( // TODO: We should also stop at popup frames other than // SCROLLABLE_ONLY_ASYNC_SCROLLABLE cases. - if ((aFlags & (nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE | - nsLayoutUtils::SCROLLABLE_ONLY_ASRS)) && + if ((aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE) && f->IsMenuPopupFrame()) { break; } @@ -1355,10 +1345,6 @@ static nsIFrame* GetNearestScrollableOrOverflowClipFrame( if (scrollContainerFrame->WantAsyncScroll()) { return f; } - } else if (aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASRS) { - if (scrollContainerFrame->IsMaybeAsynchronouslyScrolled()) { - return f; - } } else { ScrollStyles ss = scrollContainerFrame->GetScrollStyles(); if ((aFlags & nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN) || @@ -1376,45 +1362,6 @@ static nsIFrame* GetNearestScrollableOrOverflowClipFrame( } } } - - nsIFrame* anchor = nullptr; - // If the current frame also happens to be fixed then we want to check if it - // scrolls with its anchor before the special fixed behaviour below because - // scrolling with its anchor overrides that behaviour and is higher - // priority. - - // This needs to be a while loop because anchors can chain, and we don't - // want to consider each frame in this loop separately (as a potential - // scrollable ancestor) because they are all equivalent in the scrollable - // ancestor chain: they all scroll together. We are not walking up the async - // scrollable ancestor chain, but rather we are move sideways. And when we - // exit this loop we want to move up one because we haven't yet ascended - // (because of that same reason), and that moving up one will happen either - // via the special fixed pos behaviour below or the next iteration of the - // outer for loop. - if (aFlags & (nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE | - nsLayoutUtils::SCROLLABLE_ONLY_ASRS)) { - while ( - (anchor = AnchorPositioningUtils::GetAnchorThatFrameScrollsWith(f))) { - f = anchor; - } - } - - // Note that the order of checking for anchors and sticky pos is significant - // even though a frame can't be both sticky pos and anchored (because - // anchoring requires abs pos). However, if we follow an anchor, the anchor - // could be an active sticky pos, so that would generate an ASR and we want - // to return that rather than do another iteration of the outer for loop - // which moves on to the (crossdoc) parent frame. - if (aFlags & nsLayoutUtils::SCROLLABLE_ONLY_ASRS) { - if (f->StyleDisplay()->mPosition == StylePositionProperty::Sticky) { - auto* ssc = StickyScrollContainer::GetOrCreateForFrame(f); - if (ssc && ssc->ScrollContainer()->IsMaybeAsynchronouslyScrolled()) { - return f; - } - } - } - if ((aFlags & nsLayoutUtils::SCROLLABLE_FIXEDPOS_FINDS_ROOT) && f->StyleDisplay()->mPosition == StylePositionProperty::Fixed && nsLayoutUtils::IsReallyFixedPos(f)) { @@ -1429,10 +1376,6 @@ static nsIFrame* GetNearestScrollableOrOverflowClipFrame( // static ScrollContainerFrame* nsLayoutUtils::GetNearestScrollContainerFrame( nsIFrame* aFrame, uint32_t aFlags) { - // Not suitable to use SCROLLABLE_ONLY_ASRS here because it needs to return - // non-scroll frames. - MOZ_ASSERT(!(aFlags & SCROLLABLE_ONLY_ASRS), - "can't use SCROLLABLE_ONLY_ASRS flag"); nsIFrame* found = GetNearestScrollableOrOverflowClipFrame(aFrame, aFlags); if (!found) { return nullptr; @@ -2653,29 +2596,12 @@ FrameMetrics nsLayoutUtils::CalculateBasicFrameMetrics( ScrollContainerFrame* nsLayoutUtils::GetAsyncScrollableAncestorFrame( nsIFrame* aTarget) { - // This should be kept in sync with - // DisplayPortUtils::OneStepInAsyncScrollableAncestorChain. uint32_t flags = nsLayoutUtils::SCROLLABLE_ALWAYS_MATCH_ROOT | nsLayoutUtils::SCROLLABLE_ONLY_ASYNC_SCROLLABLE | nsLayoutUtils::SCROLLABLE_FIXEDPOS_FINDS_ROOT; return nsLayoutUtils::GetNearestScrollContainerFrame(aTarget, flags); } -nsIFrame* nsLayoutUtils::GetASRAncestorFrame(nsIFrame* aTarget, - nsDisplayListBuilder* aBuilder) { - MOZ_ASSERT(aBuilder->IsPaintingToWindow()); - // We use different flags from GetAsyncScrollableAncestorFrame above because - // the ASR tree is different from the "async scrollable ancestor chain". We - // don't want SCROLLABLE_ALWAYS_MATCH_ROOT because we only want to match the - // root if it generates an ASR. We don't want SCROLLABLE_FIXEDPOS_FINDS_ROOT - // because the ASR tree does not jump from fixed pos to root (that behaviour - // exists so that fixed pos in the root document in the process can find some - // apzc, ASRs have no such need and that would be incorrect). - // This should be kept in sync with DisplayPortUtils::OneStepInASRChain. - uint32_t flags = nsLayoutUtils::SCROLLABLE_ONLY_ASRS; - return GetNearestScrollableOrOverflowClipFrame(aTarget, flags); -} - void nsLayoutUtils::AddExtraBackgroundItems(nsDisplayListBuilder* aBuilder, nsDisplayList* aList, nsIFrame* aFrame, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h @@ -603,22 +603,12 @@ class nsLayoutUtils { */ SCROLLABLE_FIXEDPOS_FINDS_ROOT = 0x10, /** - * If the SCROLLABLE_ONLY_ASRS flag is set, then we only want to return - * frames that will generate an ASR. This means that they are either - * scrollable frames for which IsMaybeAsynchronouslyScrolled() returns true - * (aka mWillBuildScrollableLayer == true) or they are sticky position - * frames for which their corresponding scroll frame will generate an ASR. - * This is an internal only flag, you cannot pass it to - * GetNearestScrollContainerFrame since that can only return scroll frames. - */ - SCROLLABLE_ONLY_ASRS = 0x20, - /** * If the SCROLLABLE_STOP_AT_PAGE flag is set, then we stop searching * for scrollable ancestors when seeing a nsPageFrame. This can be used * to avoid finding the viewport scroll frame in Print Preview (which * would be undesirable as a 'position:sticky' container for content). */ - SCROLLABLE_STOP_AT_PAGE = 0x40, + SCROLLABLE_STOP_AT_PAGE = 0x20, }; /** * GetNearestScrollContainerFrame locates the first ancestor of aFrame @@ -2900,35 +2890,8 @@ class nsLayoutUtils { static FrameMetrics CalculateBasicFrameMetrics( mozilla::ScrollContainerFrame* aScrollContainerFrame); - /** - * Follows the async scrollable ancestor chain of scroll frames to find - * scroll frames that WantAsyncScroll(). This is used when activating scroll - * frames and finding APZCs. - */ static mozilla::ScrollContainerFrame* GetAsyncScrollableAncestorFrame( nsIFrame* aTarget); - /** - * Follows the ASR (ActiveScrolledRoot) chain of frames, so that if - * f is the frame of an ASR A, then calling this function on - * OneStepInASRChain(f) will return the frame of parent ASR of A. Frames that - * generate an ASR are scroll frames for which IsMaybeAsynchronouslyScrolled() - * returns true (aka mWillBuildScrollableLayer == true) or they are sticky - * position frames for which their corresponding scroll frame will generate an - * ASR. This function is different from GetAsyncScrollableAncestorFrame above - * because GetAsyncScrollableAncestorFrame looks only for scroll frames that - * WantAsyncScroll that that function walks from fixed pos to the root scroll - * frame. Because that status (ie mWillBuildScrollableLayer) can change this - * should only be called during a paint to the window after BuildDisplayList - * has been called on aTarget so that mWillBuildScrollableLayer will have been - * updated for this paint already for any frame we need to consult. Or for - * some other reason you know that mWillBuildScrollableLayer is up to date for - * this paint for any frame that might need to be consulted, ie you just - * updated them yourself. 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. - */ - static nsIFrame* GetASRAncestorFrame(nsIFrame* aTarget, - nsDisplayListBuilder* aBuilder); static void SetBSizeFromFontMetrics( const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics, diff --git a/layout/generic/ScrollContainerFrame.cpp b/layout/generic/ScrollContainerFrame.cpp @@ -4340,26 +4340,7 @@ nsRect ScrollContainerFrame::RestrictToRootDisplayPort( FissionAutostart()) { return true; } - return StaticPrefs::apz_async_scroll_css_anchor_pos_AtStartup() && - aFrame->PresShell()->GetRootPresShell()->HasSeenAnchorPos(); -} - -bool ScrollContainerFrame::DecideScrollableLayerEnsureDisplayport( - nsDisplayListBuilder* aBuilder) { - MOZ_ASSERT(ShouldActivateAllScrollFrames(aBuilder, this)); - nsIContent* content = GetContent(); - bool hasDisplayPort = DisplayPortUtils::HasDisplayPort(content); - - // Note this intentionally differs from DecideScrollableLayer below by not - // checking ShouldActivateAllScrollFrames. - if (!hasDisplayPort && aBuilder->IsPaintingToWindow() && - nsLayoutUtils::AsyncPanZoomEnabled(this) && WantAsyncScroll()) { - DisplayPortUtils::SetMinimalDisplayPortDuringPainting(content, PresShell()); - hasDisplayPort = true; - } - - mWillBuildScrollableLayer = hasDisplayPort || mZoomableByAPZ; - return mWillBuildScrollableLayer; + return aFrame->PresShell()->GetRootPresShell()->HasSeenAnchorPos(); } bool ScrollContainerFrame::DecideScrollableLayer( @@ -4381,7 +4362,18 @@ bool ScrollContainerFrame::DecideScrollableLayer( if (aSetBase && !hasDisplayPort && aBuilder->IsPaintingToWindow() && ShouldActivateAllScrollFrames(aBuilder, this) && nsLayoutUtils::AsyncPanZoomEnabled(this) && WantAsyncScroll()) { - DisplayPortUtils::SetMinimalDisplayPortDuringPainting(content, PresShell()); + // SetDisplayPortMargins calls TriggerDisplayPortExpiration which starts a + // display port expiry timer for display ports that do expire. However + // minimal display ports do not expire, so the display port has to be + // marked before the SetDisplayPortMargins call so the expiry timer + // doesn't get started. + content->SetProperty(nsGkAtoms::MinimalDisplayPort, + reinterpret_cast<void*>(true)); + + DisplayPortUtils::SetDisplayPortMargins( + content, PresShell(), DisplayPortMargins::Empty(content), + DisplayPortUtils::ClearMinimalDisplayPortProperty::No, 0, + DisplayPortUtils::RepaintMode::DoNotRepaint); hasDisplayPort = true; } diff --git a/layout/generic/ScrollContainerFrame.h b/layout/generic/ScrollContainerFrame.h @@ -738,16 +738,6 @@ class ScrollContainerFrame : public nsContainerFrame, } /** - * Like DecideScrollableLayer but skips computing dirty/visible rects and - * setting the base rect. In addition, this always ensures a display port is - * set if this scroll frame could async scroll. DecideScrollableLayer only - * sets a display port in that situation if ShouldActivateAllScrollFrames - * returns true. However you should only call this function is - * ShouldActivateAllScrollFrames returns true anyways. - * */ - bool DecideScrollableLayerEnsureDisplayport(nsDisplayListBuilder* aBuilder); - - /** * Notify the scrollframe that the current scroll offset and origin have been * sent over in a layers transaction. * diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp @@ -4421,74 +4421,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, if (savedOutOfFlowData) { aBuilder->SetBuildingInvisibleItems(false); - nsIFrame* scrollsWithAnchor = nullptr; - if (aBuilder->IsPaintingToWindow() && - // If we are in view transition capture we get a null asr no matter - // what, so don't bother checking for async scrolling with a CSS anchor - // pos anchor. - !aBuilder->IsInViewTransitionCapture() && - child->IsAbsolutelyPositioned(disp) && - // If there is an active view transition in this document it is tricky - // to determine what will be an active scroll frame outside of that - // frame's BuildDisplayList, so don't bother to async scroll with an - // anchor in that case. Bug 2001861 tracks removing this check. - !PresContext()->Document()->GetActiveViewTransition()) { - scrollsWithAnchor = - AnchorPositioningUtils::GetAnchorThatFrameScrollsWith(child); - - if (scrollsWithAnchor && aBuilder->IsRetainingDisplayList()) { - if (aBuilder->IsPartialUpdate()) { - aBuilder->SetPartialBuildFailed(true); - } else { - aBuilder->SetDisablePartialUpdates(true); - } - } - } - - const ActiveScrolledRoot* asr = - savedOutOfFlowData->mContainingBlockActiveScrolledRoot; - -#ifdef DEBUG - if (aBuilder->IsPaintingToWindow()) { - // Assert that the asr is as expected. - if (savedOutOfFlowData->mContainingBlockInViewTransitionCapture) { - MOZ_ASSERT(asr == nullptr); - MOZ_ASSERT(aBuilder->IsInViewTransitionCapture()); - } else if ((asr ? asr->mFrame : nullptr) != - nsLayoutUtils::GetASRAncestorFrame(child->GetParent(), - aBuilder)) { - // A weird case for native anonymous content in the custom content - // container when the root is captured by a view transition. This - // content is built outside of the view transition capture but the - // containing block (the canvas frame) was built inside the capture, so - // savedOutOfFlowData is saved as if we are inside the capture while we - // are outside it (bug 2002160). - MOZ_ASSERT(asr == nullptr); - MOZ_ASSERT(PresContext()->Document()->GetActiveViewTransition()); - MOZ_ASSERT( - child->GetParent()->GetContent()->IsInNativeAnonymousSubtree()); - bool inTopLayer = false; - nsIFrame* curr = child->GetParent(); - while (curr) { - if (curr->StyleDisplay()->mTopLayer == StyleTopLayer::Auto) { - inTopLayer = true; - break; - } - curr = curr->GetParent(); - } - MOZ_ASSERT(inTopLayer); - } - } -#endif - - if (scrollsWithAnchor) { - asr = DisplayPortUtils::ActivateDisplayportOnASRAncestors( - scrollsWithAnchor, child->GetParent(), asr, aBuilder); - - // TODO should we set the scroll parent id too? - // https://github.com/w3c/csswg-drafts/issues/12042 - } - if (aBuilder->IsInViewTransitionCapture()) { if (!savedOutOfFlowData->mContainingBlockInViewTransitionCapture) { clipState.Clear(); @@ -4500,7 +4432,8 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } else { clipState.SetClipChainForContainingBlockDescendants( savedOutOfFlowData->mContainingBlockClipChain); - asrSetter.SetCurrentActiveScrolledRoot(asr); + asrSetter.SetCurrentActiveScrolledRoot( + savedOutOfFlowData->mContainingBlockActiveScrolledRoot); asrSetter.SetCurrentScrollParentId(savedOutOfFlowData->mScrollParentId); } MOZ_ASSERT(awayFromCommonPath, diff --git a/layout/reftests/async-scrolling/anchor-pos-1-ref.html b/layout/reftests/async-scrolling/anchor-pos-1-ref.html @@ -1,14 +0,0 @@ -<!DOCTYPE html> -<html> -<style> -.anchored { - position: absolute; - width: 50px; - height: 50px; - background: yellow; - left: 50px; - top: 0; -} -</style> -<div class="anchored"></div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-1.html b/layout/reftests/async-scrolling/anchor-pos-1.html @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html reftest-async-scroll> -<style> -.container { - position: absolute; - left: 0; - top: 0; -} -.scroller { - position: absolute; - overflow: auto; - scrollbar-width: none; - width: 100px; - height: 100px; -} -.spacer { - width: 1px; - height: 500px; -} -.anchor { - width: 50px; - height: 50px; - background: blue; - anchor-name: --my-anchor; -} -.anchored { - position: absolute; - position-anchor: --my-anchor; - position-visibility: always; - width: 50px; - height: 50px; - background: yellow; - left: anchor(right); - top: anchor(bottom); -} -</style> -<div class="container"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="100" reftest-displayport-h="500" - reftest-async-scroll-y="50"> - <div class="anchor"></div> - <div class="spacer"></div> - </div> - <div class="anchored"></div> -</div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-2-ref.html b/layout/reftests/async-scrolling/anchor-pos-2-ref.html @@ -1,23 +0,0 @@ -<!DOCTYPE html> -<html> -<style> -.anchor1 { - position: absolute; - width: 50px; - height: 50px; - background: blue; - left: 50px; - top: 0; -} -.anchored { - position: absolute; - width: 50px; - height: 50px; - background: yellow; - left: 100px; - top: 50px; -} -</style> -<div class="anchor1"></div> -<div class="anchored"></div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-2.html b/layout/reftests/async-scrolling/anchor-pos-2.html @@ -1,64 +0,0 @@ -<!DOCTYPE html> -<html reftest-async-scroll> -<style> -.container { - position: absolute; - left: 0; - top: 0; -} -.scroller { - position: absolute; - overflow: auto; - scrollbar-width: none; - width: 150px; - height: 100px; -} -.spacer { - width: 1px; - height: 500px; -} -.anchor1 { - width: 50px; - height: 50px; - background: blue; - anchor-name: --my-anchor1; - position: absolute; - position-anchor: --my-anchor2; - position-visibility: always; - left: anchor(right); - top: anchor(bottom); -} -.anchor2 { - width: 50px; - height: 50px; - background: pink; - anchor-name: --my-anchor2; -} -.anchored { - position: absolute; - position-anchor: --my-anchor1; - position-visibility: always; - width: 50px; - height: 50px; - background: yellow; - left: anchor(right); - top: anchor(bottom); -} -</style> -<div class="container"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="150" reftest-displayport-h="500"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="150" reftest-displayport-h="500" - reftest-async-scroll-y="50"> - <div class="anchor2"></div> - <div class="spacer"></div> - </div> - <div class="anchor1"></div> - <div class="spacer"></div> - </div> - <div class="anchored"></div> -</div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-sticky-1-ref.html b/layout/reftests/async-scrolling/anchor-pos-sticky-1-ref.html @@ -1,22 +0,0 @@ -<html> -<style> -.anchor { - position: absolute; - width: 50px; - height: 50px; - background: blue; - left: 0; - top: 50px; -} -.anchored { - position: absolute; - width: 50px; - height: 50px; - background: yellow; - left: 50px; - top: 100px; -} -</style> -<div class="anchor"></div> -<div class="anchored"></div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-sticky-1.html b/layout/reftests/async-scrolling/anchor-pos-sticky-1.html @@ -1,52 +0,0 @@ -<html reftest-async-scroll> -<style> -.container { - position: absolute; - left: 0; - top: 0; -} -.scroller { - position: absolute; - overflow: auto; - scrollbar-width: none; - width: 100px; - height: 100px; -} -.spacer { - width: 1px; - height: 100px; -} -.largespacer { - width: 1px; - height: 500px; -} -.anchor { - position: sticky; - top: 0; - width: 50px; - height: 50px; - background: blue; - anchor-name: --my-anchor; -} -.anchored { - position: absolute; - position-anchor: --my-anchor; - position-visibility: always; - width: 50px; - height: 50px; - background: yellow; - left: anchor(right); - top: anchor(bottom); -} -</style> -<div class="container"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="100" reftest-displayport-h="500" - reftest-async-scroll-y="50"> - <div class="spacer"></div> - <div class="anchor"></div> - <div class="largespacer"></div> - </div> - <div class="anchored"></div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-sticky-2-ref.html b/layout/reftests/async-scrolling/anchor-pos-sticky-2-ref.html @@ -1,22 +0,0 @@ -<html> -<style> -.anchor { - position: absolute; - width: 50px; - height: 50px; - background: blue; - left: 0; - top: 0; -} -.anchored { - position: absolute; - width: 50px; - height: 50px; - background: yellow; - left: 50px; - top: 50px; -} -</style> -<div class="anchor"></div> -<div class="anchored"></div> -</html> diff --git a/layout/reftests/async-scrolling/anchor-pos-sticky-2.html b/layout/reftests/async-scrolling/anchor-pos-sticky-2.html @@ -1,52 +0,0 @@ -<html reftest-async-scroll> -<style> -.container { - position: absolute; - left: 0; - top: 0; -} -.scroller { - position: absolute; - overflow: auto; - scrollbar-width: none; - width: 100px; - height: 100px; -} -.spacer { - width: 1px; - height: 100px; -} -.largespacer { - width: 1px; - height: 500px; -} -.anchor { - position: sticky; - top: 0; - width: 50px; - height: 50px; - background: blue; - anchor-name: --my-anchor; -} -.anchored { - position: absolute; - position-anchor: --my-anchor; - position-visibility: always; - width: 50px; - height: 50px; - background: yellow; - left: anchor(right); - top: anchor(bottom); -} -</style> -<div class="container"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="100" reftest-displayport-h="500" - reftest-async-scroll-y="250"> - <div class="spacer"></div> - <div class="anchor"></div> - <div class="largespacer"></div> - </div> - <div class="anchored"></div> -</html> diff --git a/layout/reftests/async-scrolling/reftest.list b/layout/reftests/async-scrolling/reftest.list @@ -189,8 +189,3 @@ defaults pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enable == dynamic-toolbar-sticky-6b.html dynamic-toolbar-sticky-6-ref.html == dynamic-toolbar-sticky-6c.html dynamic-toolbar-sticky-6-ref.html defaults - -== anchor-pos-1.html anchor-pos-1-ref.html -== anchor-pos-2.html anchor-pos-2-ref.html -== anchor-pos-sticky-1.html anchor-pos-sticky-1-ref.html -== anchor-pos-sticky-2.html anchor-pos-sticky-2-ref.html diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml @@ -953,12 +953,6 @@ value: false mirror: always -# Whether to async scroll CSS anchor pos. -- name: apz.async_scroll_css_anchor_pos - type: bool - value: true - mirror: once - #--------------------------------------------------------------------------- # Prefs starting with "beacon." #--------------------------------------------------------------------------- diff --git a/testing/web-platform/tests/css/css-anchor-position/anchor-loop-crash.html b/testing/web-platform/tests/css/css-anchor-position/anchor-loop-crash.html @@ -1,70 +0,0 @@ -<!DOCTYPE html> -<html reftest-async-scroll> -<style> -.container { - position: absolute; - left: 0; - top: 0; -} -.scroller { - position: absolute; - overflow: auto; - scrollbar-width: none; - width: 150px; - height: 100px; -} -.spacer { - width: 1px; - height: 500px; -} -.anchor1 { - width: 50px; - height: 50px; - background: blue; - anchor-name: --my-anchor1; - position: absolute; - position-anchor: --my-anchor2; - position-visibility: always; - left: anchor(right); - top: anchor(bottom); -} -.anchor2 { - width: 50px; - height: 50px; - background: pink; - anchor-name: --my-anchor2; - position: absolute; - position-anchor: --my-anchor3; - position-visibility: always; - left: anchor(right); - top: anchor(bottom); -} -.anchored { - position: absolute; - position-anchor: --my-anchor1; - position-visibility: always; - width: 50px; - height: 50px; - background: yellow; - left: anchor(right); - top: anchor(bottom); - anchor-name: --my-anchor3; -} -</style> -<div class="container"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="150" reftest-displayport-h="500"> - <div class="scroller" - reftest-displayport-x="0" reftest-displayport-y="0" - reftest-displayport-w="150" reftest-displayport-h="500" - reftest-async-scroll-y="50"> - <div class="anchor2"></div> - <div class="spacer"></div> - </div> - <div class="anchor1"></div> - <div class="spacer"></div> - </div> - <div class="anchored"></div> -</div> -</html>