From 672dda40c953b61ffa6deddf73adee82cf6361f0 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Sat, 6 Apr 2024 08:04:29 +0000 Subject: [PATCH] Bug 1890002 - Don't create DOM event for those animation events which don't need to be dispatched, r=emilio Differential Revision: https://phabricator.services.mozilla.com/D206819 --- dom/animation/Animation.cpp | 30 +++++++++---------- dom/animation/Animation.h | 4 +-- dom/animation/AnimationEventDispatcher.cpp | 4 --- dom/animation/AnimationEventDispatcher.h | 34 ++++++++++++++++++---- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 6f0fee007c23..28af34ea30d6 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -10,7 +10,6 @@ #include "AnimationUtils.h" #include "mozAutoDocUpdate.h" #include "mozilla/dom/AnimationBinding.h" -#include "mozilla/dom/AnimationPlaybackEvent.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/DocumentInlines.h" #include "mozilla/dom/DocumentTimeline.h" @@ -644,7 +643,8 @@ void Animation::Cancel(PostRestyleMode aPostRestyle) { } ResetFinishedPromise(); - QueuePlaybackEvent(u"cancel"_ns, GetTimelineCurrentTimeAsTimeStamp()); + QueuePlaybackEvent(nsGkAtoms::oncancel, + GetTimelineCurrentTimeAsTimeStamp()); } StickyTimeDuration activeTime = @@ -1187,7 +1187,7 @@ void Animation::Remove() { UpdateEffect(PostRestyleMode::IfNeeded); PostUpdate(); - QueuePlaybackEvent(u"remove"_ns, GetTimelineCurrentTimeAsTimeStamp()); + QueuePlaybackEvent(nsGkAtoms::onremove, GetTimelineCurrentTimeAsTimeStamp()); } bool Animation::HasLowerCompositeOrderThan(const Animation& aOther) const { @@ -1866,10 +1866,11 @@ void Animation::DoFinishNotificationImmediately(MicroTaskRunnable* aAsync) { MaybeResolveFinishedPromise(); - QueuePlaybackEvent(u"finish"_ns, AnimationTimeToTimeStamp(EffectEnd())); + QueuePlaybackEvent(nsGkAtoms::onfinish, + AnimationTimeToTimeStamp(EffectEnd())); } -void Animation::QueuePlaybackEvent(const nsAString& aName, +void Animation::QueuePlaybackEvent(nsAtom* aOnEvent, TimeStamp&& aScheduledEventTime) { // Use document for timing. // https://drafts.csswg.org/web-animations-1/#document-for-timing @@ -1883,20 +1884,19 @@ void Animation::QueuePlaybackEvent(const nsAString& aName, return; } - AnimationPlaybackEventInit init; - if (aName.EqualsLiteral("finish") || aName.EqualsLiteral("remove")) { - init.mCurrentTime = GetCurrentTimeAsDouble(); + Nullable currentTime; + if (aOnEvent == nsGkAtoms::onfinish || aOnEvent == nsGkAtoms::onremove) { + currentTime = GetCurrentTimeAsDouble(); } + + Nullable timelineTime; if (mTimeline) { - init.mTimelineTime = mTimeline->GetCurrentTimeAsDouble(); + timelineTime = mTimeline->GetCurrentTimeAsDouble(); } - RefPtr event = - AnimationPlaybackEvent::Constructor(this, aName, init); - event->SetTrusted(true); - - presContext->AnimationEventDispatcher()->QueueEvent(AnimationEventInfo( - std::move(event), std::move(aScheduledEventTime), this)); + presContext->AnimationEventDispatcher()->QueueEvent( + AnimationEventInfo(aOnEvent, currentTime, timelineTime, + std::move(aScheduledEventTime), this)); } bool Animation::IsRunningOnCompositor() const { diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h index cb0859a4b68d..4d1442a9063d 100644 --- a/dom/animation/Animation.h +++ b/dom/animation/Animation.h @@ -26,6 +26,7 @@ struct JSContext; class nsCSSPropertyIDSet; class nsIFrame; class nsIGlobalObject; +class nsAtom; namespace mozilla { @@ -449,8 +450,7 @@ class Animation : public DOMEventTargetHelper, void DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag); friend class AsyncFinishNotification; void DoFinishNotificationImmediately(MicroTaskRunnable* aAsync = nullptr); - void QueuePlaybackEvent(const nsAString& aName, - TimeStamp&& aScheduledEventTime); + void QueuePlaybackEvent(nsAtom* aOnEvent, TimeStamp&& aScheduledEventTime); /** * Remove this animation from the pending animation tracker and reset diff --git a/dom/animation/AnimationEventDispatcher.cpp b/dom/animation/AnimationEventDispatcher.cpp index 86884abbe597..0ec5686d8f96 100644 --- a/dom/animation/AnimationEventDispatcher.cpp +++ b/dom/animation/AnimationEventDispatcher.cpp @@ -91,10 +91,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationEventDispatcher) ImplCycleCollectionTraverse( cb, target->mElement, "mozilla::AnimationEventDispatcher.mPendingEvents.mTarget"); - } else { - ImplCycleCollectionTraverse( - cb, info.mData.as().mEvent, - "mozilla::AnimationEventDispatcher.mPendingEvents.mEvent"); } ImplCycleCollectionTraverse( cb, info.mAnimation, diff --git a/dom/animation/AnimationEventDispatcher.h b/dom/animation/AnimationEventDispatcher.h index 98d155790106..dc11972f6df2 100644 --- a/dom/animation/AnimationEventDispatcher.h +++ b/dom/animation/AnimationEventDispatcher.h @@ -12,6 +12,7 @@ #include "mozilla/Attributes.h" #include "mozilla/ContentEvents.h" #include "mozilla/EventDispatcher.h" +#include "mozilla/EventListenerManager.h" #include "mozilla/Variant.h" #include "mozilla/dom/AnimationPlaybackEvent.h" #include "mozilla/dom/KeyframeEffect.h" @@ -44,7 +45,10 @@ struct AnimationEventInfo { }; struct WebAnimationData { - RefPtr mEvent; + const RefPtr mOnEvent; + const dom::Nullable mCurrentTime; + const dom::Nullable mTimelineTime; + const TimeStamp mEventEnqueueTimeStamp{TimeStamp::Now()}; }; using Data = Variant; @@ -100,12 +104,15 @@ struct AnimationEventInfo { } // For web animation events - AnimationEventInfo(RefPtr&& aEvent, + AnimationEventInfo(nsAtom* aOnEvent, + const dom::Nullable& aCurrentTime, + const dom::Nullable& aTimelineTime, TimeStamp&& aScheduledEventTimeStamp, dom::Animation* aAnimation) : mAnimation(aAnimation), mScheduledEventTimeStamp(std::move(aScheduledEventTimeStamp)), - mData(WebAnimationData{std::move(aEvent)}) {} + mData(WebAnimationData{RefPtr{aOnEvent}, aCurrentTime, aTimelineTime}) { + } AnimationEventInfo(const AnimationEventInfo& aOther) = delete; AnimationEventInfo& operator=(const AnimationEventInfo& aOther) = delete; @@ -137,10 +144,27 @@ struct AnimationEventInfo { // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) MOZ_CAN_RUN_SCRIPT_BOUNDARY void Dispatch(nsPresContext* aPresContext) { if (mData.is()) { - RefPtr playbackEvent = mData.as().mEvent; + const auto& data = mData.as(); + EventListenerManager* elm = mAnimation->GetExistingListenerManager(); + if (!elm || !elm->HasListenersFor(data.mOnEvent)) { + return; + } + + dom::AnimationPlaybackEventInit init; + init.mCurrentTime = data.mCurrentTime; + init.mTimelineTime = data.mTimelineTime; + MOZ_ASSERT(nsDependentAtomString(data.mOnEvent).Find(u"on"_ns) == 0, + "mOnEvent atom should start with 'on'!"); + RefPtr event = + dom::AnimationPlaybackEvent::Constructor( + mAnimation, Substring(nsDependentAtomString(data.mOnEvent), 2), + init); + event->SetTrusted(true); + event->WidgetEventPtr()->AssignEventTime( + WidgetEventTime(data.mEventEnqueueTimeStamp)); RefPtr target = mAnimation; EventDispatcher::DispatchDOMEvent(target, nullptr /* WidgetEvent */, - playbackEvent, aPresContext, + event, aPresContext, nullptr /* nsEventStatus */); return; }