diff --git a/Tests/LibWeb/Text/expected/WebAnimations/misc/animation-events-basic.txt b/Tests/LibWeb/Text/expected/WebAnimations/misc/animation-events-basic.txt new file mode 100644 index 00000000000..9e40aaf85f0 --- /dev/null +++ b/Tests/LibWeb/Text/expected/WebAnimations/misc/animation-events-basic.txt @@ -0,0 +1,2 @@ + animationstart +animationend diff --git a/Tests/LibWeb/Text/input/WebAnimations/misc/animation-events-basic.html b/Tests/LibWeb/Text/input/WebAnimations/misc/animation-events-basic.html new file mode 100644 index 00000000000..b0ccd2dc6c4 --- /dev/null +++ b/Tests/LibWeb/Text/input/WebAnimations/misc/animation-events-basic.html @@ -0,0 +1,46 @@ + + + +
+ + diff --git a/Userland/Libraries/LibWeb/Animations/Animation.cpp b/Userland/Libraries/LibWeb/Animations/Animation.cpp index b04482d872d..a2a654d7f14 100644 --- a/Userland/Libraries/LibWeb/Animations/Animation.cpp +++ b/Userland/Libraries/LibWeb/Animations/Animation.cpp @@ -456,7 +456,7 @@ void Animation::cancel(ShouldInvalidate should_invalidate) Optional scheduled_event_time; if (m_timeline && !m_timeline->is_inactive() && m_timeline->can_convert_a_timeline_time_to_an_origin_relative_time()) scheduled_event_time = m_timeline->convert_a_timeline_time_to_an_origin_relative_time(m_timeline->current_time()); - document->append_pending_animation_event({ cancel_event, *this, scheduled_event_time }); + document->append_pending_animation_event({ cancel_event, *this, *this, scheduled_event_time }); } else { HTML::queue_global_task(HTML::Task::Source::DOMManipulation, realm.global_object(), JS::create_heap_function(heap(), [this, cancel_event]() { dispatch_event(cancel_event); @@ -1127,9 +1127,12 @@ void Animation::update_finished_state(DidSeek did_seek, SynchronouslyNotify sync // animation event queue along with its target, animation. For the scheduled event time, use the result // of converting animation’s associated effect end to an origin-relative time. if (auto document_for_timing = this->document_for_timing()) { - document_for_timing->append_pending_animation_event({ .event = finish_event, + document_for_timing->append_pending_animation_event({ + .event = finish_event, + .animation = *this, .target = *this, - .scheduled_event_time = convert_a_timeline_time_to_an_origin_relative_time(associated_effect_end()) }); + .scheduled_event_time = convert_a_timeline_time_to_an_origin_relative_time(associated_effect_end()), + }); } // Otherwise, queue a task to dispatch finishEvent at animation. The task source for this task is the DOM // manipulation task source. diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 15bdb85c4a1..dcbe736bc09 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -2017,7 +2017,12 @@ void Document::dispatch_events_for_animation_if_necessary(JS::NonnullGCPtr(*animation); - if (auto target = effect->target(); target && target->paintable()) + + JS::GCPtr target = effect->target(); + if (!target) + return; + + if (target->paintable()) target->paintable()->set_needs_display(); auto previous_phase = effect->previous_phase(); @@ -2037,7 +2042,8 @@ void Document::dispatch_events_for_animation_if_necessary(JS::NonnullGCPtractive_time_using_fill(Bindings::FillMode::Both).value()); } } + effect->set_previous_phase(current_phase); + effect->set_previous_current_iteration(current_iteration); } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-the-fragment-identifier @@ -4238,8 +4246,8 @@ void Document::update_animations_and_send_events(Optional const& timesta // 6. Perform a stable sort of the animation events in events to dispatch as follows: auto sort_events_by_composite_order = [](auto const& a, auto const& b) { - auto& a_effect = verify_cast(*a.target->effect()); - auto& b_effect = verify_cast(*b.target->effect()); + auto& a_effect = verify_cast(*a.animation->effect()); + auto& b_effect = verify_cast(*b.animation->effect()); return Animations::KeyframeEffect::composite_order(a_effect, b_effect) < 0; }; @@ -4352,9 +4360,10 @@ void Document::remove_replaced_animations() // timeline with which animation is associated. if (auto document = animation->document_for_timing()) { PendingAnimationEvent pending_animation_event { - remove_event, - animation, - animation->timeline()->convert_a_timeline_time_to_an_origin_relative_time(init.timeline_time), + .event = remove_event, + .animation = animation, + .target = animation, + .scheduled_event_time = animation->timeline()->convert_a_timeline_time_to_an_origin_relative_time(init.timeline_time), }; document->append_pending_animation_event(pending_animation_event); } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 41f0f2e9a0e..50b19e7040b 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -599,7 +599,8 @@ public: struct PendingAnimationEvent { JS::NonnullGCPtr event; - JS::NonnullGCPtr target; + JS::NonnullGCPtr animation; + JS::NonnullGCPtr target; Optional scheduled_event_time; }; void append_pending_animation_event(PendingAnimationEvent const&);