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.
This commit is contained in:
Tim Ledbetter 2025-01-24 20:10:20 +00:00 committed by Luke Wilde
parent 5372d07c5c
commit 8b5a25e47f
Notes: github-actions[bot] 2025-01-28 11:32:54 +00:00
2 changed files with 9 additions and 7 deletions

View file

@ -11,6 +11,7 @@
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/HighResolutionTime/Performance.h>
#include <LibWeb/HighResolutionTime/TimeOrigin.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::Animations {
@ -22,10 +23,9 @@ GC::Ref<DocumentTimeline> DocumentTimeline::create(JS::Realm& realm, DOM::Docume
auto timeline = realm.create<DocumentTimeline>(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<HTML::WindowOrWorkerGlobalScopeMixin*>(&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;

View file

@ -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);
}