diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.cpp index 85d4c443d7..48d7426118 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -55,14 +56,22 @@ JS::NonnullGCPtr Body::clone(JS::Realm& realm) const // FIXME: 2. Set body’s stream to out1. JS::GCPtr out2; - Streams::StartAlgorithm start_algorithm = []() { return JS::js_undefined(); }; - Streams::PullAlgorithm pull_algorithm = [&realm]() { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); }; - Streams::CancelAlgorithm cancel_algorithm = [&realm](auto) { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); }; + auto start_algorithm = JS::create_heap_function(realm.heap(), []() -> WebIDL::ExceptionOr { + return JS::js_undefined(); + }); + + auto pull_algorithm = JS::create_heap_function(realm.heap(), [&realm]() -> WebIDL::ExceptionOr> { + return WebIDL::create_resolved_promise(realm, JS::js_undefined()); + }); + + auto cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm](JS::Value) -> WebIDL::ExceptionOr> { + return WebIDL::create_resolved_promise(realm, JS::js_undefined()); + }); if (m_stream->controller()->has>()) { - out2 = Streams::create_readable_stream(realm, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm)).release_value_but_fixme_should_propagate_errors(); + out2 = Streams::create_readable_stream(realm, start_algorithm, pull_algorithm, cancel_algorithm).release_value_but_fixme_should_propagate_errors(); } else { - out2 = Streams::create_readable_byte_stream(realm, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm)).release_value_but_fixme_should_propagate_errors(); + out2 = Streams::create_readable_byte_stream(realm, start_algorithm, pull_algorithm, cancel_algorithm).release_value_but_fixme_should_propagate_errors(); } // 3. Return a body whose stream is out2 and other members are copied from body. diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp index 9f67644251..ba687dfc41 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2022, Linus Groh * Copyright (c) 2023, Matthew Olsson - * Copyright (c) 2023, Shannon Booth + * Copyright (c) 2023-2024, Shannon Booth * Copyright (c) 2023, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause @@ -238,17 +238,16 @@ bool readable_stream_has_default_reader(ReadableStream const& stream) } // https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function -SizeAlgorithm extract_size_algorithm(QueuingStrategy const& strategy) +JS::NonnullGCPtr extract_size_algorithm(JS::VM& vm, QueuingStrategy const& strategy) { // 1. If strategy["size"] does not exist, return an algorithm that returns 1. if (!strategy.size) - return [](auto const&) { return JS::normal_completion(JS::Value(1)); }; + return JS::create_heap_function(vm.heap(), [](JS::Value) { return JS::normal_completion(JS::Value(1)); }); // 2. Return an algorithm that performs the following steps, taking a chunk argument: - return [strategy](auto const& chunk) { - // 1. Return the result of invoking strategy["size"] with argument list « chunk ». - return WebIDL::invoke_callback(*strategy.size, JS::js_undefined(), chunk); - }; + return JS::create_heap_function(vm.heap(), [size = strategy.size](JS::Value chunk) { + return WebIDL::invoke_callback(*size, JS::js_undefined(), chunk); + }); } // https://streams.spec.whatwg.org/#validate-and-normalize-high-water-mark @@ -935,7 +934,7 @@ WebIDL::ExceptionOr readable_stream_default_controller_enqueue(ReadableStr // 4. Otherwise, else { // 1. Let result be the result of performing controller.[[strategySizeAlgorithm]], passing in chunk, and interpreting the result as a completion record. - auto result = (*controller.strategy_size_algorithm())(chunk); + auto result = controller.strategy_size_algorithm()->function()(chunk); // 2. If result is an abrupt completion, if (result.is_abrupt()) { @@ -995,7 +994,7 @@ WebIDL::ExceptionOr readable_stream_default_controller_can_pull_if_needed( controller.set_pulling(true); // 6. Let pullPromise be the result of performing controller.[[pullAlgorithm]]. - auto pull_promise = TRY((*controller.pull_algorithm())()); + auto pull_promise = TRY(controller.pull_algorithm()->function()()); // 7. Upon fulfillment of pullPromise, WebIDL::upon_fulfillment(*pull_promise, [&](auto const&) -> WebIDL::ExceptionOr { @@ -1316,7 +1315,7 @@ bool readable_stream_default_controller_can_close_or_enqueue(ReadableStreamDefau } // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller -WebIDL::ExceptionOr set_up_readable_stream_default_controller(ReadableStream& stream, ReadableStreamDefaultController& controller, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm, double high_water_mark, SizeAlgorithm&& size_algorithm) +WebIDL::ExceptionOr set_up_readable_stream_default_controller(ReadableStream& stream, ReadableStreamDefaultController& controller, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr pull_algorithm, JS::NonnullGCPtr cancel_algorithm, double high_water_mark, JS::NonnullGCPtr size_algorithm) { auto& realm = stream.realm(); @@ -1336,20 +1335,20 @@ WebIDL::ExceptionOr set_up_readable_stream_default_controller(ReadableStre controller.set_pulling(false); // 5. Set controller.[[strategySizeAlgorithm]] to sizeAlgorithm and controller.[[strategyHWM]] to highWaterMark. - controller.set_strategy_size_algorithm(move(size_algorithm)); + controller.set_strategy_size_algorithm(size_algorithm); controller.set_strategy_hwm(high_water_mark); // 6. Set controller.[[pullAlgorithm]] to pullAlgorithm. - controller.set_pull_algorithm(move(pull_algorithm)); + controller.set_pull_algorithm(pull_algorithm); // 7. Set controller.[[cancelAlgorithm]] to cancelAlgorithm. - controller.set_cancel_algorithm(move(cancel_algorithm)); + controller.set_cancel_algorithm(cancel_algorithm); // 8. Set stream.[[controller]] to controller. stream.set_controller(ReadableStreamController { controller }); // 9. Let startResult be the result of performing startAlgorithm. (This might throw an exception.) - auto start_result = TRY(start_algorithm()); + auto start_result = TRY(start_algorithm->function()()); // 10. Let startPromise be a promise resolved with startResult. auto start_promise = WebIDL::create_resolved_promise(realm, start_result); @@ -1383,7 +1382,7 @@ WebIDL::ExceptionOr set_up_readable_stream_default_controller(ReadableStre } // https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source -WebIDL::ExceptionOr set_up_readable_stream_default_controller_from_underlying_source(ReadableStream& stream, JS::Value underlying_source_value, UnderlyingSource underlying_source, double high_water_mark, SizeAlgorithm&& size_algorithm) +WebIDL::ExceptionOr set_up_readable_stream_default_controller_from_underlying_source(ReadableStream& stream, JS::Value underlying_source_value, UnderlyingSource underlying_source, double high_water_mark, JS::NonnullGCPtr size_algorithm) { auto& realm = stream.realm(); @@ -1391,46 +1390,48 @@ WebIDL::ExceptionOr set_up_readable_stream_default_controller_from_underly auto controller = stream.heap().allocate(realm, realm); // 2. Let startAlgorithm be an algorithm that returns undefined. - StartAlgorithm start_algorithm = [] { return JS::js_undefined(); }; + auto start_algorithm = JS::create_heap_function(realm.heap(), []() -> WebIDL::ExceptionOr { + return JS::js_undefined(); + }); // 3. Let pullAlgorithm be an algorithm that returns a promise resolved with undefined. - PullAlgorithm pull_algorithm = [&realm]() { + auto pull_algorithm = JS::create_heap_function(realm.heap(), [&realm]() -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 4. Let cancelAlgorithm be an algorithm that returns a promise resolved with undefined. - CancelAlgorithm cancel_algorithm = [&realm](auto const&) { + auto cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm](JS::Value) -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 5. If underlyingSourceDict["start"] exists, then set startAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["start"] with argument list « controller » and callback this value underlyingSource. if (underlying_source.start) { - start_algorithm = [controller, underlying_source_value, callback = underlying_source.start]() -> WebIDL::ExceptionOr { + start_algorithm = JS::create_heap_function(realm.heap(), [controller, underlying_source_value, callback = underlying_source.start]() -> WebIDL::ExceptionOr { // Note: callback does not return a promise, so invoke_callback may return an abrupt completion return TRY(WebIDL::invoke_callback(*callback, underlying_source_value, controller)).release_value(); - }; + }); } // 6. If underlyingSourceDict["pull"] exists, then set pullAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["pull"] with argument list « controller » and callback this value underlyingSource. if (underlying_source.pull) { - pull_algorithm = [&realm, controller, underlying_source_value, callback = underlying_source.pull]() -> WebIDL::ExceptionOr> { + pull_algorithm = JS::create_heap_function(realm.heap(), [&realm, controller, underlying_source_value, callback = underlying_source.pull]() -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_source_value, controller)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 7. If underlyingSourceDict["cancel"] exists, then set cancelAlgorithm to an algorithm which takes an argument reason and returns the result of invoking underlyingSourceDict["cancel"] with argument list « reason » and callback this value underlyingSource. if (underlying_source.cancel) { - cancel_algorithm = [&realm, underlying_source_value, callback = underlying_source.cancel](auto const& reason) -> WebIDL::ExceptionOr> { + cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_source_value, callback = underlying_source.cancel](JS::Value reason) -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_source_value, reason)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 8. Perform ? SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm). - return set_up_readable_stream_default_controller(stream, controller, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm), high_water_mark, move(size_algorithm)); + return set_up_readable_stream_default_controller(stream, controller, start_algorithm, pull_algorithm, cancel_algorithm, high_water_mark, size_algorithm); } // https://streams.spec.whatwg.org/#readable-byte-stream-controller-call-pull-if-needed @@ -1459,7 +1460,7 @@ WebIDL::ExceptionOr readable_byte_stream_controller_call_pull_if_needed(Re controller.set_pulling(true); // 6. Let pullPromise be the result of performing controller.[[pullAlgorithm]]. - auto pull_promise = TRY((*controller.pull_algorithm())()); + auto pull_promise = TRY(controller.pull_algorithm()->function()()); // 7. Upon fulfillment of pullPromise, WebIDL::upon_fulfillment(*pull_promise, [&](auto const&) -> WebIDL::ExceptionOr { @@ -1712,15 +1713,15 @@ bool readable_byte_stream_controller_should_call_pull(ReadableByteStreamControll } // https://streams.spec.whatwg.org/#create-readable-stream -WebIDL::ExceptionOr> create_readable_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm, Optional high_water_mark, Optional&& size_algorithm) +WebIDL::ExceptionOr> create_readable_stream(JS::Realm& realm, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr pull_algorithm, JS::NonnullGCPtr cancel_algorithm, Optional high_water_mark, JS::GCPtr size_algorithm) { // 1. If highWaterMark was not passed, set it to 1. if (!high_water_mark.has_value()) high_water_mark = 1.0; // 2. If sizeAlgorithm was not passed, set it to an algorithm that returns 1. - if (!size_algorithm.has_value()) - size_algorithm = [](auto const&) { return JS::normal_completion(JS::Value(1)); }; + if (!size_algorithm) + size_algorithm = JS::create_heap_function(realm.heap(), [](JS::Value) { return JS::normal_completion(JS::Value(1)); }); // 3. Assert: ! IsNonNegativeNumber(highWaterMark) is true. VERIFY(is_non_negative_number(JS::Value { *high_water_mark })); @@ -1735,14 +1736,14 @@ WebIDL::ExceptionOr> create_readable_stream(JS: auto controller = realm.heap().allocate(realm, realm); // 7. Perform ? SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm). - TRY(set_up_readable_stream_default_controller(*stream, *controller, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm), *high_water_mark, move(*size_algorithm))); + TRY(set_up_readable_stream_default_controller(*stream, *controller, start_algorithm, pull_algorithm, cancel_algorithm, *high_water_mark, *size_algorithm)); // 8. Return stream. return stream; } // https://streams.spec.whatwg.org/#abstract-opdef-createreadablebytestream -WebIDL::ExceptionOr> create_readable_byte_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm) +WebIDL::ExceptionOr> create_readable_byte_stream(JS::Realm& realm, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr pull_algorithm, JS::NonnullGCPtr cancel_algorithm) { // 1. Let stream be a new ReadableStream. auto stream = realm.heap().allocate(realm, realm); @@ -1754,14 +1755,14 @@ WebIDL::ExceptionOr> create_readable_byte_strea auto controller = realm.heap().allocate(realm, realm); // 4. Perform ? SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, 0, undefined). - TRY(set_up_readable_byte_stream_controller(stream, controller, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm), 0, JS::js_undefined())); + TRY(set_up_readable_byte_stream_controller(stream, controller, start_algorithm, pull_algorithm, cancel_algorithm, 0, JS::js_undefined())); // 5. Return stream. return stream; } // https://streams.spec.whatwg.org/#create-writable-stream -WebIDL::ExceptionOr> create_writable_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, WriteAlgorithm&& write_algorithm, CloseAlgorithm&& close_algorithm, AbortAlgorithm&& abort_algorithm, double high_water_mark, SizeAlgorithm&& size_algorithm) +WebIDL::ExceptionOr> create_writable_stream(JS::Realm& realm, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr write_algorithm, JS::NonnullGCPtr close_algorithm, JS::NonnullGCPtr abort_algorithm, double high_water_mark, JS::NonnullGCPtr size_algorithm) { // 1. Assert: ! IsNonNegativeNumber(highWaterMark) is true. VERIFY(is_non_negative_number(JS::Value { high_water_mark })); @@ -1921,7 +1922,7 @@ WebIDL::ExceptionOr set_up_writable_stream_default_writer(WritableStreamDe } // https://streams.spec.whatwg.org/#set-up-readable-byte-stream-controller -WebIDL::ExceptionOr set_up_readable_byte_stream_controller(ReadableStream& stream, ReadableByteStreamController& controller, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm, double high_water_mark, JS::Value auto_allocate_chunk_size) +WebIDL::ExceptionOr set_up_readable_byte_stream_controller(ReadableStream& stream, ReadableByteStreamController& controller, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr pull_algorithm, JS::NonnullGCPtr cancel_algorithm, double high_water_mark, JS::Value auto_allocate_chunk_size) { auto& realm = stream.realm(); @@ -1958,10 +1959,10 @@ WebIDL::ExceptionOr set_up_readable_byte_stream_controller(ReadableStream& controller.set_strategy_hwm(high_water_mark); // 9. Set controller.[[pullAlgorithm]] to pullAlgorithm. - controller.set_pull_algorithm(move(pull_algorithm)); + controller.set_pull_algorithm(pull_algorithm); // 10. Set controller.[[cancelAlgorithm]] to cancelAlgorithm. - controller.set_cancel_algorithm(move(cancel_algorithm)); + controller.set_cancel_algorithm(cancel_algorithm); // 11. Set controller.[[autoAllocateChunkSize]] to autoAllocateChunkSize. if (auto_allocate_chunk_size.is_integral_number()) @@ -1974,7 +1975,7 @@ WebIDL::ExceptionOr set_up_readable_byte_stream_controller(ReadableStream& stream.set_controller(ReadableStreamController { controller }); // 14. Let startResult be the result of performing startAlgorithm. - auto start_result = TRY(start_algorithm()); + auto start_result = TRY(start_algorithm->function()()); // 15. Let startPromise be a promise resolved with startResult. auto start_promise = WebIDL::create_resolved_promise(realm, start_result); @@ -2338,19 +2339,19 @@ PullIntoDescriptor readable_byte_stream_controller_shift_pending_pull_into(Reada } // https://streams.spec.whatwg.org/#readablestream-set-up-with-byte-reading-support -WebIDL::ExceptionOr set_up_readable_stream_controller_with_byte_reading_support(ReadableStream& stream, Optional&& pull_algorithm, Optional&& cancel_algorithm, double high_water_mark) +WebIDL::ExceptionOr set_up_readable_stream_controller_with_byte_reading_support(ReadableStream& stream, JS::GCPtr pull_algorithm, JS::GCPtr cancel_algorithm, double high_water_mark) { auto& realm = stream.realm(); // 1. Let startAlgorithm be an algorithm that returns undefined. - StartAlgorithm start_algorithm = [] { return JS::js_undefined(); }; + auto start_algorithm = JS::create_heap_function(realm.heap(), []() -> WebIDL::ExceptionOr { return JS::js_undefined(); }); // 2. Let pullAlgorithmWrapper be an algorithm that runs these steps: - PullAlgorithm pull_algorithm_wrapper = [&realm, pull_algorithm = move(pull_algorithm)]() -> WebIDL::ExceptionOr> { + auto pull_algorithm_wrapper = JS::create_heap_function(realm.heap(), [&realm, pull_algorithm]() -> WebIDL::ExceptionOr> { // 1. Let result be the result of running pullAlgorithm, if pullAlgorithm was given, or null otherwise. If this throws an exception e, return a promise rejected with e. JS::GCPtr result = nullptr; - if (pull_algorithm.has_value()) - result = TRY(pull_algorithm.value()()); + if (pull_algorithm) + result = TRY(pull_algorithm->function()()); // 2. If result is a Promise, then return result. if (result != nullptr) @@ -2358,14 +2359,14 @@ WebIDL::ExceptionOr set_up_readable_stream_controller_with_byte_reading_su // 3. Return a promise resolved with undefined. return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 3. Let cancelAlgorithmWrapper be an algorithm that runs these steps: - CancelAlgorithm cancel_algorithm_wrapper = [&realm, cancel_algorithm = move(cancel_algorithm)](auto const& c) -> WebIDL::ExceptionOr> { + auto cancel_algorithm_wrapper = JS::create_heap_function(realm.heap(), [&realm, cancel_algorithm](JS::Value c) -> WebIDL::ExceptionOr> { // 1. Let result be the result of running cancelAlgorithm, if cancelAlgorithm was given, or null otherwise. If this throws an exception e, return a promise rejected with e. JS::GCPtr result = nullptr; - if (cancel_algorithm.has_value()) - result = TRY(cancel_algorithm.value()(c)); + if (cancel_algorithm) + result = TRY(cancel_algorithm->function()(c)); // 2. If result is a Promise, then return result. if (result != nullptr) @@ -2373,14 +2374,14 @@ WebIDL::ExceptionOr set_up_readable_stream_controller_with_byte_reading_su // 3. Return a promise resolved with undefined. return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 4. Perform ! InitializeReadableStream(stream). // 5. Let controller be a new ReadableByteStreamController. auto controller = stream.heap().allocate(realm, realm); // 6. Perform ! SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithmWrapper, cancelAlgorithmWrapper, highWaterMark, undefined). - TRY(set_up_readable_byte_stream_controller(stream, controller, move(start_algorithm), move(pull_algorithm_wrapper), move(cancel_algorithm_wrapper), high_water_mark, JS::js_undefined())); + TRY(set_up_readable_byte_stream_controller(stream, controller, start_algorithm, pull_algorithm_wrapper, cancel_algorithm_wrapper, high_water_mark, JS::js_undefined())); return {}; } @@ -3046,7 +3047,7 @@ WebIDL::ExceptionOr> writable_stream_default_w } // https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller -WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStream& stream, WritableStreamDefaultController& controller, StartAlgorithm&& start_algorithm, WriteAlgorithm&& write_algorithm, CloseAlgorithm&& close_algorithm, AbortAlgorithm&& abort_algorithm, double high_water_mark, SizeAlgorithm&& size_algorithm) +WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStream& stream, WritableStreamDefaultController& controller, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr write_algorithm, JS::NonnullGCPtr close_algorithm, JS::NonnullGCPtr abort_algorithm, double high_water_mark, JS::NonnullGCPtr size_algorithm) { auto& realm = stream.realm(); @@ -3071,19 +3072,19 @@ WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStre controller.set_started(false); // 8. Set controller.[[strategySizeAlgorithm]] to sizeAlgorithm. - controller.set_strategy_size_algorithm(move(size_algorithm)); + controller.set_strategy_size_algorithm(size_algorithm); // 9. Set controller.[[strategyHWM]] to highWaterMark. controller.set_strategy_hwm(high_water_mark); // 10. Set controller.[[writeAlgorithm]] to writeAlgorithm. - controller.set_write_algorithm(move(write_algorithm)); + controller.set_write_algorithm(write_algorithm); // 11. Set controller.[[closeAlgorithm]] to closeAlgorithm. - controller.set_close_algorithm(move(close_algorithm)); + controller.set_close_algorithm(close_algorithm); // 12. Set controller.[[abortAlgorithm]] to abortAlgorithm. - controller.set_abort_algorithm(move(abort_algorithm)); + controller.set_abort_algorithm(abort_algorithm); // 13. Let backpressure be ! WritableStreamDefaultControllerGetBackpressure(controller). auto backpressure = writable_stream_default_controller_get_backpressure(controller); @@ -3092,7 +3093,7 @@ WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStre writable_stream_update_backpressure(stream, backpressure); // 15. Let startResult be the result of performing startAlgorithm. (This may throw an exception.) - auto start_result = TRY(start_algorithm()); + auto start_result = TRY(start_algorithm->function()()); // 16. Let startPromise be a promise resolved with startResult. auto start_promise = WebIDL::create_resolved_promise(realm, start_result); @@ -3131,7 +3132,7 @@ WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStre } // https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller-from-underlying-sink -WebIDL::ExceptionOr set_up_writable_stream_default_controller_from_underlying_sink(WritableStream& stream, JS::Value underlying_sink_value, UnderlyingSink& underlying_sink, double high_water_mark, SizeAlgorithm&& size_algorithm) +WebIDL::ExceptionOr set_up_writable_stream_default_controller_from_underlying_sink(WritableStream& stream, JS::Value underlying_sink_value, UnderlyingSink& underlying_sink, double high_water_mark, JS::NonnullGCPtr size_algorithm) { auto& realm = stream.realm(); @@ -3139,60 +3140,60 @@ WebIDL::ExceptionOr set_up_writable_stream_default_controller_from_underly auto controller = realm.heap().allocate(realm, realm); // 2. Let startAlgorithm be an algorithm that returns undefined. - StartAlgorithm start_algorithm = [] { return JS::js_undefined(); }; + auto start_algorithm = JS::create_heap_function(realm.heap(), []() -> WebIDL::ExceptionOr { return JS::js_undefined(); }); // 3. Let writeAlgorithm be an algorithm that returns a promise resolved with undefined. - WriteAlgorithm write_algorithm = [&realm](auto const&) { + auto write_algorithm = JS::create_heap_function(realm.heap(), [&realm](JS::Value) -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 4. Let closeAlgorithm be an algorithm that returns a promise resolved with undefined. - CloseAlgorithm close_algorithm = [&realm] { + auto close_algorithm = JS::create_heap_function(realm.heap(), [&realm]() -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 5. Let abortAlgorithm be an algorithm that returns a promise resolved with undefined. - AbortAlgorithm abort_algorithm = [&realm](auto const&) { + auto abort_algorithm = JS::create_heap_function(realm.heap(), [&realm](JS::Value) -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 6. If underlyingSinkDict["start"] exists, then set startAlgorithm to an algorithm which returns the result of invoking underlyingSinkDict["start"] with argument list « controller » and callback this value underlyingSink. if (underlying_sink.start) { - start_algorithm = [controller, underlying_sink_value, callback = underlying_sink.start]() -> WebIDL::ExceptionOr { + start_algorithm = JS::create_heap_function(realm.heap(), [controller, underlying_sink_value, callback = underlying_sink.start]() -> WebIDL::ExceptionOr { // Note: callback does not return a promise, so invoke_callback may return an abrupt completion return TRY(WebIDL::invoke_callback(*callback, underlying_sink_value, controller)).release_value(); - }; + }); } // 7. If underlyingSinkDict["write"] exists, then set writeAlgorithm to an algorithm which takes an argument chunk and returns the result of invoking underlyingSinkDict["write"] with argument list « chunk, controller » and callback this value underlyingSink. if (underlying_sink.write) { - write_algorithm = [&realm, controller, underlying_sink_value, callback = underlying_sink.write](JS::Value chunk) -> WebIDL::ExceptionOr> { + write_algorithm = JS::create_heap_function(realm.heap(), [&realm, controller, underlying_sink_value, callback = underlying_sink.write](JS::Value chunk) -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_sink_value, chunk, controller)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 8. If underlyingSinkDict["close"] exists, then set closeAlgorithm to an algorithm which returns the result of invoking underlyingSinkDict["close"] with argument list «» and callback this value underlyingSink. if (underlying_sink.close) { - close_algorithm = [&realm, underlying_sink_value, callback = underlying_sink.close]() -> WebIDL::ExceptionOr> { + close_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.close]() -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_sink_value)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 9. If underlyingSinkDict["abort"] exists, then set abortAlgorithm to an algorithm which takes an argument reason and returns the result of invoking underlyingSinkDict["abort"] with argument list « reason » and callback this value underlyingSink. if (underlying_sink.abort) { - abort_algorithm = [&realm, underlying_sink_value, callback = underlying_sink.abort](JS::Value reason) -> WebIDL::ExceptionOr> { + abort_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.abort](JS::Value reason) -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_sink_value, reason)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 10. Perform ? SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm). - TRY(set_up_writable_stream_default_controller(stream, controller, move(start_algorithm), move(write_algorithm), move(close_algorithm), move(abort_algorithm), high_water_mark, move(size_algorithm))); + TRY(set_up_writable_stream_default_controller(stream, controller, start_algorithm, write_algorithm, close_algorithm, abort_algorithm, high_water_mark, size_algorithm)); return {}; } @@ -3316,7 +3317,7 @@ bool writable_stream_default_controller_get_backpressure(WritableStreamDefaultCo WebIDL::ExceptionOr writable_stream_default_controller_get_chunk_size(WritableStreamDefaultController& controller, JS::Value chunk) { // 1. Let returnValue be the result of performing controller.[[strategySizeAlgorithm]], passing in chunk, and interpreting the result as a completion record. - auto return_value = (*controller.strategy_size_algorithm())(chunk); + auto return_value = controller.strategy_size_algorithm()->function()(chunk); // 2. If returnValue is an abrupt completion, if (return_value.is_abrupt()) { @@ -3354,7 +3355,7 @@ WebIDL::ExceptionOr writable_stream_default_controller_process_close(Writa VERIFY(controller.queue().is_empty()); // 5. Let sinkClosePromise be the result of performing controller.[[closeAlgorithm]]. - auto sink_close_promise = TRY((*controller.close_algorithm())()); + auto sink_close_promise = TRY(controller.close_algorithm()->function()()); // 6. Perform ! WritableStreamDefaultControllerClearAlgorithms(controller). writable_stream_default_controller_clear_algorithms(controller); @@ -3388,7 +3389,7 @@ WebIDL::ExceptionOr writable_stream_default_controller_process_write(Writa writable_stream_mark_first_write_request_in_flight(*stream); // 3. Let sinkWritePromise be the result of performing controller.[[writeAlgorithm]], passing in chunk. - auto sink_write_promise = TRY((*controller.write_algorithm())(chunk)); + auto sink_write_promise = TRY(controller.write_algorithm()->function()(chunk)); // 4. Upon fulfillment of sinkWritePromise, WebIDL::upon_fulfillment(*sink_write_promise, [&, stream = stream](auto const&) -> WebIDL::ExceptionOr { @@ -3472,56 +3473,57 @@ WebIDL::ExceptionOr writable_stream_default_controller_write(WritableStrea } // https://streams.spec.whatwg.org/#initialize-transform-stream -WebIDL::ExceptionOr initialize_transform_stream(TransformStream& stream, JS::NonnullGCPtr start_promise, double writable_high_water_mark, SizeAlgorithm&& writable_size_algorithm, double readable_high_water_mark, SizeAlgorithm&& readable_size_algorithm) +WebIDL::ExceptionOr initialize_transform_stream(TransformStream& stream, JS::NonnullGCPtr start_promise, double writable_high_water_mark, JS::NonnullGCPtr writable_size_algorithm, double readable_high_water_mark, JS::NonnullGCPtr readable_size_algorithm) { auto& realm = stream.realm(); // 1. Let startAlgorithm be an algorithm that returns startPromise. - StartAlgorithm writable_start_algorithm = [start_promise] { + auto writable_start_algorithm = JS::create_heap_function(realm.heap(), [start_promise]() -> WebIDL::ExceptionOr { return start_promise->promise(); - }; - StartAlgorithm readable_start_algorithm = [start_promise] { + }); + + auto readable_start_algorithm = JS::create_heap_function(realm.heap(), [start_promise]() -> WebIDL::ExceptionOr { return start_promise->promise(); - }; + }); // 2. Let writeAlgorithm be the following steps, taking a chunk argument: - WriteAlgorithm write_algorithm = [&stream](JS::Value chunk) { + auto write_algorithm = JS::create_heap_function(realm.heap(), [&stream](JS::Value chunk) -> WebIDL::ExceptionOr> { // 1. Return ! TransformStreamDefaultSinkWriteAlgorithm(stream, chunk). return transform_stream_default_sink_write_algorithm(stream, chunk); - }; + }); // 3. Let abortAlgorithm be the following steps, taking a reason argument: - AbortAlgorithm abort_algorithm = [&stream](JS::Value reason) { + auto abort_algorithm = JS::create_heap_function(realm.heap(), [&stream](JS::Value reason) -> WebIDL::ExceptionOr> { // 1. Return ! TransformStreamDefaultSinkAbortAlgorithm(stream, reason). return transform_stream_default_sink_abort_algorithm(stream, reason); - }; + }); // 4. Let closeAlgorithm be the following steps: - CloseAlgorithm close_algorithm = [&stream] { + auto close_algorithm = JS::create_heap_function(realm.heap(), [&stream]() -> WebIDL::ExceptionOr> { // 1. Return ! TransformStreamDefaultSinkCloseAlgorithm(stream). return transform_stream_default_sink_close_algorithm(stream); - }; + }); // 5. Set stream.[[writable]] to ! CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm). - stream.set_writable(TRY(create_writable_stream(realm, move(writable_start_algorithm), move(write_algorithm), move(close_algorithm), move(abort_algorithm), writable_high_water_mark, move(writable_size_algorithm)))); + stream.set_writable(TRY(create_writable_stream(realm, writable_start_algorithm, write_algorithm, close_algorithm, abort_algorithm, writable_high_water_mark, writable_size_algorithm))); // 6. Let pullAlgorithm be the following steps: - PullAlgorithm pull_algorithm = [&stream] { + auto pull_algorithm = JS::create_heap_function(realm.heap(), [&stream]() -> WebIDL::ExceptionOr> { // 1. Return ! TransformStreamDefaultSourcePullAlgorithm(stream). return transform_stream_default_source_pull_algorithm(stream); - }; + }); // 7. Let cancelAlgorithm be the following steps, taking a reason argument: - CancelAlgorithm cancel_algorithm = [&stream, &realm](JS::Value reason) -> WebIDL::ExceptionOr> { + auto cancel_algorithm = JS::create_heap_function(realm.heap(), [&stream, &realm](JS::Value reason) -> WebIDL::ExceptionOr> { // 1. Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, reason). TRY(transform_stream_error_writable_and_unblock_write(stream, reason)); // 2. Return a promise resolved with undefined. return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 8. Set stream.[[readable]] to ! CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm). - stream.set_readable(TRY(create_readable_stream(realm, move(readable_start_algorithm), move(pull_algorithm), move(cancel_algorithm), readable_high_water_mark, move(readable_size_algorithm)))); + stream.set_readable(TRY(create_readable_stream(realm, readable_start_algorithm, pull_algorithm, cancel_algorithm, readable_high_water_mark, readable_size_algorithm))); // 9. Set stream.[[backpressure]] and stream.[[backpressureChangePromise]] to undefined. stream.set_backpressure({}); @@ -3537,7 +3539,7 @@ WebIDL::ExceptionOr initialize_transform_stream(TransformStream& stream, J } // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller -void set_up_transform_stream_default_controller(TransformStream& stream, TransformStreamDefaultController& controller, TransformAlgorithm&& transform_algorithm, FlushAlgorithm&& flush_algorithm) +void set_up_transform_stream_default_controller(TransformStream& stream, TransformStreamDefaultController& controller, JS::NonnullGCPtr transform_algorithm, JS::NonnullGCPtr flush_algorithm) { // 1. Assert: stream implements TransformStream. // 2. Assert: stream.[[controller]] is undefined. @@ -3550,10 +3552,10 @@ void set_up_transform_stream_default_controller(TransformStream& stream, Transfo stream.set_controller(controller); // 5. Set controller.[[transformAlgorithm]] to transformAlgorithm. - controller.set_transform_algorithm(move(transform_algorithm)); + controller.set_transform_algorithm(transform_algorithm); // 6. Set controller.[[flushAlgorithm]] to flushAlgorithm. - controller.set_flush_algorithm(move(flush_algorithm)); + controller.set_flush_algorithm(flush_algorithm); } // https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller-from-transformer @@ -3566,7 +3568,7 @@ WebIDL::ExceptionOr set_up_transform_stream_default_controller_from_transf auto controller = realm.heap().allocate(realm, realm); // 2. Let transformAlgorithm be the following steps, taking a chunk argument: - TransformAlgorithm transform_algorithm = [controller, &realm, &vm](JS::Value chunk) { + auto transform_algorithm = JS::create_heap_function(realm.heap(), [controller, &realm, &vm](JS::Value chunk) -> WebIDL::ExceptionOr> { // 1. Let result be TransformStreamDefaultControllerEnqueue(controller, chunk). auto result = transform_stream_default_controller_enqueue(*controller, chunk); @@ -3578,41 +3580,41 @@ WebIDL::ExceptionOr set_up_transform_stream_default_controller_from_transf // 3. Otherwise, return a promise resolved with undefined. return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 3. Let flushAlgorithm be an algorithm which returns a promise resolved with undefined. - FlushAlgorithm flush_algorithm = [&realm] { + auto flush_algorithm = JS::create_heap_function(realm.heap(), [&realm]() -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 4. If transformerDict["transform"] exists, set transformAlgorithm to an algorithm which takes an argument chunk // and returns the result of invoking transformerDict["transform"] with argument list « chunk, controller » and // callback this value transformer. if (transformer_dict.transform) { - transform_algorithm = [controller, &realm, transformer, callback = transformer_dict.transform](JS::Value chunk) -> WebIDL::ExceptionOr> { + transform_algorithm = JS::create_heap_function(realm.heap(), [controller, &realm, transformer, callback = transformer_dict.transform](JS::Value chunk) -> WebIDL::ExceptionOr> { // Note: callback does not return a promise, so invoke_callback may return an abrupt completion auto result = WebIDL::invoke_callback(*callback, transformer, chunk, controller); if (result.is_error()) return WebIDL::create_rejected_promise(realm, *result.release_value()); return WebIDL::create_resolved_promise(realm, *result.release_value()); - }; + }); } // 5. If transformerDict["flush"] exists, set flushAlgorithm to an algorithm which returns the result of invoking // transformerDict["flush"] with argument list « controller » and callback this value transformer. if (transformer_dict.flush) { - flush_algorithm = [&realm, transformer, callback = transformer_dict.flush, controller]() -> WebIDL::ExceptionOr> { + flush_algorithm = JS::create_heap_function(realm.heap(), [&realm, transformer, callback = transformer_dict.flush, controller]() -> WebIDL::ExceptionOr> { // Note: callback does not return a promise, so invoke_callback may return an abrupt completion auto result = WebIDL::invoke_callback(*callback, transformer, controller); if (result.is_error()) { return WebIDL::create_rejected_promise(realm, *result.release_value()); } return WebIDL::create_resolved_promise(realm, *result.release_value()); - }; + }); } // 6. Perform ! SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm). - set_up_transform_stream_default_controller(stream, *controller, move(transform_algorithm), move(flush_algorithm)); + set_up_transform_stream_default_controller(stream, *controller, transform_algorithm, flush_algorithm); return {}; } @@ -3712,7 +3714,7 @@ WebIDL::ExceptionOr> transform_stream_default_ auto& realm = controller.realm(); // 1. Let transformPromise be the result of performing controller.[[transformAlgorithm]], passing chunk. - auto transform_promise = TRY((*controller.transform_algorithm())(chunk)); + auto transform_promise = TRY(controller.transform_algorithm()->function()(chunk)); // 2. Return the result of reacting to transformPromise with the following rejection steps given the argument r: auto react_result = WebIDL::react_to_promise(*transform_promise, @@ -3752,7 +3754,7 @@ WebIDL::ExceptionOr> transform_stream_default_ auto controller = stream.controller(); // 3. Let flushPromise be the result of performing controller.[[flushAlgorithm]]. - auto flush_promise = TRY((*controller->flush_algorithm())()); + auto flush_promise = TRY(controller->flush_algorithm()->function()()); // 4. Perform ! TransformStreamDefaultControllerClearAlgorithms(controller). transform_stream_default_controller_clear_algorithms(*controller); @@ -3976,42 +3978,42 @@ WebIDL::ExceptionOr set_up_readable_byte_stream_controller_from_underlying auto controller = stream.heap().allocate(realm, realm); // 2. Let startAlgorithm be an algorithm that returns undefined. - StartAlgorithm start_algorithm = [] { return JS::js_undefined(); }; + auto start_algorithm = JS::create_heap_function(realm.heap(), []() -> WebIDL::ExceptionOr { return JS::js_undefined(); }); // 3. Let pullAlgorithm be an algorithm that returns a promise resolved with undefined. - PullAlgorithm pull_algorithm = [&realm]() { + auto pull_algorithm = JS::create_heap_function(realm.heap(), [&realm]() -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 4. Let cancelAlgorithm be an algorithm that returns a promise resolved with undefined. - CancelAlgorithm cancel_algorithm = [&realm](auto const&) { + auto cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm](JS::Value) -> WebIDL::ExceptionOr> { return WebIDL::create_resolved_promise(realm, JS::js_undefined()); - }; + }); // 5. If underlyingSourceDict["start"] exists, then set startAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["start"] with argument list « controller » and callback this value underlyingSource. if (underlying_source_dict.start) { - start_algorithm = [controller, underlying_source, callback = underlying_source_dict.start]() -> WebIDL::ExceptionOr { + start_algorithm = JS::create_heap_function(realm.heap(), [controller, underlying_source, callback = underlying_source_dict.start]() -> WebIDL::ExceptionOr { // Note: callback does not return a promise, so invoke_callback may return an abrupt completion return TRY(WebIDL::invoke_callback(*callback, underlying_source, controller)).release_value(); - }; + }); } // 6. If underlyingSourceDict["pull"] exists, then set pullAlgorithm to an algorithm which returns the result of invoking underlyingSourceDict["pull"] with argument list « controller » and callback this value underlyingSource. if (underlying_source_dict.pull) { - pull_algorithm = [&realm, controller, underlying_source, callback = underlying_source_dict.pull]() -> WebIDL::ExceptionOr> { + pull_algorithm = JS::create_heap_function(realm.heap(), [&realm, controller, underlying_source, callback = underlying_source_dict.pull]() -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_source, controller)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 7. If underlyingSourceDict["cancel"] exists, then set cancelAlgorithm to an algorithm which takes an argument reason and returns the result of invoking underlyingSourceDict["cancel"] with argument list « reason » and callback this value underlyingSource. if (underlying_source_dict.cancel) { - cancel_algorithm = [&realm, underlying_source, callback = underlying_source_dict.cancel](auto const& reason) -> WebIDL::ExceptionOr> { + cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_source, callback = underlying_source_dict.cancel](JS::Value reason) -> WebIDL::ExceptionOr> { // Note: callback return a promise, so invoke_callback will never return an abrupt completion auto result = MUST_OR_THROW_OOM(WebIDL::invoke_callback(*callback, underlying_source, reason)).release_value(); return WebIDL::create_resolved_promise(realm, result); - }; + }); } // 8. Let autoAllocateChunkSize be underlyingSourceDict["autoAllocateChunkSize"], if it exists, or undefined otherwise. @@ -4024,7 +4026,7 @@ WebIDL::ExceptionOr set_up_readable_byte_stream_controller_from_underlying return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot use an auto allocate chunk size of 0"sv }; // 10. Perform ? SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize). - return set_up_readable_byte_stream_controller(stream, controller, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm), high_water_mark, auto_allocate_chunk_size); + return set_up_readable_byte_stream_controller(stream, controller, start_algorithm, pull_algorithm, cancel_algorithm, high_water_mark, auto_allocate_chunk_size); } } diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h index b9bd9d1892..c7d0d7d31d 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2022, Linus Groh * Copyright (c) 2023, Matthew Olsson - * Copyright (c) 2023, Shannon Booth + * Copyright (c) 2023-2024, Shannon Booth * Copyright (c) 2023, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause @@ -18,21 +18,21 @@ namespace Web::Streams { -using SizeAlgorithm = JS::SafeFunction; -using PullAlgorithm = JS::SafeFunction>()>; -using CancelAlgorithm = JS::SafeFunction>(JS::Value)>; -using StartAlgorithm = JS::SafeFunction()>; -using AbortAlgorithm = JS::SafeFunction>(JS::Value)>; -using CloseAlgorithm = JS::SafeFunction>()>; -using WriteAlgorithm = JS::SafeFunction>(JS::Value)>; -using FlushAlgorithm = JS::SafeFunction>()>; -using TransformAlgorithm = JS::SafeFunction>(JS::Value)>; +using SizeAlgorithm = JS::HeapFunction; +using PullAlgorithm = JS::HeapFunction>()>; +using CancelAlgorithm = JS::HeapFunction>(JS::Value)>; +using StartAlgorithm = JS::HeapFunction()>; +using AbortAlgorithm = JS::HeapFunction>(JS::Value)>; +using CloseAlgorithm = JS::HeapFunction>()>; +using WriteAlgorithm = JS::HeapFunction>(JS::Value)>; +using FlushAlgorithm = JS::HeapFunction>()>; +using TransformAlgorithm = JS::HeapFunction>(JS::Value)>; WebIDL::ExceptionOr> acquire_readable_stream_default_reader(ReadableStream&); WebIDL::ExceptionOr> acquire_readable_stream_byob_reader(ReadableStream&); bool is_readable_stream_locked(ReadableStream const&); -SizeAlgorithm extract_size_algorithm(QueuingStrategy const&); +JS::NonnullGCPtr extract_size_algorithm(JS::VM&, QueuingStrategy const&); WebIDL::ExceptionOr extract_high_water_mark(QueuingStrategy const&, double default_hwm); void readable_stream_close(ReadableStream&); @@ -73,10 +73,10 @@ void readable_stream_default_controller_clear_algorithms(ReadableStreamDefaultCo void readable_stream_default_controller_error(ReadableStreamDefaultController&, JS::Value error); Optional readable_stream_default_controller_get_desired_size(ReadableStreamDefaultController&); bool readable_stream_default_controller_can_close_or_enqueue(ReadableStreamDefaultController&); -WebIDL::ExceptionOr set_up_readable_stream_default_controller(ReadableStream&, ReadableStreamDefaultController&, StartAlgorithm&&, PullAlgorithm&&, CancelAlgorithm&&, double high_water_mark, SizeAlgorithm&&); -WebIDL::ExceptionOr set_up_readable_stream_default_controller_from_underlying_source(ReadableStream&, JS::Value underlying_source_value, UnderlyingSource, double high_water_mark, SizeAlgorithm&&); -WebIDL::ExceptionOr set_up_readable_stream_controller_with_byte_reading_support(ReadableStream&, Optional&& = {}, Optional&& = {}, double high_water_mark = 0); -WebIDL::ExceptionOr set_up_readable_byte_stream_controller(ReadableStream&, ReadableByteStreamController&, StartAlgorithm&&, PullAlgorithm&&, CancelAlgorithm&&, double high_water_mark, JS::Value auto_allocate_chunk_size); +WebIDL::ExceptionOr set_up_readable_stream_default_controller(ReadableStream&, ReadableStreamDefaultController&, JS::NonnullGCPtr, JS::NonnullGCPtr, JS::NonnullGCPtr, double high_water_mark, JS::NonnullGCPtr); +WebIDL::ExceptionOr set_up_readable_stream_default_controller_from_underlying_source(ReadableStream&, JS::Value underlying_source_value, UnderlyingSource, double high_water_mark, JS::NonnullGCPtr); +WebIDL::ExceptionOr set_up_readable_stream_controller_with_byte_reading_support(ReadableStream&, JS::GCPtr = {}, JS::GCPtr = {}, double high_water_mark = 0); +WebIDL::ExceptionOr set_up_readable_byte_stream_controller(ReadableStream&, ReadableByteStreamController&, JS::NonnullGCPtr, JS::NonnullGCPtr, JS::NonnullGCPtr, double high_water_mark, JS::Value auto_allocate_chunk_size); WebIDL::ExceptionOr set_up_readable_byte_stream_controller_from_underlying_source(ReadableStream&, JS::Value underlying_source, UnderlyingSource const& underlying_source_dict, double high_water_mark); JS::GCPtr readable_byte_stream_controller_get_byob_request(JS::NonnullGCPtr); @@ -108,9 +108,9 @@ WebIDL::ExceptionOr readable_byte_stream_controller_handle_queue_drain(Rea void readable_byte_stream_controller_invalidate_byob_request(ReadableByteStreamController&); bool readable_byte_stream_controller_should_call_pull(ReadableByteStreamController const&); -WebIDL::ExceptionOr> create_readable_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm, Optional high_water_mark = {}, Optional&& size_algorithm = {}); -WebIDL::ExceptionOr> create_readable_byte_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm); -WebIDL::ExceptionOr> create_writable_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, WriteAlgorithm&& write_algorithm, CloseAlgorithm&& close_algorithm, AbortAlgorithm&& abort_algorithm, double high_water_mark, SizeAlgorithm&& size_algorithm); +WebIDL::ExceptionOr> create_readable_stream(JS::Realm& realm, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr pull_algorithm, JS::NonnullGCPtr cancel_algorithm, Optional high_water_mark = {}, JS::GCPtr size_algorithm = {}); +WebIDL::ExceptionOr> create_readable_byte_stream(JS::Realm& realm, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr pull_algorithm, JS::NonnullGCPtr cancel_algorithm); +WebIDL::ExceptionOr> create_writable_stream(JS::Realm& realm, JS::NonnullGCPtr start_algorithm, JS::NonnullGCPtr write_algorithm, JS::NonnullGCPtr close_algorithm, JS::NonnullGCPtr abort_algorithm, double high_water_mark, JS::NonnullGCPtr size_algorithm); void initialize_readable_stream(ReadableStream&); void initialize_writable_stream(WritableStream&); @@ -143,8 +143,8 @@ Optional writable_stream_default_writer_get_desired_size(WritableStreamD WebIDL::ExceptionOr writable_stream_default_writer_release(WritableStreamDefaultWriter&); WebIDL::ExceptionOr> writable_stream_default_writer_write(WritableStreamDefaultWriter&, JS::Value chunk); -WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStream&, WritableStreamDefaultController&, StartAlgorithm&&, WriteAlgorithm&&, CloseAlgorithm&&, AbortAlgorithm&&, double high_water_mark, SizeAlgorithm&&); -WebIDL::ExceptionOr set_up_writable_stream_default_controller_from_underlying_sink(WritableStream&, JS::Value underlying_sink_value, UnderlyingSink&, double high_water_mark, SizeAlgorithm&& size_algorithm); +WebIDL::ExceptionOr set_up_writable_stream_default_controller(WritableStream&, WritableStreamDefaultController&, JS::NonnullGCPtr, JS::NonnullGCPtr, JS::NonnullGCPtr, JS::NonnullGCPtr, double high_water_mark, JS::NonnullGCPtr); +WebIDL::ExceptionOr set_up_writable_stream_default_controller_from_underlying_sink(WritableStream&, JS::Value underlying_sink_value, UnderlyingSink&, double high_water_mark, JS::NonnullGCPtr size_algorithm); WebIDL::ExceptionOr writable_stream_default_controller_advance_queue_if_needed(WritableStreamDefaultController&); void writable_stream_default_controller_clear_algorithms(WritableStreamDefaultController&); WebIDL::ExceptionOr writable_stream_default_controller_close(WritableStreamDefaultController&); @@ -157,8 +157,8 @@ WebIDL::ExceptionOr writable_stream_default_controller_process_close(Writa WebIDL::ExceptionOr writable_stream_default_controller_process_write(WritableStreamDefaultController&, JS::Value chunk); WebIDL::ExceptionOr writable_stream_default_controller_write(WritableStreamDefaultController&, JS::Value chunk, JS::Value chunk_size); -WebIDL::ExceptionOr initialize_transform_stream(TransformStream&, JS::NonnullGCPtr start_promise, double writable_high_water_mark, SizeAlgorithm&& writable_size_algorithm, double readable_high_water_mark, SizeAlgorithm&& readable_size_algorithm); -void set_up_transform_stream_default_controller(TransformStream&, TransformStreamDefaultController&, TransformAlgorithm&&, FlushAlgorithm&&); +WebIDL::ExceptionOr initialize_transform_stream(TransformStream&, JS::NonnullGCPtr start_promise, double writable_high_water_mark, JS::NonnullGCPtr writable_size_algorithm, double readable_high_water_mark, JS::NonnullGCPtr readable_size_algorithm); +void set_up_transform_stream_default_controller(TransformStream&, TransformStreamDefaultController&, JS::NonnullGCPtr, JS::NonnullGCPtr); WebIDL::ExceptionOr set_up_transform_stream_default_controller_from_transformer(TransformStream&, JS::Value transformer, Transformer&); void transform_stream_default_controller_clear_algorithms(TransformStreamDefaultController&); WebIDL::ExceptionOr transform_stream_default_controller_enqueue(TransformStreamDefaultController&, JS::Value chunk); diff --git a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp index 2b40215cbc..9d85593beb 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, Matthew Olsson - * Copyright (c) 2023, Shannon Booth + * Copyright (c) 2023-2024, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -98,7 +98,7 @@ WebIDL::ExceptionOr> ReadableByteStreamControl reset_queue(*this); // 3. Let result be the result of performing this.[[cancelAlgorithm]], passing in reason. - auto result = (*m_cancel_algorithm)(reason); + auto result = m_cancel_algorithm->function()(reason); // 4. Perform ! ReadableByteStreamControllerClearAlgorithms(this). readable_byte_stream_controller_clear_algorithms(*this); @@ -201,6 +201,8 @@ void ReadableByteStreamController::visit_edges(Cell::Visitor& visitor) for (auto const& item : m_queue) visitor.visit(item.buffer); visitor.visit(m_stream); + visitor.visit(m_cancel_algorithm); + visitor.visit(m_pull_algorithm); } } diff --git a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h index b2aa4c95f9..c96a0c3532 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h @@ -94,8 +94,8 @@ public: Optional const& auto_allocate_chunk_size() { return m_auto_allocate_chunk_size; } void set_auto_allocate_chunk_size(Optional value) { m_auto_allocate_chunk_size = value; } - auto& cancel_algorithm() { return m_cancel_algorithm; } - void set_cancel_algorithm(Optional value) { m_cancel_algorithm = move(value); } + JS::GCPtr cancel_algorithm() { return m_cancel_algorithm; } + void set_cancel_algorithm(JS::GCPtr value) { m_cancel_algorithm = value; } bool close_requested() const { return m_close_requested; } void set_close_requested(bool value) { m_close_requested = value; } @@ -103,8 +103,8 @@ public: bool pull_again() const { return m_pull_again; } void set_pull_again(bool value) { m_pull_again = value; } - auto& pull_algorithm() { return m_pull_algorithm; } - void set_pull_algorithm(Optional value) { m_pull_algorithm = move(value); } + JS::GCPtr pull_algorithm() { return m_pull_algorithm; } + void set_pull_algorithm(JS::GCPtr value) { m_pull_algorithm = value; } bool pulling() const { return m_pulling; } void set_pulling(bool value) { m_pulling = value; } @@ -148,7 +148,7 @@ private: // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-cancelalgorithm // A promise-returning algorithm, taking one argument (the cancel reason), which communicates a requested cancelation to the underlying source - Optional m_cancel_algorithm; + JS::GCPtr m_cancel_algorithm; // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-closerequested // A boolean flag indicating whether the stream has been closed by its underlying source, but still has chunks in its internal queue that have not yet been read @@ -160,7 +160,7 @@ private: // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pullalgorithm // A promise-returning algorithm that pulls data from the underlying source - Optional m_pull_algorithm; + JS::GCPtr m_pull_algorithm; // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pulling // A boolean flag set to true while the underlying source's pull algorithm is executing and the returned promise has not yet fulfilled, used to prevent reentrant calls diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp index de53deb004..761837c4f2 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableStream.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, Linus Groh - * Copyright (c) 2023, Shannon Booth + * Copyright (c) 2023-2024, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -53,13 +53,13 @@ WebIDL::ExceptionOr> ReadableStream::construct_ VERIFY(!underlying_source_dict.type.has_value()); // 2. Let sizeAlgorithm be ! ExtractSizeAlgorithm(strategy). - auto size_algorithm = extract_size_algorithm(strategy); + auto size_algorithm = extract_size_algorithm(vm, strategy); // 3. Let highWaterMark be ? ExtractHighWaterMark(strategy, 1). auto high_water_mark = TRY(extract_high_water_mark(strategy, 1)); // 4. Perform ? SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, underlyingSourceDict, highWaterMark, sizeAlgorithm). - TRY(set_up_readable_stream_default_controller_from_underlying_source(*readable_stream, underlying_source, underlying_source_dict, high_water_mark, move(size_algorithm))); + TRY(set_up_readable_stream_default_controller_from_underlying_source(*readable_stream, underlying_source, underlying_source_dict, high_water_mark, size_algorithm)); } return readable_stream; diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.cpp index 3ddb67feab..75995c4522 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.cpp @@ -71,7 +71,7 @@ WebIDL::ExceptionOr> ReadableStreamDefaultCont reset_queue(*this); // 2. Let result be the result of performing this.[[cancelAlgorithm]], passing reason. - auto result = (*cancel_algorithm())(reason); + auto result = cancel_algorithm()->function()(reason); // 3. Perform ! ReadableStreamDefaultControllerClearAlgorithms(this). readable_stream_default_controller_clear_algorithms(*this); @@ -138,6 +138,9 @@ void ReadableStreamDefaultController::visit_edges(Cell::Visitor& visitor) for (auto const& item : m_queue) visitor.visit(item.value); visitor.visit(m_stream); + visitor.visit(m_cancel_algorithm); + visitor.visit(m_pull_algorithm); + visitor.visit(m_strategy_size_algorithm); } } diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.h b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.h index 322d471438..27bd00adac 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultController.h @@ -32,8 +32,8 @@ public: WebIDL::ExceptionOr enqueue(JS::Value chunk); void error(JS::Value error); - auto& cancel_algorithm() { return m_cancel_algorithm; } - void set_cancel_algorithm(Optional value) { m_cancel_algorithm = move(value); } + JS::GCPtr cancel_algorithm() { return m_cancel_algorithm; } + void set_cancel_algorithm(JS::GCPtr value) { m_cancel_algorithm = value; } bool close_requested() const { return m_close_requested; } void set_close_requested(bool value) { m_close_requested = value; } @@ -41,8 +41,8 @@ public: bool pull_again() const { return m_pull_again; } void set_pull_again(bool value) { m_pull_again = value; } - auto& pull_algorithm() { return m_pull_algorithm; } - void set_pull_algorithm(Optional value) { m_pull_algorithm = move(value); } + JS::GCPtr pull_algorithm() { return m_pull_algorithm; } + void set_pull_algorithm(JS::GCPtr value) { m_pull_algorithm = value; } bool pulling() const { return m_pulling; } void set_pulling(bool value) { m_pulling = value; } @@ -58,8 +58,8 @@ public: double strategy_hwm() const { return m_strategy_hwm; } void set_strategy_hwm(double value) { m_strategy_hwm = value; } - auto& strategy_size_algorithm() { return m_strategy_size_algorithm; } - void set_strategy_size_algorithm(Optional value) { m_strategy_size_algorithm = move(value); } + JS::GCPtr strategy_size_algorithm() { return m_strategy_size_algorithm; } + void set_strategy_size_algorithm(JS::GCPtr value) { m_strategy_size_algorithm = value; } JS::GCPtr stream() { return m_stream; } void set_stream(JS::GCPtr value) { m_stream = value; } @@ -75,7 +75,7 @@ private: // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-cancelalgorithm // A promise-returning algorithm, taking one argument (the cancel reason), which communicates a requested cancelation to the underlying source - Optional m_cancel_algorithm; + JS::GCPtr m_cancel_algorithm; // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-closerequested // A boolean flag indicating whether the stream has been closed by its underlying source, but still has chunks in its internal queue that have not yet been read @@ -87,7 +87,7 @@ private: // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pullalgorithm // A promise-returning algorithm that pulls data from the underlying source - Optional m_pull_algorithm; + JS::GCPtr m_pull_algorithm; // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pulling // A boolean flag set to true while the underlying source's pull algorithm is executing and the returned promise has not yet fulfilled, used to prevent reentrant calls @@ -111,7 +111,7 @@ private: // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-strategysizealgorithm // An algorithm to calculate the size of enqueued chunks, as part of the stream’s queuing strategy - Optional m_strategy_size_algorithm; + JS::GCPtr m_strategy_size_algorithm; // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-stream // The ReadableStream instance controlled diff --git a/Userland/Libraries/LibWeb/Streams/TransformStream.cpp b/Userland/Libraries/LibWeb/Streams/TransformStream.cpp index 0eb1a708a3..e7a9700973 100644 --- a/Userland/Libraries/LibWeb/Streams/TransformStream.cpp +++ b/Userland/Libraries/LibWeb/Streams/TransformStream.cpp @@ -42,13 +42,13 @@ WebIDL::ExceptionOr> TransformStream::construc auto readable_high_water_mark = TRY(extract_high_water_mark(readable_strategy, 0)); // 6. Let readableSizeAlgorithm be ! ExtractSizeAlgorithm(readableStrategy). - auto readable_size_algorithm = extract_size_algorithm(readable_strategy); + auto readable_size_algorithm = extract_size_algorithm(vm, readable_strategy); // 7. Let writableHighWaterMark be ? ExtractHighWaterMark(writableStrategy, 1). auto writable_high_water_mark = TRY(extract_high_water_mark(writable_strategy, 1)); // 8. Let writableSizeAlgorithm be ! ExtractSizeAlgorithm(writableStrategy). - auto writable_size_algorithm = extract_size_algorithm(writable_strategy); + auto writable_size_algorithm = extract_size_algorithm(vm, writable_strategy); // 9. Let startPromise be a new promise. auto start_promise = WebIDL::create_promise(realm); diff --git a/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.cpp b/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.cpp index ebd7a3a254..c856581fb9 100644 --- a/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.cpp +++ b/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.cpp @@ -29,6 +29,8 @@ void TransformStreamDefaultController::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_stream); + visitor.visit(m_flush_algorithm); + visitor.visit(m_transform_algorithm); } // https://streams.spec.whatwg.org/#ts-default-controller-desired-size diff --git a/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.h b/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.h index df8ce807e0..cd6bf0c171 100644 --- a/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.h +++ b/Userland/Libraries/LibWeb/Streams/TransformStreamDefaultController.h @@ -24,11 +24,11 @@ public: WebIDL::ExceptionOr error(Optional reason = {}); WebIDL::ExceptionOr terminate(); - auto& flush_algorithm() { return m_flush_algorithm; } - void set_flush_algorithm(Optional&& value) { m_flush_algorithm = move(value); } + JS::GCPtr flush_algorithm() { return m_flush_algorithm; } + void set_flush_algorithm(JS::GCPtr&& value) { m_flush_algorithm = move(value); } - auto& transform_algorithm() { return m_transform_algorithm; } - void set_transform_algorithm(Optional&& value) { m_transform_algorithm = move(value); } + JS::GCPtr transform_algorithm() { return m_transform_algorithm; } + void set_transform_algorithm(JS::GCPtr&& value) { m_transform_algorithm = move(value); } JS::GCPtr stream() { return m_stream; } void set_stream(JS::GCPtr stream) { m_stream = stream; } @@ -39,10 +39,10 @@ private: virtual void visit_edges(Cell::Visitor&) override; // https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-flushalgorithm - Optional m_flush_algorithm; + JS::GCPtr m_flush_algorithm; // https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-transformalgorithm - Optional m_transform_algorithm; + JS::GCPtr m_transform_algorithm; // https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-stream JS::GCPtr m_stream; diff --git a/Userland/Libraries/LibWeb/Streams/WritableStream.cpp b/Userland/Libraries/LibWeb/Streams/WritableStream.cpp index 30b82cffec..bbad973dc6 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStream.cpp +++ b/Userland/Libraries/LibWeb/Streams/WritableStream.cpp @@ -39,7 +39,7 @@ WebIDL::ExceptionOr> WritableStream::construct_ // Note: This AO configures slot values which are already specified in the class's field initializers. // 5. Let sizeAlgorithm be ! ExtractSizeAlgorithm(strategy). - auto size_algorithm = extract_size_algorithm(strategy); + auto size_algorithm = extract_size_algorithm(vm, strategy); // 6. Let highWaterMark be ? ExtractHighWaterMark(strategy, 1). auto high_water_mark = TRY(extract_high_water_mark(strategy, 1)); diff --git a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.cpp b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.cpp index 6b8a6d2730..28329406b0 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.cpp +++ b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.cpp @@ -19,6 +19,10 @@ void WritableStreamDefaultController::visit_edges(Visitor& visitor) for (auto& value : m_queue) visitor.visit(value.value); visitor.visit(m_stream); + visitor.visit(m_abort_algorithm); + visitor.visit(m_close_algorithm); + visitor.visit(m_strategy_size_algorithm); + visitor.visit(m_write_algorithm); } // https://streams.spec.whatwg.org/#ws-default-controller-error @@ -39,7 +43,7 @@ WebIDL::ExceptionOr WritableStreamDefaultController::error(JS::Value error WebIDL::ExceptionOr> WritableStreamDefaultController::abort_steps(JS::Value reason) { // 1. Let result be the result of performing this.[[abortAlgorithm]], passing reason. - auto result = TRY((*m_abort_algorithm)(reason)); + auto result = TRY(m_abort_algorithm->function()(reason)); // 2. Perform ! WritableStreamDefaultControllerClearAlgorithms(this). writable_stream_default_controller_clear_algorithms(*this); diff --git a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.h b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.h index 15a9a80490..14c66dae5a 100644 --- a/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.h +++ b/Userland/Libraries/LibWeb/Streams/WritableStreamDefaultController.h @@ -24,11 +24,11 @@ public: JS::NonnullGCPtr signal() { return *m_signal; } void set_signal(JS::NonnullGCPtr value) { m_signal = value; } - auto& abort_algorithm() { return m_abort_algorithm; } - void set_abort_algorithm(Optional&& value) { m_abort_algorithm = move(value); } + JS::GCPtr abort_algorithm() { return m_abort_algorithm; } + void set_abort_algorithm(JS::GCPtr value) { m_abort_algorithm = value; } - auto& close_algorithm() { return m_close_algorithm; } - void set_close_algorithm(Optional&& value) { m_close_algorithm = move(value); } + JS::GCPtr close_algorithm() { return m_close_algorithm; } + void set_close_algorithm(JS::GCPtr value) { m_close_algorithm = value; } SinglyLinkedList& queue() { return m_queue; } @@ -41,14 +41,14 @@ public: size_t strategy_hwm() const { return m_strategy_hwm; } void set_strategy_hwm(size_t value) { m_strategy_hwm = value; } - auto& strategy_size_algorithm() { return m_strategy_size_algorithm; } - void set_strategy_size_algorithm(Optional&& value) { m_strategy_size_algorithm = move(value); } + JS::GCPtr strategy_size_algorithm() { return m_strategy_size_algorithm; } + void set_strategy_size_algorithm(JS::GCPtr value) { m_strategy_size_algorithm = value; } JS::NonnullGCPtr stream() { return *m_stream; } void set_stream(JS::NonnullGCPtr value) { m_stream = value; } - auto& write_algorithm() { return m_write_algorithm; } - void set_write_algorithm(Optional&& value) { m_write_algorithm = move(value); } + JS::GCPtr write_algorithm() { return m_write_algorithm; } + void set_write_algorithm(JS::GCPtr value) { m_write_algorithm = value; } WebIDL::ExceptionOr> abort_steps(JS::Value reason); void error_steps(); @@ -60,11 +60,11 @@ private: // https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-abortalgorithm // A promise-returning algorithm, taking one argument (the abort reason), which communicates a requested abort to the underlying sink - Optional m_abort_algorithm; + JS::GCPtr m_abort_algorithm; // https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-closealgorithm // A promise-returning algorithm which communicates a requested close to the underlying sink - Optional m_close_algorithm; + JS::GCPtr m_close_algorithm; // https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-queue // A list representing the stream’s internal queue of chunks @@ -88,7 +88,7 @@ private: // https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-strategysizealgorithm // An algorithm to calculate the size of enqueued chunks, as part of the stream’s queuing strategy - Optional m_strategy_size_algorithm; + JS::GCPtr m_strategy_size_algorithm; // https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-stream // The WritableStream instance controlled @@ -96,7 +96,7 @@ private: // https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-writealgorithm // A promise-returning algorithm, taking one argument (the chunk to write), which writes data to the underlying sink - Optional m_write_algorithm; + JS::GCPtr m_write_algorithm; }; }