Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibWeb/HTML/SessionHistoryTraversalQueue.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <LibWeb/HTML/Navigable.h>
8
#include <LibWeb/HTML/SessionHistoryTraversalQueue.h>
9
10
namespace Web::HTML {
11
12
JS_DEFINE_ALLOCATOR(SessionHistoryTraversalQueue);
13
JS_DEFINE_ALLOCATOR(SessionHistoryTraversalQueueEntry);
14
15
JS::NonnullGCPtr<SessionHistoryTraversalQueueEntry> SessionHistoryTraversalQueueEntry::create(JS::VM& vm, JS::NonnullGCPtr<JS::HeapFunction<void()>> steps, JS::GCPtr<HTML::Navigable> target_navigable)
16
0
{
17
0
    return vm.heap().allocate_without_realm<SessionHistoryTraversalQueueEntry>(steps, target_navigable);
18
0
}
19
20
void SessionHistoryTraversalQueueEntry::visit_edges(JS::Cell::Visitor& visitor)
21
0
{
22
0
    Base::visit_edges(visitor);
23
0
    visitor.visit(m_steps);
24
0
    visitor.visit(m_target_navigable);
25
0
}
26
27
SessionHistoryTraversalQueue::SessionHistoryTraversalQueue()
28
0
{
29
0
    m_timer = Core::Timer::create_single_shot(0, [this] {
30
0
        if (m_is_task_running && m_queue.size() > 0) {
31
0
            m_timer->start();
32
0
            return;
33
0
        }
34
0
        while (m_queue.size() > 0) {
35
0
            m_is_task_running = true;
36
0
            auto entry = m_queue.take_first();
37
0
            entry->execute_steps();
38
0
            m_is_task_running = false;
39
0
        }
40
0
    });
41
0
}
42
43
void SessionHistoryTraversalQueue::visit_edges(JS::Cell::Visitor& visitor)
44
0
{
45
0
    Base::visit_edges(visitor);
46
0
    visitor.visit(m_queue);
47
0
}
48
49
void SessionHistoryTraversalQueue::append(JS::NonnullGCPtr<JS::HeapFunction<void()>> steps)
50
0
{
51
0
    m_queue.append(SessionHistoryTraversalQueueEntry::create(vm(), steps, nullptr));
52
0
    if (!m_timer->is_active()) {
53
0
        m_timer->start();
54
0
    }
55
0
}
56
57
void SessionHistoryTraversalQueue::append_sync(JS::NonnullGCPtr<JS::HeapFunction<void()>> steps, JS::GCPtr<Navigable> target_navigable)
58
0
{
59
0
    m_queue.append(SessionHistoryTraversalQueueEntry::create(vm(), steps, target_navigable));
60
0
    if (!m_timer->is_active()) {
61
0
        m_timer->start();
62
0
    }
63
0
}
64
65
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#sync-navigations-jump-queue
66
JS::GCPtr<SessionHistoryTraversalQueueEntry> SessionHistoryTraversalQueue::first_synchronous_navigation_steps_with_target_navigable_not_contained_in(HashTable<JS::NonnullGCPtr<Navigable>> const& set)
67
0
{
68
0
    auto index = m_queue.find_first_index_if([&set](auto const& entry) -> bool {
69
0
        return (entry->target_navigable() != nullptr) && !set.contains(*entry->target_navigable());
70
0
    });
71
0
    if (index.has_value())
72
0
        return m_queue.take(*index);
73
0
    return {};
74
0
}
75
76
}