tor-browser

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

commit 11eab16dc55b3aee3e7388059b58ceacfb194035
parent ec125e6c9636e0f8d634788b2d5b2bb26fdea6bb
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Fri,  3 Oct 2025 07:43:40 +0000

Bug 1992124 - Ignore invalid @position-try rules. r=layout-anchor-positioning-reviewers,layout-reviewers,dshin

Tested as part of bug 1992124.

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

Diffstat:
Mlayout/generic/AbsoluteContainingBlock.cpp | 71++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 48 insertions(+), 23 deletions(-)

diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -893,13 +893,47 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( } } } - do { - const StylePositionTryFallbacksItem* currentFallback = nullptr; - RefPtr<ComputedStyle> currentFallbackStyle; - if (currentFallbackIndex) { - currentFallback = &fallbacks[*currentFallbackIndex]; + const StylePositionTryFallbacksItem* currentFallback = nullptr; + RefPtr<ComputedStyle> currentFallbackStyle; + + auto TryAdvanceFallback = [&]() -> bool { + if (fallbacks.IsEmpty()) { + return false; + } + uint32_t nextFallbackIndex = + currentFallbackIndex ? *currentFallbackIndex + 1 : 0; + if (nextFallbackIndex >= fallbacks.Length()) { + return false; + } + const StylePositionTryFallbacksItem* nextFallback; + RefPtr<ComputedStyle> nextFallbackStyle; + while (true) { + nextFallback = &fallbacks[nextFallbackIndex]; + if (nextFallback->IsIdentAndOrTactic()) { + auto* ident = nextFallback->AsIdentAndOrTactic().ident.AsAtom(); + if (!ident->IsEmpty()) { + nextFallbackStyle = aPresContext->StyleSet()->ResolvePositionTry( + *aKidFrame->GetContent()->AsElement(), *aKidFrame->Style(), + ident); + if (!nextFallbackStyle) { + // No @position-try rule for this name was found, per spec we should + // skip it. + nextFallbackIndex++; + if (nextFallbackIndex >= fallbacks.Length()) { + return false; + } + } + } + } + break; } + currentFallbackIndex = Some(nextFallbackIndex); + currentFallback = nextFallback; + currentFallbackStyle = std::move(nextFallbackStyle); + return true; + }; + do { const nsRect usedCb = [&] { if (isGrid) { // TODO(emilio): how does position-area interact with grid? @@ -911,14 +945,8 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( if (currentFallback) { if (currentFallback->IsIdentAndOrTactic()) { const auto& item = currentFallback->AsIdentAndOrTactic(); - if (!item.ident.AsAtom()->IsEmpty()) { - currentFallbackStyle = aPresContext->StyleSet()->ResolvePositionTry( - *aKidFrame->GetContent()->AsElement(), *aKidFrame->Style(), - item.ident.AsAtom()); - if (currentFallbackStyle) { - positionArea = - currentFallbackStyle->StylePosition()->mPositionArea; - } + if (currentFallbackStyle) { + positionArea = currentFallbackStyle->StylePosition()->mPositionArea; } tactic = &item.try_tactic; } else { @@ -1159,21 +1187,18 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( aKidFrame->DidReflow(aPresContext, &kidReflowInput); - if (fallbacks.IsEmpty() || - (currentFallbackIndex && - *currentFallbackIndex >= fallbacks.Length() - 1) || - (usedCb.Contains(aKidFrame->GetRect()) && aStatus.IsComplete())) { - // If there are no further fallbacks, or we don't overflow, we're done. + if (usedCb.Contains(aKidFrame->GetRect()) && aStatus.IsComplete()) { + // We don't overflow our CB, no further fallback needed. + break; + } + + if (!TryAdvanceFallback()) { + // If there are no further fallbacks, we're done. break; } // Try with the next fallback. aKidFrame->AddStateBits(NS_FRAME_IS_DIRTY); - if (currentFallbackIndex) { - (*currentFallbackIndex)++; - } else { - currentFallbackIndex.emplace(0); - } aStatus.Reset(); } while (true);