ReadableStream: remove the use of get_js_stream and use DomRoot<ReadableStream> (#34836)

* Remove the use of get_js_stream and use DomRoot<ReadableStream>

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

* return an error instead of Option

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-05 12:37:15 +01:00 committed by GitHub
parent 15eb405f36
commit bcad0d50e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 43 additions and 52 deletions

View file

@ -445,7 +445,7 @@ impl Extractable for BodyInit {
BodyInit::ArrayBuffer(ref typedarray) => { BodyInit::ArrayBuffer(ref typedarray) => {
let bytes = typedarray.to_vec(); let bytes = typedarray.to_vec();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(global, bytes, can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -456,7 +456,7 @@ impl Extractable for BodyInit {
BodyInit::ArrayBufferView(ref typedarray) => { BodyInit::ArrayBufferView(ref typedarray) => {
let bytes = typedarray.to_vec(); let bytes = typedarray.to_vec();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(global, bytes, can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -489,7 +489,7 @@ impl Extractable for Vec<u8> {
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> { fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
let bytes = self.clone(); let bytes = self.clone();
let total_bytes = self.len(); let total_bytes = self.len();
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(global, bytes, can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -509,8 +509,9 @@ impl Extractable for Blob {
Some(blob_type) Some(blob_type)
}; };
let total_bytes = self.Size() as usize; let total_bytes = self.Size() as usize;
let stream = self.get_stream(can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream: self.get_stream(can_gc), stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
content_type, content_type,
source: BodySource::Object, source: BodySource::Object,
@ -523,7 +524,7 @@ impl Extractable for DOMString {
let bytes = self.as_bytes().to_owned(); let bytes = self.as_bytes().to_owned();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let content_type = Some(DOMString::from("text/plain;charset=UTF-8")); let content_type = Some(DOMString::from("text/plain;charset=UTF-8"));
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(global, bytes, can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -542,7 +543,7 @@ impl Extractable for FormData {
"multipart/form-data;boundary={}", "multipart/form-data;boundary={}",
boundary boundary
))); )));
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(global, bytes, can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -559,7 +560,7 @@ impl Extractable for URLSearchParams {
let content_type = Some(DOMString::from( let content_type = Some(DOMString::from(
"application/x-www-form-urlencoded;charset=UTF-8", "application/x-www-form-urlencoded;charset=UTF-8",
)); ));
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(global, bytes, can_gc)?;
Ok(ExtractedBody { Ok(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -752,7 +753,8 @@ fn consume_body_with_promise<T: BodyMixin + DomObject>(
// Step 2. // Step 2.
let stream = match object.body() { let stream = match object.body() {
Some(stream) => stream, Some(stream) => stream,
None => ReadableStream::new_from_bytes(&global, Vec::with_capacity(0), can_gc), None => ReadableStream::new_from_bytes(&global, Vec::with_capacity(0), can_gc)
.expect("ReadableStream::new_from_bytes should not fail with an empty Vec<u8>"),
}; };
// Step 3. // Step 3.

View file

@ -4,13 +4,11 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use base::id::{BlobId, BlobIndex, PipelineNamespaceId}; use base::id::{BlobId, BlobIndex, PipelineNamespaceId};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use encoding_rs::UTF_8; use encoding_rs::UTF_8;
use js::jsapi::JSObject;
use js::rust::HandleObject; use js::rust::HandleObject;
use net_traits::filemanager_thread::RelativePos; use net_traits::filemanager_thread::RelativePos;
use script_traits::serializable::BlobImpl; use script_traits::serializable::BlobImpl;
@ -30,7 +28,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::readablestream::ReadableStream; use crate::dom::readablestream::ReadableStream;
use crate::realms::{AlreadyInRealm, InRealm}; use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_runtime::{CanGc, JSContext}; use crate::script_runtime::CanGc;
// https://w3c.github.io/FileAPI/#blob // https://w3c.github.io/FileAPI/#blob
#[dom_struct] #[dom_struct]
@ -86,7 +84,7 @@ impl Blob {
} }
/// <https://w3c.github.io/FileAPI/#blob-get-stream> /// <https://w3c.github.io/FileAPI/#blob-get-stream>
pub fn get_stream(&self, can_gc: CanGc) -> DomRoot<ReadableStream> { pub fn get_stream(&self, can_gc: CanGc) -> Fallible<DomRoot<ReadableStream>> {
self.global().get_blob_stream(&self.blob_id, can_gc) self.global().get_blob_stream(&self.blob_id, can_gc)
} }
} }
@ -226,8 +224,8 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
} }
// <https://w3c.github.io/FileAPI/#blob-get-stream> // <https://w3c.github.io/FileAPI/#blob-get-stream>
fn Stream(&self, _cx: JSContext, can_gc: CanGc) -> NonNull<JSObject> { fn Stream(&self, can_gc: CanGc) -> Fallible<DomRoot<ReadableStream>> {
self.get_stream(can_gc).get_js_stream() self.get_stream(can_gc)
} }
// https://w3c.github.io/FileAPI/#slice-method-algo // https://w3c.github.io/FileAPI/#slice-method-algo

View file

@ -1909,12 +1909,15 @@ impl GlobalScope {
} }
/// <https://w3c.github.io/FileAPI/#blob-get-stream> /// <https://w3c.github.io/FileAPI/#blob-get-stream>
pub fn get_blob_stream(&self, blob_id: &BlobId, can_gc: CanGc) -> DomRoot<ReadableStream> { pub fn get_blob_stream(
&self,
blob_id: &BlobId,
can_gc: CanGc,
) -> Fallible<DomRoot<ReadableStream>> {
let (file_id, size) = match self.get_blob_bytes_or_file_id(blob_id) { let (file_id, size) = match self.get_blob_bytes_or_file_id(blob_id) {
BlobResult::Bytes(bytes) => { BlobResult::Bytes(bytes) => {
// If we have all the bytes in memory, queue them and close the stream. // If we have all the bytes in memory, queue them and close the stream.
let stream = ReadableStream::new_from_bytes(self, bytes, can_gc); return ReadableStream::new_from_bytes(self, bytes, can_gc);
return stream;
}, },
BlobResult::File(id, size) => (id, size), BlobResult::File(id, size) => (id, size),
}; };
@ -1923,7 +1926,7 @@ impl GlobalScope {
self, self,
UnderlyingSourceType::Blob(size), UnderlyingSourceType::Blob(size),
can_gc, can_gc,
); )?;
let recv = self.send_msg(file_id); let recv = self.send_msg(file_id);
@ -1942,7 +1945,7 @@ impl GlobalScope {
}), }),
); );
stream Ok(stream)
} }
pub fn read_file_async(&self, id: Uuid, promise: Rc<Promise>, callback: FileListenerCallback) { pub fn read_file_async(&self, id: Uuid, promise: Rc<Promise>, callback: FileListenerCallback) {

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::cell::Cell; use std::cell::Cell;
use std::ptr::{self, NonNull}; use std::ptr::{self};
use std::rc::Rc; use std::rc::Rc;
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -239,15 +239,15 @@ impl ReadableStream {
global: &GlobalScope, global: &GlobalScope,
bytes: Vec<u8>, bytes: Vec<u8>,
can_gc: CanGc, can_gc: CanGc,
) -> DomRoot<ReadableStream> { ) -> Fallible<DomRoot<ReadableStream>> {
let stream = ReadableStream::new_with_external_underlying_source( let stream = ReadableStream::new_with_external_underlying_source(
global, global,
UnderlyingSourceType::Memory(bytes.len()), UnderlyingSourceType::Memory(bytes.len()),
can_gc, can_gc,
); )?;
stream.enqueue_native(bytes); stream.enqueue_native(bytes);
stream.controller_close_native(); stream.controller_close_native();
stream Ok(stream)
} }
/// Build a stream backed by a Rust underlying source. /// Build a stream backed by a Rust underlying source.
@ -257,7 +257,7 @@ impl ReadableStream {
global: &GlobalScope, global: &GlobalScope,
source: UnderlyingSourceType, source: UnderlyingSourceType,
can_gc: CanGc, can_gc: CanGc,
) -> DomRoot<ReadableStream> { ) -> Fallible<DomRoot<ReadableStream>> {
assert!(source.is_native()); assert!(source.is_native());
let stream = ReadableStream::new_with_proto( let stream = ReadableStream::new_with_proto(
global, global,
@ -272,10 +272,8 @@ impl ReadableStream {
extract_size_algorithm(&QueuingStrategy::empty()), extract_size_algorithm(&QueuingStrategy::empty()),
can_gc, can_gc,
); );
controller controller.setup(stream.clone(), can_gc)?;
.setup(stream.clone(), can_gc) Ok(stream)
.expect("Setup of controller with external underlying source cannot fail");
stream
} }
/// Call into the release steps of the controller, /// Call into the release steps of the controller,
@ -323,13 +321,6 @@ impl ReadableStream {
} }
} }
/// Get a pointer to the underlying JS object.
/// TODO: remove,
/// by using at call point the `ReadableStream` directly instead of a JSObject.
pub fn get_js_stream(&self) -> NonNull<JSObject> {
NonNull::new(*self.reflector().get_jsobject())
.expect("Couldn't get a non-null pointer to JS stream object.")
}
/// Endpoint to enqueue chunks directly from Rust. /// Endpoint to enqueue chunks directly from Rust.
/// Note: in other use cases this call happens via the controller. /// Note: in other use cases this call happens via the controller.
pub fn enqueue_native(&self, bytes: Vec<u8>) { pub fn enqueue_native(&self, bytes: Vec<u8>) {

View file

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
@ -11,7 +10,6 @@ use dom_struct::dom_struct;
use http::header::{HeaderName, HeaderValue}; use http::header::{HeaderName, HeaderValue};
use http::method::InvalidMethod; use http::method::InvalidMethod;
use http::Method as HttpMethod; use http::Method as HttpMethod;
use js::jsapi::JSObject;
use js::rust::HandleObject; use js::rust::HandleObject;
use net_traits::fetch::headers::is_forbidden_method; use net_traits::fetch::headers::is_forbidden_method;
use net_traits::request::{ use net_traits::request::{
@ -40,7 +38,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::headers::{Guard, Headers}; use crate::dom::headers::{Guard, Headers};
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::readablestream::ReadableStream; use crate::dom::readablestream::ReadableStream;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct Request { pub struct Request {
@ -598,8 +596,8 @@ impl RequestMethods<crate::DomTypeHolder> for Request {
} }
/// <https://fetch.spec.whatwg.org/#dom-body-body> /// <https://fetch.spec.whatwg.org/#dom-body-body>
fn GetBody(&self, _cx: SafeJSContext) -> Option<NonNull<JSObject>> { fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
self.body().map(|stream| stream.get_js_stream()) self.body()
} }
// https://fetch.spec.whatwg.org/#dom-body-bodyused // https://fetch.spec.whatwg.org/#dom-body-bodyused

View file

@ -2,14 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use http::header::HeaderMap as HyperHeaders; use http::header::HeaderMap as HyperHeaders;
use hyper_serde::Serde; use hyper_serde::Serde;
use js::jsapi::JSObject;
use js::rust::HandleObject; use js::rust::HandleObject;
use net_traits::http_status::HttpStatus; use net_traits::http_status::HttpStatus;
use servo_url::ServoUrl; use servo_url::ServoUrl;
@ -32,7 +30,7 @@ use crate::dom::headers::{is_obs_text, is_vchar, Guard, Headers};
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::readablestream::ReadableStream; use crate::dom::readablestream::ReadableStream;
use crate::dom::underlyingsourcecontainer::UnderlyingSourceType; use crate::dom::underlyingsourcecontainer::UnderlyingSourceType;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext, StreamConsumer}; use crate::script_runtime::{CanGc, StreamConsumer};
#[dom_struct] #[dom_struct]
pub struct Response { pub struct Response {
@ -59,7 +57,8 @@ impl Response {
global, global,
UnderlyingSourceType::FetchResponse, UnderlyingSourceType::FetchResponse,
can_gc, can_gc,
); )
.expect("Failed to create ReadableStream with external underlying source");
Response { Response {
reflector_: Reflector::new(), reflector_: Reflector::new(),
headers_reflector: Default::default(), headers_reflector: Default::default(),
@ -212,7 +211,7 @@ impl ResponseMethods<crate::DomTypeHolder> for Response {
} else { } else {
// Reset FetchResponse to an in-memory stream with empty byte sequence here for // Reset FetchResponse to an in-memory stream with empty byte sequence here for
// no-init-body case // no-init-body case
let stream = ReadableStream::new_from_bytes(global, Vec::with_capacity(0), can_gc); let stream = ReadableStream::new_from_bytes(global, Vec::with_capacity(0), can_gc)?;
r.body_stream.set(Some(&*stream)); r.body_stream.set(Some(&*stream));
} }
@ -359,8 +358,8 @@ impl ResponseMethods<crate::DomTypeHolder> for Response {
} }
/// <https://fetch.spec.whatwg.org/#dom-body-body> /// <https://fetch.spec.whatwg.org/#dom-body-body>
fn GetBody(&self, _cx: SafeJSContext) -> Option<NonNull<JSObject>> { fn GetBody(&self) -> Option<DomRoot<ReadableStream>> {
self.body().map(|stream| stream.get_js_stream()) self.body()
} }
// https://fetch.spec.whatwg.org/#dom-body-text // https://fetch.spec.whatwg.org/#dom-body-text

View file

@ -17,7 +17,7 @@ interface Blob {
optional [Clamp] long long end, optional [Clamp] long long end,
optional DOMString contentType); optional DOMString contentType);
[NewObject] object stream(); [NewObject, Throws] ReadableStream stream();
[NewObject] Promise<DOMString> text(); [NewObject] Promise<DOMString> text();
[NewObject] Promise<ArrayBuffer> arrayBuffer(); [NewObject] Promise<ArrayBuffer> arrayBuffer();
}; };

View file

@ -7,7 +7,7 @@
[Exposed=(Window,Worker)] [Exposed=(Window,Worker)]
interface mixin Body { interface mixin Body {
readonly attribute boolean bodyUsed; readonly attribute boolean bodyUsed;
readonly attribute object? body; readonly attribute ReadableStream? body;
[NewObject] Promise<ArrayBuffer> arrayBuffer(); [NewObject] Promise<ArrayBuffer> arrayBuffer();
[NewObject] Promise<Blob> blob(); [NewObject] Promise<Blob> blob();

View file

@ -564,7 +564,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
}; };
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let global = self.global(); let global = self.global();
let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc)?;
Some(ExtractedBody { Some(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -601,7 +601,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
let bytes = typedarray.to_vec(); let bytes = typedarray.to_vec();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let global = self.global(); let global = self.global();
let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc)?;
Some(ExtractedBody { Some(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),
@ -613,7 +613,7 @@ impl XMLHttpRequestMethods<crate::DomTypeHolder> for XMLHttpRequest {
let bytes = typedarray.to_vec(); let bytes = typedarray.to_vec();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let global = self.global(); let global = self.global();
let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc); let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc)?;
Some(ExtractedBody { Some(ExtractedBody {
stream, stream,
total_bytes: Some(total_bytes), total_bytes: Some(total_bytes),