tor-browser

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

commit 282a5bc016f34bf23cd617f198eb7ecf7c814990
parent c2271ec0ede2fcb68ac7329fffc5833a341f85a9
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Tue,  2 Dec 2025 22:57:39 +0000

Bug 2003593 - Invalidate for anchor changes correctly. r=dshin,layout-anchor-positioning-reviewers,firefox-style-system-reviewers,layout-reviewers

We need to start the reflow from our parent, even if we happen to be a
reflow root.

Differential Revision: https://phabricator.services.mozilla.com/D274805

Diffstat:
Mlayout/base/AnchorPositioningUtils.cpp | 3+--
Mlayout/base/PresShell.cpp | 19+++++++++++--------
Mlayout/base/PresShell.h | 5++++-
Mlayout/base/nsPresContext.cpp | 2+-
Mlayout/style/nsStyleStruct.cpp | 2+-
Atesting/web-platform/tests/css/css-anchor-position/anchor-name-dynamic-reflow-root-ref.html | 14++++++++++++++
Atesting/web-platform/tests/css/css-anchor-position/anchor-name-dynamic-reflow-root.html | 45+++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 77 insertions(+), 13 deletions(-)

diff --git a/layout/base/AnchorPositioningUtils.cpp b/layout/base/AnchorPositioningUtils.cpp @@ -951,8 +951,7 @@ static bool TriggerFallbackReflow(PresShell* aPresShell, nsIFrame* aPositioned, // We want to retry from the first position; remove the last position // property so all potential positions are re-evaluated. aPositioned->RemoveProperty(nsIFrame::LastSuccessfulPositionFallback()); - aPresShell->FrameNeedsReflow(aPositioned, mozilla::IntrinsicDirty::None, - NS_FRAME_IS_DIRTY); + aPresShell->MarkPositionedFrameForReflow(aPositioned); return true; } diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp @@ -11575,9 +11575,7 @@ PresShell::AnchorPosUpdateResult PresShell::UpdateAnchorPosLayout() { } if (shouldReflow) { result = AnchorPosUpdateResult::NeedReflow; - // Abspos frames should not affect ancestor intrinsics. - FrameNeedsReflow(positioned, IntrinsicDirty::None, - NS_FRAME_HAS_DIRTY_CHILDREN); + MarkPositionedFrameForReflow(positioned); } } return result; @@ -11817,8 +11815,7 @@ void PresShell::UpdateAnchorPosForScroll( accService->NotifyAnchorPositionedScrollUpdate(this, positioned); } #endif - FrameNeedsReflow(positioned, IntrinsicDirty::None, - NS_FRAME_HAS_DIRTY_CHILDREN); + MarkPositionedFrameForReflow(positioned); } } } @@ -12146,13 +12143,19 @@ size_t PresShell::SizeOfTextRuns(MallocSizeOf aMallocSizeOf) const { /* clear = */ false); } -void PresShell::MarkFixedFramesForReflow(IntrinsicDirty aIntrinsicDirty) { +void PresShell::MarkPositionedFrameForReflow(nsIFrame* aFrame) { + // Abspos frames don't affect intrinsic sizes of ancestors. + FrameNeedsReflow(aFrame, IntrinsicDirty::None, NS_FRAME_HAS_DIRTY_CHILDREN, + ReflowRootHandling::PositionOrSizeChange); +} + +void PresShell::MarkFixedFramesForReflow() { nsIFrame* rootFrame = mFrameConstructor->GetRootFrame(); if (rootFrame) { const nsFrameList& childList = rootFrame->GetChildList(FrameChildListID::Fixed); for (nsIFrame* childFrame : childList) { - FrameNeedsReflow(childFrame, aIntrinsicDirty, NS_FRAME_IS_DIRTY); + MarkPositionedFrameForReflow(childFrame); } } } @@ -12230,7 +12233,7 @@ void PresShell::CompleteChangeToVisualViewportSize() { if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) { sf->MarkScrollbarsDirtyForReflow(); } - MarkFixedFramesForReflow(IntrinsicDirty::None); + MarkFixedFramesForReflow(); } MaybeReflowForInflationScreenSizeChange(); diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h @@ -1544,7 +1544,10 @@ class PresShell final : public nsStubDocumentObserver, /** * Calls FrameNeedsReflow on all fixed position children of the root frame. */ - void MarkFixedFramesForReflow(IntrinsicDirty aIntrinsicDirty); + void MarkFixedFramesForReflow(); + // Marks a positioned frame for reflow, assuming that size or position of the + // frame might change. + void MarkPositionedFrameForReflow(nsIFrame*); /** * Similar to above MarkFixedFramesForReflow, but for sticky position children diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp @@ -2948,7 +2948,7 @@ void nsPresContext::UpdateDynamicToolbarOffset(ScreenIntCoord aOffset) { // position:fixed or position:sticky element is painted at the correct // position on the main-thread. if (mDynamicToolbarHeight == 0 || aOffset == -mDynamicToolbarMaxHeight) { - mPresShell->MarkFixedFramesForReflow(IntrinsicDirty::None); + mPresShell->MarkFixedFramesForReflow(); mPresShell->MarkStickyFramesForReflow(); mPresShell->ScheduleResizeEventIfNeeded( PresShell::ResizeEventKind::Regular); diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp @@ -1257,7 +1257,7 @@ nsChangeHint nsStylePosition::CalcDifference( mPositionArea != aNewData.mPositionArea) { // We need to reflow in order to update the `AnchorPosReferences` // property at minimum. - hint |= nsChangeHint_NeedReflow; + hint |= nsChangeHint_NeedReflow | nsChangeHint_ReflowChangesSizeOrPosition; } if (mAspectRatio != aNewData.mAspectRatio) { diff --git a/testing/web-platform/tests/css/css-anchor-position/anchor-name-dynamic-reflow-root-ref.html b/testing/web-platform/tests/css/css-anchor-position/anchor-name-dynamic-reflow-root-ref.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<style> +body { margin: 0 } +.green { + position: absolute; + top: 20px; + left: 100px; + width: 100px; + height: 100px; + background-color: green; +} +</style> +<div class="green"></div> diff --git a/testing/web-platform/tests/css/css-anchor-position/anchor-name-dynamic-reflow-root.html b/testing/web-platform/tests/css/css-anchor-position/anchor-name-dynamic-reflow-root.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<title>Dynamic changes to anchor-name and reflow roots</title> +<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#anchor-name"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2003593"> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<link rel="author" title="Mozilla" href="https://mozilla.com"> +<link rel="match" href="anchor-name-dynamic-reflow-root-ref.html"> +<style> +body { margin: 0 } +.tabs { + display: flex; +} +.tab { + height: 20px; + width: 100px; +} +.cur { + anchor-name: --current-tab; +} +.highlight { + position: absolute; + width: anchor-size(width); + left: anchor(left); + right: anchor(right); + height: 100px; + background: green; + top: anchor(bottom); + position-anchor: --current-tab; + transform: scaleY(1); /* This is important to test the bug */ +} +</style> +<div class=tabs> + <div id=t1 class="tab cur"></div> + <div id=t2 class="tab"></div> + <div class=highlight></div> +</div> +<script> +document.addEventListener("TestRendered", function() { + t1.classList.remove('cur'); + t2.classList.add('cur'); + document.documentElement.className = ""; +}); +</script>