Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Function.h>
10
#include <AK/WeakPtr.h>
11
#include <LibCore/Forward.h>
12
#include <LibJS/Forward.h>
13
#include <LibJS/SafeFunction.h>
14
#include <LibWeb/HTML/EventLoop/TaskQueue.h>
15
16
namespace Web::HTML {
17
18
class EventLoop : public JS::Cell {
19
    JS_CELL(EventLoop, JS::Cell);
20
    JS_DECLARE_ALLOCATOR(EventLoop);
21
22
public:
23
    enum class Type {
24
        // https://html.spec.whatwg.org/multipage/webappapis.html#window-event-loop
25
        Window,
26
        // https://html.spec.whatwg.org/multipage/webappapis.html#worker-event-loop
27
        Worker,
28
        // https://html.spec.whatwg.org/multipage/webappapis.html#worklet-event-loop
29
        Worklet,
30
    };
31
32
    virtual ~EventLoop() override;
33
34
0
    Type type() const { return m_type; }
35
36
0
    TaskQueue& task_queue() { return *m_task_queue; }
37
0
    TaskQueue const& task_queue() const { return *m_task_queue; }
38
39
0
    TaskQueue& microtask_queue() { return *m_microtask_queue; }
40
0
    TaskQueue const& microtask_queue() const { return *m_microtask_queue; }
41
42
    void spin_until(JS::SafeFunction<bool()> goal_condition);
43
    void spin_processing_tasks_with_source_until(Task::Source, JS::SafeFunction<bool()> goal_condition);
44
    void process();
45
46
    // https://html.spec.whatwg.org/multipage/browsing-the-web.html#termination-nesting-level
47
0
    size_t termination_nesting_level() const { return m_termination_nesting_level; }
48
0
    void increment_termination_nesting_level() { ++m_termination_nesting_level; }
49
0
    void decrement_termination_nesting_level() { --m_termination_nesting_level; }
50
51
0
    Task const* currently_running_task() const { return m_currently_running_task; }
52
53
    void schedule();
54
55
    void perform_a_microtask_checkpoint();
56
57
    void register_document(Badge<DOM::Document>, DOM::Document&);
58
    void unregister_document(Badge<DOM::Document>, DOM::Document&);
59
60
    Vector<JS::Handle<DOM::Document>> documents_in_this_event_loop() const;
61
62
    Vector<JS::Handle<HTML::Window>> same_loop_windows() const;
63
64
    void push_onto_backup_incumbent_settings_object_stack(Badge<EnvironmentSettingsObject>, EnvironmentSettingsObject& environment_settings_object);
65
    void pop_backup_incumbent_settings_object_stack(Badge<EnvironmentSettingsObject>);
66
    EnvironmentSettingsObject& top_of_backup_incumbent_settings_object_stack();
67
0
    bool is_backup_incumbent_settings_object_stack_empty() const { return m_backup_incumbent_settings_object_stack.is_empty(); }
68
69
    void register_environment_settings_object(Badge<EnvironmentSettingsObject>, EnvironmentSettingsObject&);
70
    void unregister_environment_settings_object(Badge<EnvironmentSettingsObject>, EnvironmentSettingsObject&);
71
72
    double compute_deadline() const;
73
74
    // https://html.spec.whatwg.org/multipage/webappapis.html#pause
75
0
    void set_execution_paused(bool execution_paused) { m_execution_paused = execution_paused; }
76
0
    bool execution_paused() const { return m_execution_paused; }
77
78
private:
79
    explicit EventLoop(Type);
80
81
    virtual void visit_edges(Visitor&) override;
82
83
    Type m_type { Type::Window };
84
85
    JS::GCPtr<TaskQueue> m_task_queue;
86
    JS::GCPtr<TaskQueue> m_microtask_queue;
87
88
    // https://html.spec.whatwg.org/multipage/webappapis.html#currently-running-task
89
    JS::GCPtr<Task> m_currently_running_task { nullptr };
90
91
    // https://html.spec.whatwg.org/multipage/webappapis.html#last-render-opportunity-time
92
    double m_last_render_opportunity_time { 0 };
93
    // https://html.spec.whatwg.org/multipage/webappapis.html#last-idle-period-start-time
94
    double m_last_idle_period_start_time { 0 };
95
96
    RefPtr<Platform::Timer> m_system_event_loop_timer;
97
98
    // https://html.spec.whatwg.org/#performing-a-microtask-checkpoint
99
    bool m_performing_a_microtask_checkpoint { false };
100
101
    Vector<WeakPtr<DOM::Document>> m_documents;
102
103
    // Used to implement step 4 of "perform a microtask checkpoint".
104
    // NOTE: These are weak references! ESO registers and unregisters itself from the event loop manually.
105
    Vector<RawPtr<EnvironmentSettingsObject>> m_related_environment_settings_objects;
106
107
    // https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
108
    Vector<JS::NonnullGCPtr<EnvironmentSettingsObject>> m_backup_incumbent_settings_object_stack;
109
110
    // https://html.spec.whatwg.org/multipage/browsing-the-web.html#termination-nesting-level
111
    size_t m_termination_nesting_level { 0 };
112
113
    bool m_execution_paused { false };
114
115
    bool m_skip_event_loop_processing_steps { false };
116
117
    bool m_is_running_reflow_steps { false };
118
};
119
120
EventLoop& main_thread_event_loop();
121
TaskID queue_a_task(HTML::Task::Source, JS::GCPtr<EventLoop>, JS::GCPtr<DOM::Document>, JS::NonnullGCPtr<JS::HeapFunction<void()>> steps);
122
TaskID queue_global_task(HTML::Task::Source, JS::Object&, JS::NonnullGCPtr<JS::HeapFunction<void()>> steps);
123
void queue_a_microtask(DOM::Document const*, JS::NonnullGCPtr<JS::HeapFunction<void()>> steps);
124
void perform_a_microtask_checkpoint();
125
126
}