2022-09-21 23:27:13 +01:00
/*
* Copyright ( c ) 2022 , Linus Groh < linusg @ serenityos . org >
2024-01-26 18:54:24 +13:00
* Copyright ( c ) 2023 - 2024 , Shannon Booth < shannon @ serenityos . org >
2024-04-06 19:02:28 +02:00
* Copyright ( c ) 2024 , Kenneth Myhra < kennethmyhra @ serenityos . org >
2022-09-21 23:27:13 +01:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2023-03-28 20:01:04 -07:00
# include <LibJS/Runtime/PromiseCapability.h>
2024-12-08 17:28:44 +13:00
# include <LibJS/Runtime/TypedArray.h>
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/ReadableStreamPrototype.h>
2024-04-06 19:02:28 +02:00
# include <LibWeb/DOM/AbortSignal.h>
2022-09-21 23:27:13 +01:00
# include <LibWeb/Streams/AbstractOperations.h>
2023-04-08 12:25:32 -07:00
# include <LibWeb/Streams/ReadableByteStreamController.h>
2022-09-21 23:27:13 +01:00
# include <LibWeb/Streams/ReadableStream.h>
2023-04-09 01:26:48 -07:00
# include <LibWeb/Streams/ReadableStreamBYOBReader.h>
2024-12-23 16:20:02 +13:00
# include <LibWeb/Streams/ReadableStreamBYOBRequest.h>
2023-03-28 18:56:11 -07:00
# include <LibWeb/Streams/ReadableStreamDefaultController.h>
2023-03-28 18:30:22 -07:00
# include <LibWeb/Streams/ReadableStreamDefaultReader.h>
2024-12-26 12:02:07 +13:00
# include <LibWeb/Streams/TransformStream.h>
2023-03-28 19:11:22 -07:00
# include <LibWeb/Streams/UnderlyingSource.h>
2024-12-23 16:20:02 +13:00
# include <LibWeb/Streams/WritableStream.h>
# include <LibWeb/WebIDL/Buffers.h>
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
# include <LibWeb/WebIDL/ExceptionOr.h>
2022-09-21 23:27:13 +01:00
namespace Web : : Streams {
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( ReadableStream ) ;
2023-11-19 19:47:52 +01:00
2022-09-21 23:27:13 +01:00
// https://streams.spec.whatwg.org/#rs-constructor
2024-11-15 04:01:23 +13:00
WebIDL : : ExceptionOr < GC : : Ref < ReadableStream > > ReadableStream : : construct_impl ( JS : : Realm & realm , Optional < GC : : Root < JS : : Object > > const & underlying_source_object , QueuingStrategy const & strategy )
2022-09-21 23:27:13 +01:00
{
2023-04-12 23:21:17 +02:00
auto & vm = realm . vm ( ) ;
2024-11-14 05:50:17 +13:00
auto readable_stream = realm . create < ReadableStream > ( realm ) ;
2023-03-28 19:11:22 -07:00
// 1. If underlyingSource is missing, set it to null.
2023-12-18 14:01:39 -07:00
auto underlying_source = underlying_source_object . has_value ( ) ? JS : : Value ( underlying_source_object . value ( ) ) : JS : : js_null ( ) ;
2023-03-28 19:11:22 -07:00
// 2. Let underlyingSourceDict be underlyingSource, converted to an IDL value of type UnderlyingSource.
2023-04-12 23:21:17 +02:00
auto underlying_source_dict = TRY ( UnderlyingSource : : from_value ( vm , underlying_source ) ) ;
2023-03-28 19:11:22 -07:00
// 3. Perform ! InitializeReadableStream(this).
// 4. If underlyingSourceDict["type"] is "bytes":
if ( underlying_source_dict . type . has_value ( ) & & underlying_source_dict . type . value ( ) = = ReadableStreamType : : Bytes ) {
// 1. If strategy["size"] exists, throw a RangeError exception.
2023-06-18 21:57:07 +12:00
if ( strategy . size )
return WebIDL : : SimpleException { WebIDL : : SimpleExceptionType : : RangeError , " Size strategy not allowed for byte stream " sv } ;
2023-03-28 19:11:22 -07:00
// 2. Let highWaterMark be ? ExtractHighWaterMark(strategy, 0).
2023-06-18 21:57:07 +12:00
auto high_water_mark = TRY ( extract_high_water_mark ( strategy , 0 ) ) ;
2023-03-28 19:11:22 -07:00
// 3. Perform ? SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, underlyingSourceDict, highWaterMark).
2023-06-18 21:57:07 +12:00
TRY ( set_up_readable_byte_stream_controller_from_underlying_source ( * readable_stream , underlying_source , underlying_source_dict , high_water_mark ) ) ;
2023-03-28 19:11:22 -07:00
}
// 5. Otherwise,
else {
// 1. Assert: underlyingSourceDict["type"] does not exist.
VERIFY ( ! underlying_source_dict . type . has_value ( ) ) ;
2023-06-18 21:57:07 +12:00
// 2. Let sizeAlgorithm be ! ExtractSizeAlgorithm(strategy).
2024-01-26 18:54:24 +13:00
auto size_algorithm = extract_size_algorithm ( vm , strategy ) ;
2023-03-28 19:11:22 -07:00
2023-06-18 21:57:07 +12:00
// 3. Let highWaterMark be ? ExtractHighWaterMark(strategy, 1).
auto high_water_mark = TRY ( extract_high_water_mark ( strategy , 1 ) ) ;
2023-03-28 19:11:22 -07:00
// 4. Perform ? SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, underlyingSourceDict, highWaterMark, sizeAlgorithm).
2024-01-26 18:54:24 +13:00
TRY ( set_up_readable_stream_default_controller_from_underlying_source ( * readable_stream , underlying_source , underlying_source_dict , high_water_mark , size_algorithm ) ) ;
2023-03-28 19:11:22 -07:00
}
return readable_stream ;
2022-09-21 23:27:13 +01:00
}
2024-06-08 10:44:35 +02:00
// https://streams.spec.whatwg.org/#rs-from
2024-11-15 04:01:23 +13:00
WebIDL : : ExceptionOr < GC : : Ref < ReadableStream > > ReadableStream : : from ( JS : : VM & vm , JS : : Value async_iterable )
2024-06-08 10:44:35 +02:00
{
// 1. Return ? ReadableStreamFromIterable(asyncIterable).
return TRY ( readable_stream_from_iterable ( vm , async_iterable ) ) ;
}
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
ReadableStream : : ReadableStream ( JS : : Realm & realm )
: PlatformObject ( realm )
2022-09-21 23:27:13 +01:00
{
}
ReadableStream : : ~ ReadableStream ( ) = default ;
2023-03-28 20:01:04 -07:00
// https://streams.spec.whatwg.org/#rs-locked
2023-06-18 21:34:41 +12:00
bool ReadableStream : : locked ( ) const
2023-03-28 20:01:04 -07:00
{
// 1. Return ! IsReadableStreamLocked(this).
return is_readable_stream_locked ( * this ) ;
}
// https://streams.spec.whatwg.org/#rs-cancel
2024-11-15 04:01:23 +13:00
GC : : Ref < WebIDL : : Promise > ReadableStream : : cancel ( JS : : Value reason )
2023-03-28 20:01:04 -07:00
{
2023-04-12 23:21:17 +02:00
auto & realm = this - > realm ( ) ;
2023-03-28 20:01:04 -07:00
// 1. If ! IsReadableStreamLocked(this) is true, return a promise rejected with a TypeError exception.
if ( is_readable_stream_locked ( * this ) ) {
2023-09-06 08:18:01 -04:00
auto exception = JS : : TypeError : : create ( realm , " Cannot cancel a locked stream " sv ) ;
2024-10-25 12:38:19 -06:00
return WebIDL : : create_rejected_promise ( realm , exception ) ;
2023-03-28 20:01:04 -07:00
}
// 2. Return ! ReadableStreamCancel(this, reason).
2024-10-25 12:38:19 -06:00
return readable_stream_cancel ( * this , reason ) ;
2023-03-28 20:01:04 -07:00
}
// https://streams.spec.whatwg.org/#rs-get-reader
2023-06-29 20:53:19 +12:00
WebIDL : : ExceptionOr < ReadableStreamReader > ReadableStream : : get_reader ( ReadableStreamGetReaderOptions const & options )
2023-03-28 20:01:04 -07:00
{
// 1. If options["mode"] does not exist, return ? AcquireReadableStreamDefaultReader(this).
2023-06-29 20:53:19 +12:00
if ( ! options . mode . has_value ( ) )
2023-07-26 19:02:37 +02:00
return ReadableStreamReader { TRY ( acquire_readable_stream_default_reader ( * this ) ) } ;
2023-06-29 20:53:19 +12:00
2023-03-28 20:01:04 -07:00
// 2. Assert: options["mode"] is "byob".
2023-06-29 20:53:19 +12:00
VERIFY ( * options . mode = = Bindings : : ReadableStreamReaderMode : : Byob ) ;
2023-03-28 20:01:04 -07:00
2023-06-29 20:53:19 +12:00
// 3. Return ? AcquireReadableStreamBYOBReader(this).
2023-07-26 19:02:37 +02:00
return ReadableStreamReader { TRY ( acquire_readable_stream_byob_reader ( * this ) ) } ;
2023-03-28 20:01:04 -07:00
}
2024-11-22 12:19:37 +01:00
// https://streams.spec.whatwg.org/#rs-pipe-through
2024-11-15 04:01:23 +13:00
WebIDL : : ExceptionOr < GC : : Ref < ReadableStream > > ReadableStream : : pipe_through ( ReadableWritablePair transform , StreamPipeOptions const & options )
2024-04-07 13:01:33 +02:00
{
// 1. If ! IsReadableStreamLocked(this) is true, throw a TypeError exception.
if ( is_readable_stream_locked ( * this ) )
return WebIDL : : SimpleException { WebIDL : : SimpleExceptionType : : TypeError , " Failed to execute 'pipeThrough' on 'ReadableStream': Cannot pipe a locked stream " sv } ;
// 2. If ! IsWritableStreamLocked(transform["writable"]) is true, throw a TypeError exception.
if ( is_writable_stream_locked ( * transform . writable ) )
return WebIDL : : SimpleException { WebIDL : : SimpleExceptionType : : TypeError , " Failed to execute 'pipeThrough' on 'ReadableStream': parameter 1's 'writable' is locked " sv } ;
// 3. Let signal be options["signal"] if it exists, or undefined otherwise.
2024-04-07 15:10:36 +02:00
auto signal = options . signal ? JS : : Value ( options . signal ) : JS : : js_undefined ( ) ;
2024-04-07 13:01:33 +02:00
// 4. Let promise be ! ReadableStreamPipeTo(this, transform["writable"], options["preventClose"], options["preventAbort"], options["preventCancel"], signal).
2024-04-29 16:45:50 -04:00
auto promise = readable_stream_pipe_to ( * this , * transform . writable , options . prevent_close , options . prevent_abort , options . prevent_cancel , signal ) ;
2024-04-07 13:01:33 +02:00
// 5. Set promise.[[PromiseIsHandled]] to true.
WebIDL : : mark_promise_as_handled ( * promise ) ;
// 6. Return transform["readable"].
2024-11-15 04:01:23 +13:00
return GC : : Ref { * transform . readable } ;
2024-04-07 13:01:33 +02:00
}
2024-11-22 12:19:37 +01:00
// https://streams.spec.whatwg.org/#rs-pipe-to
2024-11-15 04:01:23 +13:00
GC : : Ref < WebIDL : : Promise > ReadableStream : : pipe_to ( WritableStream & destination , StreamPipeOptions const & options )
2024-04-06 19:02:28 +02:00
{
auto & realm = this - > realm ( ) ;
2024-10-25 12:38:19 -06:00
auto & vm = realm . vm ( ) ;
2024-04-06 19:02:28 +02:00
// 1. If ! IsReadableStreamLocked(this) is true, return a promise rejected with a TypeError exception.
if ( is_readable_stream_locked ( * this ) ) {
2024-10-25 12:38:19 -06:00
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : TypeError > ( " Failed to execute 'pipeTo' on 'ReadableStream': Cannot pipe a locked stream " sv ) ) ;
2024-04-06 19:02:28 +02:00
}
// 2. If ! IsWritableStreamLocked(destination) is true, return a promise rejected with a TypeError exception.
if ( is_writable_stream_locked ( destination ) ) {
2024-10-25 12:38:19 -06:00
return WebIDL : : create_rejected_promise_from_exception ( realm , vm . throw_completion < JS : : TypeError > ( " Failed to execute 'pipeTo' on 'ReadableStream': Cannot pipe to a locked stream " sv ) ) ;
2024-04-06 19:02:28 +02:00
}
// 3. Let signal be options["signal"] if it exists, or undefined otherwise.
2024-04-07 15:10:36 +02:00
auto signal = options . signal ? JS : : Value ( options . signal ) : JS : : js_undefined ( ) ;
2024-04-06 19:02:28 +02:00
// 4. Return ! ReadableStreamPipeTo(this, destination, options["preventClose"], options["preventAbort"], options["preventCancel"], signal).
2024-10-25 12:38:19 -06:00
return readable_stream_pipe_to ( * this , destination , options . prevent_close , options . prevent_abort , options . prevent_cancel , signal ) ;
2024-04-06 19:02:28 +02:00
}
2024-01-28 10:28:59 -05:00
// https://streams.spec.whatwg.org/#readablestream-tee
WebIDL : : ExceptionOr < ReadableStreamPair > ReadableStream : : tee ( )
{
// To tee a ReadableStream stream, return ? ReadableStreamTee(stream, true).
return TRY ( readable_stream_tee ( realm ( ) , * this , true ) ) ;
}
2024-05-20 14:28:17 +02:00
// https://streams.spec.whatwg.org/#readablestream-close
void ReadableStream : : close ( )
{
controller ( ) - > visit (
// 1. If stream.[[controller]] implements ReadableByteStreamController
2024-11-15 04:01:23 +13:00
[ & ] ( GC : : Ref < ReadableByteStreamController > controller ) {
2024-05-20 14:28:17 +02:00
// 1. Perform ! ReadableByteStreamControllerClose(stream.[[controller]]).
MUST ( readable_byte_stream_controller_close ( controller ) ) ;
// 2. If stream.[[controller]].[[pendingPullIntos]] is not empty, perform ! ReadableByteStreamControllerRespond(stream.[[controller]], 0).
if ( ! controller - > pending_pull_intos ( ) . is_empty ( ) )
MUST ( readable_byte_stream_controller_respond ( controller , 0 ) ) ;
} ,
// 2. Otherwise, perform ! ReadableStreamDefaultControllerClose(stream.[[controller]]).
2024-11-15 04:01:23 +13:00
[ & ] ( GC : : Ref < ReadableStreamDefaultController > controller ) {
2024-05-20 14:28:17 +02:00
readable_stream_default_controller_close ( * controller ) ;
} ) ;
}
2024-05-25 16:55:38 -04:00
// https://streams.spec.whatwg.org/#readablestream-error
void ReadableStream : : error ( JS : : Value error )
{
controller ( ) - > visit (
// 1. If stream.[[controller]] implements ReadableByteStreamController, then perform
// ! ReadableByteStreamControllerError(stream.[[controller]], e).
2024-11-15 04:01:23 +13:00
[ & ] ( GC : : Ref < ReadableByteStreamController > controller ) {
2024-05-25 16:55:38 -04:00
readable_byte_stream_controller_error ( controller , error ) ;
} ,
// 2. Otherwise, perform ! ReadableStreamDefaultControllerError(stream.[[controller]], e).
2024-11-15 04:01:23 +13:00
[ & ] ( GC : : Ref < ReadableStreamDefaultController > controller ) {
2024-05-25 16:55:38 -04:00
readable_stream_default_controller_error ( controller , error ) ;
} ) ;
}
2023-08-07 08:41:28 +02:00
void ReadableStream : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( ReadableStream ) ;
2023-01-10 06:28:20 -05:00
}
2022-09-21 23:27:13 +01:00
void ReadableStream : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2023-04-14 08:43:47 -04:00
if ( m_controller . has_value ( ) )
m_controller - > visit ( [ & ] ( auto & controller ) { visitor . visit ( controller ) ; } ) ;
2022-09-21 23:27:13 +01:00
visitor . visit ( m_stored_error ) ;
2023-04-09 01:26:48 -07:00
if ( m_reader . has_value ( ) )
m_reader - > visit ( [ & ] ( auto & reader ) { visitor . visit ( reader ) ; } ) ;
2022-09-21 23:27:13 +01:00
}
// https://streams.spec.whatwg.org/#readablestream-locked
bool ReadableStream : : is_readable ( ) const
{
// A ReadableStream stream is readable if stream.[[state]] is "readable".
return m_state = = State : : Readable ;
}
// https://streams.spec.whatwg.org/#readablestream-closed
bool ReadableStream : : is_closed ( ) const
{
// A ReadableStream stream is closed if stream.[[state]] is "closed".
return m_state = = State : : Closed ;
}
// https://streams.spec.whatwg.org/#readablestream-errored
bool ReadableStream : : is_errored ( ) const
{
// A ReadableStream stream is errored if stream.[[state]] is "errored".
return m_state = = State : : Errored ;
}
// https://streams.spec.whatwg.org/#readablestream-locked
bool ReadableStream : : is_locked ( ) const
{
// A ReadableStream stream is locked if ! IsReadableStreamLocked(stream) returns true.
return is_readable_stream_locked ( * this ) ;
}
// https://streams.spec.whatwg.org/#is-readable-stream-disturbed
bool ReadableStream : : is_disturbed ( ) const
{
// A ReadableStream stream is disturbed if stream.[[disturbed]] is true.
return m_disturbed ;
}
2024-12-24 12:38:25 +13:00
// https://streams.spec.whatwg.org/#readablestream-get-a-reader
WebIDL : : ExceptionOr < GC : : Ref < ReadableStreamDefaultReader > > ReadableStream : : get_a_reader ( )
{
// To get a reader for a ReadableStream stream, return ? AcquireReadableStreamDefaultReader(stream). The result will be a ReadableStreamDefaultReader.
return TRY ( acquire_readable_stream_default_reader ( * this ) ) ;
}
2024-12-08 17:28:44 +13:00
// https://streams.spec.whatwg.org/#readablestream-pull-from-bytes
WebIDL : : ExceptionOr < void > ReadableStream : : pull_from_bytes ( ByteBuffer bytes )
{
auto & realm = this - > realm ( ) ;
// 1. Assert: stream.[[controller]] implements ReadableByteStreamController.
auto & controller = this - > controller ( ) - > get < GC : : Ref < ReadableByteStreamController > > ( ) ;
// 2. Let available be bytes’ s length.
auto available = bytes . size ( ) ;
// 3. Let desiredSize be available.
auto desired_size = available ;
2024-12-23 16:20:02 +13:00
// 4. If stream’ s current BYOB request view is non-null, then set desiredSize to stream’ s current BYOB request
// view's byte length.
if ( auto byob_view = current_byob_request_view ( ) )
desired_size = byob_view - > byte_length ( ) ;
2024-12-08 17:28:44 +13:00
// 5. Let pullSize be the smaller value of available and desiredSize.
auto pull_size = min ( available , desired_size ) ;
// 6. Let pulled be the first pullSize bytes of bytes.
auto pulled = pull_size = = available ? move ( bytes ) : MUST ( bytes . slice ( 0 , pull_size ) ) ;
// 7. Remove the first pullSize bytes from bytes.
if ( pull_size ! = available )
bytes = MUST ( bytes . slice ( pull_size , available - pull_size ) ) ;
2024-12-23 16:20:02 +13:00
// 8. If stream’ s current BYOB request view is non-null, then:
if ( auto byob_view = current_byob_request_view ( ) ) {
// 1. Write pulled into stream’ s current BYOB request view.
byob_view - > write ( pulled ) ;
// 2. Perform ? ReadableByteStreamControllerRespond(stream.[[controller]], pullSize).
TRY ( readable_byte_stream_controller_respond ( controller , pull_size ) ) ;
}
2024-12-08 17:28:44 +13:00
// 9. Otherwise,
2024-12-23 16:20:02 +13:00
else {
2024-12-08 17:28:44 +13:00
// 1. Set view to the result of creating a Uint8Array from pulled in stream’ s relevant Realm.
auto array_buffer = JS : : ArrayBuffer : : create ( realm , move ( pulled ) ) ;
auto view = JS : : Uint8Array : : create ( realm , array_buffer - > byte_length ( ) , * array_buffer ) ;
// 2. Perform ? ReadableByteStreamControllerEnqueue(stream.[[controller]], view).
TRY ( readable_byte_stream_controller_enqueue ( controller , view ) ) ;
}
return { } ;
}
2024-12-23 16:20:02 +13:00
// https://streams.spec.whatwg.org/#readablestream-current-byob-request-view
GC : : Ptr < WebIDL : : ArrayBufferView > ReadableStream : : current_byob_request_view ( )
{
// 1. Assert: stream.[[controller]] implements ReadableByteStreamController.
VERIFY ( m_controller - > has < GC : : Ref < ReadableByteStreamController > > ( ) ) ;
// 2. Let byobRequest be ! ReadableByteStreamControllerGetBYOBRequest(stream.[[controller]]).
auto byob_request = readable_byte_stream_controller_get_byob_request ( m_controller - > get < GC : : Ref < ReadableByteStreamController > > ( ) ) ;
// 3. If byobRequest is null, then return null.
if ( ! byob_request )
return { } ;
// 4. Return byobRequest.[[view]].
return byob_request - > view ( ) ;
}
2024-12-08 17:28:44 +13:00
// https://streams.spec.whatwg.org/#readablestream-enqueue
WebIDL : : ExceptionOr < void > ReadableStream : : enqueue ( JS : : Value chunk )
{
VERIFY ( m_controller . has_value ( ) ) ;
// 1. If stream.[[controller]] implements ReadableStreamDefaultController,
if ( m_controller - > has < GC : : Ref < ReadableStreamDefaultController > > ( ) ) {
// 1. Perform ! ReadableStreamDefaultControllerEnqueue(stream.[[controller]], chunk).
2024-12-23 16:20:02 +13:00
MUST ( readable_stream_default_controller_enqueue ( m_controller - > get < GC : : Ref < ReadableStreamDefaultController > > ( ) , chunk ) ) ;
2024-12-08 17:28:44 +13:00
}
// 2. Otherwise,
else {
// 1. Assert: stream.[[controller]] implements ReadableByteStreamController.
VERIFY ( m_controller - > has < GC : : Ref < ReadableByteStreamController > > ( ) ) ;
auto readable_byte_controller = m_controller - > get < GC : : Ref < ReadableByteStreamController > > ( ) ;
2024-12-23 16:20:02 +13:00
// 2. Assert: chunk is an ArrayBufferView.
VERIFY ( chunk . is_object ( ) ) ;
auto chunk_view = heap ( ) . allocate < WebIDL : : ArrayBufferView > ( chunk . as_object ( ) ) ;
2024-12-08 17:28:44 +13:00
// 3. Let byobView be the current BYOB request view for stream.
2024-12-23 16:20:02 +13:00
auto byob_view = current_byob_request_view ( ) ;
2024-12-08 17:28:44 +13:00
// 4. If byobView is non-null, and chunk.[[ViewedArrayBuffer]] is byobView.[[ViewedArrayBuffer]], then:
2024-12-23 16:20:02 +13:00
if ( byob_view & & chunk_view - > viewed_array_buffer ( ) = = byob_view - > viewed_array_buffer ( ) ) {
// 1. Assert: chunk.[[ByteOffset]] is byobView.[[ByteOffset]].
VERIFY ( chunk_view - > byte_offset ( ) = = byob_view - > byte_offset ( ) ) ;
// 2. Assert: chunk.[[ByteLength]] ≤ byobView.[[ByteLength]].
VERIFY ( chunk_view - > byte_length ( ) < = byob_view - > byte_length ( ) ) ;
2024-12-08 17:28:44 +13:00
2024-12-23 16:20:02 +13:00
// 3. Perform ? ReadableByteStreamControllerRespond(stream.[[controller]], chunk.[[ByteLength]]).
TRY ( readable_byte_stream_controller_respond ( readable_byte_controller , chunk_view - > byte_length ( ) ) ) ;
}
2024-12-08 17:28:44 +13:00
// 5. Otherwise, perform ? ReadableByteStreamControllerEnqueue(stream.[[controller]], chunk).
2024-12-23 16:20:02 +13:00
else {
TRY ( readable_byte_stream_controller_enqueue ( readable_byte_controller , chunk ) ) ;
}
2024-12-08 17:28:44 +13:00
}
2024-12-23 16:20:02 +13:00
return { } ;
2024-12-08 17:28:44 +13:00
}
// https://streams.spec.whatwg.org/#readablestream-set-up-with-byte-reading-support
void ReadableStream : : set_up_with_byte_reading_support ( GC : : Ptr < PullAlgorithm > pull_algorithm , GC : : Ptr < CancelAlgorithm > cancel_algorithm , double high_water_mark )
{
auto & realm = this - > realm ( ) ;
// 1. Let startAlgorithm be an algorithm that returns undefined.
auto start_algorithm = GC : : create_function ( realm . heap ( ) , [ ] ( ) - > WebIDL : : ExceptionOr < JS : : Value > { return JS : : js_undefined ( ) ; } ) ;
// 2. Let pullAlgorithmWrapper be an algorithm that runs these steps:
auto pull_algorithm_wrapper = GC : : create_function ( realm . heap ( ) , [ & realm , pull_algorithm ] ( ) {
// 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.
GC : : Ptr < JS : : PromiseCapability > result = nullptr ;
if ( pull_algorithm )
result = pull_algorithm - > function ( ) ( ) ;
// 2. If result is a Promise, then return result.
if ( result ! = nullptr )
return GC : : Ref ( * result ) ;
// 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:
auto cancel_algorithm_wrapper = GC : : create_function ( realm . heap ( ) , [ & realm , cancel_algorithm ] ( JS : : Value c ) {
// 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.
GC : : Ptr < JS : : PromiseCapability > result = nullptr ;
if ( cancel_algorithm )
result = cancel_algorithm - > function ( ) ( c ) ;
// 2. If result is a Promise, then return result.
if ( result ! = nullptr )
return GC : : Ref ( * result ) ;
// 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 = realm . create < ReadableByteStreamController > ( realm ) ;
// 6. Perform ! SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithmWrapper, cancelAlgorithmWrapper, highWaterMark, undefined).
MUST ( set_up_readable_byte_stream_controller ( * this , controller , start_algorithm , pull_algorithm_wrapper , cancel_algorithm_wrapper , high_water_mark , JS : : js_undefined ( ) ) ) ;
}
2024-12-24 12:25:01 +13:00
// https://streams.spec.whatwg.org/#readablestream-pipe-through
2024-12-26 12:02:07 +13:00
GC : : Ref < ReadableStream > ReadableStream : : piped_through ( GC : : Ref < TransformStream > transform , bool prevent_close , bool prevent_abort , bool prevent_cancel , JS : : Value signal )
2024-12-24 12:25:01 +13:00
{
// 1. Assert: ! IsReadableStreamLocked(readable) is false.
VERIFY ( ! is_readable_stream_locked ( * this ) ) ;
2024-12-26 12:02:07 +13:00
// 2. Assert: ! IsWritableStreamLocked(transform.[[writable]]) is false.
VERIFY ( ! is_writable_stream_locked ( transform - > writable ( ) ) ) ;
2024-12-24 12:25:01 +13:00
// 3. Let signalArg be signal if signal was given, or undefined otherwise.
// NOTE: Done by default arguments.
2024-12-26 12:02:07 +13:00
// 4. Let promise be ! ReadableStreamPipeTo(readable, transform.[[writable]], preventClose, preventAbort, preventCancel, signalArg).
auto promise = readable_stream_pipe_to ( * this , transform - > writable ( ) , prevent_close , prevent_abort , prevent_cancel , signal ) ;
// 5. Set promise.[[PromiseIsHandled]] to true.
WebIDL : : mark_promise_as_handled ( * promise ) ;
// 6. Return transform.[[readable]].
return transform - > readable ( ) ;
2024-12-24 12:25:01 +13:00
}
2022-09-21 23:27:13 +01:00
}