LibWeb: Make EventLoopPlugin::deferred_invoke take a HeapFunction

This commit is contained in:
Shannon Booth 2024-10-31 02:39:29 +13:00 committed by Alexander Kalenik
parent 7487a782db
commit 29cea5bd24
Notes: github-actions[bot] 2024-10-30 19:57:08 +00:00
21 changed files with 75 additions and 73 deletions

View file

@ -209,7 +209,7 @@ JS::NonnullGCPtr<WebIDL::Promise> CSSStyleSheet::replace(String text)
set_disallow_modification(true);
// 4. In parallel, do these steps:
Platform::EventLoopPlugin::the().deferred_invoke([&realm, this, text = move(text), promise = JS::Handle(promise)] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, this, text = move(text), promise = JS::Handle(promise)] {
HTML::TemporaryExecutionContext execution_context { HTML::relevant_settings_object(*this), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
// 1. Let rules be the result of running parse a stylesheets contents from text.
@ -232,7 +232,7 @@ JS::NonnullGCPtr<WebIDL::Promise> CSSStyleSheet::replace(String text)
// 5. Resolve promise with sheet.
WebIDL::resolve_promise(realm, *promise, this);
});
}));
return promise;
}

View file

@ -25,13 +25,13 @@
namespace Web::CSS {
static NonnullRefPtr<Core::Promise<NonnullRefPtr<Gfx::Typeface>>> load_vector_font(ByteBuffer const& data)
static NonnullRefPtr<Core::Promise<NonnullRefPtr<Gfx::Typeface>>> load_vector_font(JS::Realm& realm, ByteBuffer const& data)
{
auto promise = Core::Promise<NonnullRefPtr<Gfx::Typeface>>::construct();
// FIXME: 'Asynchronously' shouldn't mean 'later on the main thread'.
// Can we defer this to a background thread?
Platform::EventLoopPlugin::the().deferred_invoke([&data, promise] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&data, promise] {
// FIXME: This should be de-duplicated with StyleComputer::FontLoader::try_load_font
// We don't have the luxury of knowing the MIME type, so we have to try all formats.
auto ttf = Gfx::Typeface::try_load_from_externally_owned_memory(data);
@ -50,7 +50,7 @@ static NonnullRefPtr<Core::Promise<NonnullRefPtr<Gfx::Typeface>>> load_vector_fo
return;
}
promise->reject(Error::from_string_literal("Automatic format detection failed"));
});
}));
return promise;
}
@ -118,7 +118,7 @@ JS::NonnullGCPtr<FontFace> FontFace::construct_impl(JS::Realm& realm, String fam
if (font->m_binary_data.is_empty())
return font;
HTML::queue_global_task(HTML::Task::Source::FontLoading, HTML::relevant_global_object(*font), JS::create_heap_function(vm.heap(), [font] {
HTML::queue_global_task(HTML::Task::Source::FontLoading, HTML::relevant_global_object(*font), JS::create_heap_function(vm.heap(), [&realm, font] {
// 1. Set font faces status attribute to "loading".
font->m_status = Bindings::FontFaceLoadStatus::Loading;
@ -126,7 +126,7 @@ JS::NonnullGCPtr<FontFace> FontFace::construct_impl(JS::Realm& realm, String fam
// 3. Asynchronously, attempt to parse the data in it as a font.
// When this is completed, successfully or not, queue a task to run the following steps synchronously:
font->m_font_load_promise = load_vector_font(font->m_binary_data);
font->m_font_load_promise = load_vector_font(realm, font->m_binary_data);
font->m_font_load_promise->when_resolved([font = JS::make_handle(font)](auto const& vector_font) -> ErrorOr<void> {
HTML::queue_global_task(HTML::Task::Source::FontLoading, HTML::relevant_global_object(*font), JS::create_heap_function(font->heap(), [font = JS::NonnullGCPtr(*font), vector_font] {
@ -349,7 +349,7 @@ void FontFace::load_font_source()
// and continue executing the rest of this algorithm asynchronously.
m_status = Bindings::FontFaceLoadStatus::Loading;
Web::Platform::EventLoopPlugin::the().deferred_invoke([font = JS::make_handle(this)] {
Web::Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [font = JS::make_handle(this)] {
// 4. Using the value of font faces [[Urls]] slot, attempt to load a font as defined in [CSS-FONTS-3],
// as if it was the value of a @font-face rules src descriptor.
@ -411,7 +411,7 @@ void FontFace::load_font_source()
// FIXME: Don't know how to load fonts in workers! They don't have a StyleComputer
dbgln("FIXME: Worker font loading not implemented");
}
});
}));
}
}

View file

@ -235,7 +235,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> FontFaceSet::load(Strin
JS::NonnullGCPtr font_face_set = *this;
auto promise = WebIDL::create_promise(realm);
Platform::EventLoopPlugin::the().deferred_invoke([&realm, font_face_set, promise, font, text]() mutable {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, font_face_set, promise, font, text]() mutable {
// 3. Find the matching font faces from font face set using the font and text arguments passed to the function,
// and let font face list be the return value (ignoring the found faces flag). If a syntax error was returned,
// reject promise with a SyntaxError exception and terminate these steps.
@ -275,7 +275,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> FontFaceSet::load(Strin
WebIDL::reject_promise(realm, promise, error);
});
}));
});
}));
// 2. Return promise. Complete the rest of these steps asynchronously.
return promise;

View file

@ -151,7 +151,7 @@ JS::NonnullGCPtr<WebIDL::Promise> Clipboard::write_text(String data)
auto promise = WebIDL::create_promise(realm);
// 3. Run the following steps in parallel:
Platform::EventLoopPlugin::the().deferred_invoke([&realm, promise, data = move(data)]() mutable {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, promise, data = move(data)]() mutable {
// 1. Let r be the result of running check clipboard write permission.
auto result = check_clipboard_write_permission(realm);
@ -191,7 +191,7 @@ JS::NonnullGCPtr<WebIDL::Promise> Clipboard::write_text(String data)
HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object(realm) };
WebIDL::resolve_promise(realm, promise, JS::js_undefined());
}));
});
}));
// 4. Return p.
return promise;

View file

@ -147,7 +147,7 @@ JS::NonnullGCPtr<WebIDL::Promise> SubtleCrypto::encrypt(AlgorithmIdentifier cons
// 6. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -172,7 +172,7 @@ JS::NonnullGCPtr<WebIDL::Promise> SubtleCrypto::encrypt(AlgorithmIdentifier cons
// 9. Resolve promise with ciphertext.
WebIDL::resolve_promise(realm, promise, cipher_text.release_value());
});
}));
return promise;
}
@ -204,7 +204,7 @@ JS::NonnullGCPtr<WebIDL::Promise> SubtleCrypto::decrypt(AlgorithmIdentifier cons
// 6. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -229,7 +229,7 @@ JS::NonnullGCPtr<WebIDL::Promise> SubtleCrypto::decrypt(AlgorithmIdentifier cons
// 9. Resolve promise with plaintext.
WebIDL::resolve_promise(realm, promise, plain_text.release_value());
});
}));
return promise;
}
@ -262,7 +262,7 @@ JS::NonnullGCPtr<WebIDL::Promise> SubtleCrypto::digest(AlgorithmIdentifier const
auto promise = WebIDL::create_promise(realm);
// 6. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, algorithm_object = normalized_algorithm.release_value(), promise, data_buffer = move(data_buffer)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, algorithm_object = normalized_algorithm.release_value(), promise, data_buffer = move(data_buffer)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
// FIXME: Need spec reference to https://webidl.spec.whatwg.org/#reject
@ -277,7 +277,7 @@ JS::NonnullGCPtr<WebIDL::Promise> SubtleCrypto::digest(AlgorithmIdentifier const
// 9. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result.release_value());
});
}));
return promise;
}
@ -302,7 +302,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::generate_
auto promise = WebIDL::create_promise(realm);
// 5. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, extractable, key_usages = move(key_usages)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, extractable, key_usages = move(key_usages)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 6. If the following steps or referenced procedures say to throw an error, reject promise with
// the returned error and then terminate the algorithm.
@ -337,7 +337,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::generate_
}
WebIDL::resolve_promise(realm, promise, key_pair);
});
});
}));
return promise;
}
@ -384,7 +384,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::import_ke
auto promise = WebIDL::create_promise(realm);
// 8. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, real_key_data = move(real_key_data), normalized_algorithm = normalized_algorithm.release_value(), promise, format, extractable, key_usages = move(key_usages), algorithm = move(algorithm)]() mutable -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [&realm, real_key_data = move(real_key_data), normalized_algorithm = normalized_algorithm.release_value(), promise, format, extractable, key_usages = move(key_usages), algorithm = move(algorithm)]() mutable -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 9. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -413,7 +413,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::import_ke
// 14. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result);
});
}));
return promise;
}
@ -428,7 +428,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::export_ke
auto promise = WebIDL::create_promise(realm);
// 3. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, key, promise, format]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [&realm, key, promise, format]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 4. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -459,7 +459,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::export_ke
// 8. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result_or_error.release_value());
});
}));
return promise;
}
@ -491,7 +491,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::sign(Algo
// 6. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, data = move(data)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 7. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -516,7 +516,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::sign(Algo
// 9. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result.release_value());
});
}));
return promise;
}
@ -555,7 +555,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::verify(Al
auto promise = WebIDL::create_promise(realm);
// 7. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, signature = move(signature), data = move(data)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, key, signature = move(signature), data = move(data)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 8. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -580,7 +580,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::verify(Al
// 12. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result.release_value());
});
}));
return promise;
}
@ -602,7 +602,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::derive_bi
auto promise = WebIDL::create_promise(realm);
// 5. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, base_key, length]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, normalized_algorithm = normalized_algorithm.release_value(), promise, base_key, length]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 6. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -627,7 +627,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::derive_bi
// 10. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result.release_value());
});
}));
return promise;
}
@ -663,7 +663,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::derive_ke
auto promise = WebIDL::create_promise(realm);
// 9. Return promise and perform the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, &vm, normalized_algorithm = normalized_algorithm.release_value(), promise, normalized_derived_key_algorithm_import = normalized_derived_key_algorithm_import.release_value(), normalized_derived_key_algorithm_length = normalized_derived_key_algorithm_length.release_value(), base_key = move(base_key), extractable, key_usages = move(key_usages)]() -> void {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, &vm, normalized_algorithm = normalized_algorithm.release_value(), promise, normalized_derived_key_algorithm_import = normalized_derived_key_algorithm_import.release_value(), normalized_derived_key_algorithm_length = normalized_derived_key_algorithm_length.release_value(), base_key = move(base_key), extractable, key_usages = move(key_usages)]() -> void {
HTML::TemporaryExecutionContext context(Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
// 10. If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
@ -720,7 +720,7 @@ JS::ThrowCompletionOr<JS::NonnullGCPtr<WebIDL::Promise>> SubtleCrypto::derive_ke
// 17. Resolve promise with result.
WebIDL::resolve_promise(realm, promise, result.release_value());
});
}));
return promise;
}

View file

@ -92,10 +92,10 @@ static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOM::Document>> load_html_document(H
else {
// FIXME: Parse as we receive the document data, instead of waiting for the whole document to be fetched first.
auto process_body = JS::create_heap_function(document->heap(), [document, url = navigation_params.response->url().value(), mime_type = navigation_params.response->header_list()->extract_mime_type()](ByteBuffer data) {
Platform::EventLoopPlugin::the().deferred_invoke([document = document, data = move(data), url = url, mime_type] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(document->heap(), [document = document, data = move(data), url = url, mime_type] {
auto parser = HTML::HTMLParser::create_with_uncertain_encoding(document, data, mime_type);
parser->run(url);
});
}));
});
auto process_body_error = JS::create_heap_function(document->heap(), [](JS::Value) {

View file

@ -145,7 +145,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
// 12. If action is non-null, then run these steps in parallel:
if (action) {
Platform::EventLoopPlugin::the().deferred_invoke([&realm, stream, action = move(action)] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, stream, action = move(action)] {
HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
// 1. Run action.
@ -162,7 +162,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
// When running action is done, close stream.
stream->close();
});
}));
}
// 13. Let body be a body whose stream is stream, source is source, and length is length.

View file

@ -440,7 +440,7 @@ WebIDL::ExceptionOr<JS::GCPtr<PendingResponse>> main_fetch(JS::Realm& realm, Inf
}
// 11. If recursive is false, then run the remaining steps in parallel.
Platform::EventLoopPlugin::the().deferred_invoke([&realm, &vm, &fetch_params, request, response, get_response = move(get_response)] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, &vm, &fetch_params, request, response, get_response = move(get_response)] {
// 12. If response is null, then set response to the result of running the steps corresponding to the first
// matching statement:
auto pending_response = PendingResponse::create(vm, request, Infrastructure::Response::create(vm));
@ -589,7 +589,7 @@ WebIDL::ExceptionOr<JS::GCPtr<PendingResponse>> main_fetch(JS::Realm& realm, Inf
fetch_response_handover(realm, fetch_params, *response);
}
});
});
}));
return JS::GCPtr<PendingResponse> {};
}
@ -1920,9 +1920,9 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<PendingResponse>> http_network_or_cache_fet
revalidate_request->set_service_workers_mode(Infrastructure::Request::ServiceWorkersMode::None);
// 7. In parallel, run main fetch given a new fetch params whose request is revalidateRequest.
Platform::EventLoopPlugin::the().deferred_invoke([&vm, &realm, revalidate_request, fetch_params = JS::NonnullGCPtr(fetch_params)] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&vm, &realm, revalidate_request, fetch_params = JS::NonnullGCPtr(fetch_params)] {
(void)main_fetch(realm, Infrastructure::FetchParams::create(vm, revalidate_request, fetch_params->timing_info()));
});
}));
}
// 2. Otherwise:
else {

View file

@ -59,12 +59,12 @@ void PendingResponse::run_callback()
{
VERIFY(m_callback);
VERIFY(m_response);
Platform::EventLoopPlugin::the().deferred_invoke([this] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [this] {
VERIFY(m_callback);
VERIFY(m_response);
m_callback->function()(*m_response);
m_request->remove_pending_response({}, *this);
});
}));
}
}

View file

@ -146,7 +146,7 @@ WebIDL::ExceptionOr<void> FileReader::read_operation(Blob& blob, Type type, Opti
bool is_first_chunk = true;
// 10. In parallel, while true:
Platform::EventLoopPlugin::the().deferred_invoke([this, chunk_promise, reader, bytes, is_first_chunk, &realm, type, encoding_name, blobs_type]() mutable {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [this, chunk_promise, reader, bytes, is_first_chunk, &realm, type, encoding_name, blobs_type]() mutable {
HTML::TemporaryExecutionContext execution_context { Bindings::host_defined_environment_settings_object(realm), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
Optional<MonotonicTime> progress_timer;
@ -257,7 +257,7 @@ WebIDL::ExceptionOr<void> FileReader::read_operation(Blob& blob, Type type, Opti
return;
}
}
});
}));
return {};
}

View file

@ -297,7 +297,7 @@ WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(JS::NonnullGCPtr<WebIDL::Ca
bitmap_result = TRY_OR_THROW_OOM(vm(), m_bitmap->clone());
// 4. Run these steps in parallel:
Platform::EventLoopPlugin::the().deferred_invoke([this, callback, bitmap_result, type, quality] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [this, callback, bitmap_result, type, quality] {
// 1. If result is non-null, then set result to a serialization of result as a file with type and quality if given.
Optional<SerializeBitmapResult> file_result;
if (bitmap_result) {
@ -320,7 +320,7 @@ WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(JS::NonnullGCPtr<WebIDL::Ca
if (maybe_error.is_throw_completion())
report_exception(maybe_error.throw_completion(), realm());
});
});
}));
return {};
}

View file

@ -323,7 +323,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> HTMLImageElement::decode(
return;
// 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().deferred_invoke(JS::create_heap_function(heap(), [this, promise, &realm, reject_if_document_not_fully_active, reject_if_current_request_state_broken] {
Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [&] {
auto state = this->current_request().state();
@ -357,7 +357,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> HTMLImageElement::decode(
HTML::TemporaryExecutionContext context(HTML::relevant_settings_object(*this));
WebIDL::resolve_promise(realm, promise, JS::js_undefined());
}
});
}));
}));
return promise;

View file

@ -1401,7 +1401,7 @@ WebIDL::ExceptionOr<void> Navigable::navigate(NavigateParams params)
}
// 20. In parallel, run these steps:
Platform::EventLoopPlugin::the().deferred_invoke([this, source_snapshot_params, target_snapshot_params, csp_navigation_type, document_resource, url, navigation_id, referrer_policy, initiator_origin_snapshot, response, history_handling, initiator_base_url_snapshot] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(heap(), [this, source_snapshot_params, target_snapshot_params, csp_navigation_type, document_resource, url, navigation_id, referrer_policy, initiator_origin_snapshot, response, history_handling, initiator_base_url_snapshot] {
// AD-HOC: Not in the spec but subsequent steps will fail if the navigable doesn't have an active window.
if (!active_window()) {
set_delaying_load_events(false);
@ -1489,7 +1489,7 @@ WebIDL::ExceptionOr<void> Navigable::navigate(NavigateParams params)
finalize_a_cross_document_navigation(*this, to_history_handling_behavior(history_handling), history_entry);
}));
})).release_value_but_fixme_should_propagate_errors();
});
}));
return {};
}

View file

@ -146,14 +146,14 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<TraversableNavigable>> TraversableNavigable
// Skip the initial navigation as well. This matches the behavior of the window open steps.
if (url_matches_about_blank(initial_navigation_url)) {
Platform::EventLoopPlugin::the().deferred_invoke([traversable, initial_navigation_url] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(traversable->heap(), [traversable, initial_navigation_url] {
// FIXME: We do this other places too when creating a new about:blank document. Perhaps it's worth a spec issue?
HTML::HTMLParser::the_end(*traversable->active_document());
// FIXME: If we perform the URL and history update steps here, we start hanging tests and the UI process will
// try to load() the initial URLs passed on the command line before we finish processing the events here.
// However, because we call this before the PageClient is fully initialized... that gets awkward.
});
}));
}
else {
@ -642,7 +642,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
// 7. In parallel, attempt to populate the history entry's document for targetEntry, given navigable, potentiallyTargetSpecificSourceSnapshotParams,
// targetSnapshotParams, with allowPOST set to allowPOST and completionSteps set to queue a global task on the navigation and traversal task source given
// navigable's active window to run afterDocumentPopulated.
Platform::EventLoopPlugin::the().deferred_invoke([populated_target_entry, potentially_target_specific_source_snapshot_params, target_snapshot_params, this, allow_POST, navigable, after_document_populated = JS::create_heap_function(this->heap(), move(after_document_populated))] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(this->heap(), [populated_target_entry, potentially_target_specific_source_snapshot_params, target_snapshot_params, this, allow_POST, navigable, after_document_populated = JS::create_heap_function(this->heap(), move(after_document_populated))] {
navigable->populate_session_history_entry_document(populated_target_entry, *potentially_target_specific_source_snapshot_params, target_snapshot_params, {}, Empty {}, CSPNavigationType::Other, allow_POST, JS::create_heap_function(this->heap(), [this, after_document_populated, populated_target_entry]() mutable {
VERIFY(active_window());
queue_global_task(Task::Source::NavigationAndTraversal, *active_window(), JS::create_heap_function(this->heap(), [after_document_populated, populated_target_entry]() mutable {
@ -650,7 +650,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
}));
}))
.release_value_but_fixme_should_propagate_errors();
});
}));
}
// Otherwise, run afterDocumentPopulated immediately.
else {

View file

@ -210,7 +210,7 @@ JS::NonnullGCPtr<WebIDL::Promise> WindowOrWorkerGlobalScopeMixin::create_image_b
image.visit(
[&](JS::Handle<FileAPI::Blob>& blob) {
// Run these step in parallel:
Platform::EventLoopPlugin::the().deferred_invoke([=]() {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [=]() {
// 1. Let imageData be the result of reading image's data. If an error occurs during reading of the
// object, then reject p with an "InvalidStateError" DOMException and abort these steps.
// FIXME: I guess this is always fine for us as the data is already read.
@ -246,7 +246,7 @@ JS::NonnullGCPtr<WebIDL::Promise> WindowOrWorkerGlobalScopeMixin::create_image_b
};
(void)Web::Platform::ImageCodecPlugin::the().decode_image(image_data, move(on_successful_decode), move(on_failed_decode));
});
}));
},
[&](auto&) {
dbgln("(STUBBED) createImageBitmap() for non-blob types");

View file

@ -159,7 +159,7 @@ void ResourceClient::set_resource(Resource* resource)
// This ensures that these callbacks always happen in a consistent way, instead of being invoked
// synchronously in some cases, and asynchronously in others.
if (resource->is_loaded() || resource->is_failed()) {
Platform::EventLoopPlugin::the().deferred_invoke([weak_this = make_weak_ptr(), strong_resource = NonnullRefPtr { *m_resource }] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(ResourceLoader::the().heap(), [weak_this = make_weak_ptr(), strong_resource = NonnullRefPtr { *m_resource }] {
if (!weak_this)
return;
@ -177,7 +177,7 @@ void ResourceClient::set_resource(Resource* resource)
weak_this->resource_did_fail();
return;
}
});
}));
}
}
}

View file

@ -278,9 +278,9 @@ void ResourceLoader::load(LoadRequest& request, SuccessCallback success_callback
return;
}
Platform::EventLoopPlugin::the().deferred_invoke([success_callback = move(success_callback), response_headers = move(response_headers)] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(m_heap, [success_callback = move(success_callback), response_headers = move(response_headers)] {
success_callback(ByteString::empty().to_byte_buffer(), response_headers, {});
});
}));
return;
}
@ -303,9 +303,9 @@ void ResourceLoader::load(LoadRequest& request, SuccessCallback success_callback
log_success(request);
Platform::EventLoopPlugin::the().deferred_invoke([data = move(data_url.body), response_headers = move(response_headers), success_callback = move(success_callback)] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(m_heap, [data = move(data_url.body), response_headers = move(response_headers), success_callback = move(success_callback)] {
success_callback(data, response_headers, {});
});
}));
return;
}
@ -560,9 +560,9 @@ void ResourceLoader::finish_network_request(NonnullRefPtr<Requests::Request> con
if (on_load_counter_change)
on_load_counter_change();
Platform::EventLoopPlugin::the().deferred_invoke([this, protocol_request] {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(m_heap, [this, protocol_request] {
m_active_requests.remove(protocol_request);
});
}));
}
void ResourceLoader::clear_cache()

View file

@ -22,7 +22,7 @@ public:
virtual ~EventLoopPlugin();
virtual void spin_until(JS::Handle<JS::HeapFunction<bool()>> goal_condition) = 0;
virtual void deferred_invoke(ESCAPING JS::SafeFunction<void()>) = 0;
virtual void deferred_invoke(ESCAPING JS::Handle<JS::HeapFunction<void()>>) = 0;
virtual JS::NonnullGCPtr<Timer> create_timer(JS::Heap&) = 0;
virtual void quit() = 0;
};

View file

@ -21,10 +21,12 @@ void EventLoopPluginSerenity::spin_until(JS::Handle<JS::HeapFunction<bool()>> go
});
}
void EventLoopPluginSerenity::deferred_invoke(JS::SafeFunction<void()> function)
void EventLoopPluginSerenity::deferred_invoke(JS::Handle<JS::HeapFunction<void()>> function)
{
VERIFY(function);
Core::deferred_invoke(move(function));
Core::deferred_invoke([function = move(function)]() {
function->function()();
});
}
JS::NonnullGCPtr<Timer> EventLoopPluginSerenity::create_timer(JS::Heap& heap)

View file

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

View file

@ -346,7 +346,7 @@ void execute_script(HTML::BrowsingContext const& browsing_context, ByteString bo
auto promise = WebIDL::create_promise(realm);
// 8. Run the following substeps in parallel:
Platform::EventLoopPlugin::the().deferred_invoke([&realm, &browsing_context, promise, document, body = move(body), arguments = move(arguments)]() mutable {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&realm, &browsing_context, promise, document, body = move(body), arguments = move(arguments)]() mutable {
HTML::TemporaryExecutionContext execution_context { document->relevant_settings_object() };
// 1. Let scriptPromise be the result of promise-calling execute a function body, with arguments body and arguments.
@ -362,7 +362,7 @@ void execute_script(HTML::BrowsingContext const& browsing_context, ByteString bo
if (script_result.is_throw_completion()) {
WebIDL::reject_promise(realm, promise, *script_result.throw_completion().value());
}
});
}));
// 9. Wait until promise is resolved, or timer's timeout fired flag is set, whichever occurs first.
auto reaction_steps = JS::create_heap_function(vm.heap(), [&realm, &browsing_context, promise, timer, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
@ -425,7 +425,7 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteStr
JS::NonnullGCPtr promise { verify_cast<JS::Promise>(*promise_capability->promise()) };
// 8. Run the following substeps in parallel:
Platform::EventLoopPlugin::the().deferred_invoke([&vm, &realm, &browsing_context, timer, document, promise_capability, promise, body = move(body), arguments = move(arguments)]() mutable {
Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(realm.heap(), [&vm, &realm, &browsing_context, timer, document, promise_capability, promise, body = move(body), arguments = move(arguments)]() mutable {
HTML::TemporaryExecutionContext execution_context { document->relevant_settings_object() };
// 1. Let resolvingFunctions be CreateResolvingFunctions(promise).
@ -481,7 +481,7 @@ void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteStr
// 11. Upon rejection of scriptPromise with value r, reject promise with value r.
if (script_promise.state() == JS::Promise::State::Rejected)
WebIDL::reject_promise(realm, promise_capability, script_promise.result());
});
}));
// 9. Wait until promise is resolved, or timer's timeout fired flag is set, whichever occurs first.
auto reaction_steps = JS::create_heap_function(vm.heap(), [&realm, &browsing_context, promise, timer, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {