refactor: add CanGc as argument to Promise::reject_native (#35640)

Signed-off-by: Yerkebulan Tulibergenov <yerkebulan@gmail.com>
This commit is contained in:
Yerkebulan Tulibergenov 2025-02-24 19:58:36 -08:00 committed by GitHub
parent 3c3b6cfdc4
commit 31199076ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 148 additions and 136 deletions

View file

@ -281,14 +281,14 @@ struct TransmitBodyPromiseHandler {
impl Callback for TransmitBodyPromiseHandler { impl Callback for TransmitBodyPromiseHandler {
/// Step 5 of <https://fetch.spec.whatwg.org/#concept-request-transmit-body> /// Step 5 of <https://fetch.spec.whatwg.org/#concept-request-transmit-body>
fn callback(&self, cx: JSContext, v: HandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, cx: JSContext, v: HandleValue, _realm: InRealm, can_gc: CanGc) {
let is_done = match get_read_promise_done(cx, &v) { let is_done = match get_read_promise_done(cx, &v) {
Ok(is_done) => is_done, Ok(is_done) => is_done,
Err(_) => { Err(_) => {
// Step 5.5, the "otherwise" steps. // Step 5.5, the "otherwise" steps.
// TODO: terminate fetch. // TODO: terminate fetch.
let _ = self.control_sender.send(BodyChunkRequest::Done); let _ = self.control_sender.send(BodyChunkRequest::Done);
return self.stream.stop_reading(); return self.stream.stop_reading(can_gc);
}, },
}; };
@ -296,7 +296,7 @@ impl Callback for TransmitBodyPromiseHandler {
// Step 5.3, the "done" steps. // Step 5.3, the "done" steps.
// TODO: queue a fetch task on request to process request end-of-body. // TODO: queue a fetch task on request to process request end-of-body.
let _ = self.control_sender.send(BodyChunkRequest::Done); let _ = self.control_sender.send(BodyChunkRequest::Done);
return self.stream.stop_reading(); return self.stream.stop_reading(can_gc);
} }
let chunk = match get_read_promise_bytes(cx, &v) { let chunk = match get_read_promise_bytes(cx, &v) {
@ -304,7 +304,7 @@ impl Callback for TransmitBodyPromiseHandler {
Err(_) => { Err(_) => {
// Step 5.5, the "otherwise" steps. // Step 5.5, the "otherwise" steps.
let _ = self.control_sender.send(BodyChunkRequest::Error); let _ = self.control_sender.send(BodyChunkRequest::Error);
return self.stream.stop_reading(); return self.stream.stop_reading(can_gc);
}, },
}; };
@ -330,10 +330,10 @@ struct TransmitBodyPromiseRejectionHandler {
impl Callback for TransmitBodyPromiseRejectionHandler { impl Callback for TransmitBodyPromiseRejectionHandler {
/// <https://fetch.spec.whatwg.org/#concept-request-transmit-body> /// <https://fetch.spec.whatwg.org/#concept-request-transmit-body>
fn callback(&self, _cx: JSContext, _v: HandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, _cx: JSContext, _v: HandleValue, _realm: InRealm, can_gc: CanGc) {
// Step 5.4, the "rejection" steps. // Step 5.4, the "rejection" steps.
let _ = self.control_sender.send(BodyChunkRequest::Error); let _ = self.control_sender.send(BodyChunkRequest::Error);
self.stream.stop_reading(); self.stream.stop_reading(can_gc);
} }
} }
@ -640,7 +640,9 @@ impl ConsumeBodyPromiseHandler {
FetchedData::FormData(f) => self.result_promise.resolve_native(&f, can_gc), FetchedData::FormData(f) => self.result_promise.resolve_native(&f, can_gc),
FetchedData::Bytes(b) => self.result_promise.resolve_native(&b, can_gc), FetchedData::Bytes(b) => self.result_promise.resolve_native(&b, can_gc),
FetchedData::ArrayBuffer(a) => self.result_promise.resolve_native(&a, can_gc), FetchedData::ArrayBuffer(a) => self.result_promise.resolve_native(&a, can_gc),
FetchedData::JSException(e) => self.result_promise.reject_native(&e.handle()), FetchedData::JSException(e) => {
self.result_promise.reject_native(&e.handle(), can_gc)
},
}; };
}, },
Err(err) => self.result_promise.reject_error(err), Err(err) => self.result_promise.reject_error(err),
@ -661,7 +663,7 @@ impl Callback for ConsumeBodyPromiseHandler {
let is_done = match get_read_promise_done(cx, &v) { let is_done = match get_read_promise_done(cx, &v) {
Ok(is_done) => is_done, Ok(is_done) => is_done,
Err(err) => { Err(err) => {
stream.stop_reading(); stream.stop_reading(can_gc);
// When read is fulfilled with a value that doesn't matches with neither of the above patterns. // When read is fulfilled with a value that doesn't matches with neither of the above patterns.
return self.result_promise.reject_error(err); return self.result_promise.reject_error(err);
}, },
@ -674,7 +676,7 @@ impl Callback for ConsumeBodyPromiseHandler {
let chunk = match get_read_promise_bytes(cx, &v) { let chunk = match get_read_promise_bytes(cx, &v) {
Ok(chunk) => chunk, Ok(chunk) => chunk,
Err(err) => { Err(err) => {
stream.stop_reading(); stream.stop_reading(can_gc);
// When read is fulfilled with a value that matches with neither of the above patterns // When read is fulfilled with a value that matches with neither of the above patterns
return self.result_promise.reject_error(err); return self.result_promise.reject_error(err);
}, },

View file

@ -579,11 +579,14 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
// Step 1 // Step 1
if !is_valid_custom_element_name(&name) { if !is_valid_custom_element_name(&name) {
let promise = Promise::new_in_current_realm(comp, can_gc); let promise = Promise::new_in_current_realm(comp, can_gc);
promise.reject_native(&DOMException::new( promise.reject_native(
self.window.as_global_scope(), &DOMException::new(
DOMErrorName::SyntaxError, self.window.as_global_scope(),
DOMErrorName::SyntaxError,
can_gc,
),
can_gc, can_gc,
)); );
return promise; return promise;
} }

View file

@ -138,12 +138,14 @@ impl DefaultTeeReadRequest {
self.readable_stream_default_controller_error( self.readable_stream_default_controller_error(
&self.branch_1, &self.branch_1,
clone_result.handle(), clone_result.handle(),
can_gc,
); );
// Perform ! ReadableStreamDefaultControllerError(branch_2.[[controller]], cloneResult.[[Value]]). // Perform ! ReadableStreamDefaultControllerError(branch_2.[[controller]], cloneResult.[[Value]]).
self.readable_stream_default_controller_error( self.readable_stream_default_controller_error(
&self.branch_2, &self.branch_2,
clone_result.handle(), clone_result.handle(),
can_gc,
); );
// Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]). // Resolve cancelPromise with ! ReadableStreamCancel(stream, cloneResult.[[Value]]).
self.stream_cancel(clone_result.handle(), can_gc); self.stream_cancel(clone_result.handle(), can_gc);
@ -225,8 +227,9 @@ impl DefaultTeeReadRequest {
&self, &self,
stream: &ReadableStream, stream: &ReadableStream,
error: SafeHandleValue, error: SafeHandleValue,
can_gc: CanGc,
) { ) {
stream.get_default_controller().error(error); stream.get_default_controller().error(error, can_gc);
} }
pub(crate) fn pull_algorithm(&self, can_gc: CanGc) { pub(crate) fn pull_algorithm(&self, can_gc: CanGc) {

View file

@ -585,7 +585,7 @@ fn stream_handle_incoming(stream: &ReadableStream, bytes: Fallible<Vec<u8>>, can
stream.enqueue_native(b, can_gc); stream.enqueue_native(b, can_gc);
}, },
Err(e) => { Err(e) => {
stream.error_native(e); stream.error_native(e, can_gc);
}, },
} }
} }

View file

@ -1176,11 +1176,10 @@ impl HTMLImageElement {
if !document.is_fully_active() || if !document.is_fully_active() ||
matches!(self.current_request.borrow().state, State::Broken) matches!(self.current_request.borrow().state, State::Broken)
{ {
promise.reject_native(&DOMException::new( promise.reject_native(
&document.global(), &DOMException::new(&document.global(), DOMErrorName::EncodingError, can_gc),
DOMErrorName::EncodingError,
can_gc, can_gc,
)); );
} else if matches!( } else if matches!(
self.current_request.borrow().state, self.current_request.borrow().state,
State::CompletelyAvailable State::CompletelyAvailable
@ -1204,11 +1203,10 @@ impl HTMLImageElement {
fn reject_image_decode_promises(&self, can_gc: CanGc) { fn reject_image_decode_promises(&self, can_gc: CanGc) {
let document = self.owner_document(); let document = self.owner_document();
for promise in self.image_decode_promises.borrow().iter() { for promise in self.image_decode_promises.borrow().iter() {
promise.reject_native(&DOMException::new( promise.reject_native(
&document.global(), &DOMException::new(&document.global(), DOMErrorName::EncodingError, can_gc),
DOMErrorName::EncodingError,
can_gc, can_gc,
)); );
} }
self.image_decode_promises.borrow_mut().clear(); self.image_decode_promises.borrow_mut().clear();
} }

View file

@ -52,11 +52,10 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
promise.reject_native(&DOMException::new( promise.reject_native(
&self.global(), &DOMException::new(&self.global(), DOMErrorName::InvalidStateError, can_gc),
DOMErrorName::InvalidStateError,
can_gc, can_gc,
)); );
} else { } else {
// 3. // 3.
self.serviceworker_registration self.serviceworker_registration
@ -75,11 +74,10 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
promise.reject_native(&DOMException::new( promise.reject_native(
&self.global(), &DOMException::new(&self.global(), DOMErrorName::InvalidStateError, can_gc),
DOMErrorName::InvalidStateError,
can_gc, can_gc,
)); );
} else { } else {
// 3. // 3.
self.serviceworker_registration self.serviceworker_registration
@ -98,11 +96,10 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
promise.reject_native(&DOMException::new( promise.reject_native(
&self.global(), &DOMException::new(&self.global(), DOMErrorName::InvalidStateError, can_gc),
DOMErrorName::InvalidStateError,
can_gc, can_gc,
)); );
} else { } else {
// 3. // 3.
self.serviceworker_registration self.serviceworker_registration

View file

@ -208,7 +208,7 @@ impl Promise {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub(crate) fn reject_native<T>(&self, val: &T) pub(crate) fn reject_native<T>(&self, val: &T, can_gc: CanGc)
where where
T: ToJSValConvertible, T: ToJSValConvertible,
{ {
@ -218,7 +218,7 @@ impl Promise {
unsafe { unsafe {
val.to_jsval(*cx, v.handle_mut()); val.to_jsval(*cx, v.handle_mut());
} }
self.reject(cx, v.handle(), CanGc::note()); self.reject(cx, v.handle(), can_gc);
} }
pub(crate) fn reject_error(&self, error: Error) { pub(crate) fn reject_error(&self, error: Error) {

View file

@ -79,8 +79,8 @@ impl Callback for SourceCancelPromiseRejectionHandler {
/// The rejection handler for the reacting to sourceCancelPromise part of /// The rejection handler for the reacting to sourceCancelPromise part of
/// <https://streams.spec.whatwg.org/#readable-stream-cancel>. /// <https://streams.spec.whatwg.org/#readable-stream-cancel>.
/// An implementation of <https://webidl.spec.whatwg.org/#dfn-perform-steps-once-promise-is-settled> /// An implementation of <https://webidl.spec.whatwg.org/#dfn-perform-steps-once-promise-is-settled>
fn callback(&self, _cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, _cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
self.result.reject_native(&v); self.result.reject_native(&v, can_gc);
} }
} }
@ -388,7 +388,7 @@ impl ReadableStream {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-error> /// <https://streams.spec.whatwg.org/#readable-stream-error>
pub(crate) fn error(&self, e: SafeHandleValue) { pub(crate) fn error(&self, e: SafeHandleValue, can_gc: CanGc) {
// Assert: stream.[[state]] is "readable". // Assert: stream.[[state]] is "readable".
assert!(self.is_readable()); assert!(self.is_readable());
// Set stream.[[state]] to "errored". // Set stream.[[state]] to "errored".
@ -403,7 +403,7 @@ impl ReadableStream {
// If reader is undefined, return. // If reader is undefined, return.
return; return;
}; };
reader.error(e); reader.error(e, can_gc);
}, },
// Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e). // Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e).
_ => todo!(), _ => todo!(),
@ -417,11 +417,11 @@ impl ReadableStream {
/// <https://streams.spec.whatwg.org/#readable-stream-error> /// <https://streams.spec.whatwg.org/#readable-stream-error>
/// Note: in other use cases this call happens via the controller. /// Note: in other use cases this call happens via the controller.
pub(crate) fn error_native(&self, error: Error) { pub(crate) fn error_native(&self, error: Error, can_gc: CanGc) {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut error_val = UndefinedValue()); rooted!(in(*cx) let mut error_val = UndefinedValue());
error.to_jsval(cx, &self.global(), error_val.handle_mut()); error.to_jsval(cx, &self.global(), error_val.handle_mut());
self.error(error_val.handle()); self.error(error_val.handle(), can_gc);
} }
/// Call into the controller's `Close` method. /// Call into the controller's `Close` method.
@ -536,13 +536,13 @@ impl ReadableStream {
/// must be done after `start_reading`. /// must be done after `start_reading`.
/// Native call to /// Native call to
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease>
pub(crate) fn stop_reading(&self) { pub(crate) fn stop_reading(&self, can_gc: CanGc) {
match self.reader { match self.reader {
ReaderType::Default(ref reader) => { ReaderType::Default(ref reader) => {
let Some(reader) = reader.get() else { let Some(reader) = reader.get() else {
unreachable!("Attempt to stop reading without having first acquired a reader."); unreachable!("Attempt to stop reading without having first acquired a reader.");
}; };
reader.release().expect("Reader release cannot fail."); reader.release(can_gc).expect("Reader release cannot fail.");
}, },
ReaderType::BYOB(_) => { ReaderType::BYOB(_) => {
unreachable!("Native stop reading can only be done with a default reader.") unreachable!("Native stop reading can only be done with a default reader.")
@ -675,7 +675,7 @@ impl ReadableStream {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
self.stored_error.to_jsval(*cx, rval.handle_mut()); self.stored_error.to_jsval(*cx, rval.handle_mut());
promise.reject_native(&rval.handle()); promise.reject_native(&rval.handle(), can_gc);
return promise; return promise;
} }
} }

View file

@ -75,11 +75,11 @@ impl ReadIntoRequest {
} }
/// <https://streams.spec.whatwg.org/#ref-for-read-into-request-error-steps> /// <https://streams.spec.whatwg.org/#ref-for-read-into-request-error-steps>
pub(crate) fn error_steps(&self, e: SafeHandleValue) { pub(crate) fn error_steps(&self, e: SafeHandleValue, can_gc: CanGc) {
// error steps, given e // error steps, given e
// Reject promise with e. // Reject promise with e.
match self { match self {
ReadIntoRequest::Read(promise) => promise.reject_native(&e), ReadIntoRequest::Read(promise) => promise.reject_native(&e, can_gc),
} }
} }
} }
@ -159,7 +159,7 @@ impl ReadableStreamBYOBReader {
} }
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreaderrelease> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreaderrelease>
pub(crate) fn release(&self) -> Fallible<()> { pub(crate) fn release(&self, can_gc: CanGc) -> Fallible<()> {
// Perform ! ReadableStreamReaderGenericRelease(reader). // Perform ! ReadableStreamReaderGenericRelease(reader).
self.generic_release()?; self.generic_release()?;
// Let e be a new TypeError exception. // Let e be a new TypeError exception.
@ -172,19 +172,19 @@ impl ReadableStreamBYOBReader {
); );
// Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e). // Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e).
self.error_read_into_requests(error.handle()); self.error_read_into_requests(error.handle(), can_gc);
Ok(()) Ok(())
} }
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreadererrorreadintorequests> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreadererrorreadintorequests>
fn error_read_into_requests(&self, rval: SafeHandleValue) { fn error_read_into_requests(&self, rval: SafeHandleValue, can_gc: CanGc) {
// Let readRequests be reader.[[readRequests]]. // Let readRequests be reader.[[readRequests]].
let mut read_into_requests = self.take_read_into_requests(); let mut read_into_requests = self.take_read_into_requests();
// Set reader.[[readIntoRequests]] to a new empty list. // Set reader.[[readIntoRequests]] to a new empty list.
for request in read_into_requests.drain(0..) { for request in read_into_requests.drain(0..) {
// Perform readIntoRequests error steps, given e. // Perform readIntoRequests error steps, given e.
request.error_steps(rval); request.error_steps(rval, can_gc);
} }
} }
@ -234,7 +234,7 @@ impl ReadableStreamBYOBReader {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut error = UndefinedValue()); rooted!(in(*cx) let mut error = UndefinedValue());
stream.get_stored_error(error.handle_mut()); stream.get_stored_error(error.handle_mut());
read_into_request.error_steps(error.handle()); read_into_request.error_steps(error.handle(), can_gc);
} else { } else {
// Otherwise, // Otherwise,
// perform ! ReadableByteStreamControllerPullInto(stream.[[controller]], view, min, readIntoRequest). // perform ! ReadableByteStreamControllerPullInto(stream.[[controller]], view, min, readIntoRequest).
@ -342,14 +342,14 @@ impl ReadableStreamBYOBReaderMethods<crate::DomTypeHolder> for ReadableStreamBYO
} }
/// <https://streams.spec.whatwg.org/#byob-reader-release-lock> /// <https://streams.spec.whatwg.org/#byob-reader-release-lock>
fn ReleaseLock(&self) -> Fallible<()> { fn ReleaseLock(&self, can_gc: CanGc) -> Fallible<()> {
if self.stream.get().is_none() { if self.stream.get().is_none() {
// If this.[[stream]] is undefined, return. // If this.[[stream]] is undefined, return.
return Ok(()); return Ok(());
} }
// Perform !ReadableStreamBYOBReaderRelease(this). // Perform !ReadableStreamBYOBReaderRelease(this).
self.release() self.release(can_gc)
} }
/// <https://streams.spec.whatwg.org/#generic-reader-closed> /// <https://streams.spec.whatwg.org/#generic-reader-closed>

View file

@ -71,9 +71,9 @@ struct PullAlgorithmRejectionHandler {
impl Callback for PullAlgorithmRejectionHandler { impl Callback for PullAlgorithmRejectionHandler {
/// Continuation of <https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed> /// Continuation of <https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed>
/// Upon rejection of pullPromise with reason e. /// Upon rejection of pullPromise with reason e.
fn callback(&self, _cx: JSContext, v: HandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, _cx: JSContext, v: HandleValue, _realm: InRealm, can_gc: CanGc) {
// Perform ! ReadableStreamDefaultControllerError(controller, e). // Perform ! ReadableStreamDefaultControllerError(controller, e).
self.controller.error(v); self.controller.error(v, can_gc);
} }
} }
@ -108,9 +108,9 @@ struct StartAlgorithmRejectionHandler {
impl Callback for StartAlgorithmRejectionHandler { impl Callback for StartAlgorithmRejectionHandler {
/// Continuation of <https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller> /// Continuation of <https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller>
/// Upon rejection of startPromise with reason r, /// Upon rejection of startPromise with reason r,
fn callback(&self, _cx: JSContext, v: HandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, _cx: JSContext, v: HandleValue, _realm: InRealm, can_gc: CanGc) {
// Perform ! ReadableStreamDefaultControllerError(controller, r). // Perform ! ReadableStreamDefaultControllerError(controller, r).
self.controller.error(v); self.controller.error(v, can_gc);
} }
} }
@ -552,7 +552,7 @@ impl ReadableStreamDefaultController {
.clone() .clone()
.to_jsval(cx, &self.global(), rval.handle_mut()); .to_jsval(cx, &self.global(), rval.handle_mut());
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_native(&rval.handle()); promise.reject_native(&rval.handle(), can_gc);
promise promise
}); });
promise.append_native_handler(&handler, comp, can_gc); promise.append_native_handler(&handler, comp, can_gc);
@ -589,7 +589,7 @@ impl ReadableStreamDefaultController {
.clone() .clone()
.to_jsval(cx, &self.global(), rval.handle_mut()); .to_jsval(cx, &self.global(), rval.handle_mut());
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_native(&rval.handle()); promise.reject_native(&rval.handle(), can_gc);
promise promise
}); });
@ -689,7 +689,7 @@ impl ReadableStreamDefaultController {
unsafe { assert!(JS_GetPendingException(*cx, rval.handle_mut())) }; unsafe { assert!(JS_GetPendingException(*cx, rval.handle_mut())) };
// Perform ! ReadableStreamDefaultControllerError(controller, result.[[Value]]). // Perform ! ReadableStreamDefaultControllerError(controller, result.[[Value]]).
self.error(rval.handle()); self.error(rval.handle(), can_gc);
// Return result. // Return result.
// Note: we need to return a type error, because no exception is pending. // Note: we need to return a type error, because no exception is pending.
@ -723,7 +723,7 @@ impl ReadableStreamDefaultController {
unsafe { assert!(JS_GetPendingException(*cx, rval.handle_mut())) }; unsafe { assert!(JS_GetPendingException(*cx, rval.handle_mut())) };
// Perform ! ReadableStreamDefaultControllerError(controller, enqueueResult.[[Value]]). // Perform ! ReadableStreamDefaultControllerError(controller, enqueueResult.[[Value]]).
self.error(rval.handle()); self.error(rval.handle(), can_gc);
// Return enqueueResult. // Return enqueueResult.
// Note: because we threw the exception above, // Note: because we threw the exception above,
@ -845,7 +845,7 @@ impl ReadableStreamDefaultController {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-default-controller-error> /// <https://streams.spec.whatwg.org/#readable-stream-default-controller-error>
pub(crate) fn error(&self, e: SafeHandleValue) { pub(crate) fn error(&self, e: SafeHandleValue, can_gc: CanGc) {
let Some(stream) = self.stream.get() else { let Some(stream) = self.stream.get() else {
return; return;
}; };
@ -861,7 +861,7 @@ impl ReadableStreamDefaultController {
// Perform ! ReadableStreamDefaultControllerClearAlgorithms(controller). // Perform ! ReadableStreamDefaultControllerClearAlgorithms(controller).
self.clear_algorithms(); self.clear_algorithms();
stream.error(e); stream.error(e, can_gc);
} }
} }
@ -899,8 +899,8 @@ impl ReadableStreamDefaultControllerMethods<crate::DomTypeHolder>
} }
/// <https://streams.spec.whatwg.org/#rs-default-controller-error> /// <https://streams.spec.whatwg.org/#rs-default-controller-error>
fn Error(&self, _cx: SafeJSContext, e: SafeHandleValue) -> Fallible<()> { fn Error(&self, _cx: SafeJSContext, e: SafeHandleValue, can_gc: CanGc) -> Fallible<()> {
self.error(e); self.error(e, can_gc);
Ok(()) Ok(())
} }
} }

View file

@ -88,12 +88,12 @@ impl ReadRequest {
} }
/// <https://streams.spec.whatwg.org/#read-request-error-steps> /// <https://streams.spec.whatwg.org/#read-request-error-steps>
pub(crate) fn error_steps(&self, e: SafeHandleValue) { pub(crate) fn error_steps(&self, e: SafeHandleValue, can_gc: CanGc) {
match self { match self {
ReadRequest::Read(promise) => { ReadRequest::Read(promise) => {
// error steps, given e // error steps, given e
// Reject promise with e. // Reject promise with e.
promise.reject_native(&e) promise.reject_native(&e, can_gc)
}, },
ReadRequest::DefaultTee { tee_read_request } => { ReadRequest::DefaultTee { tee_read_request } => {
tee_read_request.error_steps(); tee_read_request.error_steps();
@ -125,9 +125,9 @@ impl Callback for ClosedPromiseRejectionHandler {
let branch_2_controller = &self.branch_2_controller; let branch_2_controller = &self.branch_2_controller;
// Perform ! ReadableStreamDefaultControllerError(branch_1.[[controller]], r). // Perform ! ReadableStreamDefaultControllerError(branch_1.[[controller]], r).
branch_1_controller.error(v); branch_1_controller.error(v, can_gc);
// Perform ! ReadableStreamDefaultControllerError(branch_2.[[controller]], r). // Perform ! ReadableStreamDefaultControllerError(branch_2.[[controller]], r).
branch_2_controller.error(v); branch_2_controller.error(v, can_gc);
// If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined. // If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined.
if !self.canceled_1.get() || !self.canceled_2.get() { if !self.canceled_1.get() || !self.canceled_2.get() {
@ -231,15 +231,15 @@ impl ReadableStreamDefaultReader {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-error> /// <https://streams.spec.whatwg.org/#readable-stream-error>
pub(crate) fn error(&self, e: SafeHandleValue) { pub(crate) fn error(&self, e: SafeHandleValue, can_gc: CanGc) {
// Reject reader.[[closedPromise]] with e. // Reject reader.[[closedPromise]] with e.
self.closed_promise.borrow().reject_native(&e); self.closed_promise.borrow().reject_native(&e, can_gc);
// Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
self.closed_promise.borrow().set_promise_is_handled(); self.closed_promise.borrow().set_promise_is_handled();
// Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e). // Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e).
self.error_read_requests(e); self.error_read_requests(e, can_gc);
} }
/// The removal steps of <https://streams.spec.whatwg.org/#readable-stream-fulfill-read-request> /// The removal steps of <https://streams.spec.whatwg.org/#readable-stream-fulfill-read-request>
@ -251,7 +251,7 @@ impl ReadableStreamDefaultReader {
} }
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease>
pub(crate) fn release(&self) -> Fallible<()> { pub(crate) fn release(&self, can_gc: CanGc) -> Fallible<()> {
// Perform ! ReadableStreamReaderGenericRelease(reader). // Perform ! ReadableStreamReaderGenericRelease(reader).
self.generic_release()?; self.generic_release()?;
// Let e be a new TypeError exception. // Let e be a new TypeError exception.
@ -264,7 +264,7 @@ impl ReadableStreamDefaultReader {
); );
// Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e). // Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e).
self.error_read_requests(error.handle()); self.error_read_requests(error.handle(), can_gc);
Ok(()) Ok(())
} }
@ -273,13 +273,13 @@ impl ReadableStreamDefaultReader {
} }
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreadererrorreadrequests> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreadererrorreadrequests>
fn error_read_requests(&self, rval: SafeHandleValue) { fn error_read_requests(&self, rval: SafeHandleValue, can_gc: CanGc) {
// step 1 // step 1
let mut read_requests = self.take_read_requests(); let mut read_requests = self.take_read_requests();
// step 2 & 3 // step 2 & 3
for request in read_requests.drain(0..) { for request in read_requests.drain(0..) {
request.error_steps(rval); request.error_steps(rval, can_gc);
} }
} }
@ -303,7 +303,7 @@ impl ReadableStreamDefaultReader {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut error = UndefinedValue()); rooted!(in(*cx) let mut error = UndefinedValue());
stream.get_stored_error(error.handle_mut()); stream.get_stored_error(error.handle_mut());
read_request.error_steps(error.handle()); read_request.error_steps(error.handle(), can_gc);
} else { } else {
// Otherwise // Otherwise
// Assert: stream.[[state]] is "readable". // Assert: stream.[[state]] is "readable".
@ -405,14 +405,14 @@ impl ReadableStreamDefaultReaderMethods<crate::DomTypeHolder> for ReadableStream
} }
/// <https://streams.spec.whatwg.org/#default-reader-release-lock> /// <https://streams.spec.whatwg.org/#default-reader-release-lock>
fn ReleaseLock(&self) -> Fallible<()> { fn ReleaseLock(&self, can_gc: CanGc) -> Fallible<()> {
if self.stream.get().is_none() { if self.stream.get().is_none() {
// Step 1: If this.[[stream]] is undefined, return. // Step 1: If this.[[stream]] is undefined, return.
return Ok(()); return Ok(());
} }
// Step 2: Perform !ReadableStreamDefaultReaderRelease(this). // Step 2: Perform !ReadableStreamDefaultReaderRelease(this).
self.release() self.release(can_gc)
} }
/// <https://streams.spec.whatwg.org/#generic-reader-closed> /// <https://streams.spec.whatwg.org/#generic-reader-closed>

View file

@ -90,9 +90,9 @@ impl Response {
) )
} }
pub(crate) fn error_stream(&self, error: Error) { pub(crate) fn error_stream(&self, error: Error, can_gc: CanGc) {
if let Some(body) = self.body_stream.get() { if let Some(body) = self.body_stream.get() {
body.error_native(error); body.error_native(error, can_gc);
} }
} }
} }

View file

@ -605,21 +605,25 @@ impl AsyncWGPUListener for GPUDevice {
), ),
can_gc, can_gc,
), ),
Err(webgpu::Error::Validation(msg)) => { Err(webgpu::Error::Validation(msg)) => promise.reject_native(
promise.reject_native(&GPUPipelineError::new( &GPUPipelineError::new(
&self.global(), &self.global(),
msg.into(), msg.into(),
GPUPipelineErrorReason::Validation, GPUPipelineErrorReason::Validation,
can_gc, can_gc,
)) ),
}, can_gc,
),
Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise
.reject_native(&GPUPipelineError::new( .reject_native(
&self.global(), &GPUPipelineError::new(
msg.into(), &self.global(),
GPUPipelineErrorReason::Internal, msg.into(),
GPUPipelineErrorReason::Internal,
can_gc,
),
can_gc, can_gc,
)), ),
}, },
WebGPUResponse::RenderPipeline(result) => match result { WebGPUResponse::RenderPipeline(result) => match result {
Ok(pipeline) => promise.resolve_native( Ok(pipeline) => promise.resolve_native(
@ -632,21 +636,25 @@ impl AsyncWGPUListener for GPUDevice {
), ),
can_gc, can_gc,
), ),
Err(webgpu::Error::Validation(msg)) => { Err(webgpu::Error::Validation(msg)) => promise.reject_native(
promise.reject_native(&GPUPipelineError::new( &GPUPipelineError::new(
&self.global(), &self.global(),
msg.into(), msg.into(),
GPUPipelineErrorReason::Validation, GPUPipelineErrorReason::Validation,
can_gc, can_gc,
)) ),
}, can_gc,
),
Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise Err(webgpu::Error::OutOfMemory(msg) | webgpu::Error::Internal(msg)) => promise
.reject_native(&GPUPipelineError::new( .reject_native(
&self.global(), &GPUPipelineError::new(
msg.into(), &self.global(),
GPUPipelineErrorReason::Internal, msg.into(),
GPUPipelineErrorReason::Internal,
can_gc,
),
can_gc, can_gc,
)), ),
}, },
_ => unreachable!("Wrong response received on AsyncWGPUListener for GPUDevice"), _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUDevice"),
} }

View file

@ -61,7 +61,7 @@ impl XRTest {
.push(Dom::from_ref(&device)); .push(Dom::from_ref(&device));
promise.resolve_native(&device, can_gc); promise.resolve_native(&device, can_gc);
} else { } else {
promise.reject_native(&()); promise.reject_native(&(), can_gc);
} }
} }
} }

View file

@ -54,7 +54,7 @@ impl Callback for AbortAlgorithmFulfillmentHandler {
// Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream). // Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
self.stream self.stream
.as_rooted() .as_rooted()
.reject_close_and_closed_promise_if_needed(cx); .reject_close_and_closed_promise_if_needed(cx, can_gc);
} }
} }
@ -71,20 +71,14 @@ struct AbortAlgorithmRejectionHandler {
} }
impl Callback for AbortAlgorithmRejectionHandler { impl Callback for AbortAlgorithmRejectionHandler {
fn callback( fn callback(&self, cx: SafeJSContext, reason: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
&self,
cx: SafeJSContext,
reason: SafeHandleValue,
_realm: InRealm,
_can_gc: CanGc,
) {
// Reject abortRequests promise with reason. // Reject abortRequests promise with reason.
self.abort_request_promise.reject_native(&reason); self.abort_request_promise.reject_native(&reason, can_gc);
// Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream). // Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
self.stream self.stream
.as_rooted() .as_rooted()
.reject_close_and_closed_promise_if_needed(cx); .reject_close_and_closed_promise_if_needed(cx, can_gc);
} }
} }
@ -272,7 +266,7 @@ impl WritableStream {
// If stream.[[pendingAbortRequest]] is undefined, // If stream.[[pendingAbortRequest]] is undefined,
if self.pending_abort_request.borrow().is_none() { if self.pending_abort_request.borrow().is_none() {
// Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream). // Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
self.reject_close_and_closed_promise_if_needed(cx); self.reject_close_and_closed_promise_if_needed(cx, can_gc);
// Return. // Return.
return; return;
@ -290,7 +284,7 @@ impl WritableStream {
.reject(cx, stored_error.handle(), can_gc); .reject(cx, stored_error.handle(), can_gc);
// Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream). // Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
self.reject_close_and_closed_promise_if_needed(cx); self.reject_close_and_closed_promise_if_needed(cx, can_gc);
// Return. // Return.
return; return;
@ -326,7 +320,7 @@ impl WritableStream {
} }
/// <https://streams.spec.whatwg.org/#writable-stream-reject-close-and-closed-promise-if-needed> /// <https://streams.spec.whatwg.org/#writable-stream-reject-close-and-closed-promise-if-needed>
fn reject_close_and_closed_promise_if_needed(&self, cx: SafeJSContext) { fn reject_close_and_closed_promise_if_needed(&self, cx: SafeJSContext, can_gc: CanGc) {
// Assert: stream.[[state]] is "errored". // Assert: stream.[[state]] is "errored".
assert!(self.is_errored()); assert!(self.is_errored());
@ -340,7 +334,7 @@ impl WritableStream {
assert!(self.in_flight_close_request.borrow().is_none()); assert!(self.in_flight_close_request.borrow().is_none());
// Reject stream.[[closeRequest]] with stream.[[storedError]]. // Reject stream.[[closeRequest]] with stream.[[storedError]].
close_request.reject_native(&stored_error.handle()) close_request.reject_native(&stored_error.handle(), can_gc)
// Set stream.[[closeRequest]] to undefined. // Set stream.[[closeRequest]] to undefined.
// Done with `take` above. // Done with `take` above.
@ -350,7 +344,7 @@ impl WritableStream {
// If writer is not undefined, // If writer is not undefined,
if let Some(writer) = self.writer.get() { if let Some(writer) = self.writer.get() {
// Reject writer.[[closedPromise]] with stream.[[storedError]]. // Reject writer.[[closedPromise]] with stream.[[storedError]].
writer.reject_closed_promise_with_stored_error(&stored_error.handle()); writer.reject_closed_promise_with_stored_error(&stored_error.handle(), can_gc);
// Set writer.[[closedPromise]].[[PromiseIsHandled]] to true. // Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
writer.set_close_promise_is_handled(); writer.set_close_promise_is_handled();
@ -545,7 +539,7 @@ impl WritableStream {
}; };
// Reject stream.[[inFlightCloseRequest]] with error. // Reject stream.[[inFlightCloseRequest]] with error.
in_flight_close_request.reject_native(&error); in_flight_close_request.reject_native(&error, can_gc);
// Set stream.[[inFlightCloseRequest]] to undefined. // Set stream.[[inFlightCloseRequest]] to undefined.
// Done above with `take`. // Done above with `take`.
@ -557,7 +551,7 @@ impl WritableStream {
rooted!(in(*cx) let pending_abort_request = self.pending_abort_request.borrow_mut().take()); rooted!(in(*cx) let pending_abort_request = self.pending_abort_request.borrow_mut().take());
if let Some(pending_abort_request) = &*pending_abort_request { if let Some(pending_abort_request) = &*pending_abort_request {
// Reject stream.[[pendingAbortRequest]]'s promise with error. // Reject stream.[[pendingAbortRequest]]'s promise with error.
pending_abort_request.promise.reject_native(&error); pending_abort_request.promise.reject_native(&error, can_gc);
// Set stream.[[pendingAbortRequest]] to undefined. // Set stream.[[pendingAbortRequest]] to undefined.
// Done above with `take`. // Done above with `take`.
@ -581,7 +575,7 @@ impl WritableStream {
}; };
// Reject stream.[[inFlightWriteRequest]] with error. // Reject stream.[[inFlightWriteRequest]] with error.
in_flight_write_request.reject_native(&error); in_flight_write_request.reject_native(&error, can_gc);
// Set stream.[[inFlightWriteRequest]] to undefined. // Set stream.[[inFlightWriteRequest]] to undefined.
// Done above with `take`. // Done above with `take`.

View file

@ -109,7 +109,7 @@ impl WritableStreamDefaultWriter {
// Set writer.[[readyPromise]].[[PromiseIsHandled]] to true. // Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
// Note: new promise created in `new_inherited`. // Note: new promise created in `new_inherited`.
let ready_promise = self.ready_promise.borrow(); let ready_promise = self.ready_promise.borrow();
ready_promise.reject_native(&error.handle()); ready_promise.reject_native(&error.handle(), can_gc);
ready_promise.set_promise_is_handled(); ready_promise.set_promise_is_handled();
// Set writer.[[closedPromise]] to a new promise. // Set writer.[[closedPromise]] to a new promise.
@ -141,21 +141,25 @@ impl WritableStreamDefaultWriter {
// Set writer.[[readyPromise]].[[PromiseIsHandled]] to true. // Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
// Note: new promise created in `new_inherited`. // Note: new promise created in `new_inherited`.
let ready_promise = self.ready_promise.borrow(); let ready_promise = self.ready_promise.borrow();
ready_promise.reject_native(&error.handle()); ready_promise.reject_native(&error.handle(), can_gc);
ready_promise.set_promise_is_handled(); ready_promise.set_promise_is_handled();
// Set writer.[[closedPromise]] to a promise rejected with storedError. // Set writer.[[closedPromise]] to a promise rejected with storedError.
// Set writer.[[closedPromise]].[[PromiseIsHandled]] to true. // Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
// Note: new promise created in `new_inherited`. // Note: new promise created in `new_inherited`.
let ready_promise = self.closed_promise.borrow(); let ready_promise = self.closed_promise.borrow();
ready_promise.reject_native(&error.handle()); ready_promise.reject_native(&error.handle(), can_gc);
ready_promise.set_promise_is_handled(); ready_promise.set_promise_is_handled();
Ok(()) Ok(())
} }
pub(crate) fn reject_closed_promise_with_stored_error(&self, error: &SafeHandleValue) { pub(crate) fn reject_closed_promise_with_stored_error(
self.closed_promise.borrow().reject_native(error); &self,
error: &SafeHandleValue,
can_gc: CanGc,
) {
self.closed_promise.borrow().reject_native(error, can_gc);
} }
pub(crate) fn set_close_promise_is_handled(&self) { pub(crate) fn set_close_promise_is_handled(&self) {
@ -186,14 +190,14 @@ impl WritableStreamDefaultWriter {
// If writer.[[readyPromise]].[[PromiseState]] is "pending", // If writer.[[readyPromise]].[[PromiseState]] is "pending",
if ready_promise.is_pending() { if ready_promise.is_pending() {
// reject writer.[[readyPromise]] with error. // reject writer.[[readyPromise]] with error.
ready_promise.reject_native(&error); ready_promise.reject_native(&error, can_gc);
// Set writer.[[readyPromise]].[[PromiseIsHandled]] to true. // Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
ready_promise.set_promise_is_handled(); ready_promise.set_promise_is_handled();
} else { } else {
// Otherwise, set writer.[[readyPromise]] to a promise rejected with error. // Otherwise, set writer.[[readyPromise]] to a promise rejected with error.
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_native(&error); promise.reject_native(&error, can_gc);
// Set writer.[[readyPromise]].[[PromiseIsHandled]] to true. // Set writer.[[readyPromise]].[[PromiseIsHandled]] to true.
promise.set_promise_is_handled(); promise.set_promise_is_handled();
@ -213,14 +217,14 @@ impl WritableStreamDefaultWriter {
// If writer.[[closedPromise]].[[PromiseState]] is "pending", // If writer.[[closedPromise]].[[PromiseState]] is "pending",
if closed_promise.is_pending() { if closed_promise.is_pending() {
// reject writer.[[closedPromise]] with error. // reject writer.[[closedPromise]] with error.
closed_promise.reject_native(&error); closed_promise.reject_native(&error, can_gc);
// Set writer.[[closedPromise]].[[PromiseIsHandled]] to true. // Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
closed_promise.set_promise_is_handled(); closed_promise.set_promise_is_handled();
} else { } else {
// Otherwise, set writer.[[closedPromise]] to a promise rejected with error. // Otherwise, set writer.[[closedPromise]] to a promise rejected with error.
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_native(&error); promise.reject_native(&error, can_gc);
// Set writer.[[closedPromise]].[[PromiseIsHandled]] to true. // Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
promise.set_promise_is_handled(); promise.set_promise_is_handled();
@ -302,7 +306,7 @@ impl WritableStreamDefaultWriter {
rooted!(in(*cx) let mut error = UndefinedValue()); rooted!(in(*cx) let mut error = UndefinedValue());
stream.get_stored_error(error.handle_mut()); stream.get_stored_error(error.handle_mut());
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_native(&error.handle()); promise.reject_native(&error.handle(), can_gc);
return promise; return promise;
} }
@ -324,7 +328,7 @@ impl WritableStreamDefaultWriter {
rooted!(in(*cx) let mut error = UndefinedValue()); rooted!(in(*cx) let mut error = UndefinedValue());
stream.get_stored_error(error.handle_mut()); stream.get_stored_error(error.handle_mut());
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_native(&error.handle()); promise.reject_native(&error.handle(), can_gc);
return promise; return promise;
} }

View file

@ -150,7 +150,7 @@ pub(crate) fn Fetch(
// with input and init as arguments. If this throws an exception, reject p with it and return p. // with input and init as arguments. If this throws an exception, reject p with it and return p.
let request = match Request::Constructor(global, None, can_gc, input, init) { let request = match Request::Constructor(global, None, can_gc, input, init) {
Err(e) => { Err(e) => {
response.error_stream(e.clone()); response.error_stream(e.clone(), can_gc);
promise.reject_error(e); promise.reject_error(e);
return promise; return promise;
}, },
@ -227,7 +227,10 @@ impl FetchResponseListener for FetchContext {
self.fetch_promise = Some(TrustedPromise::new(promise)); self.fetch_promise = Some(TrustedPromise::new(promise));
let response = self.response_object.root(); let response = self.response_object.root();
response.set_type(DOMResponseType::Error, CanGc::note()); response.set_type(DOMResponseType::Error, CanGc::note());
response.error_stream(Error::Type("Network error occurred".to_string())); response.error_stream(
Error::Type("Network error occurred".to_string()),
CanGc::note(),
);
return; return;
}, },
// Step 4.2 // Step 4.2

View file

@ -593,15 +593,15 @@ DOMInterfaces = {
}, },
"ReadableStreamDefaultController": { "ReadableStreamDefaultController": {
"canGc": ["Close", "Enqueue"] "canGc": ["Close", "Enqueue", "Error"]
}, },
"ReadableStreamBYOBReader": { "ReadableStreamBYOBReader": {
"canGc": ["Read", "Cancel"] "canGc": ["Cancel", "Read", "ReleaseLock"]
}, },
"ReadableStreamDefaultReader": { "ReadableStreamDefaultReader": {
"canGc": ["Read", "Cancel"] "canGc": ["Cancel", "Read", "ReleaseLock"]
}, },
'WritableStream': { 'WritableStream': {