tor-browser

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

commit e0fbb9ac145e37754510f98494572a972b43b23e
parent d1ffd2aea20bc5548dfc526734aaf2b0fec542d6
Author: Boris Chiou <boris.chiou@gmail.com>
Date:   Tue, 16 Dec 2025 07:13:41 +0000

Bug 1817051 - Part 3: Start to sample scroll timeline in the HTML loop. r=firefox-style-system-reviewers,layout-reviewers,hiro,emilio

Also, we drop ProgressTimelineScheduler since we don't need it anymore.

The update in the test is necessary (just like what we do for wpt) for
make sure getComputedStyle() works after we sample the scroll timelines,
because the updating of stale timelines has no effect on forced style and
layout calculations triggered by getComputedStyle() or similar.
In other words, initially stale timelines are visible as such through those
APIs.

Note: there are two new test failures because the timing of caching the
current time is later than the moment we trigger the animation and
scrollTo API. I will try to fix them in the following patch. In this
patch we focus on switching the sampling way and to make sure we don't
cause lots of regressions.

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

Diffstat:
Mdom/animation/AnimationTimelinesController.cpp | 10++++------
Mdom/animation/ElementAnimationData.cpp | 16----------------
Mdom/animation/ElementAnimationData.h | 52+++++++---------------------------------------------
Mdom/animation/ScrollTimeline.cpp | 168+++++++++----------------------------------------------------------------------
Mdom/animation/ScrollTimeline.h | 79-------------------------------------------------------------------------------
Mdom/animation/ViewTimeline.cpp | 8+++++++-
Mdom/animation/test/mozilla/test_get_animations_on_scroll_animations.html | 12++++++++++--
Mlayout/base/nsPresContext.cpp | 1-
Mlayout/generic/ScrollContainerFrame.cpp | 26++++----------------------
Mlayout/style/TimelineManager.cpp | 16----------------
Mlayout/style/TimelineManager.h | 2--
Mtesting/web-platform/meta/css/css-contain/content-visibility/content-visibility-animation-with-scroll-timeline-in-auto-subtree.html.ini | 2++
Mtesting/web-platform/meta/css/css-contain/content-visibility/content-visibility-animation-with-scroll-timeline-in-hidden-subtree.html.ini | 2++
Atesting/web-platform/meta/scroll-animations/crashtests/scroll-timeline-resize.html.ini | 2++
Mtesting/web-platform/meta/scroll-animations/css/scroll-timeline-multi-pass.tentative.html.ini | 3+--
Dtesting/web-platform/meta/scroll-animations/css/scroll-timeline-sampling.html.ini | 6------
Mtesting/web-platform/tests/scroll-animations/crashtests/scroll-timeline-resize.html | 4++++
17 files changed, 62 insertions(+), 347 deletions(-)

diff --git a/dom/animation/AnimationTimelinesController.cpp b/dom/animation/AnimationTimelinesController.cpp @@ -29,10 +29,10 @@ void AnimationTimelinesController::WillRefresh() { // TODO: Switch to sample scroll timelines in HTML event loop in the following // patches. - /*for (ScrollTimeline* tl : + for (ScrollTimeline* tl : ToTArray<AutoTArray<RefPtr<ScrollTimeline>, 32>>(mScrollTimelines)) { tl->WillRefresh(); - }*/ + } } void AnimationTimelinesController::UpdateLastRefreshDriverTime() { @@ -56,11 +56,9 @@ void AnimationTimelinesController::UpdateHiddenByContentVisibility() { timeline->UpdateHiddenByContentVisibility(); } - // TODO: Uncomment this once we start to sample scroll timelines in HTML event - // loop in the following patches. - /*for (AnimationTimeline* timeline : mScrollTimelines) { + for (AnimationTimeline* timeline : mScrollTimelines) { timeline->UpdateHiddenByContentVisibility(); - }*/ + } } } // namespace mozilla::dom diff --git a/dom/animation/ElementAnimationData.cpp b/dom/animation/ElementAnimationData.cpp @@ -51,7 +51,6 @@ void ElementAnimationData::ClearAllAnimationCollections() { mElementData.mTransitions = nullptr; mElementData.mScrollTimelines = nullptr; mElementData.mViewTimelines = nullptr; - mElementData.mProgressTimelineScheduler = nullptr; ClearAllPseudos(false); } @@ -77,7 +76,6 @@ void ElementAnimationData::ClearAllPseudos(bool aOnlyViewTransitions) { data->mTransitions = nullptr; data->mScrollTimelines = nullptr; data->mViewTimelines = nullptr; - data->mProgressTimelineScheduler = nullptr; if (data->IsEmpty()) { iter.Remove(); @@ -178,13 +176,6 @@ void ElementAnimationData::ClearViewTimelineCollectionFor( }); } -void ElementAnimationData::ClearProgressTimelineScheduler( - const PseudoStyleRequest& aRequest) { - WithDataForRemoval(aRequest, [](PerElementOrPseudoData& aData) { - aData.mProgressTimelineScheduler = nullptr; - }); -} - ElementAnimationData::PerElementOrPseudoData::PerElementOrPseudoData() = default; ElementAnimationData::PerElementOrPseudoData::~PerElementOrPseudoData() = @@ -237,11 +228,4 @@ ElementAnimationData::PerElementOrPseudoData::DoEnsureViewTimelines( return *mViewTimelines; } -dom::ProgressTimelineScheduler& ElementAnimationData::PerElementOrPseudoData:: - DoEnsureProgressTimelineScheduler() { - MOZ_ASSERT(!mProgressTimelineScheduler); - mProgressTimelineScheduler = MakeUnique<dom::ProgressTimelineScheduler>(); - return *mProgressTimelineScheduler; -} - } // namespace mozilla diff --git a/dom/animation/ElementAnimationData.h b/dom/animation/ElementAnimationData.h @@ -23,7 +23,6 @@ namespace dom { class Element; class CSSAnimation; class CSSTransition; -class ProgressTimelineScheduler; class ScrollTimeline; class ViewTimeline; } // namespace dom @@ -47,31 +46,15 @@ class ElementAnimationData { // // So it should be fine to create timeline objects only on the elements and // pseudo elements which support animations. + // + // Note: TimelineCollection owns and manages the named progress timeline + // generated by specifying scroll-timeline-name property and + // view-timeline-name property on this element. However, the anonymous + // progress timelines (e.g. animation-timeline:scroll()) are owned by + // Animation objects only. UniquePtr<ScrollTimelineCollection> mScrollTimelines; UniquePtr<ViewTimelineCollection> mViewTimelines; - // This is different from |mScrollTimelines|. We use this to schedule all - // scroll-driven animations (which use anonymous/named scroll timelines or - // anonymous/name view timelines) for a specific scroll source (which is the - // element with ScrollContainerFrame). - // - // TimelineCollection owns and manages the named progress timeline generated - // by specifying scroll-timeline-name property and view-timeline-name - // property on this element. However, the anonymous progress timelines (e.g. - // animation-timeline:scroll()) are owned by Animation objects only. - // - // Note: - // 1. For named scroll timelines. The element which specifies - // scroll-timeline-name is the scroll source. However, for named view - // timelines, the element which specifies view-timeline-name may not be - // the scroll source because we use its nearest scroll container as the - // scroll source. - // 2. For anonymous progress timelines, we don't keep their timeline obejcts - // in TimelineCollection. - // So, per 1) and 2), we use |mProgressTimelineScheduler| for the scroll - // source element to schedule scroll-driven animations. - UniquePtr<dom::ProgressTimelineScheduler> mProgressTimelineScheduler; - PerElementOrPseudoData(); ~PerElementOrPseudoData(); @@ -84,12 +67,10 @@ class ElementAnimationData { dom::Element&, const PseudoStyleRequest&); ViewTimelineCollection& DoEnsureViewTimelines(dom::Element&, const PseudoStyleRequest&); - dom::ProgressTimelineScheduler& DoEnsureProgressTimelineScheduler(); bool IsEmpty() const { return !mEffectSet && !mAnimations && !mTransitions && - !mScrollTimelines && !mViewTimelines && - !mProgressTimelineScheduler; + !mScrollTimelines && !mViewTimelines; } void Traverse(nsCycleCollectionTraversalCallback&); @@ -261,25 +242,6 @@ class ElementAnimationData { return data.DoEnsureViewTimelines(aOwner, aRequest); } - dom::ProgressTimelineScheduler* GetProgressTimelineScheduler( - const PseudoStyleRequest& aRequest) const { - if (auto* data = GetData(aRequest)) { - return data->mProgressTimelineScheduler.get(); - } - return nullptr; - } - - void ClearProgressTimelineScheduler(const PseudoStyleRequest& aRequest); - - dom::ProgressTimelineScheduler& EnsureProgressTimelineScheduler( - const PseudoStyleRequest& aRequest) { - auto& data = GetOrCreateData(aRequest); - if (auto* collection = data.mProgressTimelineScheduler.get()) { - return *collection; - } - return data.DoEnsureProgressTimelineScheduler(); - } - ElementAnimationData() = default; }; diff --git a/dom/animation/ScrollTimeline.cpp b/dom/animation/ScrollTimeline.cpp @@ -51,8 +51,6 @@ ScrollTimeline::ScrollTimeline(Document* aDocument, const Scroller& aScroller, mAxis(aAxis) { MOZ_ASSERT(aDocument); - RegisterWithScrollSource(); - mDocument->TimelinesController().AddScrollTimeline(*this); } @@ -126,43 +124,18 @@ already_AddRefed<ScrollTimeline> ScrollTimeline::MakeNamed( aStyleTimeline.GetAxis()); } -// TODO: Update this function to use the cached values in the following patches. Nullable<TimeDuration> ScrollTimeline::GetCurrentTimeAsDuration() const { - // If no layout box, this timeline is inactive. - if (!mSource || !mSource.mElement->GetPrimaryFrame()) { - return nullptr; - } - - // if this is not a scroller container, this timeline is inactive. - const ScrollContainerFrame* scrollContainerFrame = GetScrollContainerFrame(); - if (!scrollContainerFrame) { + if (!mCachedCurrentTime) { return nullptr; } - const auto orientation = Axis(); - - // If there is no scrollable overflow, then the ScrollTimeline is inactive. - // https://drafts.csswg.org/scroll-animations-1/#scrolltimeline-interface - if (!scrollContainerFrame->GetAvailableScrollingDirections().contains( - orientation)) { - return nullptr; - } - - const bool isHorizontal = orientation == layers::ScrollDirection::eHorizontal; - const nsPoint& scrollPosition = scrollContainerFrame->GetScrollPosition(); - const Maybe<ScrollOffsets>& offsets = - ComputeOffsets(scrollContainerFrame, orientation); - if (!offsets) { - return nullptr; - } - - // Note: For RTL, scrollPosition.x or scrollPosition.y may be negative, - // e.g. the range of its value is [0, -range], so we have to use the - // absolute value. - nscoord position = - std::abs(isHorizontal ? scrollPosition.x : scrollPosition.y); - double progress = static_cast<double>(position - offsets->mStart) / - static_cast<double>(offsets->mEnd - offsets->mStart); + const CurrentTimeData& data = mCachedCurrentTime.ref(); + // FIXME: Scroll offsets on the RTL container is complicated specifically on + // mobile, see https://github.com/w3c/csswg-drafts/issues/12893. For now, we + // use the absoluate value to make things simple. + double progress = + static_cast<double>(std::abs(data.mPosition) - data.mOffsets.mStart) / + static_cast<double>(data.mOffsets.mEnd - data.mOffsets.mStart); return TimeDuration::FromMilliseconds(progress * PROGRESS_TIMELINE_DURATION_MILLISEC); } @@ -289,43 +262,6 @@ void ScrollTimeline::UpdateCachedCurrentTime() { offsets.value()}); } -void ScrollTimeline::RegisterWithScrollSource() { - if (!mSource) { - return; - } - - auto& scheduler = ProgressTimelineScheduler::Ensure( - mSource.mElement, PseudoStyleRequest(mSource.mPseudoType)); - scheduler.AddTimeline(this); -} - -void ScrollTimeline::UnregisterFromScrollSource() { - if (!mSource) { - return; - } - - auto* scheduler = ProgressTimelineScheduler::Get( - mSource.mElement, PseudoStyleRequest(mSource.mPseudoType)); - if (!scheduler) { - return; - } - - // If we are trying to unregister this timeline from the scheduler in - // ProgressTimelineScheduler::ScheduleAnimations(), we have to unregister this - // after we finish the scheduling, to avoid mutating the hashtset - // and destroying the scheduler here. - if (scheduler->IsInScheduling()) { - mState = TimelineState::PendingRemove; - return; - } - - scheduler->RemoveTimeline(this); - if (scheduler->IsEmpty()) { - ProgressTimelineScheduler::Destroy(mSource.mElement, - PseudoStyleRequest(mSource.mPseudoType)); - } -} - const ScrollContainerFrame* ScrollTimeline::GetScrollContainerFrame() const { if (!mSource) { return nullptr; @@ -348,102 +284,36 @@ const ScrollContainerFrame* ScrollTimeline::GetScrollContainerFrame() const { return nullptr; } +static nsRefreshDriver* GetRefreshDriver(Document* aDocument) { + nsPresContext* presContext = aDocument->GetPresContext(); + if (MOZ_UNLIKELY(!presContext)) { + return nullptr; + } + return presContext->RefreshDriver(); +} + void ScrollTimeline::NotifyAnimationUpdated(Animation& aAnimation) { AnimationTimeline::NotifyAnimationUpdated(aAnimation); - // TODO: Switch to sample scroll timelines in HTML event loop in the following - // patches. - /*if (!mAnimationOrder.isEmpty()) { + if (!mAnimationOrder.isEmpty()) { if (auto* rd = GetRefreshDriver(mDocument)) { MOZ_ASSERT(isInList(), "We should not register with the refresh driver if we are not" " in the document's list of timelines"); rd->EnsureAnimationUpdate(); } - }*/ + } } void ScrollTimeline::NotifyAnimationContentVisibilityChanged( Animation* aAnimation, bool aIsVisible) { AnimationTimeline::NotifyAnimationContentVisibilityChanged(aAnimation, aIsVisible); - if (mAnimationOrder.isEmpty()) { - UnregisterFromScrollSource(); - } else { - RegisterWithScrollSource(); - } - - // TODO: Switch to sample scroll timelines in HTML event loop in the following - // patches. - /*if (auto* rd = GetRefreshDriver(mDocument)) { + if (auto* rd = GetRefreshDriver(mDocument)) { MOZ_ASSERT(isInList(), "We should not register with the refresh driver if we are not" " in the document's list of timelines"); rd->EnsureAnimationUpdate(); - }*/ -} - -// ------------------------------------ -// Methods of ProgressTimelineScheduler -// ------------------------------------ -/* static */ ProgressTimelineScheduler* ProgressTimelineScheduler::Get( - const Element* aElement, const PseudoStyleRequest& aPseudoRequest) { - MOZ_ASSERT(aElement); - auto* data = aElement->GetAnimationData(); - if (!data) { - return nullptr; - } - - return data->GetProgressTimelineScheduler(aPseudoRequest); -} - -/* static */ ProgressTimelineScheduler& ProgressTimelineScheduler::Ensure( - Element* aElement, const PseudoStyleRequest& aPseudoRequest) { - MOZ_ASSERT(aElement); - return aElement->EnsureAnimationData().EnsureProgressTimelineScheduler( - aPseudoRequest); -} - -/* static */ -void ProgressTimelineScheduler::Destroy( - const Element* aElement, const PseudoStyleRequest& aPseudoRequest) { - auto* data = aElement->GetAnimationData(); - MOZ_ASSERT(data); - data->ClearProgressTimelineScheduler(aPseudoRequest); -} - -/* static */ -void ProgressTimelineScheduler::ScheduleAnimations( - const Element* aElement, const PseudoStyleRequest& aRequest) { - auto* scheduler = Get(aElement, aRequest); - if (!scheduler) { - return; - } - - // Note: We only need to handle the removal. It's impossible to iterate the - // non-existing timelines and add them into the hashset. - nsTArray<ScrollTimeline*> timelinesToBeRemoved; - - scheduler->mIsInScheduling = true; - for (auto iter = scheduler->mTimelines.iter(); !iter.done(); iter.next()) { - auto* timeline = iter.get(); - const auto state = timeline->ScheduleAnimations(); - if (state == ScrollTimeline::TimelineState::PendingRemove) { - timelinesToBeRemoved.AppendElement(timeline); - } - } - MOZ_ASSERT(Get(aElement, aRequest), "Make sure the scheduler still exists"); - scheduler->mIsInScheduling = false; - - // In the common case, this array is empty. It could be non-empty only when - // we change the content-visibility in their Tick()s. - for (auto* timeline : timelinesToBeRemoved) { - timeline->ResetState(); - scheduler->RemoveTimeline(timeline); - } - - if (scheduler->IsEmpty()) { - ProgressTimelineScheduler::Destroy(aElement, aRequest); } } diff --git a/dom/animation/ScrollTimeline.h b/dom/animation/ScrollTimeline.h @@ -7,7 +7,6 @@ #ifndef mozilla_dom_ScrollTimeline_h #define mozilla_dom_ScrollTimeline_h -#include "mozilla/HashTable.h" #include "mozilla/LinkedList.h" #include "mozilla/ServoStyleConsts.h" #include "mozilla/WritingModes.h" @@ -156,25 +155,6 @@ class ScrollTimeline : public AnimationTimeline, return TimeDuration::FromMilliseconds(PROGRESS_TIMELINE_DURATION_MILLISEC); } - enum class TimelineState : uint8_t { - // Normal case. The timeline is still in the scheduler. - None, - // This timeline is pending for removal from the scheduler. - PendingRemove, - }; - TimelineState ScheduleAnimations() { - MOZ_ASSERT(mState == TimelineState::None); - - // FIXME: Bug 1737927: Need to check the animation mutation observers for - // animations with scroll timelines. - // nsAutoAnimationMutationBatch mb(mDocument); - TickState state; - Tick(state); - // TODO: Do we need to synchronize scroll animations? - - return mState; - } - void WillRefresh(); // If the source of a ScrollTimeline is an element whose principal box does @@ -209,8 +189,6 @@ class ScrollTimeline : public AnimationTimeline, void NotifyAnimationContentVisibilityChanged(Animation* aAnimation, bool aIsVisible) override; - void ResetState() { mState = TimelineState::None; } - protected: virtual ~ScrollTimeline(); ScrollTimeline() = delete; @@ -234,15 +212,8 @@ class ScrollTimeline : public AnimationTimeline, if (isInList()) { remove(); } - UnregisterFromScrollSource(); } - // Register this scroll timeline to the element property. - void RegisterWithScrollSource(); - - // Unregister this scroll timeline from the element property. - void UnregisterFromScrollSource(); - const ScrollContainerFrame* GetScrollContainerFrame() const; static std::pair<const Element*, PseudoStyleRequest> FindNearestScroller( @@ -256,11 +227,6 @@ class ScrollTimeline : public AnimationTimeline, Scroller mSource; StyleScrollAxis mAxis; - // The current state of this timeline. We set this flag during scheduling - // because we shouldn't remove this timeline from the scheduler immediately - // while scheduling, to avoid any unexpected behaviors. - TimelineState mState = TimelineState::None; - struct CurrentTimeData { // The position of the scroller, and this may be negative for RTL or // sideways, e.g. the range of its value could be [0, -range]. The user @@ -271,51 +237,6 @@ class ScrollTimeline : public AnimationTimeline, Maybe<CurrentTimeData> mCachedCurrentTime; }; -/** - * A wrapper around a hashset of ScrollTimeline objects to handle the scheduling - * of scroll driven animations. This is used for all kinds of progress - * timelines, i.e. anonymous/named scroll timelines and anonymous/named view - * timelines. And this object is owned by the scroll source (See - * ElementAnimationData and ScrollContainerFrame for the usage). - */ -class ProgressTimelineScheduler { - public: - ProgressTimelineScheduler() { MOZ_COUNT_CTOR(ProgressTimelineScheduler); } - ~ProgressTimelineScheduler() { MOZ_COUNT_DTOR(ProgressTimelineScheduler); } - - static ProgressTimelineScheduler* Get( - const Element* aElement, const PseudoStyleRequest& aPseudoRequest); - static ProgressTimelineScheduler& Ensure( - Element* aElement, const PseudoStyleRequest& aPseudoRequest); - static void Destroy(const Element* aElement, - const PseudoStyleRequest& aPseudoRequest); - - void AddTimeline(ScrollTimeline* aScrollTimeline) { - MOZ_ASSERT(!mIsInScheduling, "Do not mutate the hashset during scheduling"); - (void)mTimelines.put(aScrollTimeline); - } - void RemoveTimeline(ScrollTimeline* aScrollTimeline) { - MOZ_ASSERT(!mIsInScheduling, "Do not mutate the hashset during scheduling"); - mTimelines.remove(aScrollTimeline); - } - - bool IsEmpty() const { return mTimelines.empty(); } - bool IsInScheduling() const { return mIsInScheduling; } - - // Note: Use static function because this may destroy the scheduler if all - // timelines are removed. - static void ScheduleAnimations(const Element* aElement, - const PseudoStyleRequest& aRequest); - - private: - // We let Animations own its scroll timeline or view timeline if it is - // anonymous. For named progress timelines, they are created and destroyed by - // TimelineCollection. - HashSet<ScrollTimeline*> mTimelines; - // Used to avoid mutating |mTimelines| while scheduling. - bool mIsInScheduling = false; -}; - } // namespace dom } // namespace mozilla diff --git a/dom/animation/ViewTimeline.cpp b/dom/animation/ViewTimeline.cpp @@ -72,9 +72,15 @@ Maybe<ScrollTimeline::ScrollOffsets> ViewTimeline::ComputeOffsets( MOZ_ASSERT(mSubject); MOZ_ASSERT(aScrollContainerFrame); + // Note: We may fail to get the pseudo element (or its primary frame) if it is + // not generated yet or just get destroyed, while we are sampling this view + // timeline. + // FIXME: Bug 1954230. It's probably a case we need to discard this timeline. + // For now, this is just a hot fix. const Element* subjectElement = mSubject->GetPseudoElement(PseudoStyleRequest(mSubjectPseudoType)); - const nsIFrame* subject = subjectElement->GetPrimaryFrame(); + const nsIFrame* subject = + subjectElement ? subjectElement->GetPrimaryFrame() : nullptr; if (!subject) { // No principal box of the subject, so we cannot compute the offset. This // may happen when we clear all animation collections during unbinding from diff --git a/dom/animation/test/mozilla/test_get_animations_on_scroll_animations.html b/dom/animation/test/mozilla/test_get_animations_on_scroll_animations.html @@ -24,7 +24,7 @@ <script> "use strict"; -test(function(t) { +promise_test(async (t) => { const div = addDiv(t, { style: "width: 10px; height: 100px; " + "animation: animWidth 100s, animTop 200s; " + @@ -35,6 +35,10 @@ test(function(t) { const scroller = document.scrollingElement; const maxScroll = scroller.scrollHeight - scroller.clientHeight; scroller.scrollTop = maxScroll; + // Wait for one frame to make sure getComputedStyle() works because we sample + // the scroll timeline during the HTML event loop. + await waitForNextFrame(); + assert_equals(getComputedStyle(div).width, "200px", "The scroll animation is there"); @@ -48,7 +52,7 @@ test(function(t) { 'scroll animation should not return scroll timeline'); }, 'Element.getAnimation() should include scroll animations'); -test(function(t) { +promise_test(async (t) => { const div = addDiv(t, { style: "width: 10px; height: 100px; " + "animation: animWidth 100s, animTop 100s; " + @@ -59,6 +63,10 @@ test(function(t) { const scroller = document.scrollingElement; const maxScroll = scroller.scrollHeight - scroller.clientHeight; scroller.scrollTop = maxScroll; + // Wait for one frame to make sure getComputedStyle() works because we sample + // the scroll timeline during the HTML event loop. + await waitForNextFrame(); + assert_equals(getComputedStyle(div).width, "200px", "The scroll animation is there"); diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp @@ -3057,7 +3057,6 @@ void nsPresContext::DoUpdateHiddenByContentVisibilityForAnimations() { MOZ_ASSERT(NeedsToUpdateHiddenByContentVisibilityForAnimations()); mNeedsToUpdateHiddenByContentVisibilityForAnimations = false; mDocument->UpdateHiddenByContentVisibilityForAnimations(); - TimelineManager()->UpdateHiddenByContentVisibilityForAnimations(); } #ifdef DEBUG diff --git a/layout/generic/ScrollContainerFrame.cpp b/layout/generic/ScrollContainerFrame.cpp @@ -7851,28 +7851,10 @@ void ScrollContainerFrame::AppendScrollUpdate( } void ScrollContainerFrame::ScheduleScrollAnimations() { - nsIContent* content = GetContent(); - MOZ_ASSERT(content && content->IsElement(), - "The ScrollContainerFrame should have the element."); - - const Element* elementOrPseudo = content->AsElement(); - PseudoStyleType pseudo = elementOrPseudo->GetPseudoElementType(); - if (pseudo != PseudoStyleType::NotPseudo && - !AnimationUtils::IsSupportedPseudoForAnimations(pseudo)) { - // This is not an animatable pseudo element, and so we don't generate - // scroll-timeline for it. - return; - } - - const auto [element, request] = - AnimationUtils::GetElementPseudoPair(elementOrPseudo); - ProgressTimelineScheduler::ScheduleAnimations(element, request); - - // TODO: Switch to sample scroll timelines in HTML event loop in the following - // patches. - // auto* rd = PresContext()->RefreshDriver(); - // MOZ_ASSERT(rd); - // rd->EnsureAnimationUpdate(); + auto* rd = PresContext()->RefreshDriver(); + MOZ_ASSERT(rd); + // This schedules UpdateAnimationsAndSendEvents in the HTML loop. + rd->EnsureAnimationUpdate(); } nsSize ScrollContainerFrame::GetSizeForWindowInnerSize() const { diff --git a/layout/style/TimelineManager.cpp b/layout/style/TimelineManager.cpp @@ -170,20 +170,4 @@ void TimelineManager::DoUpdateTimelines( // siblings when mutating {scroll|view}-timeline-name. } -void TimelineManager::UpdateHiddenByContentVisibilityForAnimations() { - for (auto* scrollTimelineCollection : mScrollTimelineCollections) { - for (ScrollTimeline* timeline : - scrollTimelineCollection->Timelines().Values()) { - timeline->UpdateHiddenByContentVisibility(); - } - } - - for (auto* viewTimelineCollection : mViewTimelineCollections) { - for (ViewTimeline* timeline : - viewTimelineCollection->Timelines().Values()) { - timeline->UpdateHiddenByContentVisibility(); - } - } -} - } // namespace mozilla diff --git a/layout/style/TimelineManager.h b/layout/style/TimelineManager.h @@ -52,8 +52,6 @@ class TimelineManager { const ComputedStyle* aComputedStyle, ProgressTimelineType aType); - void UpdateHiddenByContentVisibilityForAnimations(); - private: template <typename StyleType, typename TimelineType> void DoUpdateTimelines(nsPresContext* aPresContext, dom::Element* aElement, diff --git a/testing/web-platform/meta/css/css-contain/content-visibility/content-visibility-animation-with-scroll-timeline-in-auto-subtree.html.ini b/testing/web-platform/meta/css/css-contain/content-visibility/content-visibility-animation-with-scroll-timeline-in-auto-subtree.html.ini @@ -1,2 +1,4 @@ [content-visibility-animation-with-scroll-timeline-in-auto-subtree.html] prefs: [layout.css.scroll-driven-animations.enabled:true] + [Animation with scroll-timeline should be affected c-v] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/content-visibility/content-visibility-animation-with-scroll-timeline-in-hidden-subtree.html.ini b/testing/web-platform/meta/css/css-contain/content-visibility/content-visibility-animation-with-scroll-timeline-in-hidden-subtree.html.ini @@ -1,2 +1,4 @@ [content-visibility-animation-with-scroll-timeline-in-hidden-subtree.html] prefs: [layout.css.scroll-driven-animations.enabled:true] + [Animation with scroll-timeline should be affected c-v] + expected: FAIL diff --git a/testing/web-platform/meta/scroll-animations/crashtests/scroll-timeline-resize.html.ini b/testing/web-platform/meta/scroll-animations/crashtests/scroll-timeline-resize.html.ini @@ -0,0 +1,2 @@ +[scroll-timeline-resize.html] + expected: TIMEOUT diff --git a/testing/web-platform/meta/scroll-animations/css/scroll-timeline-multi-pass.tentative.html.ini b/testing/web-platform/meta/scroll-animations/css/scroll-timeline-multi-pass.tentative.html.ini @@ -1,6 +1,5 @@ [scroll-timeline-multi-pass.tentative.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] + expected: [OK, ERROR] [Multiple style/layout passes occur when necessary] expected: FAIL bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1817051 diff --git a/testing/web-platform/meta/scroll-animations/css/scroll-timeline-sampling.html.ini b/testing/web-platform/meta/scroll-animations/css/scroll-timeline-sampling.html.ini @@ -1,6 +0,0 @@ -[scroll-timeline-sampling.html] - expected: - if (os == "android") and fission: [OK, TIMEOUT] - [Scroll position is sampled once per frame] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1817051 diff --git a/testing/web-platform/tests/scroll-animations/crashtests/scroll-timeline-resize.html b/testing/web-platform/tests/scroll-animations/crashtests/scroll-timeline-resize.html @@ -24,6 +24,10 @@ <script> async function run() { let anims = document.getAnimations(); + if (anims.length == 0) { + // Make this timeout. + return; + } await anims[0].ready; // Wait for some frames to wait for the setup of compositor animations. await waitForAnimationFrames(2);