diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp index ad0b24ba2c..660f18849c 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -2908,6 +2909,67 @@ void set_up_transform_stream_default_controller(TransformStream& stream, Transfo controller.set_flush_algorithm(move(flush_algorithm)); } +// https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller-from-transformer +WebIDL::ExceptionOr set_up_transform_stream_default_controller_from_transformer(TransformStream& stream, JS::Value transformer, Transformer& transformer_dict) +{ + auto& realm = stream.realm(); + auto& vm = realm.vm(); + + // 1. Let controller be a new TransformStreamDefaultController. + auto controller = MUST_OR_THROW_OOM(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) { + // 1. Let result be TransformStreamDefaultControllerEnqueue(controller, chunk). + auto result = transform_stream_default_controller_enqueue(*controller, chunk); + + // 2. If result is an abrupt completion, return a promise rejected with result.[[Value]]. + if (result.is_error()) { + auto throw_completion = Bindings::dom_exception_to_throw_completion(vm, result.exception()); + return WebIDL::create_rejected_promise(realm, *throw_completion.release_value()); + } + + // 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] { + 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> { + // 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> { + // 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)); + + return {}; +} + // https://streams.spec.whatwg.org/#transform-stream-default-controller-clear-algorithms void transform_stream_default_controller_clear_algorithms(TransformStreamDefaultController& controller) { diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h index d4678c0eed..52627f0b29 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -140,6 +140,7 @@ WebIDL::ExceptionOr writable_stream_default_controller_write(WritableStrea 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 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); WebIDL::ExceptionOr transform_stream_default_controller_error(TransformStreamDefaultController&, JS::Value error);