@@ -630,6 +630,8 @@ WebIDL::ExceptionOr<void> Animation::silently_set_current_time(Optional<double>
630
630
// https://www.w3.org/TR/web-animations-1/#update-an-animations-finished-state
631
631
void Animation::update_finished_state (DidSeek did_seek, SynchronouslyNotify synchronously_notify)
632
632
{
633
+ auto & realm = this ->realm ();
634
+
633
635
// 1. Let the unconstrained current time be the result of calculating the current time substituting an unresolved
634
636
// time value for the hold time if did seek is false. If did seek is true, the unconstrained current time is
635
637
// equal to the current time.
@@ -706,30 +708,23 @@ void Animation::update_finished_state(DidSeek did_seek, SynchronouslyNotify sync
706
708
if (current_finished_state && !m_is_finished) {
707
709
// 1. Let finish notification steps refer to the following procedure:
708
710
JS::SafeFunction<void ()> finish_notification_steps = [&]() {
709
- if (m_should_abort_finish_notification_microtask) {
710
- m_should_abort_finish_notification_microtask = false ;
711
- m_has_finish_notification_microtask_scheduled = false ;
712
- return ;
713
- }
714
-
715
711
// 1. If animation’s play state is not equal to finished, abort these steps.
716
712
if (play_state () != Bindings::AnimationPlayState::Finished)
717
713
return ;
718
714
719
715
// 2. Resolve animation’s current finished promise object with animation.
720
716
{
721
- HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object (realm () ) };
722
- WebIDL::resolve_promise (realm () , current_finished_promise (), this );
717
+ HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object (realm) };
718
+ WebIDL::resolve_promise (realm, current_finished_promise (), this );
723
719
}
724
720
m_is_finished = true ;
725
721
726
722
// 3. Create an AnimationPlaybackEvent, finishEvent.
727
723
// 4. Set finishEvent’s type attribute to finish.
728
724
// 5. Set finishEvent’s currentTime attribute to the current time of animation.
729
- auto & realm = this ->realm ();
730
725
AnimationPlaybackEventInit init;
731
726
init.current_time = current_time ();
732
- auto finish_event = AnimationPlaybackEvent::create (realm, " finish" _fly_string , init);
727
+ auto finish_event = AnimationPlaybackEvent::create (realm, HTML::EventNames:: finish, init);
733
728
734
729
// 6. Set finishEvent’s timelineTime attribute to the current time of the timeline with which animation is
735
730
// associated. If animation is not associated with a timeline, or the timeline is inactive, let
@@ -750,44 +745,47 @@ void Animation::update_finished_state(DidSeek did_seek, SynchronouslyNotify sync
750
745
// Otherwise, queue a task to dispatch finishEvent at animation. The task source for this task is the DOM
751
746
// manipulation task source.
752
747
else {
753
- HTML::queue_global_task (HTML::Task::Source::DOMManipulation, realm.global_object (), [this , finish_event]() {
748
+ // Manually create a task so its ID can be saved
749
+ auto & document = verify_cast<HTML::Window>(realm.global_object ()).associated_document ();
750
+ auto task = HTML::Task::create (HTML::Task::Source::DOMManipulation, &document, [this , finish_event]() {
754
751
dispatch_event (finish_event);
755
752
});
753
+ m_pending_finish_microtask_id = task->id ();
754
+ HTML::main_thread_event_loop ().task_queue ().add (move (task));
756
755
}
757
-
758
- m_has_finish_notification_microtask_scheduled = false ;
759
756
};
760
757
761
758
// 2. If synchronously notify is true, cancel any queued microtask to run the finish notification steps for this
762
759
// animation, and run the finish notification steps immediately.
763
760
if (synchronously_notify == SynchronouslyNotify::Yes) {
764
- m_should_abort_finish_notification_microtask = false ;
761
+ if (m_pending_finish_microtask_id.has_value ()) {
762
+ HTML::main_thread_event_loop ().task_queue ().remove_tasks_matching ([id = move (m_pending_finish_microtask_id)](auto const & task) {
763
+ return task.id () == id;
764
+ });
765
+ }
765
766
finish_notification_steps ();
766
- m_should_abort_finish_notification_microtask = true ;
767
767
}
768
768
// Otherwise, if synchronously notify is false, queue a microtask to run finish notification steps for
769
769
// animation unless there is already a microtask queued to run those steps for animation.
770
- else {
771
- if (!m_has_finish_notification_microtask_scheduled)
772
- HTML::queue_a_microtask ({}, move (finish_notification_steps));
773
-
774
- m_has_finish_notification_microtask_scheduled = true ;
775
- m_should_abort_finish_notification_microtask = false ;
770
+ else if (!m_pending_finish_microtask_id.has_value ()) {
771
+ auto & document = verify_cast<HTML::Window>(realm.global_object ()).associated_document ();
772
+ auto task = HTML::Task::create (HTML::Task::Source::DOMManipulation, &document, move (finish_notification_steps));
773
+ m_pending_finish_microtask_id = task->id ();
774
+ HTML::main_thread_event_loop ().task_queue ().add (move (task));
776
775
}
777
776
}
778
777
779
778
// 6. If current finished state is false and animation’s current finished promise is already resolved, set
780
779
// animation’s current finished promise to a new promise in the relevant Realm of animation.
781
780
if (!current_finished_state && m_is_finished) {
782
- m_current_finished_promise = WebIDL::create_promise (realm ());
781
+ {
782
+ HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object (realm) };
783
+ m_current_finished_promise = WebIDL::create_promise (realm);
784
+ }
783
785
m_is_finished = false ;
784
786
}
785
787
786
- // Invalidate the style of our target element, if applicable
787
- if (m_effect) {
788
- if (auto target = m_effect->target ())
789
- target->invalidate_style ();
790
- }
788
+ invalidate_effect ();
791
789
}
792
790
793
791
// Step 12 of https://www.w3.org/TR/web-animations-1/#playing-an-animation-section
@@ -881,6 +879,14 @@ JS::NonnullGCPtr<WebIDL::Promise> Animation::current_finished_promise() const
881
879
return *m_current_finished_promise;
882
880
}
883
881
882
+ void Animation::invalidate_effect ()
883
+ {
884
+ if (m_effect) {
885
+ if (auto target = m_effect->target ())
886
+ target->invalidate_style ();
887
+ }
888
+ }
889
+
884
890
Animation::Animation (JS::Realm& realm)
885
891
: DOM::EventTarget(realm)
886
892
{
0 commit comments