LibWeb: Use HeapFunction for EventLoopPlugin::spin_until

This commit is contained in:
Shannon Booth 2024-10-31 01:06:56 +13:00 committed by Alexander Kalenik
parent de1a805898
commit 7487a782db
Notes: github-actions[bot] 2024-10-30 19:57:14 +00:00
15 changed files with 29 additions and 26 deletions

View file

@ -101,9 +101,9 @@ ThrowCompletionOr<Value> 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.

View file

@ -42,7 +42,7 @@ public:
struct CustomData {
virtual ~CustomData() = default;
virtual void spin_event_loop_until(JS::SafeFunction<bool()> goal_condition) = 0;
virtual void spin_event_loop_until(JS::Handle<JS::HeapFunction<bool()>> goal_condition) = 0;
};
static ErrorOr<NonnullRefPtr<VM>> create(OwnPtr<CustomData> = {});

View file

@ -658,7 +658,7 @@ NonnullOwnPtr<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM& vm, Fu
return realm_execution_context;
}
void WebEngineCustomData::spin_event_loop_until(JS::SafeFunction<bool()> goal_condition)
void WebEngineCustomData::spin_event_loop_until(JS::Handle<JS::HeapFunction<bool()>> goal_condition)
{
Platform::EventLoopPlugin::the().spin_until(move(goal_condition));
}

View file

@ -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<bool()> goal_condition) override;
virtual void spin_event_loop_until(JS::Handle<JS::HeapFunction<bool()>> goal_condition) override;
JS::Handle<HTML::EventLoop> event_loop;

View file

@ -157,9 +157,9 @@ WebIDL::ExceptionOr<void> 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]

View file

@ -92,7 +92,7 @@ void EventLoop::spin_until(JS::SafeFunction<bool()> 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<bool()> 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;

View file

@ -324,11 +324,11 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> 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.

View file

@ -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());

View file

@ -8,6 +8,7 @@
#include <AK/Forward.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Heap/HeapFunction.h>
#include <LibJS/SafeFunction.h>
#include <LibWeb/Forward.h>
@ -20,7 +21,7 @@ public:
virtual ~EventLoopPlugin();
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) = 0;
virtual void spin_until(JS::Handle<JS::HeapFunction<bool()>> goal_condition) = 0;
virtual void deferred_invoke(ESCAPING JS::SafeFunction<void()>) = 0;
virtual JS::NonnullGCPtr<Timer> create_timer(JS::Heap&) = 0;
virtual void quit() = 0;

View file

@ -14,9 +14,11 @@ namespace Web::Platform {
EventLoopPluginSerenity::EventLoopPluginSerenity() = default;
EventLoopPluginSerenity::~EventLoopPluginSerenity() = default;
void EventLoopPluginSerenity::spin_until(JS::SafeFunction<bool()> goal_condition)
void EventLoopPluginSerenity::spin_until(JS::Handle<JS::HeapFunction<bool()>> 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<void()> function)

View file

@ -15,7 +15,7 @@ public:
EventLoopPluginSerenity();
virtual ~EventLoopPluginSerenity() override;
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) override;
virtual void spin_until(JS::Handle<JS::HeapFunction<bool()>> goal_condition) override;
virtual void deferred_invoke(JS::SafeFunction<void()>) override;
virtual JS::NonnullGCPtr<Timer> create_timer(JS::Heap&) override;
virtual void quit() override;

View file

@ -470,9 +470,9 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteStr
return;
auto& script_promise = static_cast<JS::Promise&>(*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)

View file

@ -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();
}

View file

@ -942,9 +942,9 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
}
// FIXME: This is not exactly correct, as it allows the HTML event loop to continue executing tasks.
Platform::EventLoopPlugin::the().spin_until([&]() {
Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [&]() {
return processed_response || did_time_out;
});
}));
// 6. If processedResponse is false, then set thiss timed out flag and terminate thiss fetch controller.
if (!processed_response) {

View file

@ -2613,14 +2613,14 @@ ErrorOr<JsonArray, Web::WebDriver::Error> 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);