summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-10-03 15:38:11 +0200
committerAndreas Kling <kling@serenityos.org>2021-10-03 16:42:34 +0200
commitbbfde63f79b62080ade37051fc11a61ca132184f (patch)
treeb135f4de3ab23061705e6470adb159651e96831b /Userland
parent6283c098ad16a7005fac53b6c1c983dbbd3776a9 (diff)
downloadserenity-bbfde63f79b62080ade37051fc11a61ca132184f.zip
LibWeb: Only take runnable tasks from the HTML task queue
We were previously willing to execute tasks before they had become runnable.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp3
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp7
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/Task.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp11
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h6
5 files changed, 23 insertions, 6 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
index a8eb9e4315..3989fc4b0d 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
@@ -90,9 +90,8 @@ void EventLoop::process()
// 1. Let taskQueue be one of the event loop's task queues, chosen in an implementation-defined manner, with the constraint that the chosen task queue must contain at least one runnable task. If there is no such task queue, then jump to the microtasks step below.
auto& task_queue = m_task_queue;
- if (!task_queue.is_empty()) {
+ if (auto oldest_task = task_queue.take_first_runnable()) {
// 2. Let oldestTask be the first runnable task in taskQueue, and remove it from taskQueue.
- auto oldest_task = task_queue.take_first_runnable();
// 3. Set the event loop's currently running task to oldestTask.
m_currently_running_task = oldest_task.ptr();
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp
index ab282941ae..375220bd65 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp
@@ -25,4 +25,11 @@ void Task::execute()
m_steps();
}
+// https://html.spec.whatwg.org/#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();
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h
index 9b9402f3cc..51947f58d3 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/Task.h
@@ -40,6 +40,8 @@ public:
DOM::Document* document() { return m_document; }
DOM::Document const* document() const { return m_document; }
+ bool is_runnable() const;
+
private:
Task(Source, DOM::Document*, Function<void()> steps);
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp
index 50c8598d67..51fb07df29 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp
@@ -20,8 +20,17 @@ TaskQueue::~TaskQueue()
void TaskQueue::add(NonnullOwnPtr<Task> task)
{
- m_tasks.enqueue(move(task));
+ m_tasks.append(move(task));
m_event_loop.schedule();
}
+OwnPtr<Task> TaskQueue::take_first_runnable()
+{
+ for (size_t i = 0; i < m_tasks.size(); ++i) {
+ if (m_tasks[i]->is_runnable())
+ return m_tasks.take(i);
+ }
+ return nullptr;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h b/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h
index 68e971b334..e7638b07bb 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h
@@ -19,20 +19,20 @@ public:
bool is_empty() const { return m_tasks.is_empty(); }
void add(NonnullOwnPtr<HTML::Task>);
- OwnPtr<HTML::Task> take_first_runnable() { return m_tasks.dequeue(); }
+ OwnPtr<HTML::Task> take_first_runnable();
void enqueue(NonnullOwnPtr<HTML::Task> task) { add(move(task)); }
OwnPtr<HTML::Task> dequeue()
{
if (m_tasks.is_empty())
return {};
- return m_tasks.dequeue();
+ return m_tasks.take_first();
}
private:
HTML::EventLoop& m_event_loop;
- Queue<NonnullOwnPtr<HTML::Task>> m_tasks;
+ Vector<NonnullOwnPtr<HTML::Task>> m_tasks;
};
}