tor-browser

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

commit d82c74ec452de160807e56da6c1fde677edd6232
parent 8684c3bcd0ad2ff392214d702d8bb48fe556a820
Author: Jonathan Kew <jkew@mozilla.com>
Date:   Fri,  2 Jan 2026 17:22:04 +0000

Bug 2006513 - Restore size as well as position of aKidFrame if no position-try fallback fits. r=layout-anchor-positioning-reviewers,layout-reviewers,emilio

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

Diffstat:
Mlayout/generic/AbsoluteContainingBlock.cpp | 69+++++++++++++++++++++++++++++++++++++++------------------------------
Mtesting/web-platform/meta/css/css-anchor-position/anchor-scroll-position-try-007.html.ini | 1-
Dtesting/web-platform/meta/css/css-anchor-position/position-try-001.html.ini | 3---
3 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -1296,7 +1296,7 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( return SeekFallbackTo(Some(nextFallbackIndex)); }; - Maybe<nsPoint> firstTryNormalPosition; + Maybe<nsRect> firstTryNormalRect; if (auto* lastSuccessfulPosition = aKidFrame->GetProperty(nsIFrame::LastSuccessfulPositionFallback())) { if (SeekFallbackTo(Some(lastSuccessfulPosition->mIndex))) { @@ -1660,9 +1660,9 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( aKidFrame->DidReflow(aPresContext, &kidReflowInput); [&]() { - const auto position = aKidFrame->GetPosition(); - if (!firstTryNormalPosition) { - firstTryNormalPosition = Some(position); + const auto rect = aKidFrame->GetRect(); + if (!firstTryNormalRect) { + firstTryNormalRect = Some(rect); } if (!aAnchorPosResolutionCache) { return; @@ -1685,9 +1685,10 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( // Apply the hypothetical scroll offset. // Set initial scroll position. TODO(dshin, bug 1987962): Need // additional work for remembered scroll offset here. - aKidFrame->SetProperty(nsIFrame::NormalPositionProperty(), position); + aKidFrame->SetProperty(nsIFrame::NormalPositionProperty(), + rect.TopLeft()); if (offset != nsPoint{}) { - aKidFrame->SetPosition(position - offset); + aKidFrame->SetPosition(rect.TopLeft() - offset); // Ensure that the positioned frame's overflow is updated. Absolutely // containing block's overflow will be updated shortly below. aKidFrame->UpdateOverflow(); @@ -1747,11 +1748,22 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( if (!TryAdvanceFallback()) { // If there are no further fallbacks, we're done. if (bestSize >= 0) { - finalizing = true; SeekFallbackTo(bestIndex); } else { - break; + // If we're going to roll back to the first try position, and the + // target's size was different, we need to do a "finalizing" reflow + // to ensure the inner layout is correct. If the size is unchanged, + // we can just break the fallback loop now. + if (isOverflowingCB && firstTryNormalRect && + firstTryNormalRect->Size() != aKidFrame->GetSize()) { + SeekFallbackTo(firstTryIndex); + } else { + break; + } } + // The fallback we've just selected is the final choice, regardless of + // whether it overflows. + finalizing = true; } // Try with the next fallback. @@ -1760,7 +1772,7 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( } while (true); [&]() { - if (!isOverflowingCB || !firstTryNormalPosition) { + if (!isOverflowingCB || !firstTryNormalRect) { return; } // We gave up applying fallbacks. Recover previous values, if changed, and @@ -1768,45 +1780,42 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( // Because we rolled back to first try data, our cache should be up-to-date. currentFallbackIndex = firstTryIndex; currentFallbackStyle = firstTryStyle; - const auto normalPosition = *firstTryNormalPosition; + const auto normalRect = *firstTryNormalRect; const auto oldNormalPosition = aKidFrame->GetNormalPosition(); - if (normalPosition != oldNormalPosition) { + if (normalRect.TopLeft() != oldNormalPosition) { aKidFrame->SetProperty(nsIFrame::NormalPositionProperty(), - normalPosition); + normalRect.TopLeft()); } - auto position = normalPosition; + auto rect = normalRect; if (aAnchorPosResolutionCache) { - position -= - aAnchorPosResolutionCache->mReferenceData->mDefaultScrollShift; + rect.MoveBy( + -aAnchorPosResolutionCache->mReferenceData->mDefaultScrollShift); } if (isOverflowingCB && !aKidFrame->StylePosition()->mPositionArea.IsNone()) { // The anchored element overflows the IMCB of its position-area. Would it // have fit within the original CB? If so, shift it to stay within that. - nsSize size = aKidFrame->GetSize(); - if (size.width <= aOriginalContainingBlockRect.width && - size.height <= aOriginalContainingBlockRect.height) { - if (position.x < aOriginalContainingBlockRect.x) { - position.x = aOriginalContainingBlockRect.x; - } else if (position.x + size.width > - aOriginalContainingBlockRect.XMost()) { - position.x = aOriginalContainingBlockRect.XMost() - size.width; + if (rect.width <= aOriginalContainingBlockRect.width && + rect.height <= aOriginalContainingBlockRect.height) { + if (rect.x < aOriginalContainingBlockRect.x) { + rect.x = aOriginalContainingBlockRect.x; + } else if (rect.XMost() > aOriginalContainingBlockRect.XMost()) { + rect.x = aOriginalContainingBlockRect.XMost() - rect.width; } - if (position.y < aOriginalContainingBlockRect.y) { - position.y = aOriginalContainingBlockRect.y; - } else if (position.y + size.height > - aOriginalContainingBlockRect.YMost()) { - position.y = aOriginalContainingBlockRect.YMost() - size.height; + if (rect.y < aOriginalContainingBlockRect.y) { + rect.y = aOriginalContainingBlockRect.y; + } else if (rect.YMost() > aOriginalContainingBlockRect.YMost()) { + rect.y = aOriginalContainingBlockRect.YMost() - rect.height; } } } const auto oldPosition = aKidFrame->GetPosition(); - if (position == oldPosition) { + if (rect.TopLeft() == oldPosition) { return; } - aKidFrame->SetPosition(position); + aKidFrame->SetPosition(rect.TopLeft()); aKidFrame->UpdateOverflow(); }(); diff --git a/testing/web-platform/meta/css/css-anchor-position/anchor-scroll-position-try-007.html.ini b/testing/web-platform/meta/css/css-anchor-position/anchor-scroll-position-try-007.html.ini @@ -3,4 +3,3 @@ expected: if os == "android": PASS FAIL - diff --git a/testing/web-platform/meta/css/css-anchor-position/position-try-001.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-try-001.html.ini @@ -1,3 +0,0 @@ -[position-try-001.html] - [.target 6] - expected: FAIL