Skip to content

Commit

Permalink
LibWeb: Use JS::HeapFunction for WebIDL promise reaction steps
Browse files Browse the repository at this point in the history
Switching away from SafeFunction immediately backfired here, as we're
dealing with two layers of captures, not one.

Let's do the correct fix, which is to use HeapFunction. This makes the
API and its behavior explicit, and keeps captures alive as long as the
HeapFunction is alive.

Fixes SerenityOS#23819.
  • Loading branch information
awesomekling committed Apr 3, 2024
1 parent f1eb837 commit ffac32d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 76 deletions.
8 changes: 4 additions & 4 deletions Userland/Libraries/LibWeb/FileAPI/Blob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,15 +375,15 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> Blob::text()
auto promise = TRY(reader->read_all_bytes_deprecated());

// 4. Return the result of transforming promise by a fulfillment handler that returns the result of running UTF-8 decode on its first argument.
return WebIDL::upon_fulfillment(*promise, [&](auto const& first_argument) -> WebIDL::ExceptionOr<JS::Value> {
return WebIDL::upon_fulfillment(*promise, JS::create_heap_function(heap(), [&vm](JS::Value first_argument) -> WebIDL::ExceptionOr<JS::Value> {
auto const& object = first_argument.as_object();
VERIFY(is<JS::ArrayBuffer>(object));
auto const& buffer = static_cast<const JS::ArrayBuffer&>(object).buffer();

auto decoder = TextCodec::decoder_for("UTF-8"sv);
auto utf8_text = TRY_OR_THROW_OOM(vm, TextCodec::convert_input_to_utf8_using_given_decoder_unless_there_is_a_byte_order_mark(*decoder, buffer));
return JS::PrimitiveString::create(vm, move(utf8_text));
});
}));
}

// https://w3c.github.io/FileAPI/#dom-blob-arraybuffer
Expand All @@ -404,13 +404,13 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> Blob::array_buffer()
auto promise = TRY(reader->read_all_bytes_deprecated());

// 4. Return the result of transforming promise by a fulfillment handler that returns a new ArrayBuffer whose contents are its first argument.
return WebIDL::upon_fulfillment(*promise, [&](auto const& first_argument) -> WebIDL::ExceptionOr<JS::Value> {
return WebIDL::upon_fulfillment(*promise, JS::create_heap_function(heap(), [&realm](JS::Value first_argument) -> WebIDL::ExceptionOr<JS::Value> {
auto const& object = first_argument.as_object();
VERIFY(is<JS::ArrayBuffer>(object));
auto const& buffer = static_cast<const JS::ArrayBuffer&>(object).buffer();

return JS::ArrayBuffer::create(realm, buffer);
});
}));
}

}
8 changes: 4 additions & 4 deletions Userland/Libraries/LibWeb/HTML/Scripting/Fetching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ void fetch_descendants_of_and_link_a_module_script(JS::Realm& realm,
auto& loading_promise = record->load_requested_modules(state);

// 6. Upon fulfillment of loadingPromise, run the following steps:
WebIDL::upon_fulfillment(loading_promise, [&realm, record, &module_script, on_complete](auto const&) -> WebIDL::ExceptionOr<JS::Value> {
WebIDL::upon_fulfillment(loading_promise, JS::create_heap_function(realm.heap(), [&realm, record, &module_script, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
// 1. Perform record.Link().
auto linking_result = record->link(realm.vm());

Expand All @@ -840,10 +840,10 @@ void fetch_descendants_of_and_link_a_module_script(JS::Realm& realm,
on_complete->function()(module_script);

return JS::js_undefined();
});
}));

// 7. Upon rejection of loadingPromise, run the following steps:
WebIDL::upon_rejection(loading_promise, [state, &module_script, on_complete](auto const&) -> WebIDL::ExceptionOr<JS::Value> {
WebIDL::upon_rejection(loading_promise, JS::create_heap_function(realm.heap(), [state, &module_script, on_complete](JS::Value) -> WebIDL::ExceptionOr<JS::Value> {
// 1. If state.[[ParseError]] is not null, set moduleScript's error to rethrow to state.[[ParseError]] and run
// onComplete given moduleScript.
if (!state->parse_error.is_null()) {
Expand All @@ -857,7 +857,7 @@ void fetch_descendants_of_and_link_a_module_script(JS::Realm& realm,
}

return JS::js_undefined();
});
}));

fetch_client.clean_up_after_running_callback();
realm.vm().pop_execution_context();
Expand Down
Loading

0 comments on commit ffac32d

Please sign in to comment.