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 { 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 { impl ErrorToJsval for Error {
/// Convert this error value to a JS value, consuming it in the process. /// Convert this error value to a JS value, consuming it in the process.
#[allow(clippy::wrong_self_convention)] #[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 { match self {
Error::JSFailed => (), Error::JSFailed => (),
_ => unsafe { assert!(!JS_IsExceptionPending(*cx)) }, _ => unsafe { assert!(!JS_IsExceptionPending(*cx)) },
} }
throw_dom_exception(cx, global, self, CanGc::note()); throw_dom_exception(cx, global, self, can_gc);
unsafe { unsafe {
assert!(JS_IsExceptionPending(*cx)); assert!(JS_IsExceptionPending(*cx));
assert!(JS_GetPendingException(*cx, rval)); assert!(JS_GetPendingException(*cx, rval));

View file

@ -225,7 +225,7 @@ impl Promise {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(self); let _ac = enter_realm(self);
rooted!(in(*cx) let mut v = UndefinedValue()); 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); self.reject(cx, v.handle(), can_gc);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -363,7 +363,7 @@ impl WritableStreamDefaultWriter {
// Root the js val of the error. // Root the js val of the error.
rooted!(in(*cx) let mut error = UndefinedValue()); 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). // Perform ! WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError).
self.ensure_ready_promise_rejected(global, error.handle(), can_gc); 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::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::task::TaskBox; 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()); 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()))) RethrowError(RootedTraceableBox::from_box(Heap::boxed(thrown.get())))
} }
@ -463,7 +463,7 @@ impl ModuleTree {
options: ScriptFetchOptions, options: ScriptFetchOptions,
mut module_script: RustMutableHandleObject, mut module_script: RustMutableHandleObject,
inline: bool, inline: bool,
_can_gc: CanGc, can_gc: CanGc,
) -> Result<(), RethrowError> { ) -> Result<(), RethrowError> {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject()); let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
@ -509,6 +509,7 @@ impl ModuleTree {
global, global,
module_script.handle().into_handle(), module_script.handle().into_handle(),
url, url,
can_gc,
) )
.map(|_| ()) .map(|_| ())
} }
@ -612,6 +613,7 @@ impl ModuleTree {
global: &GlobalScope, global: &GlobalScope,
module_object: HandleObject, module_object: HandleObject,
base_url: &ServoUrl, base_url: &ServoUrl,
can_gc: CanGc,
) -> Result<IndexSet<ServoUrl>, RethrowError> { ) -> Result<IndexSet<ServoUrl>, RethrowError> {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject()); let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
@ -634,7 +636,7 @@ impl ModuleTree {
if url.is_err() { if url.is_err() {
let specifier_error = 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); return Err(specifier_error);
} }
@ -768,6 +770,7 @@ impl ModuleTree {
&global, &global,
raw_record.handle(), raw_record.handle(),
&self.url, &self.url,
can_gc,
), ),
} }
}; };
@ -1045,7 +1048,7 @@ impl ModuleOwner {
// Ensure any failures related to importing this dynamic module are immediately reported. // Ensure any failures related to importing this dynamic module are immediately reported.
match (network_error, existing_rethrow_error) { match (network_error, existing_rethrow_error) {
(Some(_), _) => unsafe { (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); JS_SetPendingException(*cx, err.handle(), ExceptionStackBehavior::Capture);
}, },
(None, Some(rethrow_error)) => unsafe { (None, Some(rethrow_error)) => unsafe {
@ -1430,7 +1433,7 @@ fn fetch_an_import_module_script_graph(
// Step 2. // Step 2.
if url.is_err() { 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); return Err(specifier_error);
} }