diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2023-04-11 16:33:32 -0700 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-04-12 01:47:48 +0200 |
commit | 819b6332d13b38521f21fcdf848fb794027ad59d (patch) | |
tree | 1fa946d4d8aa04015288afccf2b456f586cd38a4 | |
parent | c7aa4fa166163ac877daeefe46b85a09d8b77454 (diff) | |
download | serenity-819b6332d13b38521f21fcdf848fb794027ad59d.zip |
LibWeb: Add ReadableStreamByteController interface
10 files changed, 253 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 76dabc2736..14c8a9a400 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -464,6 +464,7 @@ set(SOURCES ResizeObserver/ResizeObserver.cpp SecureContexts/AbstractOperations.cpp Streams/AbstractOperations.cpp + Streams/ReadableByteStreamController.cpp Streams/ReadableStream.cpp Streams/ReadableStreamBYOBRequest.cpp Streams/ReadableStreamDefaultController.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 47b0f117d1..8d13da0808 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -426,6 +426,7 @@ class Selection; namespace Web::Streams { class ReadableStream; +class ReadableByteStreamController; class ReadableStreamBYOBRequest; class ReadableStreamDefaultController; class ReadableStreamDefaultReader; diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp index 38535157af..9e0364d065 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.cpp @@ -10,6 +10,7 @@ #include <LibWeb/Bindings/ExceptionOrUtils.h> #include <LibWeb/DOM/AbortSignal.h> #include <LibWeb/Streams/AbstractOperations.h> +#include <LibWeb/Streams/ReadableByteStreamController.h> #include <LibWeb/Streams/ReadableStream.h> #include <LibWeb/Streams/ReadableStreamDefaultController.h> #include <LibWeb/Streams/ReadableStreamDefaultReader.h> @@ -739,6 +740,24 @@ WebIDL::ExceptionOr<void> set_up_readable_stream_default_controller_from_underly return set_up_readable_stream_default_controller(stream, controller, move(start_algorithm), move(pull_algorithm), move(cancel_algorithm), high_water_mark, move(size_algorithm)); } +// https://streams.spec.whatwg.org/#readable-byte-stream-controller-get-desired-size +Optional<double> readable_byte_stream_controller_get_desired_size(ReadableByteStreamController const& controller) +{ + auto stream = controller.stream(); + + // 1. Let state be controller.[[stream]].[[state]]. + // 2. If state is "errored", return null. + if (stream->is_errored()) + return {}; + + // 3. If state is "closed", return 0. + if (stream->is_closed()) + return 0.0; + + // 4. Return controller.[[strategyHWM]] − controller.[[queueTotalSize]]. + return controller.strategy_hwm() - controller.queue_total_size(); +} + // https://streams.spec.whatwg.org/#acquire-writable-stream-default-writer WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStreamDefaultWriter>> acquire_writable_stream_default_writer(WritableStream& stream) { diff --git a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h index 8c2cff90df..13b696b6be 100644 --- a/Userland/Libraries/LibWeb/Streams/AbstractOperations.h +++ b/Userland/Libraries/LibWeb/Streams/AbstractOperations.h @@ -53,6 +53,8 @@ bool readable_stream_default_controller_can_close_or_enqueue(ReadableStreamDefau 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&&); +Optional<double> readable_byte_stream_controller_get_desired_size(ReadableByteStreamController const&); + WebIDL::ExceptionOr<JS::NonnullGCPtr<WritableStreamDefaultWriter>> acquire_writable_stream_default_writer(WritableStream&); bool is_writable_stream_locked(WritableStream const&); WebIDL::ExceptionOr<void> set_up_writable_stream_default_writer(WritableStreamDefaultWriter&, WritableStream&); diff --git a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp new file mode 100644 index 0000000000..bcaa70c273 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/Streams/ReadableByteStreamController.h> +#include <LibWeb/Streams/ReadableStream.h> +#include <LibWeb/Streams/ReadableStreamBYOBRequest.h> + +namespace Web::Streams { + +// https://streams.spec.whatwg.org/#rbs-controller-desired-size +Optional<double> ReadableByteStreamController::desired_size() const +{ + // 1. Return ! ReadableByteStreamControllerGetDesiredSize(this). + return readable_byte_stream_controller_get_desired_size(*this); +} + +ReadableByteStreamController::ReadableByteStreamController(JS::Realm& realm) + : Bindings::PlatformObject(realm) +{ +} + +void ReadableByteStreamController::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_byob_request); + for (auto const& pending_pull_into : m_pending_pull_intos) { + visitor.visit(pending_pull_into.buffer); + visitor.visit(pending_pull_into.view_constructor); + } + for (auto const& item : m_queue) + visitor.visit(item.buffer); + visitor.visit(m_stream); +} + +} diff --git a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h new file mode 100644 index 0000000000..fd04225bff --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Optional.h> +#include <AK/SinglyLinkedList.h> +#include <LibWeb/Bindings/PlatformObject.h> +#include <LibWeb/Streams/AbstractOperations.h> + +namespace Web::Streams { + +enum class ReaderType { + Default, + Byob, + None, +}; + +// https://streams.spec.whatwg.org/#pull-into-descriptor +struct PullIntoDescriptor { + // https://streams.spec.whatwg.org/#pull-into-descriptor-buffer + // An ArrayBuffer + JS::NonnullGCPtr<JS::ArrayBuffer> buffer; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-buffer-byte-length + // A positive integer representing the initial byte length of buffer + u32 buffer_byte_length; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-byte-offset + // A nonnegative integer byte offset into the buffer where the underlying byte source will start writing + u32 byte_offset; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-byte-length + // A positive integer number of bytes which can be written into the buffer + u32 byte_length; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-bytes-filled + // A nonnegative integer number of bytes that have been written into the buffer so far + u32 bytes_filled; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-element-size + // A positive integer representing the number of bytes that can be written into the buffer at a time, using views of the type described by the view constructor + u32 element_size; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-view-constructor + // A typed array constructor or %DataView%, which will be used for constructing a view with which to write into the buffer + JS::NonnullGCPtr<JS::NativeFunction> view_constructor; + + // https://streams.spec.whatwg.org/#pull-into-descriptor-reader-type + // Either "default" or "byob", indicating what type of readable stream reader initiated this request, or "none" if the initiating reader was released + ReaderType reader_type; +}; + +// https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry +struct ReadableByteStreamQueueEntry { + // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry-buffer + // An ArrayBuffer, which will be a transferred version of the one originally supplied by the underlying byte source + JS::NonnullGCPtr<JS::ArrayBuffer> buffer; + + // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry-byte-offset + // A nonnegative integer number giving the byte offset derived from the view originally supplied by the underlying byte source + u32 byte_offset; + + // https://streams.spec.whatwg.org/#readable-byte-stream-queue-entry-byte-length + // A nonnegative integer number giving the byte length derived from the view originally supplied by the underlying byte source + u32 byte_length; +}; + +// https://streams.spec.whatwg.org/#readablebytestreamcontroller +class ReadableByteStreamController : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(ReadableByteStreamController, Bindings::PlatformObject); + +public: + virtual ~ReadableByteStreamController() override = default; + + JS::GCPtr<ReadableStreamBYOBRequest> byob_request() { return m_byob_request; } + void set_byob_request(JS::GCPtr<ReadableStreamBYOBRequest> request) { m_byob_request = request; } + + Optional<double> desired_size() const; + + Optional<u32> const& auto_allocate_chunk_size() { return m_auto_allocate_chunk_size; } + void set_auto_allocate_chunk_size(Optional<u32> 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); } + + bool close_requested() const { return m_close_requested; } + void set_close_requested(bool value) { m_close_requested = value; } + + 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); } + + bool pulling() const { return m_pulling; } + void set_pulling(bool value) { m_pulling = value; } + + SinglyLinkedList<PullIntoDescriptor>& pending_pull_intos() { return m_pending_pull_intos; } + + SinglyLinkedList<ReadableByteStreamQueueEntry>& queue() { return m_queue; } + + u32 queue_total_size() const { return m_queue_total_size; } + void set_queue_total_size(u32 size) { m_queue_total_size = size; } + + bool started() const { return m_started; } + void set_started(bool value) { m_started = value; } + + u32 strategy_hwm() const { return m_strategy_hwm; } + void set_strategy_hwm(u32 value) { m_strategy_hwm = value; } + + JS::GCPtr<ReadableStream const> stream() const { return m_stream; } + JS::GCPtr<ReadableStream> stream() { return m_stream; } + void set_stream(JS::GCPtr<ReadableStream> stream) { m_stream = stream; } + +private: + explicit ReadableByteStreamController(JS::Realm&); + + virtual void visit_edges(Cell::Visitor&) override; + + // https://streams.spec.whatwg.org/#readablebytestreamcontroller-autoallocatechunksize + // A positive integer, when the automatic buffer allocation feature is enabled. In that case, this value specifies the size of buffer to allocate. It is undefined otherwise. + Optional<u32> m_auto_allocate_chunk_size; + + // https://streams.spec.whatwg.org/#readablebytestreamcontroller-byobrequest + // A ReadableStreamBYOBRequest instance representing the current BYOB pull request, or null if there are no pending requests + JS::GCPtr<ReadableStreamBYOBRequest> m_byob_request; + + // 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; + + // 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 + bool m_close_requested { false }; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pullagain + // A boolean flag set to true if the stream’s mechanisms requested a call to the underlying source's pull algorithm to pull more data, but the pull could not yet be done since a previous call is still executing + bool m_pull_again { false }; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-pullalgorithm + // A promise-returning algorithm that pulls data from the underlying source + Optional<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 + bool m_pulling { false }; + + // https://streams.spec.whatwg.org/#readablebytestreamcontroller-pendingpullintos + // A list of pull-into descriptors + SinglyLinkedList<PullIntoDescriptor> m_pending_pull_intos; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-queue + // A list representing the stream’s internal queue of chunks + SinglyLinkedList<ReadableByteStreamQueueEntry> m_queue; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-queuetotalsize + // The total size of all the chunks stored in [[queue]] + u32 m_queue_total_size { 0 }; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-started + // A boolean flag indicating whether the underlying source has finished starting + bool m_started { false }; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-strategyhwm + // A number supplied to the constructor as part of the stream’s queuing strategy, indicating the point at which the stream will apply backpressure to its underlying source + u32 m_strategy_hwm { 0 }; + + // https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-stream + // The ReadableStream instance controlled + JS::GCPtr<ReadableStream> m_stream; +}; + +} diff --git a/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.idl b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.idl new file mode 100644 index 0000000000..27c4f4bb72 --- /dev/null +++ b/Userland/Libraries/LibWeb/Streams/ReadableByteStreamController.idl @@ -0,0 +1,12 @@ +#import <Streams/ReadableStreamBYOBRequest.idl> + +[Exposed=*] +interface ReadableByteStreamController { + readonly attribute ReadableStreamBYOBRequest? byobRequest; + readonly attribute unrestricted double? desiredSize; + + // FIXME: Implement + // undefined close(); + // undefined enqueue(ArrayBufferView chunk); + // undefined error(optional any e); +}; diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.cpp index a73ff2a125..1ab501dd00 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Streams/ReadableByteStreamController.h> #include <LibWeb/Streams/ReadableStreamBYOBRequest.h> namespace Web::Streams { diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.h b/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.h index e60253ad8f..29b74d24e0 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.h +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamBYOBRequest.h @@ -27,7 +27,7 @@ private: // https://streams.spec.whatwg.org/#readablestreambyobrequest-controller // The parent ReadableByteStreamController instance - JS::GCPtr<JS::Object> m_controller; + JS::GCPtr<ReadableByteStreamController> m_controller; // https://streams.spec.whatwg.org/#readablestreambyobrequest-view // A typed array representing the destination region to which the controller can write generated data, or null after the BYOB request has been invalidated. diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 0374e39b55..1c2c66077e 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -179,6 +179,7 @@ libweb_js_bindings(NavigationTiming/PerformanceTiming) libweb_js_bindings(PerformanceTimeline/PerformanceEntry) libweb_js_bindings(RequestIdleCallback/IdleDeadline) libweb_js_bindings(ResizeObserver/ResizeObserver) +libweb_js_bindings(Streams/ReadableByteStreamController) libweb_js_bindings(Streams/ReadableStream) libweb_js_bindings(Streams/ReadableStreamBYOBRequest) libweb_js_bindings(Streams/ReadableStreamDefaultController) |