Browse Source

LibWeb: Add a bare-bones HTML event loop with a task queue

This patch attaches a HTML::EventLoop to the main thread JS::VM used
for JavaScript bindings in the web engine.

The goal here is to model the various task scheduling mechanisms of the
HTML specification.
Andreas Kling 3 years ago
parent
commit
ecb72f3b57

+ 1 - 1
Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp

@@ -13,7 +13,7 @@ JS::VM& main_thread_vm()
 {
 {
     static RefPtr<JS::VM> vm;
     static RefPtr<JS::VM> vm;
     if (!vm)
     if (!vm)
-        vm = JS::VM::create();
+        vm = JS::VM::create(make<WebEngineCustomData>());
     return *vm;
     return *vm;
 }
 }
 
 

+ 7 - 0
Userland/Libraries/LibWeb/Bindings/MainThreadVM.h

@@ -7,9 +7,16 @@
 #pragma once
 #pragma once
 
 
 #include <LibJS/Forward.h>
 #include <LibJS/Forward.h>
+#include <LibWeb/HTML/EventLoop/EventLoop.h>
 
 
 namespace Web::Bindings {
 namespace Web::Bindings {
 
 
+struct WebEngineCustomData final : public JS::VM::CustomData {
+    virtual ~WebEngineCustomData() override { }
+
+    HTML::EventLoop event_loop;
+};
+
 JS::VM& main_thread_vm();
 JS::VM& main_thread_vm();
 
 
 }
 }

+ 3 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -71,6 +71,9 @@ set(SOURCES
     HTML/BrowsingContextContainer.cpp
     HTML/BrowsingContextContainer.cpp
     HTML/CanvasRenderingContext2D.cpp
     HTML/CanvasRenderingContext2D.cpp
     HTML/DOMParser.cpp
     HTML/DOMParser.cpp
+    HTML/EventLoop/EventLoop.cpp
+    HTML/EventLoop/Task.cpp
+    HTML/EventLoop/TaskQueue.cpp
     HTML/EventNames.cpp
     HTML/EventNames.cpp
     HTML/FormAssociatedElement.cpp
     HTML/FormAssociatedElement.cpp
     HTML/GlobalEventHandlers.cpp
     HTML/GlobalEventHandlers.cpp

+ 26 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp

@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/VM.h>
+#include <LibWeb/Bindings/MainThreadVM.h>
+#include <LibWeb/HTML/EventLoop/EventLoop.h>
+
+namespace Web::HTML {
+
+EventLoop::EventLoop()
+{
+}
+
+EventLoop::~EventLoop()
+{
+}
+
+EventLoop& main_thread_event_loop()
+{
+    return static_cast<Bindings::WebEngineCustomData*>(Bindings::main_thread_vm().custom_data())->event_loop;
+}
+
+}

+ 28 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Function.h>
+#include <LibWeb/HTML/EventLoop/TaskQueue.h>
+
+namespace Web::HTML {
+
+class EventLoop {
+public:
+    EventLoop();
+    ~EventLoop();
+
+    TaskQueue& task_queue() { return m_task_queue; }
+    TaskQueue const& task_queue() const { return m_task_queue; }
+
+private:
+    TaskQueue m_task_queue;
+};
+
+EventLoop& main_thread_event_loop();
+
+}

+ 27 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/Task.cpp

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/HTML/EventLoop/Task.h>
+
+namespace Web::HTML {
+
+Task::Task(DOM::Document* document, Function<void()> steps)
+    : m_steps(move(steps))
+    , m_document(document)
+{
+}
+
+Task::~Task()
+{
+}
+
+void Task::execute()
+{
+    m_steps();
+}
+
+}

+ 36 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/Task.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Function.h>
+#include <AK/NonnullOwnPtr.h>
+#include <AK/RefPtr.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::HTML {
+
+class Task {
+public:
+    static NonnullOwnPtr<Task> create(DOM::Document* document, Function<void()> steps)
+    {
+        return adopt_own(*new Task(document, move(steps)));
+    }
+    ~Task();
+
+    void execute();
+
+    DOM::Document* document() { return m_document; }
+    DOM::Document const* document() const { return m_document; }
+
+private:
+    Task(DOM::Document*, Function<void()> steps);
+
+    Function<void()> m_steps;
+    RefPtr<DOM::Document> m_document;
+};
+
+}

+ 24 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp

@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/HTML/EventLoop/TaskQueue.h>
+
+namespace Web::HTML {
+
+TaskQueue::TaskQueue()
+{
+}
+
+TaskQueue::~TaskQueue()
+{
+}
+
+void TaskQueue::add(NonnullOwnPtr<Task> task)
+{
+    m_tasks.enqueue(move(task));
+}
+
+}

+ 28 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/TaskQueue.h

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Queue.h>
+#include <LibWeb/HTML/EventLoop/Task.h>
+
+namespace Web::HTML {
+
+class TaskQueue {
+public:
+    TaskQueue();
+    ~TaskQueue();
+
+    bool is_empty() const { return m_tasks.is_empty(); }
+
+    void add(NonnullOwnPtr<HTML::Task>);
+    OwnPtr<HTML::Task> take_first_runnable() { return m_tasks.dequeue(); }
+
+private:
+    Queue<NonnullOwnPtr<HTML::Task>> m_tasks;
+};
+
+}