tor-browser

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

commit 1cc7bc843d67c458c65904e389f926010e01ff14
parent 4ccd058d0fa0a5362e86002de794802ed496ebe0
Author: Timothy Nikkel <tnikkel@gmail.com>
Date:   Fri, 12 Dec 2025 00:10:57 +0000

Bug 2004833. Use scroll-linked-effects code for anchor pos scrolling we can't represent as async scrolling to improve experience. r=hiro,layout-reviewers

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

Diffstat:
Mdom/base/Document.cpp | 6++++--
Mdom/base/Document.h | 5++++-
Agfx/layers/apz/test/mochitest/helper_scroll_linked_effect_anchor.html | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mgfx/layers/apz/test/mochitest/test_group_scroll_linked_effect.html | 3++-
Mlayout/base/DisplayPortUtils.cpp | 17++++++++++++++---
5 files changed, 117 insertions(+), 7 deletions(-)

diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp @@ -18137,7 +18137,8 @@ FontFaceSet* Document::Fonts() { return mFontFaceSet; } -void Document::ReportHasScrollLinkedEffect(const TimeStamp& aTimeStamp) { +void Document::ReportHasScrollLinkedEffect( + const TimeStamp& aTimeStamp, ReportToConsole aReportToConsole /* = Yes */) { MOZ_ASSERT(!aTimeStamp.IsNull()); if (!mLastScrollLinkedEffectDetectionTime.IsNull() && @@ -18145,7 +18146,8 @@ void Document::ReportHasScrollLinkedEffect(const TimeStamp& aTimeStamp) { return; } - if (mLastScrollLinkedEffectDetectionTime.IsNull()) { + if (aReportToConsole == ReportToConsole::Yes && + mLastScrollLinkedEffectDetectionTime.IsNull()) { // Report to console just once. nsContentUtils::ReportToConsole( nsIScriptError::warningFlag, "Async Pan/Zoom"_ns, this, diff --git a/dom/base/Document.h b/dom/base/Document.h @@ -3945,7 +3945,10 @@ class Document : public nsINode, bool HasScriptsBlockedBySandbox() const; - void ReportHasScrollLinkedEffect(const TimeStamp& aTimeStamp); + enum class ReportToConsole : bool { No, Yes }; + void ReportHasScrollLinkedEffect( + const TimeStamp& aTimeStamp, + ReportToConsole aReportToConsole = ReportToConsole::Yes); bool HasScrollLinkedEffect() const; #ifdef DEBUG diff --git a/gfx/layers/apz/test/mochitest/helper_scroll_linked_effect_anchor.html b/gfx/layers/apz/test/mochitest/helper_scroll_linked_effect_anchor.html @@ -0,0 +1,93 @@ +<!DOCTYPE html> +<html> +<meta charset="utf-8"> +<script src="/tests/SimpleTest/paint_listener.js"></script> +<script src="apz_test_utils.js"></script> +<script src="apz_test_native_event_utils.js"></script> +<title>Scroll Linked Effect for anchor tests</title> + +<style> +.abs-container { + position: absolute; +} + +.anchor { + width: 150px; + height: 50px; + background: purple; + anchor-name: --foo; + position: absolute; + left: 500px; +} + +.scroller { + border: 1px solid; + height: 600px; + width: 500px; + overflow: scroll; + position: absolute; + top: 40px; +} + +.anchor-queryh { + width: 100px; + height: 25px; + background: pink; + position: absolute; + position-anchor: --foo; + top: 200px; + left: anchor(right); + position-visibility: always; +} + +.anchor-queryv { + width: 100px; + height: 25px; + background: pink; + position: absolute; + position-anchor: --foo; + top: anchor(bottom); + position-visibility: always; +} + +.filler { + width: 2000px; + height: 750px; +} + +</style> +<div class="abs-container"> + <div class="scroller"> + <div class="filler"></div> + <div class="anchor">Anchor</div> + <div class="filler"></div> + </div> + <div class="anchor-queryh">Queried horz</div> + <div class="anchor-queryv">Queried vert</div> +</div> + +<script> +async function test() { + + // Make sure every element gets repainted on every tick + function toggleBg() { + document.documentElement.style.background == "white" + ? document.documentElement.style.background = "black" + : document.documentElement.style.background = "white"; + window.requestAnimationFrame(toggleBg); + } + window.requestAnimationFrame(toggleBg); + + await new Promise(r => window.requestAnimationFrame(r)); + // we are now in the mid-way through refresh driver tick, before painting + await new Promise(r => setTimeout(r, 0)); + // we are now after the painting + + ok(SpecialPowers.DOMWindowUtils.hasScrollLinkedEffect, + "scroll-linked effect found"); +} + +waitUntilApzStable() +.then(test) +.then(subtestDone, subtestFailed); +</script> diff --git a/gfx/layers/apz/test/mochitest/test_group_scroll_linked_effect.html b/gfx/layers/apz/test/mochitest/test_group_scroll_linked_effect.html @@ -19,7 +19,8 @@ var subtests = [ "prefs": [ ...prefs, [ "general.smoothScroll", false ], - ]} + ]}, + {"file": "helper_scroll_linked_effect_anchor.html", prefs}, ]; if (isApzEnabled()) { diff --git a/layout/base/DisplayPortUtils.cpp b/layout/base/DisplayPortUtils.cpp @@ -26,6 +26,7 @@ #include "mozilla/layers/PAPZ.h" #include "nsLayoutUtils.h" #include "nsPlaceholderFrame.h" +#include "nsRefreshDriver.h" #include "nsSubDocumentFrame.h" #include "nsIFrameInlines.h" @@ -1316,12 +1317,15 @@ static bool CheckForStickyAndAxes(nsIFrame* aFrame, PhysicalAxes aAxes, static bool ShouldAsyncScrollWithAnchorNotCached(nsIFrame* aFrame, nsIFrame* aAnchor, nsDisplayListBuilder* aBuilder, - PhysicalAxes aAxes) { + PhysicalAxes aAxes, + bool* aReportToDoc) { // This has the same basic structure as GetASRAncestorFrame and // OneStepInASRChain. They should all be kept in sync. if (aFrame->IsMenuPopupFrame()) { + *aReportToDoc = false; return false; } + *aReportToDoc = true; nsIFrame* limitAncestor = aFrame->GetParent(); MOZ_ASSERT(limitAncestor); // Start from aAnchor (not aFrame) so we don't infinite loop. @@ -1400,8 +1404,15 @@ bool DisplayPortUtils::ShouldAsyncScrollWithAnchor( return true; }); if (!wasPresent) { - entry = - ShouldAsyncScrollWithAnchorNotCached(aFrame, aAnchor, aBuilder, aAxes); + bool reportToDoc = false; + entry = ShouldAsyncScrollWithAnchorNotCached(aFrame, aAnchor, aBuilder, + aAxes, &reportToDoc); + if (!entry && reportToDoc) { + auto* pc = aFrame->PresContext(); + pc->Document()->ReportHasScrollLinkedEffect( + pc->RefreshDriver()->MostRecentRefresh(), + dom::Document::ReportToConsole::No); + } } return entry;