ladybird/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h
Andreas Kling ad183e04d4 LibWeb: Store idle tasks separately from normal tasks
Idle callbacks are only appropriate when the event loop has no other
runnable work. TaskQueue previously stored idle tasks in the same FIFO
list as all other tasks, so an idle callback queued during an idle
period could still run ahead of later posted-message work.

Keep idle tasks in a separate queue and only select from it after all
normal runnable tasks have been considered. This keeps cleanup queued
with requestIdleCallback from racing React hydration on Shopify.
2026-05-13 20:54:10 +02:00

49 lines
1.2 KiB
C++

/*
* Copyright (c) 2021-2024, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Vector.h>
#include <LibJS/Heap/Cell.h>
#include <LibWeb/HTML/EventLoop/Task.h>
namespace Web::HTML {
class TaskQueue : public JS::Cell {
GC_CELL(TaskQueue, JS::Cell);
GC_DECLARE_ALLOCATOR(TaskQueue);
public:
explicit TaskQueue(HTML::EventLoop&);
virtual ~TaskQueue() override;
bool is_empty() const { return m_tasks.is_empty() && m_idle_tasks.is_empty(); }
bool has_runnable_tasks() const;
bool has_rendering_tasks() const;
void add(GC::Ref<HTML::Task>);
GC::Ptr<HTML::Task> take_first_runnable();
void enqueue(GC::Ref<HTML::Task> task) { add(task); }
GC::Ptr<HTML::Task> dequeue();
void remove_tasks_matching(Function<bool(HTML::Task const&)>);
GC::Ptr<Task> take_first_runnable_matching(Function<bool(HTML::Task const&)>);
Task const* last_added_task() const;
private:
virtual void visit_edges(Visitor&) override;
GC::Ref<HTML::EventLoop> m_event_loop;
Vector<GC::Ref<HTML::Task>> m_tasks;
Vector<GC::Ref<HTML::Task>> m_idle_tasks;
GC::Ptr<HTML::Task const> m_last_added_task;
};
}