From 8b5a25e47f4aa839d49a8b33814d8f224457b7fd Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Fri, 24 Jan 2025 20:10:20 +0000 Subject: [PATCH] LibWeb: Generate correct timestamp values when updating animations Previously, we were generating timestamps relative to the current time of the monotonic clock. We now generate timestamps relative to the event loop's last render opportunity time, per the spec. --- Libraries/LibWeb/Animations/DocumentTimeline.cpp | 8 ++++---- Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Libraries/LibWeb/Animations/DocumentTimeline.cpp b/Libraries/LibWeb/Animations/DocumentTimeline.cpp index d20670945b23..9f2a74ff5c4b 100644 --- a/Libraries/LibWeb/Animations/DocumentTimeline.cpp +++ b/Libraries/LibWeb/Animations/DocumentTimeline.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Web::Animations { @@ -22,10 +23,9 @@ GC::Ref DocumentTimeline::create(JS::Realm& realm, DOM::Docume auto timeline = realm.create(realm, document, origin_time); 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(); + // The document hasn't processed an animation frame yet, we use the navigation start time, which is either the time + // that the previous document started to be unloaded or the creation time of the current document. + current_time = HighResolutionTime::relative_high_resolution_time(document.load_timing_info().navigation_start_time, realm.global_object()); } timeline->set_current_time(current_time); return timeline; diff --git a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index cb3090682e70..0816431c39ae 100644 --- a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -261,7 +261,8 @@ void EventLoop::update_the_rendering() m_is_running_rendering_task = false; }; - // FIXME: 1. Let frameTimestamp be eventLoop's last render opportunity time. + // 1. Let frameTimestamp be eventLoop's last render opportunity time. + auto frame_timestamp = m_last_render_opportunity_time; // FIXME: 2. Let docs be all fully active Document objects whose relevant agent's event loop is eventLoop, sorted arbitrarily except that the following conditions must be met: // 3. Filter non-renderable documents: Remove from docs any Document object doc for which any of the following are true: @@ -313,7 +314,7 @@ void EventLoop::update_the_rendering() // 11. For each doc of docs, update animations and send events for doc, passing in relative high resolution time given frameTimestamp and doc's relevant global object as the timestamp [WEBANIMATIONS] for (auto& document : docs) { - document->update_animations_and_send_events(document->window()->performance()->now()); + document->update_animations_and_send_events(HighResolutionTime::relative_high_resolution_time(frame_timestamp, relevant_global_object(*document))); }; // FIXME: 12. For each doc of docs, run the fullscreen steps for doc. [FULLSCREEN] @@ -321,8 +322,8 @@ void EventLoop::update_the_rendering() // FIXME: 13. For each doc of docs, if the user agent detects that the backing storage associated with a CanvasRenderingContext2D or an OffscreenCanvasRenderingContext2D, context, has been lost, then it must run the context lost steps for each such context: // 14. For each doc of docs, run the animation frame callbacks for doc, passing in the relative high resolution time given frameTimestamp and doc's relevant global object as the timestamp. - auto now = HighResolutionTime::unsafe_shared_current_time(); for (auto& document : docs) { + auto now = HighResolutionTime::relative_high_resolution_time(frame_timestamp, relevant_global_object(*document)); run_animation_frame_callbacks(*document, now); } @@ -398,6 +399,7 @@ void EventLoop::update_the_rendering() // 19. For each doc of docs, run the update intersection observations steps for doc, passing in the relative high resolution time given now and doc's relevant global object as the timestamp. [INTERSECTIONOBSERVER] for (auto& document : docs) { + auto now = HighResolutionTime::relative_high_resolution_time(frame_timestamp, relevant_global_object(*document)); document->run_the_update_intersection_observations_steps(now); }