diff --git a/Tests/LibWeb/Text/expected/WebAnimations/misc/DocumentTimeline.txt b/Tests/LibWeb/Text/expected/WebAnimations/misc/DocumentTimeline.txt new file mode 100644 index 0000000000..c98c32c778 --- /dev/null +++ b/Tests/LibWeb/Text/expected/WebAnimations/misc/DocumentTimeline.txt @@ -0,0 +1,3 @@ +new timeline time equals document timeline time: true +new timeline originTime defaults to 0: true +new timeline originTime offsets from document timeline: true diff --git a/Tests/LibWeb/Text/input/WebAnimations/misc/DocumentTimeline.html b/Tests/LibWeb/Text/input/WebAnimations/misc/DocumentTimeline.html new file mode 100644 index 0000000000..36e6f3a797 --- /dev/null +++ b/Tests/LibWeb/Text/input/WebAnimations/misc/DocumentTimeline.html @@ -0,0 +1,18 @@ + + + diff --git a/Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp b/Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp index cb1d2403f6..9571c47c43 100644 --- a/Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp +++ b/Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp @@ -20,9 +20,14 @@ JS_DEFINE_ALLOCATOR(DocumentTimeline); JS::NonnullGCPtr DocumentTimeline::create(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time) { auto timeline = realm.heap().allocate(realm, realm, document, origin_time); - auto* window_or_worker = dynamic_cast(&realm.global_object()); - VERIFY(window_or_worker); - timeline->set_current_time(window_or_worker->performance()->now()); + auto current_time = document.last_animation_frame_timestamp(); + if (!current_time.has_value()) { + // The document hasn't processed an animation frame yet, so just use the exact current time + auto* window_or_worker = dynamic_cast(&realm.global_object()); + VERIFY(window_or_worker); + current_time = window_or_worker->performance()->now(); + } + timeline->set_current_time(current_time); return timeline; } diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index de28809bea..3a1616ce74 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -4233,6 +4233,7 @@ void Document::update_animations_and_send_events(Optional const& timesta // - Running the update an animation’s finished state procedure for any animations whose current time has been // updated. // - Queueing animation events for any such animations. + m_last_animation_frame_timestamp = timestamp; for (auto const& timeline : m_associated_animation_timelines) timeline->set_current_time(timestamp); diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 6108a6cbf9..f049f717df 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -596,6 +596,7 @@ public: void restore_the_history_object_state(JS::NonnullGCPtr entry); JS::NonnullGCPtr timeline(); + auto const& last_animation_frame_timestamp() const { return m_last_animation_frame_timestamp; } void associate_with_timeline(JS::NonnullGCPtr); void disassociate_with_timeline(JS::NonnullGCPtr); @@ -889,6 +890,7 @@ private: // https://www.w3.org/TR/web-animations-1/#document-default-document-timeline JS::GCPtr m_default_timeline; + Optional m_last_animation_frame_timestamp; // https://www.w3.org/TR/web-animations-1/#pending-animation-event-queue Vector m_pending_animation_event_queue;