LibWeb: Port Stream algorithms from JS::SafeFunction to JS::HeapFunction

This commit is contained in:
Shannon Booth 2024-01-26 18:54:24 +13:00 committed by Tim Flynn
parent e118430648
commit 5f484d200a
Notes: sideshowbarker 2024-07-17 04:49:48 +09:00
14 changed files with 211 additions and 189 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Heap/HeapFunction.h>
#include <LibJS/Runtime/PromiseCapability.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Fetch/BodyInit.h>
@ -55,14 +56,22 @@ JS::NonnullGCPtr<Body> Body::clone(JS::Realm& realm) const
// FIXME: 2. Set bodys stream to out1.
JS::GCPtr<Streams::ReadableStream> 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<JS::Value> {
return JS::js_undefined();
});
auto pull_algorithm = JS::create_heap_function(realm.heap(), [&realm]() -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
return WebIDL::create_resolved_promise(realm, JS::js_undefined());
});
auto cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm](JS::Value) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
return WebIDL::create_resolved_promise(realm, JS::js_undefined());
});
if (m_stream->controller()->has<JS::NonnullGCPtr<Streams::ReadableStreamDefaultController>>()) {
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.

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023, Kenneth Myhra <kennethmyhra@serenityos.org>
*
* 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<SizeAlgorithm> 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<void> 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<void> 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<JS::Value> {
@ -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<void> 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<void> set_up_readable_stream_default_controller(ReadableStream& stream, ReadableStreamDefaultController& controller, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<PullAlgorithm> pull_algorithm, JS::NonnullGCPtr<CancelAlgorithm> cancel_algorithm, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> size_algorithm)
{
auto& realm = stream.realm();
@ -1336,20 +1335,20 @@ WebIDL::ExceptionOr<void> 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<void> set_up_readable_stream_default_controller(ReadableStre
}
// https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source
WebIDL::ExceptionOr<void> 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<void> 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<SizeAlgorithm> size_algorithm)
{
auto& realm = stream.realm();
@ -1391,46 +1390,48 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underly
auto controller = stream.heap().allocate<ReadableStreamDefaultController>(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<JS::Value> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::Value> {
start_algorithm = JS::create_heap_function(realm.heap(), [controller, underlying_source_value, callback = underlying_source.start]() -> WebIDL::ExceptionOr<JS::Value> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
pull_algorithm = JS::create_heap_function(realm.heap(), [&realm, controller, underlying_source_value, callback = underlying_source.pull]() -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_source_value, callback = underlying_source.cancel](JS::Value reason) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<void> 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<JS::Value> {
@ -1712,15 +1713,15 @@ bool readable_byte_stream_controller_should_call_pull(ReadableByteStreamControll
}
// https://streams.spec.whatwg.org/#create-readable-stream
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> create_readable_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm, Optional<double> high_water_mark, Optional<SizeAlgorithm>&& size_algorithm)
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> create_readable_stream(JS::Realm& realm, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<PullAlgorithm> pull_algorithm, JS::NonnullGCPtr<CancelAlgorithm> cancel_algorithm, Optional<double> high_water_mark, JS::GCPtr<SizeAlgorithm> 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<JS::NonnullGCPtr<ReadableStream>> create_readable_stream(JS:
auto controller = realm.heap().allocate<ReadableStreamDefaultController>(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<JS::NonnullGCPtr<ReadableStream>> create_readable_byte_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm)
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> create_readable_byte_stream(JS::Realm& realm, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<PullAlgorithm> pull_algorithm, JS::NonnullGCPtr<CancelAlgorithm> cancel_algorithm)
{
// 1. Let stream be a new ReadableStream.
auto stream = realm.heap().allocate<ReadableStream>(realm, realm);
@ -1754,14 +1755,14 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> create_readable_byte_strea
auto controller = realm.heap().allocate<ReadableByteStreamController>(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<JS::NonnullGCPtr<WritableStream>> 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<JS::NonnullGCPtr<WritableStream>> create_writable_stream(JS::Realm& realm, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<WriteAlgorithm> write_algorithm, JS::NonnullGCPtr<CloseAlgorithm> close_algorithm, JS::NonnullGCPtr<AbortAlgorithm> abort_algorithm, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> size_algorithm)
{
// 1. Assert: ! IsNonNegativeNumber(highWaterMark) is true.
VERIFY(is_non_negative_number(JS::Value { high_water_mark }));
@ -1921,7 +1922,7 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_writer(WritableStreamDe
}
// https://streams.spec.whatwg.org/#set-up-readable-byte-stream-controller
WebIDL::ExceptionOr<void> 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<void> set_up_readable_byte_stream_controller(ReadableStream& stream, ReadableByteStreamController& controller, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<PullAlgorithm> pull_algorithm, JS::NonnullGCPtr<CancelAlgorithm> cancel_algorithm, double high_water_mark, JS::Value auto_allocate_chunk_size)
{
auto& realm = stream.realm();
@ -1958,10 +1959,10 @@ WebIDL::ExceptionOr<void> 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<void> 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<void> set_up_readable_stream_controller_with_byte_reading_support(ReadableStream& stream, Optional<PullAlgorithm>&& pull_algorithm, Optional<CancelAlgorithm>&& cancel_algorithm, double high_water_mark)
WebIDL::ExceptionOr<void> set_up_readable_stream_controller_with_byte_reading_support(ReadableStream& stream, JS::GCPtr<PullAlgorithm> pull_algorithm, JS::GCPtr<CancelAlgorithm> 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<JS::Value> { 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<JS::NonnullGCPtr<WebIDL::Promise>> {
auto pull_algorithm_wrapper = JS::create_heap_function(realm.heap(), [&realm, pull_algorithm]() -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::PromiseCapability> 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<void> 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<JS::NonnullGCPtr<WebIDL::Promise>> {
auto cancel_algorithm_wrapper = JS::create_heap_function(realm.heap(), [&realm, cancel_algorithm](JS::Value c) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::PromiseCapability> 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<void> 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<ReadableByteStreamController>(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<JS::NonnullGCPtr<WebIDL::Promise>> writable_stream_default_w
}
// https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller
WebIDL::ExceptionOr<void> 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<void> set_up_writable_stream_default_controller(WritableStream& stream, WritableStreamDefaultController& controller, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<WriteAlgorithm> write_algorithm, JS::NonnullGCPtr<CloseAlgorithm> close_algorithm, JS::NonnullGCPtr<AbortAlgorithm> abort_algorithm, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> size_algorithm)
{
auto& realm = stream.realm();
@ -3071,19 +3072,19 @@ WebIDL::ExceptionOr<void> 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<void> 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<void> set_up_writable_stream_default_controller(WritableStre
}
// https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller-from-underlying-sink
WebIDL::ExceptionOr<void> 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<void> 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<SizeAlgorithm> size_algorithm)
{
auto& realm = stream.realm();
@ -3139,60 +3140,60 @@ WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underly
auto controller = realm.heap().allocate<WritableStreamDefaultController>(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<JS::Value> { 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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::Value> {
start_algorithm = JS::create_heap_function(realm.heap(), [controller, underlying_sink_value, callback = underlying_sink.start]() -> WebIDL::ExceptionOr<JS::Value> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
write_algorithm = JS::create_heap_function(realm.heap(), [&realm, controller, underlying_sink_value, callback = underlying_sink.write](JS::Value chunk) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
close_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.close]() -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
abort_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_sink_value, callback = underlying_sink.abort](JS::Value reason) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::Value> 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<void> 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<void> 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<JS::Value> {
@ -3472,56 +3473,57 @@ WebIDL::ExceptionOr<void> writable_stream_default_controller_write(WritableStrea
}
// https://streams.spec.whatwg.org/#initialize-transform-stream
WebIDL::ExceptionOr<void> initialize_transform_stream(TransformStream& stream, JS::NonnullGCPtr<JS::PromiseCapability> start_promise, double writable_high_water_mark, SizeAlgorithm&& writable_size_algorithm, double readable_high_water_mark, SizeAlgorithm&& readable_size_algorithm)
WebIDL::ExceptionOr<void> initialize_transform_stream(TransformStream& stream, JS::NonnullGCPtr<JS::PromiseCapability> start_promise, double writable_high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> writable_size_algorithm, double readable_high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> 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<JS::Value> {
return start_promise->promise();
};
StartAlgorithm readable_start_algorithm = [start_promise] {
});
auto readable_start_algorithm = JS::create_heap_function(realm.heap(), [start_promise]() -> WebIDL::ExceptionOr<JS::Value> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
auto cancel_algorithm = JS::create_heap_function(realm.heap(), [&stream, &realm](JS::Value reason) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<void> 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<TransformAlgorithm> transform_algorithm, JS::NonnullGCPtr<FlushAlgorithm> 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<void> set_up_transform_stream_default_controller_from_transf
auto controller = realm.heap().allocate<TransformStreamDefaultController>(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<JS::NonnullGCPtr<WebIDL::Promise>> {
// 1. Let result be TransformStreamDefaultControllerEnqueue(controller, chunk).
auto result = transform_stream_default_controller_enqueue(*controller, chunk);
@ -3578,41 +3580,41 @@ WebIDL::ExceptionOr<void> 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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
transform_algorithm = JS::create_heap_function(realm.heap(), [controller, &realm, transformer, callback = transformer_dict.transform](JS::Value chunk) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
flush_algorithm = JS::create_heap_function(realm.heap(), [&realm, transformer, callback = transformer_dict.flush, controller]() -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> 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<JS::NonnullGCPtr<WebIDL::Promise>> 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<void> set_up_readable_byte_stream_controller_from_underlying
auto controller = stream.heap().allocate<ReadableByteStreamController>(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<JS::Value> { 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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::NonnullGCPtr<WebIDL::Promise>> {
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<JS::Value> {
start_algorithm = JS::create_heap_function(realm.heap(), [controller, underlying_source, callback = underlying_source_dict.start]() -> WebIDL::ExceptionOr<JS::Value> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
pull_algorithm = JS::create_heap_function(realm.heap(), [&realm, controller, underlying_source, callback = underlying_source_dict.pull]() -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<JS::NonnullGCPtr<WebIDL::Promise>> {
cancel_algorithm = JS::create_heap_function(realm.heap(), [&realm, underlying_source, callback = underlying_source_dict.cancel](JS::Value reason) -> WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> {
// 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<void> 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);
}
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023, Kenneth Myhra <kennethmyhra@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -18,21 +18,21 @@
namespace Web::Streams {
using SizeAlgorithm = JS::SafeFunction<JS::Completion(JS::Value)>;
using PullAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>()>;
using CancelAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using StartAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::Value>()>;
using AbortAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using CloseAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>()>;
using WriteAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using FlushAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>()>;
using TransformAlgorithm = JS::SafeFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using SizeAlgorithm = JS::HeapFunction<JS::Completion(JS::Value)>;
using PullAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>()>;
using CancelAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using StartAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::Value>()>;
using AbortAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using CloseAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>()>;
using WriteAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
using FlushAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>()>;
using TransformAlgorithm = JS::HeapFunction<WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>>(JS::Value)>;
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStreamDefaultReader>> acquire_readable_stream_default_reader(ReadableStream&);
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStreamBYOBReader>> acquire_readable_stream_byob_reader(ReadableStream&);
bool is_readable_stream_locked(ReadableStream const&);
SizeAlgorithm extract_size_algorithm(QueuingStrategy const&);
JS::NonnullGCPtr<SizeAlgorithm> extract_size_algorithm(JS::VM&, QueuingStrategy const&);
WebIDL::ExceptionOr<double> 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<double> readable_stream_default_controller_get_desired_size(ReadableStreamDefaultController&);
bool readable_stream_default_controller_can_close_or_enqueue(ReadableStreamDefaultController&);
WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller(ReadableStream&, ReadableStreamDefaultController&, StartAlgorithm&&, PullAlgorithm&&, CancelAlgorithm&&, double high_water_mark, SizeAlgorithm&&);
WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underlying_source(ReadableStream&, JS::Value underlying_source_value, UnderlyingSource, double high_water_mark, SizeAlgorithm&&);
WebIDL::ExceptionOr<void> set_up_readable_stream_controller_with_byte_reading_support(ReadableStream&, Optional<PullAlgorithm>&& = {}, Optional<CancelAlgorithm>&& = {}, double high_water_mark = 0);
WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller(ReadableStream&, ReadableByteStreamController&, StartAlgorithm&&, PullAlgorithm&&, CancelAlgorithm&&, double high_water_mark, JS::Value auto_allocate_chunk_size);
WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller(ReadableStream&, ReadableStreamDefaultController&, JS::NonnullGCPtr<StartAlgorithm>, JS::NonnullGCPtr<PullAlgorithm>, JS::NonnullGCPtr<CancelAlgorithm>, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm>);
WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underlying_source(ReadableStream&, JS::Value underlying_source_value, UnderlyingSource, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm>);
WebIDL::ExceptionOr<void> set_up_readable_stream_controller_with_byte_reading_support(ReadableStream&, JS::GCPtr<PullAlgorithm> = {}, JS::GCPtr<CancelAlgorithm> = {}, double high_water_mark = 0);
WebIDL::ExceptionOr<void> set_up_readable_byte_stream_controller(ReadableStream&, ReadableByteStreamController&, JS::NonnullGCPtr<StartAlgorithm>, JS::NonnullGCPtr<PullAlgorithm>, JS::NonnullGCPtr<CancelAlgorithm>, double high_water_mark, JS::Value auto_allocate_chunk_size);
WebIDL::ExceptionOr<void> 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<ReadableStreamBYOBRequest> readable_byte_stream_controller_get_byob_request(JS::NonnullGCPtr<ReadableByteStreamController>);
@ -108,9 +108,9 @@ WebIDL::ExceptionOr<void> 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<JS::NonnullGCPtr<ReadableStream>> create_readable_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm, Optional<double> high_water_mark = {}, Optional<SizeAlgorithm>&& size_algorithm = {});
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> create_readable_byte_stream(JS::Realm& realm, StartAlgorithm&& start_algorithm, PullAlgorithm&& pull_algorithm, CancelAlgorithm&& cancel_algorithm);
WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStream>> 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<JS::NonnullGCPtr<ReadableStream>> create_readable_stream(JS::Realm& realm, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<PullAlgorithm> pull_algorithm, JS::NonnullGCPtr<CancelAlgorithm> cancel_algorithm, Optional<double> high_water_mark = {}, JS::GCPtr<SizeAlgorithm> size_algorithm = {});
WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> create_readable_byte_stream(JS::Realm& realm, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<PullAlgorithm> pull_algorithm, JS::NonnullGCPtr<CancelAlgorithm> cancel_algorithm);
WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStream>> create_writable_stream(JS::Realm& realm, JS::NonnullGCPtr<StartAlgorithm> start_algorithm, JS::NonnullGCPtr<WriteAlgorithm> write_algorithm, JS::NonnullGCPtr<CloseAlgorithm> close_algorithm, JS::NonnullGCPtr<AbortAlgorithm> abort_algorithm, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> size_algorithm);
void initialize_readable_stream(ReadableStream&);
void initialize_writable_stream(WritableStream&);
@ -143,8 +143,8 @@ Optional<double> writable_stream_default_writer_get_desired_size(WritableStreamD
WebIDL::ExceptionOr<void> writable_stream_default_writer_release(WritableStreamDefaultWriter&);
WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> writable_stream_default_writer_write(WritableStreamDefaultWriter&, JS::Value chunk);
WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller(WritableStream&, WritableStreamDefaultController&, StartAlgorithm&&, WriteAlgorithm&&, CloseAlgorithm&&, AbortAlgorithm&&, double high_water_mark, SizeAlgorithm&&);
WebIDL::ExceptionOr<void> 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<void> set_up_writable_stream_default_controller(WritableStream&, WritableStreamDefaultController&, JS::NonnullGCPtr<StartAlgorithm>, JS::NonnullGCPtr<WriteAlgorithm>, JS::NonnullGCPtr<CloseAlgorithm>, JS::NonnullGCPtr<AbortAlgorithm>, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm>);
WebIDL::ExceptionOr<void> set_up_writable_stream_default_controller_from_underlying_sink(WritableStream&, JS::Value underlying_sink_value, UnderlyingSink&, double high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> size_algorithm);
WebIDL::ExceptionOr<void> writable_stream_default_controller_advance_queue_if_needed(WritableStreamDefaultController&);
void writable_stream_default_controller_clear_algorithms(WritableStreamDefaultController&);
WebIDL::ExceptionOr<void> writable_stream_default_controller_close(WritableStreamDefaultController&);
@ -157,8 +157,8 @@ WebIDL::ExceptionOr<void> writable_stream_default_controller_process_close(Writa
WebIDL::ExceptionOr<void> writable_stream_default_controller_process_write(WritableStreamDefaultController&, JS::Value chunk);
WebIDL::ExceptionOr<void> writable_stream_default_controller_write(WritableStreamDefaultController&, JS::Value chunk, JS::Value chunk_size);
WebIDL::ExceptionOr<void> initialize_transform_stream(TransformStream&, JS::NonnullGCPtr<JS::PromiseCapability> 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<void> initialize_transform_stream(TransformStream&, JS::NonnullGCPtr<JS::PromiseCapability> start_promise, double writable_high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> writable_size_algorithm, double readable_high_water_mark, JS::NonnullGCPtr<SizeAlgorithm> readable_size_algorithm);
void set_up_transform_stream_default_controller(TransformStream&, TransformStreamDefaultController&, JS::NonnullGCPtr<TransformAlgorithm>, JS::NonnullGCPtr<FlushAlgorithm>);
WebIDL::ExceptionOr<void> set_up_transform_stream_default_controller_from_transformer(TransformStream&, JS::Value transformer, Transformer&);
void transform_stream_default_controller_clear_algorithms(TransformStreamDefaultController&);
WebIDL::ExceptionOr<void> transform_stream_default_controller_enqueue(TransformStreamDefaultController&, JS::Value chunk);

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -98,7 +98,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> 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);
}
}

View file

@ -94,8 +94,8 @@ public:
Optional<u64> const& auto_allocate_chunk_size() { return m_auto_allocate_chunk_size; }
void set_auto_allocate_chunk_size(Optional<u64> value) { m_auto_allocate_chunk_size = value; }
auto& cancel_algorithm() { return m_cancel_algorithm; }
void set_cancel_algorithm(Optional<CancelAlgorithm> value) { m_cancel_algorithm = move(value); }
JS::GCPtr<CancelAlgorithm> cancel_algorithm() { return m_cancel_algorithm; }
void set_cancel_algorithm(JS::GCPtr<CancelAlgorithm> 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<PullAlgorithm> value) { m_pull_algorithm = move(value); }
JS::GCPtr<PullAlgorithm> pull_algorithm() { return m_pull_algorithm; }
void set_pull_algorithm(JS::GCPtr<PullAlgorithm> 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<CancelAlgorithm> m_cancel_algorithm;
JS::GCPtr<CancelAlgorithm> 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<PullAlgorithm> m_pull_algorithm;
JS::GCPtr<PullAlgorithm> 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

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -53,13 +53,13 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<ReadableStream>> 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;

View file

@ -71,7 +71,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WebIDL::Promise>> 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);
}
}

View file

@ -32,8 +32,8 @@ public:
WebIDL::ExceptionOr<void> enqueue(JS::Value chunk);
void error(JS::Value error);
auto& cancel_algorithm() { return m_cancel_algorithm; }
void set_cancel_algorithm(Optional<CancelAlgorithm> value) { m_cancel_algorithm = move(value); }
JS::GCPtr<CancelAlgorithm> cancel_algorithm() { return m_cancel_algorithm; }
void set_cancel_algorithm(JS::GCPtr<CancelAlgorithm> 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<PullAlgorithm> value) { m_pull_algorithm = move(value); }
JS::GCPtr<PullAlgorithm> pull_algorithm() { return m_pull_algorithm; }
void set_pull_algorithm(JS::GCPtr<PullAlgorithm> 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<SizeAlgorithm> value) { m_strategy_size_algorithm = move(value); }
JS::GCPtr<SizeAlgorithm> strategy_size_algorithm() { return m_strategy_size_algorithm; }
void set_strategy_size_algorithm(JS::GCPtr<SizeAlgorithm> value) { m_strategy_size_algorithm = value; }
JS::GCPtr<ReadableStream> stream() { return m_stream; }
void set_stream(JS::GCPtr<ReadableStream> 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<CancelAlgorithm> m_cancel_algorithm;
JS::GCPtr<CancelAlgorithm> 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<PullAlgorithm> m_pull_algorithm;
JS::GCPtr<PullAlgorithm> 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 streams queuing strategy
Optional<SizeAlgorithm> m_strategy_size_algorithm;
JS::GCPtr<SizeAlgorithm> m_strategy_size_algorithm;
// https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-stream
// The ReadableStream instance controlled

View file

@ -42,13 +42,13 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<TransformStream>> 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);

View file

@ -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

View file

@ -24,11 +24,11 @@ public:
WebIDL::ExceptionOr<void> error(Optional<JS::Value> reason = {});
WebIDL::ExceptionOr<void> terminate();
auto& flush_algorithm() { return m_flush_algorithm; }
void set_flush_algorithm(Optional<FlushAlgorithm>&& value) { m_flush_algorithm = move(value); }
JS::GCPtr<FlushAlgorithm> flush_algorithm() { return m_flush_algorithm; }
void set_flush_algorithm(JS::GCPtr<FlushAlgorithm>&& value) { m_flush_algorithm = move(value); }
auto& transform_algorithm() { return m_transform_algorithm; }
void set_transform_algorithm(Optional<TransformAlgorithm>&& value) { m_transform_algorithm = move(value); }
JS::GCPtr<TransformAlgorithm> transform_algorithm() { return m_transform_algorithm; }
void set_transform_algorithm(JS::GCPtr<TransformAlgorithm>&& value) { m_transform_algorithm = move(value); }
JS::GCPtr<TransformStream> stream() { return m_stream; }
void set_stream(JS::GCPtr<TransformStream> stream) { m_stream = stream; }
@ -39,10 +39,10 @@ private:
virtual void visit_edges(Cell::Visitor&) override;
// https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-flushalgorithm
Optional<FlushAlgorithm> m_flush_algorithm;
JS::GCPtr<FlushAlgorithm> m_flush_algorithm;
// https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-transformalgorithm
Optional<TransformAlgorithm> m_transform_algorithm;
JS::GCPtr<TransformAlgorithm> m_transform_algorithm;
// https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-stream
JS::GCPtr<TransformStream> m_stream;

View file

@ -39,7 +39,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStream>> 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));

View file

@ -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<void> WritableStreamDefaultController::error(JS::Value error
WebIDL::ExceptionOr<JS::GCPtr<WebIDL::Promise>> 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);

View file

@ -24,11 +24,11 @@ public:
JS::NonnullGCPtr<DOM::AbortSignal> signal() { return *m_signal; }
void set_signal(JS::NonnullGCPtr<DOM::AbortSignal> value) { m_signal = value; }
auto& abort_algorithm() { return m_abort_algorithm; }
void set_abort_algorithm(Optional<AbortAlgorithm>&& value) { m_abort_algorithm = move(value); }
JS::GCPtr<AbortAlgorithm> abort_algorithm() { return m_abort_algorithm; }
void set_abort_algorithm(JS::GCPtr<AbortAlgorithm> value) { m_abort_algorithm = value; }
auto& close_algorithm() { return m_close_algorithm; }
void set_close_algorithm(Optional<CloseAlgorithm>&& value) { m_close_algorithm = move(value); }
JS::GCPtr<CloseAlgorithm> close_algorithm() { return m_close_algorithm; }
void set_close_algorithm(JS::GCPtr<CloseAlgorithm> value) { m_close_algorithm = value; }
SinglyLinkedList<ValueWithSize>& 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<SizeAlgorithm>&& value) { m_strategy_size_algorithm = move(value); }
JS::GCPtr<SizeAlgorithm> strategy_size_algorithm() { return m_strategy_size_algorithm; }
void set_strategy_size_algorithm(JS::GCPtr<SizeAlgorithm> value) { m_strategy_size_algorithm = value; }
JS::NonnullGCPtr<WritableStream> stream() { return *m_stream; }
void set_stream(JS::NonnullGCPtr<WritableStream> value) { m_stream = value; }
auto& write_algorithm() { return m_write_algorithm; }
void set_write_algorithm(Optional<WriteAlgorithm>&& value) { m_write_algorithm = move(value); }
JS::GCPtr<WriteAlgorithm> write_algorithm() { return m_write_algorithm; }
void set_write_algorithm(JS::GCPtr<WriteAlgorithm> value) { m_write_algorithm = value; }
WebIDL::ExceptionOr<JS::GCPtr<WebIDL::Promise>> 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<AbortAlgorithm> m_abort_algorithm;
JS::GCPtr<AbortAlgorithm> m_abort_algorithm;
// https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-closealgorithm
// A promise-returning algorithm which communicates a requested close to the underlying sink
Optional<CloseAlgorithm> m_close_algorithm;
JS::GCPtr<CloseAlgorithm> m_close_algorithm;
// https://streams.spec.whatwg.org/#writablestreamdefaultcontroller-queue
// A list representing the streams 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 streams queuing strategy
Optional<SizeAlgorithm> m_strategy_size_algorithm;
JS::GCPtr<SizeAlgorithm> 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<WriteAlgorithm> m_write_algorithm;
JS::GCPtr<WriteAlgorithm> m_write_algorithm;
};
}