feat: add CanGc argument to Error::to_jsval (#36014)

* feat: add CanGc argument to Error::to_jsval

Signed-off-by: Arya Nair <aryaajitnair@gmail.com>

* feat: pass CanGc to gen_type_error

Signed-off-by: Arya Nair <aryaajitnair@gmail.com>

* fix: linting issues

Signed-off-by: Arya Nair <aryaajitnair@gmail.com>

---------

Signed-off-by: Arya Nair <aryaajitnair@gmail.com>
This commit is contained in:
Arya Nair 2025-03-18 03:59:41 +05:30 committed by GitHub
parent 6807a6e532
commit 94d12de7fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 45 additions and 24 deletions

View file

@ -275,18 +275,30 @@ pub(crate) fn throw_constructor_without_new(cx: SafeJSContext, name: &str) {
}
pub(crate) trait ErrorToJsval {
fn to_jsval(self, cx: SafeJSContext, global: &GlobalScope, rval: MutableHandleValue);
fn to_jsval(
self,
cx: SafeJSContext,
global: &GlobalScope,
rval: MutableHandleValue,
can_gc: CanGc,
);
}
impl ErrorToJsval for Error {
/// Convert this error value to a JS value, consuming it in the process.
#[allow(clippy::wrong_self_convention)]
fn to_jsval(self, cx: SafeJSContext, global: &GlobalScope, rval: MutableHandleValue) {
fn to_jsval(
self,
cx: SafeJSContext,
global: &GlobalScope,
rval: MutableHandleValue,
can_gc: CanGc,
) {
match self {
Error::JSFailed => (),
_ => unsafe { assert!(!JS_IsExceptionPending(*cx)) },
}
throw_dom_exception(cx, global, self, CanGc::note());
throw_dom_exception(cx, global, self, can_gc);
unsafe {
assert!(JS_IsExceptionPending(*cx));
assert!(JS_GetPendingException(*cx, rval));

View file

@ -225,7 +225,7 @@ impl Promise {
let cx = GlobalScope::get_cx();
let _ac = enter_realm(self);
rooted!(in(*cx) let mut v = UndefinedValue());
error.to_jsval(cx, &self.global(), v.handle_mut());
error.to_jsval(cx, &self.global(), v.handle_mut(), can_gc);
self.reject(cx, v.handle(), can_gc);
}

View file

@ -417,6 +417,7 @@ impl ReadableByteStreamController {
cx,
&self.global(),
error.handle_mut(),
can_gc,
);
// Perform ! ReadableByteStreamControllerError(controller, e).
@ -449,7 +450,7 @@ impl ReadableByteStreamController {
rooted!(in(*cx) let mut rval = UndefinedValue());
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
read_into_request.error_steps(rval.handle(), can_gc);
// Return.
@ -888,7 +889,8 @@ impl ReadableByteStreamController {
// Perform ! ReadableByteStreamControllerError(controller, e).
rooted!(in(*cx) let mut error = UndefinedValue());
e.clone().to_jsval(cx, &self.global(), error.handle_mut());
e.clone()
.to_jsval(cx, &self.global(), error.handle_mut(), can_gc);
self.error(error.handle(), can_gc);
// Throw e.
@ -1451,7 +1453,7 @@ impl ReadableByteStreamController {
let error = Error::Type("can not clone array buffer".to_owned());
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
self.error(rval.handle(), can_gc);
// Return cloneResult.
@ -1622,7 +1624,7 @@ impl ReadableByteStreamController {
// TODO: check if `self.global()` is the right globalscope.
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
let promise = Promise::new(&global, can_gc);
promise.reject_native(&rval.handle(), can_gc);
promise
@ -1809,7 +1811,7 @@ impl ReadableByteStreamController {
// TODO: check if `self.global()` is the right globalscope.
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
let promise = Promise::new(&global, can_gc);
promise.reject_native(&rval.handle(), can_gc);
promise
@ -1890,7 +1892,7 @@ impl ReadableByteStreamController {
rooted!(in(*cx) let mut rval = UndefinedValue());
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
read_request.error_steps(rval.handle(), can_gc);
// Return.

View file

@ -451,7 +451,7 @@ impl ReadableStream {
pub(crate) fn error_native(&self, error: Error, can_gc: CanGc) {
let cx = GlobalScope::get_cx();
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(), can_gc);
self.error(error_val.handle(), can_gc);
}

View file

@ -178,6 +178,7 @@ impl ReadableStreamBYOBReader {
cx,
&self.global(),
error.handle_mut(),
can_gc,
);
// Perform ! ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e).

View file

@ -552,7 +552,7 @@ impl ReadableStreamDefaultController {
// TODO: check if `self.global()` is the right globalscope.
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
let promise = Promise::new(&global, can_gc);
promise.reject_native(&rval.handle(), can_gc);
promise
@ -589,7 +589,7 @@ impl ReadableStreamDefaultController {
// TODO: check if `self.global()` is the right globalscope.
error
.clone()
.to_jsval(cx, &self.global(), rval.handle_mut());
.to_jsval(cx, &self.global(), rval.handle_mut(), can_gc);
let promise = Promise::new(&global, can_gc);
promise.reject_native(&rval.handle(), can_gc);
promise

View file

@ -67,7 +67,7 @@ impl Callback for ReadLoopFulFillmentHandler {
.release(can_gc)
.expect("Releasing the reader should succeed");
rooted!(in(*cx) let mut v = UndefinedValue());
err.to_jsval(cx, &global, v.handle_mut());
err.to_jsval(cx, &global, v.handle_mut(), can_gc);
(self.failure_steps)(cx, v.handle());
return;
},
@ -87,7 +87,7 @@ impl Callback for ReadLoopFulFillmentHandler {
Err(err) => {
// If chunk is not a Uint8Array object, call failureSteps with a TypeError and abort these steps.
rooted!(in(*cx) let mut v = UndefinedValue());
err.to_jsval(cx, &global, v.handle_mut());
err.to_jsval(cx, &global, v.handle_mut(), can_gc);
(self.failure_steps)(cx, v.handle());
self.reader
.release(can_gc)
@ -387,6 +387,7 @@ impl ReadableStreamDefaultReader {
cx,
&self.global(),
error.handle_mut(),
can_gc,
);
// Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e).
@ -557,6 +558,7 @@ impl ReadableStreamDefaultReaderMethods<crate::DomTypeHolder> for ReadableStream
cx,
&self.global(),
error.handle_mut(),
can_gc,
);
return Promise::new_rejected(&self.global(), cx, error.handle(), can_gc);
}

View file

@ -103,6 +103,7 @@ pub(crate) trait ReadableStreamGenericReader {
cx,
&stream.global(),
error.handle_mut(),
can_gc,
);
self.set_closed_promise(Promise::new_rejected(

View file

@ -702,7 +702,7 @@ impl WritableStreamDefaultController {
// Perform ! WritableStreamDefaultControllerErrorIfNeeded(controller, returnValue.[[Value]]).
// Create a rooted value for the error.
rooted!(in(*cx) let mut rooted_error = UndefinedValue());
error.to_jsval(cx, global, rooted_error.handle_mut());
error.to_jsval(cx, global, rooted_error.handle_mut(), can_gc);
self.error_if_needed(cx, rooted_error.handle(), global, can_gc);
// Return 1.
@ -734,7 +734,7 @@ impl WritableStreamDefaultController {
// Perform ! WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueResult.[[Value]]).
// Create a rooted value for the error.
rooted!(in(*cx) let mut rooted_error = UndefinedValue());
error.to_jsval(cx, global, rooted_error.handle_mut());
error.to_jsval(cx, global, rooted_error.handle_mut(), can_gc);
self.error_if_needed(cx, rooted_error.handle(), global, can_gc);
// Return.

View file

@ -363,7 +363,7 @@ impl WritableStreamDefaultWriter {
// Root the js val of the error.
rooted!(in(*cx) let mut error = UndefinedValue());
released_error.to_jsval(cx, global, error.handle_mut());
released_error.to_jsval(cx, global, error.handle_mut(), can_gc);
// Perform ! WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError).
self.ensure_ready_promise_rejected(global, error.handle(), can_gc);

View file

@ -76,9 +76,9 @@ use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::task::TaskBox;
fn gen_type_error(global: &GlobalScope, string: String) -> RethrowError {
fn gen_type_error(global: &GlobalScope, string: String, can_gc: CanGc) -> RethrowError {
rooted!(in(*GlobalScope::get_cx()) let mut thrown = UndefinedValue());
Error::Type(string).to_jsval(GlobalScope::get_cx(), global, thrown.handle_mut());
Error::Type(string).to_jsval(GlobalScope::get_cx(), global, thrown.handle_mut(), can_gc);
RethrowError(RootedTraceableBox::from_box(Heap::boxed(thrown.get())))
}
@ -463,7 +463,7 @@ impl ModuleTree {
options: ScriptFetchOptions,
mut module_script: RustMutableHandleObject,
inline: bool,
_can_gc: CanGc,
can_gc: CanGc,
) -> Result<(), RethrowError> {
let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
@ -509,6 +509,7 @@ impl ModuleTree {
global,
module_script.handle().into_handle(),
url,
can_gc,
)
.map(|_| ())
}
@ -612,6 +613,7 @@ impl ModuleTree {
global: &GlobalScope,
module_object: HandleObject,
base_url: &ServoUrl,
can_gc: CanGc,
) -> Result<IndexSet<ServoUrl>, RethrowError> {
let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
@ -634,7 +636,7 @@ impl ModuleTree {
if url.is_err() {
let specifier_error =
gen_type_error(global, "Wrong module specifier".to_owned());
gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
return Err(specifier_error);
}
@ -768,6 +770,7 @@ impl ModuleTree {
&global,
raw_record.handle(),
&self.url,
can_gc,
),
}
};
@ -1045,7 +1048,7 @@ impl ModuleOwner {
// Ensure any failures related to importing this dynamic module are immediately reported.
match (network_error, existing_rethrow_error) {
(Some(_), _) => unsafe {
let err = gen_type_error(&global, "Dynamic import failed".to_owned());
let err = gen_type_error(&global, "Dynamic import failed".to_owned(), can_gc);
JS_SetPendingException(*cx, err.handle(), ExceptionStackBehavior::Capture);
},
(None, Some(rethrow_error)) => unsafe {
@ -1430,7 +1433,7 @@ fn fetch_an_import_module_script_graph(
// Step 2.
if url.is_err() {
let specifier_error = gen_type_error(global, "Wrong module specifier".to_owned());
let specifier_error = gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
return Err(specifier_error);
}