Script: implement ReadableStreamBYOBReader::Read (#35040)

* Script: implement ReadableStreamBYOBReader::Read

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* fix ReadRequest::close_steps

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* fix clippy

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* implement viewed_buffer_array_byte_length and byte_length

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* fix clippy

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* Correct BufferSource implemntation

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* Correct detach_buffer implemantation

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* fix JS_IsArrayBufferViewObject usage

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* Reduce BufferSource to two variants ArrayBuffer and ArrayBufferView

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

* Add more doc and use promise.reject_error

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>

---------

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
This commit is contained in:
Taym Haddadi 2025-01-27 16:52:54 +01:00 committed by GitHub
parent 177b5b2cef
commit 9943e97726
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 406 additions and 224 deletions

View file

@ -14,6 +14,7 @@ use js::rust::{
HandleObject as SafeHandleObject, HandleValue as SafeHandleValue,
MutableHandleValue as SafeMutableHandleValue,
};
use js::typedarray::ArrayBufferViewU8;
use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategy;
use crate::dom::bindings::codegen::Bindings::ReadableStreamBinding::{
@ -45,6 +46,10 @@ use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use super::bindings::buffer_source::HeapBufferSource;
use super::bindings::codegen::Bindings::ReadableStreamBYOBReaderBinding::ReadableStreamBYOBReaderReadOptions;
use super::readablestreambyobreader::ReadIntoRequest;
/// The fulfillment handler for the reacting to sourceCancelPromise part of
/// <https://streams.spec.whatwg.org/#readable-stream-cancel>.
#[derive(Clone, JSTraceable, MallocSizeOf)]
@ -296,7 +301,32 @@ impl ReadableStream {
.get()
.expect("Stream should have controller.")
.perform_pull_steps(read_request, can_gc),
ControllerType::Byte(_) => todo!(),
ControllerType::Byte(_) => {
unreachable!(
"Pulling a chunk from a stream with a byte controller using a default reader"
)
},
}
}
/// Call into the pull steps of the controller,
/// as part of
/// <https://streams.spec.whatwg.org/#readable-stream-byob-reader-read>
pub(crate) fn perform_pull_into_steps(
&self,
read_into_request: &ReadIntoRequest,
view: HeapBufferSource<ArrayBufferViewU8>,
options: &ReadableStreamBYOBReaderReadOptions,
can_gc: CanGc,
) {
match self.controller {
ControllerType::Byte(ref controller) => controller
.get()
.expect("Stream should have controller.")
.perform_pull_into(read_into_request, view, options, can_gc),
ControllerType::Default(_) => unreachable!(
"Pulling a chunk from a stream with a default controller using a BYOB reader"
),
}
}
@ -321,6 +351,28 @@ impl ReadableStream {
}
}
#[allow(dead_code)]
/// <https://streams.spec.whatwg.org/#readable-stream-add-read-into-request>
pub(crate) fn add_read_into_request(&self, read_request: &ReadIntoRequest) {
match self.reader {
// Assert: stream.[[reader]] implements ReadableStreamBYOBReader.
ReaderType::Default(_) => {
unreachable!("Adding a read into request can only be done on a BYOB reader.")
},
ReaderType::BYOB(ref reader) => {
let Some(reader) = reader.get() else {
unreachable!("Attempt to add a read into request without having first acquired a reader.");
};
// Assert: stream.[[state]] is "readable" or "closed".
assert!(self.is_readable() || self.is_closed());
// Append readRequest to stream.[[reader]].[[readIntoRequests]].
reader.add_read_into_request(read_request);
},
}
}
/// Endpoint to enqueue chunks directly from Rust.
/// Note: in other use cases this call happens via the controller.
pub(crate) fn enqueue_native(&self, bytes: Vec<u8>) {