mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibWeb: Use HeapFunction for EventLoopPlugin::spin_until
This commit is contained in:
parent
de1a805898
commit
7487a782db
Notes:
github-actions[bot]
2024-10-30 19:57:14 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/7487a782dbd Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2062 Reviewed-by: https://github.com/kalenikaliaksandr ✅
15 changed files with 29 additions and 26 deletions
|
@ -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.
|
||||
|
|
|
@ -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> = {});
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 this’s timed out flag and terminate this’s fetch controller.
|
||||
if (!processed_response) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue