/* * Copyright (c) 2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ #include #include namespace Web::HTML { JS_DEFINE_ALLOCATOR(SessionHistoryTraversalQueue); JS_DEFINE_ALLOCATOR(SessionHistoryTraversalQueueEntry); JS::NonnullGCPtr SessionHistoryTraversalQueueEntry::create(JS::VM& vm, Function steps, JS::GCPtr target_navigable) { return vm.heap().allocate_without_realm(JS::create_heap_function(vm.heap(), move(steps)), target_navigable); } void SessionHistoryTraversalQueueEntry::visit_edges(JS::Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_steps); visitor.visit(m_target_navigable); } SessionHistoryTraversalQueue::SessionHistoryTraversalQueue() { m_timer = Core::Timer::create_single_shot(0, [this] { if (m_is_task_running && m_queue.size() > 0) { m_timer->start(); return; } while (m_queue.size() > 0) { m_is_task_running = true; auto entry = m_queue.take_first(); entry->execute_steps(); m_is_task_running = false; } }).release_value_but_fixme_should_propagate_errors(); } void SessionHistoryTraversalQueue::visit_edges(JS::Cell::Visitor& visitor) { Base::visit_edges(visitor); for (auto const& entry : m_queue) { visitor.visit(entry); } } void SessionHistoryTraversalQueue::append(Function steps) { m_queue.append(SessionHistoryTraversalQueueEntry::create(vm(), move(steps), nullptr)); if (!m_timer->is_active()) { m_timer->start(); } } void SessionHistoryTraversalQueue::append_sync(Function steps, JS::GCPtr target_navigable) { m_queue.append(SessionHistoryTraversalQueueEntry::create(vm(), move(steps), target_navigable)); if (!m_timer->is_active()) { m_timer->start(); } } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#sync-navigations-jump-queue JS::GCPtr SessionHistoryTraversalQueue::first_synchronous_navigation_steps_with_target_navigable_not_contained_in(Vector> const& list) { auto index = m_queue.find_first_index_if([&list](auto const& entry) -> bool { return (entry->target_navigable() != nullptr) && !list.contains_slow(entry->target_navigable()); }); if (index.has_value()) return m_queue.take(*index); return {}; } }