From 7487a782dbd529e35bf075cdaaa2e471742af51c Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Thu, 31 Oct 2024 01:06:56 +1300 Subject: [PATCH] LibWeb: Use HeapFunction for EventLoopPlugin::spin_until --- Userland/Libraries/LibJS/Runtime/Completion.cpp | 4 ++-- Userland/Libraries/LibJS/Runtime/VM.h | 2 +- Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp | 2 +- Userland/Libraries/LibWeb/Bindings/MainThreadVM.h | 2 +- Userland/Libraries/LibWeb/FileAPI/FileReader.cpp | 4 ++-- Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp | 8 ++++---- Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp | 4 ++-- Userland/Libraries/LibWeb/Page/Page.cpp | 4 ++-- Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h | 3 ++- .../Libraries/LibWeb/Platform/EventLoopPluginSerenity.cpp | 6 ++++-- .../Libraries/LibWeb/Platform/EventLoopPluginSerenity.h | 2 +- Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp | 4 ++-- Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp | 2 +- Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp | 4 ++-- Userland/Services/WebContent/WebDriverConnection.cpp | 4 ++-- 15 files changed, 29 insertions(+), 26 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Completion.cpp b/Userland/Libraries/LibJS/Runtime/Completion.cpp index 64605f542b6..f466893f8b5 100644 --- a/Userland/Libraries/LibJS/Runtime/Completion.cpp +++ b/Userland/Libraries/LibJS/Runtime/Completion.cpp @@ -101,9 +101,9 @@ ThrowCompletionOr await(VM& vm, Value value) // running all queued promise jobs. // Note: This is not used by LibJS itself, and is performed for the embedder (i.e. LibWeb). if (auto* custom_data = vm.custom_data()) { - custom_data->spin_event_loop_until([&] { + custom_data->spin_event_loop_until(create_heap_function(vm.heap(), [success] { return success.has_value(); - }); + })); } // 8. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context. diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index ee6a8a4b73d..373b67e6449 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -42,7 +42,7 @@ public: struct CustomData { virtual ~CustomData() = default; - virtual void spin_event_loop_until(JS::SafeFunction goal_condition) = 0; + virtual void spin_event_loop_until(JS::Handle> goal_condition) = 0; }; static ErrorOr> create(OwnPtr = {}); diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp index 0ab0ebe61dc..8e50e57a0d1 100644 --- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp +++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp @@ -658,7 +658,7 @@ NonnullOwnPtr create_a_new_javascript_realm(JS::VM& vm, Fu return realm_execution_context; } -void WebEngineCustomData::spin_event_loop_until(JS::SafeFunction goal_condition) +void WebEngineCustomData::spin_event_loop_until(JS::Handle> goal_condition) { Platform::EventLoopPlugin::the().spin_until(move(goal_condition)); } diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h index 7089ef2546b..e570194a0e2 100644 --- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h +++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.h @@ -38,7 +38,7 @@ struct CustomElementReactionsStack { struct WebEngineCustomData final : public JS::VM::CustomData { virtual ~WebEngineCustomData() override = default; - virtual void spin_event_loop_until(JS::SafeFunction goal_condition) override; + virtual void spin_event_loop_until(JS::Handle> goal_condition) override; JS::Handle event_loop; diff --git a/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp b/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp index f856495e7f9..29c225e89b5 100644 --- a/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/FileReader.cpp @@ -157,9 +157,9 @@ WebIDL::ExceptionOr FileReader::read_operation(Blob& blob, Type type, Opti // 1. Wait for chunkPromise to be fulfilled or rejected. // FIXME: Create spec issue to use WebIDL react to promise steps here instead of this custom logic - Platform::EventLoopPlugin::the().spin_until([&]() { + Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [promise]() { return promise->state() == JS::Promise::State::Fulfilled || promise->state() == JS::Promise::State::Rejected; - }); + })); // 2. If chunkPromise is fulfilled, and isFirstChunk is true, queue a task to fire a progress event called loadstart at fr. // NOTE: ISSUE 2 We might change loadstart to be dispatched synchronously, to align with XMLHttpRequest behavior. [Issue #119] diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index 4ce29d19347..f7a91c0c4f4 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -92,7 +92,7 @@ void EventLoop::spin_until(JS::SafeFunction goal_condition) // 2. Perform any steps that appear after this spin the event loop instance in the original algorithm. // NOTE: This is achieved by returning from the function. - Platform::EventLoopPlugin::the().spin_until([&] { + Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [&] { if (goal_condition()) return true; if (m_task_queue->has_runnable_tasks()) { @@ -101,7 +101,7 @@ void EventLoop::spin_until(JS::SafeFunction goal_condition) Core::EventLoop::current().wake(); } return goal_condition(); - }); + })); vm.restore_execution_context_stack(); @@ -120,7 +120,7 @@ void EventLoop::spin_processing_tasks_with_source_until(Task::Source source, JS: // NOTE: HTML event loop processing steps could run a task with arbitrary source m_skip_event_loop_processing_steps = true; - Platform::EventLoopPlugin::the().spin_until([&] { + Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [&] { if (goal_condition()) return true; if (m_task_queue->has_runnable_tasks()) { @@ -138,7 +138,7 @@ void EventLoop::spin_processing_tasks_with_source_until(Task::Source source, JS: // FIXME: Remove the platform event loop plugin so that this doesn't look out of place Core::EventLoop::current().wake(); return goal_condition(); - }); + })); m_skip_event_loop_processing_steps = false; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 13c8c9d066b..f808fefeecc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -324,11 +324,11 @@ WebIDL::ExceptionOr> HTMLImageElement::decode( // 2.2 Otherwise, in parallel wait for one of the following cases to occur, and perform the corresponding actions: Platform::EventLoopPlugin::the().deferred_invoke([this, promise, &realm, reject_if_document_not_fully_active, reject_if_current_request_state_broken] { - Platform::EventLoopPlugin::the().spin_until([&] { + Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [&] { auto state = this->current_request().state(); return !this->document().is_fully_active() || state == ImageRequest::State::Broken || state == ImageRequest::State::CompletelyAvailable; - }); + })); // 2.2.1 This img element's node document stops being fully active // 2.2.1 Reject promise with an "EncodingError" DOMException. diff --git a/Userland/Libraries/LibWeb/Page/Page.cpp b/Userland/Libraries/LibWeb/Page/Page.cpp index 36f2abcbcc0..60602a3c84e 100644 --- a/Userland/Libraries/LibWeb/Page/Page.cpp +++ b/Userland/Libraries/LibWeb/Page/Page.cpp @@ -269,9 +269,9 @@ static ResponseType spin_event_loop_until_dialog_closed(PageClient& client, Opti ScopeGuard guard { [&] { event_loop.set_execution_paused(false); } }; event_loop.set_execution_paused(true); - Web::Platform::EventLoopPlugin::the().spin_until([&]() { + Web::Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(event_loop.heap(), [&]() { return response.has_value() || !client.is_connection_open(); - }); + })); if (!client.is_connection_open()) { dbgln("WebContent client disconnected during {}. Exiting peacefully.", location.function_name()); diff --git a/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h b/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h index 303ca36efd9..d3ed6182c9f 100644 --- a/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h +++ b/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -20,7 +21,7 @@ public: virtual ~EventLoopPlugin(); - virtual void spin_until(JS::SafeFunction goal_condition) = 0; + virtual void spin_until(JS::Handle> goal_condition) = 0; virtual void deferred_invoke(ESCAPING JS::SafeFunction) = 0; virtual JS::NonnullGCPtr create_timer(JS::Heap&) = 0; virtual void quit() = 0; diff --git a/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.cpp b/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.cpp index 7e1e9a2eb04..c5acd37e78b 100644 --- a/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.cpp +++ b/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.cpp @@ -14,9 +14,11 @@ namespace Web::Platform { EventLoopPluginSerenity::EventLoopPluginSerenity() = default; EventLoopPluginSerenity::~EventLoopPluginSerenity() = default; -void EventLoopPluginSerenity::spin_until(JS::SafeFunction goal_condition) +void EventLoopPluginSerenity::spin_until(JS::Handle> goal_condition) { - Core::EventLoop::current().spin_until(move(goal_condition)); + Core::EventLoop::current().spin_until([goal_condition = move(goal_condition)]() { + return goal_condition->function()(); + }); } void EventLoopPluginSerenity::deferred_invoke(JS::SafeFunction function) diff --git a/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.h b/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.h index e6a9783d0ca..ff29ba267d2 100644 --- a/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.h +++ b/Userland/Libraries/LibWeb/Platform/EventLoopPluginSerenity.h @@ -15,7 +15,7 @@ public: EventLoopPluginSerenity(); virtual ~EventLoopPluginSerenity() override; - virtual void spin_until(JS::SafeFunction goal_condition) override; + virtual void spin_until(JS::Handle> goal_condition) override; virtual void deferred_invoke(JS::SafeFunction) override; virtual JS::NonnullGCPtr create_timer(JS::Heap&) override; virtual void quit() override; diff --git a/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp b/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp index 4e510047ba1..0d9ba610c1f 100644 --- a/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/ExecuteScript.cpp @@ -470,9 +470,9 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteStr return; auto& script_promise = static_cast(*script_promise_or_error.value()); - vm.custom_data()->spin_event_loop_until([&] { + vm.custom_data()->spin_event_loop_until(JS::create_heap_function(vm.heap(), [timer, &script_promise]() { return timer->is_timed_out() || script_promise.state() != JS::Promise::State::Pending; - }); + })); // 10. Upon fulfillment of scriptPromise with value v, resolve promise with value v. if (script_promise.state() == JS::Promise::State::Fulfilled) diff --git a/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp b/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp index a2f72c7a7fb..420b71c33fb 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp @@ -102,7 +102,7 @@ Response capture_element_screenshot(Painter const& painter, Page& page, DOM::Ele encoded_string_or_error = encode_canvas_element(canvas_or_error.release_value()); }); - Platform::EventLoopPlugin::the().spin_until([&]() { return encoded_string_or_error.has_value(); }); + Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(element.document().heap(), [&]() { return encoded_string_or_error.has_value(); })); return encoded_string_or_error.release_value(); } diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index 200ebfc91ec..f47033efb1a 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -942,9 +942,9 @@ WebIDL::ExceptionOr XMLHttpRequest::send(Optional WebDriverConnection::find(StartNodeGet return elements.release_value(); }; - Web::Platform::EventLoopPlugin::the().spin_until([&]() { + Web::Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(current_top_level_browsing_context()->heap(), [&]() { maybe_elements = try_to_find_element(); if (maybe_elements.is_error()) return true; // 6. If elements returned is empty and the current time is less than end time return to step 4. Otherwise, continue to the next step. return maybe_elements.value()->length() != 0 || MonotonicTime::now() >= end_time; - }); + })); auto elements = TRY(maybe_elements); VERIFY(elements);