LibWeb: Prevent running permanently unrunnable tasks in EventLoop

In `::spin_processing_tasks_with_source_until()`, we would first take a
set of tasks based on a filter, and then run them one by one. If there
was more than one task matched and put in that vector, they could
interfere with each other's runnability by making later tasks
permanently unrunnable.

The `::take_tasks_matching()` API is a footgun - remove it in favor of
an API that takes tasks one by one, performing the runnability check
just in time.
This commit is contained in:
Jelle Raaijmakers
2026-03-26 16:14:14 +01:00
committed by Jelle Raaijmakers
parent f5d76ec2d0
commit a5000d07c0
Notes: github-actions[bot] 2026-03-26 17:49:49 +00:00
4 changed files with 22 additions and 29 deletions

View File

@@ -131,16 +131,15 @@ void EventLoop::spin_processing_tasks_with_source_until(Task::Source source, GC:
Platform::EventLoopPlugin::the().spin_until(GC::create_function(heap(), [this, source, goal_condition] {
if (goal_condition->function()())
return true;
if (m_task_queue->has_runnable_tasks()) {
auto tasks = m_task_queue->take_tasks_matching([&](auto& task) {
return task.source() == source && task.is_runnable();
});
while (auto task = m_task_queue->take_first_runnable_matching([&](auto& candidate_task) {
return candidate_task.source() == source;
})) {
m_currently_running_task = task.ptr();
task->execute();
m_currently_running_task = nullptr;
for (auto& task : tasks) {
m_currently_running_task = task.ptr();
task->execute();
m_currently_running_task = nullptr;
}
if (goal_condition->function()())
break;
}
// FIXME: Remove the platform event loop plugin so that this doesn't look out of place