Coverage Report

Created: 2025-09-05 06:52

/src/serenity/Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>.
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <LibJS/Heap/Heap.h>
8
#include <LibJS/Runtime/Realm.h>
9
#include <LibWeb/Animations/DocumentTimeline.h>
10
#include <LibWeb/Bindings/DocumentTimelinePrototype.h>
11
#include <LibWeb/DOM/Document.h>
12
#include <LibWeb/HTML/Window.h>
13
#include <LibWeb/HighResolutionTime/Performance.h>
14
#include <LibWeb/WebIDL/ExceptionOr.h>
15
16
namespace Web::Animations {
17
18
JS_DEFINE_ALLOCATOR(DocumentTimeline);
19
20
JS::NonnullGCPtr<DocumentTimeline> DocumentTimeline::create(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time)
21
0
{
22
0
    auto timeline = realm.heap().allocate<DocumentTimeline>(realm, realm, document, origin_time);
23
0
    auto current_time = document.last_animation_frame_timestamp();
24
0
    if (!current_time.has_value()) {
25
        // The document hasn't processed an animation frame yet, so just use the exact current time
26
0
        auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object());
27
0
        VERIFY(window_or_worker);
28
0
        current_time = window_or_worker->performance()->now();
29
0
    }
30
0
    timeline->set_current_time(current_time);
31
0
    return timeline;
32
0
}
33
34
// https://www.w3.org/TR/web-animations-1/#dom-documenttimeline-documenttimeline
35
WebIDL::ExceptionOr<JS::NonnullGCPtr<DocumentTimeline>> DocumentTimeline::construct_impl(JS::Realm& realm, DocumentTimelineOptions options)
36
0
{
37
    // Creates a new DocumentTimeline. The Document with which the timeline is associated is the Document associated
38
    // with the Window that is the current global object.
39
0
    auto& window = verify_cast<HTML::Window>(realm.global_object());
40
0
    return create(realm, window.associated_document(), options.origin_time);
41
0
}
42
43
// https://www.w3.org/TR/web-animations-1/#ref-for-timeline-time-to-origin-relative-time
44
Optional<double> DocumentTimeline::convert_a_timeline_time_to_an_origin_relative_time(Optional<double> timeline_time)
45
0
{
46
    // To convert a timeline time, timeline time, to an origin-relative time for a document timeline, timeline, return
47
    // the sum of the timeline time and timeline’s origin time. If timeline is inactive, return an unresolved time
48
    // value.
49
0
    if (is_inactive() || !timeline_time.has_value())
50
0
        return {};
51
0
    return timeline_time.value() + m_origin_time;
52
0
}
53
54
// https://www.w3.org/TR/web-animations-1/#origin-time
55
void DocumentTimeline::set_current_time(Optional<double> current_time)
56
0
{
57
    // A document timeline is a type of timeline that is associated with a document and whose current time is calculated
58
    // as a fixed offset from the now timestamp provided each time the update animations and send events procedure is
59
    // run. This fixed offset is referred to as the document timeline’s origin time.
60
0
    if (!current_time.has_value())
61
0
        Base::set_current_time({});
62
0
    else
63
0
        Base::set_current_time(current_time.value() - m_origin_time);
64
65
    // After a document timeline becomes active, it is monotonically increasing.
66
0
    if (!is_inactive())
67
0
        VERIFY(is_monotonically_increasing());
68
0
}
69
70
// https://www.w3.org/TR/web-animations-1/#document-timelines
71
bool DocumentTimeline::is_inactive() const
72
0
{
73
    // A document timeline that is associated with a Document which is not an active document is also considered to be
74
    // inactive.
75
0
    return Base::is_inactive() || !associated_document()->is_active();
76
0
}
77
78
DocumentTimeline::DocumentTimeline(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time)
79
0
    : AnimationTimeline(realm)
80
0
    , m_origin_time(origin_time)
81
0
{
82
0
    set_associated_document(document);
83
0
}
84
85
void DocumentTimeline::initialize(JS::Realm& realm)
86
0
{
87
0
    Base::initialize(realm);
88
0
    WEB_SET_PROTOTYPE_FOR_INTERFACE(DocumentTimeline);
89
0
}
90
91
}