mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-19 02:10:26 +00:00
Previously, destroyed-document tasks were forced to be runnable to prevent them from leaking in the task queue. Instead, discard them during task selection so their callbacks never run with stale state. This used to cause issues with a couple of `spin_until()`s in the past, but since we've removed some of them that had to do with the document lifecycle, let's see if we can stick closer to the spec now.
85 lines
2 KiB
C++
85 lines
2 KiB
C++
/*
|
|
* Copyright (c) 2021-2024, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/IDAllocator.h>
|
|
#include <LibWeb/DOM/Document.h>
|
|
#include <LibWeb/HTML/EventLoop/Task.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
GC_DEFINE_ALLOCATOR(Task);
|
|
|
|
static IDAllocator s_unique_task_source_allocator { static_cast<int>(Task::Source::UniqueTaskSourceStart) };
|
|
|
|
[[nodiscard]] static TaskID allocate_task_id()
|
|
{
|
|
static u64 next_task_id = 1;
|
|
return next_task_id++;
|
|
}
|
|
|
|
GC::Ref<Task> Task::create(JS::VM& vm, Source source, GC::Ptr<DOM::Document const> document, GC::Ref<GC::Function<void()>> steps)
|
|
{
|
|
return vm.heap().allocate<Task>(source, document, move(steps));
|
|
}
|
|
|
|
Task::Task(Source source, GC::Ptr<DOM::Document const> document, GC::Ref<GC::Function<void()>> steps)
|
|
: m_id(allocate_task_id())
|
|
, m_source(source)
|
|
, m_steps(steps)
|
|
, m_document(document)
|
|
{
|
|
}
|
|
|
|
Task::~Task() = default;
|
|
|
|
void Task::visit_edges(Visitor& visitor)
|
|
{
|
|
Base::visit_edges(visitor);
|
|
visitor.visit(m_steps);
|
|
visitor.visit(m_document);
|
|
}
|
|
|
|
void Task::execute()
|
|
{
|
|
m_steps->function()();
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-task-runnable
|
|
bool Task::is_runnable() const
|
|
{
|
|
// A task is runnable if its document is either null or fully active.
|
|
return !m_document || m_document->is_fully_active();
|
|
}
|
|
|
|
DOM::Document const* Task::document() const
|
|
{
|
|
return m_document.ptr();
|
|
}
|
|
|
|
UniqueTaskSource::UniqueTaskSource()
|
|
: source(static_cast<Task::Source>(s_unique_task_source_allocator.allocate()))
|
|
{
|
|
}
|
|
|
|
UniqueTaskSource::~UniqueTaskSource()
|
|
{
|
|
s_unique_task_source_allocator.deallocate(static_cast<int>(source));
|
|
}
|
|
|
|
NonnullRefPtr<ParallelQueue> ParallelQueue::create()
|
|
{
|
|
return adopt_ref(*new (nothrow) ParallelQueue);
|
|
}
|
|
|
|
TaskID ParallelQueue::enqueue(GC::Ref<GC::Function<void()>> algorithm)
|
|
{
|
|
auto& event_loop = HTML::main_thread_event_loop();
|
|
auto task = HTML::Task::create(event_loop.vm(), m_task_source.source, nullptr, algorithm);
|
|
event_loop.task_queue().add(task);
|
|
return task->id();
|
|
}
|
|
|
|
}
|