Pārlūkot izejas kodu

LibWeb: Run queued promise jobs after callbacks

We now run queued promise jobs after calling event handler, timer, and
requestAnimationFrame() callbacks - this is a bit ad-hoc, but I don't
want to switch LibWeb to use an event loop right now - this works just
fine, too.
We might want to revisit this at a later point and do tasks and
microtasks properly.
Linus Groh 4 gadi atpakaļ
vecāks
revīzija
ade3adcc7a

+ 6 - 2
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -543,8 +543,12 @@ Color Document::visited_link_color() const
 
 JS::Interpreter& Document::interpreter()
 {
-    if (!m_interpreter)
-        m_interpreter = JS::Interpreter::create<Bindings::WindowObject>(Bindings::main_thread_vm(), *m_window);
+    if (!m_interpreter) {
+        auto& vm = Bindings::main_thread_vm();
+        // TODO: Hook up vm.on_promise_unhandled_rejection and vm.on_promise_rejection_handled
+        // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#promise_rejection_events
+        m_interpreter = JS::Interpreter::create<Bindings::WindowObject>(vm, *m_window);
+    }
     return *m_interpreter;
 }
 

+ 2 - 0
Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp

@@ -114,6 +114,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<EventTarget::EventListen
             vm.clear_exception();
             // FIXME: Set legacyOutputDidListenersThrowFlag if given. (Only used by IndexedDB currently)
         }
+        vm.run_queued_promise_jobs();
+        VERIFY(!vm.exception());
 
         event.set_in_passive_listener(false);
         if (is<Bindings::WindowObject>(global)) {

+ 4 - 0
Userland/Libraries/LibWeb/DOM/Window.cpp

@@ -109,6 +109,8 @@ void Window::timer_did_fire(Badge<Timer>, Timer& timer)
     [[maybe_unused]] auto rc = vm.call(timer.callback(), wrapper());
     if (vm.exception())
         vm.clear_exception();
+    vm.run_queued_promise_jobs();
+    VERIFY(!vm.exception());
 }
 
 i32 Window::allocate_timer_id(Badge<Timer>)
@@ -143,6 +145,8 @@ i32 Window::request_animation_frame(JS::Function& callback)
         [[maybe_unused]] auto rc = vm.call(function, JS::js_undefined(), JS::Value(fake_timestamp));
         if (vm.exception())
             vm.clear_exception();
+        vm.run_queued_promise_jobs();
+        VERIFY(!vm.exception());
         GUI::DisplayLink::unregister_callback(link_id);
     });