refactor: add CanGc as argument to Promise::reject_error (#35646)

Signed-off-by: Yerkebulan Tulibergenov <yerkebulan@gmail.com>
This commit is contained in:
Yerkebulan Tulibergenov 2025-02-25 02:12:58 -08:00 committed by GitHub
parent c844ed232a
commit 38b71087bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 323 additions and 249 deletions

View file

@ -645,7 +645,7 @@ impl ConsumeBodyPromiseHandler {
}, },
}; };
}, },
Err(err) => self.result_promise.reject_error(err), Err(err) => self.result_promise.reject_error(err, can_gc),
} }
} }
} }
@ -665,7 +665,7 @@ impl Callback for ConsumeBodyPromiseHandler {
Err(err) => { Err(err) => {
stream.stop_reading(can_gc); 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, can_gc);
}, },
}; };
@ -678,7 +678,7 @@ impl Callback for ConsumeBodyPromiseHandler {
Err(err) => { Err(err) => {
stream.stop_reading(can_gc); 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, can_gc);
}, },
}; };
@ -734,9 +734,10 @@ pub(crate) fn consume_body<T: BodyMixin + DomObject>(
// Step 1 // Step 1
if object.is_disturbed() || object.is_locked() { if object.is_disturbed() || object.is_locked() {
promise.reject_error(Error::Type( promise.reject_error(
"The body's stream is disturbed or locked".to_string(), Error::Type("The body's stream is disturbed or locked".to_string()),
)); can_gc,
);
return promise; return promise;
} }
@ -770,9 +771,10 @@ fn consume_body_with_promise<T: BodyMixin + DomObject>(
// Step 3. // Step 3.
if stream.acquire_default_reader(can_gc).is_err() { if stream.acquire_default_reader(can_gc).is_err() {
return promise.reject_error(Error::Type( return promise.reject_error(
"The response's stream is disturbed or locked".to_string(), Error::Type("The response's stream is disturbed or locked".to_string()),
)); can_gc,
);
} }
// Step 4, read all the bytes. // Step 4, read all the bytes.

View file

@ -146,7 +146,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
// Step 2. // Step 2.
if self.context.control_thread_state() == ProcessingState::Closed { if self.context.control_thread_state() == ProcessingState::Closed {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }
@ -186,7 +186,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
.dom_manipulation_task_source() .dom_manipulation_task_source()
.queue(task!(suspend_error: move || { .queue(task!(suspend_error: move || {
let promise = trusted_promise.root(); let promise = trusted_promise.root();
promise.reject_error(Error::Type("Something went wrong".to_owned())); promise.reject_error(Error::Type("Something went wrong".to_owned()), CanGc::note());
})); }));
}, },
}; };
@ -202,7 +202,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
// Step 2. // Step 2.
if self.context.control_thread_state() == ProcessingState::Closed { if self.context.control_thread_state() == ProcessingState::Closed {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }
@ -242,7 +242,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
.dom_manipulation_task_source() .dom_manipulation_task_source()
.queue(task!(suspend_error: move || { .queue(task!(suspend_error: move || {
let promise = trusted_promise.root(); let promise = trusted_promise.root();
promise.reject_error(Error::Type("Something went wrong".to_owned())); promise.reject_error(Error::Type("Something went wrong".to_owned()), CanGc::note());
})); }));
}, },
}; };

View file

@ -212,7 +212,7 @@ impl BaseAudioContext {
for promise in &*promises { for promise in &*promises {
match result { match result {
Ok(ref value) => promise.resolve_native(value, CanGc::note()), Ok(ref value) => promise.resolve_native(value, CanGc::note()),
Err(ref error) => promise.reject_error(error.clone()), Err(ref error) => promise.reject_error(error.clone(), CanGc::note()),
} }
} }
} }
@ -292,7 +292,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
// Step 2. // Step 2.
if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed { if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }
@ -564,7 +564,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
ExceptionHandling::Report); ExceptionHandling::Report);
} }
let error = format!("Audio decode error {:?}", error); let error = format!("Audio decode error {:?}", error);
resolver.promise.reject_error(Error::Type(error)); resolver.promise.reject_error(Error::Type(error), CanGc::note());
})); }));
}) })
.build(); .build();
@ -574,7 +574,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
.decode_audio_data(audio_data, callbacks); .decode_audio_data(audio_data, callbacks);
} else { } else {
// Step 3. // Step 3.
promise.reject_error(Error::DataClone); promise.reject_error(Error::DataClone, can_gc);
return promise; return promise;
} }

View file

@ -139,7 +139,7 @@ impl TrustedPromise {
let this = self; let this = self;
task!(reject_promise: move || { task!(reject_promise: move || {
debug!("Rejecting promise."); debug!("Rejecting promise.");
this.root().reject_error(error); this.root().reject_error(error, CanGc::note());
}) })
} }

View file

@ -259,7 +259,7 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
promise.resolve_native(&text, CanGc::note()); promise.resolve_native(&text, CanGc::note());
}, },
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
}, },
}), }),
); );
@ -287,11 +287,11 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
Ok(FetchedData::ArrayBuffer(a)) => { Ok(FetchedData::ArrayBuffer(a)) => {
promise.resolve_native(&a, CanGc::note()) promise.resolve_native(&a, CanGc::note())
}, },
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
_ => panic!("Unexpected result from run_array_buffer_data_algorithm"), _ => panic!("Unexpected result from run_array_buffer_data_algorithm"),
} }
}, },
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
}; };
}), }),
); );

View file

@ -131,7 +131,7 @@ where
.handle_response(response, &promise, can_gc), .handle_response(response, &promise, can_gc),
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
// Step 3 - 4. // Step 3 - 4.
Err(error) => promise.reject_error(error.convert()), Err(error) => promise.reject_error(error.convert(), can_gc),
} }
} }
} }
@ -170,6 +170,7 @@ impl Bluetooth {
filters: &Option<Vec<BluetoothLEScanFilterInit>>, filters: &Option<Vec<BluetoothLEScanFilterInit>>,
optional_services: &[BluetoothServiceUUID], optional_services: &[BluetoothServiceUUID],
sender: IpcSender<BluetoothResponseResult>, sender: IpcSender<BluetoothResponseResult>,
can_gc: CanGc,
) { ) {
// TODO: Step 1: Triggered by user activation. // TODO: Step 1: Triggered by user activation.
@ -179,7 +180,7 @@ impl Bluetooth {
if let Some(filters) = filters { if let Some(filters) = filters {
// Step 2.1. // Step 2.1.
if filters.is_empty() { if filters.is_empty() {
p.reject_error(Type(FILTER_EMPTY_ERROR.to_owned())); p.reject_error(Type(FILTER_EMPTY_ERROR.to_owned()), can_gc);
return; return;
} }
@ -192,7 +193,7 @@ impl Bluetooth {
// Step 2.4.2. // Step 2.4.2.
Ok(f) => uuid_filters.push(f), Ok(f) => uuid_filters.push(f),
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return; return;
}, },
} }
@ -206,7 +207,7 @@ impl Bluetooth {
let uuid = match BluetoothUUID::service(opt_service.clone()) { let uuid = match BluetoothUUID::service(opt_service.clone()) {
Ok(u) => u.to_string(), Ok(u) => u.to_string(),
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return; return;
}, },
}; };
@ -229,7 +230,7 @@ impl Bluetooth {
if let PermissionState::Denied = if let PermissionState::Denied =
descriptor_permission_state(PermissionName::Bluetooth, None) descriptor_permission_state(PermissionName::Bluetooth, None)
{ {
return p.reject_error(Error::NotFound); return p.reject_error(Error::NotFound, can_gc);
} }
// Note: Step 3, 6 - 8 are implemented in // Note: Step 3, 6 - 8 are implemented in
@ -307,13 +308,13 @@ where
let canonicalized = match uuid_canonicalizer(u) { let canonicalized = match uuid_canonicalizer(u) {
Ok(canonicalized_uuid) => canonicalized_uuid.to_string(), Ok(canonicalized_uuid) => canonicalized_uuid.to_string(),
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return p; return p;
}, },
}; };
// Step 2. // Step 2.
if uuid_is_blocklisted(canonicalized.as_ref(), Blocklist::All) { if uuid_is_blocklisted(canonicalized.as_ref(), Blocklist::All) {
p.reject_error(Security); p.reject_error(Security, can_gc);
return p; return p;
} }
Some(canonicalized) Some(canonicalized)
@ -323,7 +324,7 @@ where
// Step 3 - 4. // Step 3 - 4.
if !connected { if !connected {
p.reject_error(Network); p.reject_error(Network, can_gc);
return p; return p;
} }
@ -550,13 +551,19 @@ impl BluetoothMethods<crate::DomTypeHolder> for Bluetooth {
if (option.filters.is_some() && option.acceptAllDevices) || if (option.filters.is_some() && option.acceptAllDevices) ||
(option.filters.is_none() && !option.acceptAllDevices) (option.filters.is_none() && !option.acceptAllDevices)
{ {
p.reject_error(Error::Type(OPTIONS_ERROR.to_owned())); p.reject_error(Error::Type(OPTIONS_ERROR.to_owned()), can_gc);
return p; return p;
} }
// Step 2. // Step 2.
let sender = response_async(&p, self); let sender = response_async(&p, self);
self.request_bluetooth_devices(&p, &option.filters, &option.optionalServices, sender); self.request_bluetooth_devices(
&p,
&option.filters,
&option.optionalServices,
sender,
can_gc,
);
//Note: Step 3 - 4. in response function, Step 5. in handle_response function. //Note: Step 3 - 4. in response function, Step 5. in handle_response function.
p p
} }
@ -616,7 +623,7 @@ impl AsyncBluetoothListener for Bluetooth {
BluetoothResponse::GetAvailability(is_available) => { BluetoothResponse::GetAvailability(is_available) => {
promise.resolve_native(&is_available, can_gc); promise.resolve_native(&is_available, can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }
@ -689,7 +696,7 @@ impl PermissionAlgorithm for Bluetooth {
for filter in filters { for filter in filters {
match canonicalize_filter(filter) { match canonicalize_filter(filter) {
Ok(f) => scan_filters.push(f), Ok(f) => scan_filters.push(f),
Err(error) => return promise.reject_error(error), Err(error) => return promise.reject_error(error, CanGc::note()),
} }
} }
@ -710,7 +717,7 @@ impl PermissionAlgorithm for Bluetooth {
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(true) => (), Ok(true) => (),
Ok(false) => continue, Ok(false) => continue,
Err(error) => return promise.reject_error(error.convert()), Err(error) => return promise.reject_error(error.convert(), CanGc::note()),
}; };
} }
@ -739,7 +746,7 @@ impl PermissionAlgorithm for Bluetooth {
) { ) {
// Step 1. // Step 1.
if descriptor.filters.is_some() == descriptor.acceptAllDevices { if descriptor.filters.is_some() == descriptor.acceptAllDevices {
return promise.reject_error(Error::Type(OPTIONS_ERROR.to_owned())); return promise.reject_error(Error::Type(OPTIONS_ERROR.to_owned()), CanGc::note());
} }
// Step 2. // Step 2.
@ -750,6 +757,7 @@ impl PermissionAlgorithm for Bluetooth {
&descriptor.filters, &descriptor.filters,
&descriptor.optionalServices, &descriptor.optionalServices,
sender, sender,
CanGc::note(),
); );
// NOTE: Step 3. is in BluetoothPermissionResult's `handle_response` function. // NOTE: Step 3. is in BluetoothPermissionResult's `handle_response` function.

View file

@ -336,7 +336,7 @@ impl AsyncBluetoothListener for BluetoothDevice {
// Step 3.2. // Step 3.2.
promise.resolve_native(&(), can_gc); promise.resolve_native(&(), can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }

View file

@ -137,7 +137,7 @@ impl AsyncBluetoothListener for BluetoothPermissionResult {
// Step 8. // Step 8.
promise.resolve_native(self, can_gc); promise.resolve_native(self, can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }

View file

@ -154,13 +154,13 @@ impl BluetoothRemoteGATTCharacteristicMethods<crate::DomTypeHolder>
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
p.reject_error(Security); p.reject_error(Security, can_gc);
return p; return p;
} }
// Step 2. // Step 2.
if !self.Service().Device().get_gatt().Connected() { if !self.Service().Device().get_gatt().Connected() {
p.reject_error(Network); p.reject_error(Network, can_gc);
return p; return p;
} }
@ -168,7 +168,7 @@ impl BluetoothRemoteGATTCharacteristicMethods<crate::DomTypeHolder>
// Step 5.1. // Step 5.1.
if !self.Properties().Read() { if !self.Properties().Read() {
p.reject_error(NotSupported); p.reject_error(NotSupported, can_gc);
return p; return p;
} }
@ -192,7 +192,7 @@ impl BluetoothRemoteGATTCharacteristicMethods<crate::DomTypeHolder>
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {
p.reject_error(Security); p.reject_error(Security, can_gc);
return p; return p;
} }
@ -203,13 +203,13 @@ impl BluetoothRemoteGATTCharacteristicMethods<crate::DomTypeHolder>
}; };
if vec.len() > MAXIMUM_ATTRIBUTE_LENGTH { if vec.len() > MAXIMUM_ATTRIBUTE_LENGTH {
p.reject_error(InvalidModification); p.reject_error(InvalidModification, can_gc);
return p; return p;
} }
// Step 4. // Step 4.
if !self.Service().Device().get_gatt().Connected() { if !self.Service().Device().get_gatt().Connected() {
p.reject_error(Network); p.reject_error(Network, can_gc);
return p; return p;
} }
@ -220,7 +220,7 @@ impl BluetoothRemoteGATTCharacteristicMethods<crate::DomTypeHolder>
self.Properties().WriteWithoutResponse() || self.Properties().WriteWithoutResponse() ||
self.Properties().AuthenticatedSignedWrites()) self.Properties().AuthenticatedSignedWrites())
{ {
p.reject_error(NotSupported); p.reject_error(NotSupported, can_gc);
return p; return p;
} }
@ -243,19 +243,19 @@ impl BluetoothRemoteGATTCharacteristicMethods<crate::DomTypeHolder>
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
p.reject_error(Security); p.reject_error(Security, can_gc);
return p; return p;
} }
// Step 2. // Step 2.
if !self.Service().Device().get_gatt().Connected() { if !self.Service().Device().get_gatt().Connected() {
p.reject_error(Network); p.reject_error(Network, can_gc);
return p; return p;
} }
// Step 5. // Step 5.
if !(self.Properties().Notify() || self.Properties().Indicate()) { if !(self.Properties().Notify() || self.Properties().Indicate()) {
p.reject_error(NotSupported); p.reject_error(NotSupported, can_gc);
return p; return p;
} }
@ -359,7 +359,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
// (StopNotification) Step 5. // (StopNotification) Step 5.
promise.resolve_native(self, can_gc); promise.resolve_native(self, can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }

View file

@ -102,7 +102,7 @@ impl BluetoothRemoteGATTDescriptorMethods<crate::DomTypeHolder> for BluetoothRem
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
p.reject_error(Security); p.reject_error(Security, can_gc);
return p; return p;
} }
@ -114,7 +114,7 @@ impl BluetoothRemoteGATTDescriptorMethods<crate::DomTypeHolder> for BluetoothRem
.get_gatt() .get_gatt()
.Connected() .Connected()
{ {
p.reject_error(Network); p.reject_error(Network, can_gc);
return p; return p;
} }
@ -139,7 +139,7 @@ impl BluetoothRemoteGATTDescriptorMethods<crate::DomTypeHolder> for BluetoothRem
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {
p.reject_error(Security); p.reject_error(Security, can_gc);
return p; return p;
} }
@ -149,7 +149,7 @@ impl BluetoothRemoteGATTDescriptorMethods<crate::DomTypeHolder> for BluetoothRem
ArrayBufferViewOrArrayBuffer::ArrayBuffer(ab) => ab.to_vec(), ArrayBufferViewOrArrayBuffer::ArrayBuffer(ab) => ab.to_vec(),
}; };
if vec.len() > MAXIMUM_ATTRIBUTE_LENGTH { if vec.len() > MAXIMUM_ATTRIBUTE_LENGTH {
p.reject_error(InvalidModification); p.reject_error(InvalidModification, can_gc);
return p; return p;
} }
@ -161,7 +161,7 @@ impl BluetoothRemoteGATTDescriptorMethods<crate::DomTypeHolder> for BluetoothRem
.get_gatt() .get_gatt()
.Connected() .Connected()
{ {
p.reject_error(Network); p.reject_error(Network, can_gc);
return p; return p;
} }
@ -207,7 +207,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor {
// TODO: Resolve promise with undefined instead of a value. // TODO: Resolve promise with undefined instead of a value.
promise.resolve_native(&(), can_gc); promise.resolve_native(&(), can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }

View file

@ -155,9 +155,9 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
// Step 5.2.3 // Step 5.2.3
if self.Device().is_represented_device_null() { if self.Device().is_represented_device_null() {
if let Err(e) = self.Device().garbage_collect_the_connection() { if let Err(e) = self.Device().garbage_collect_the_connection() {
return promise.reject_error(e); return promise.reject_error(e, can_gc);
} }
return promise.reject_error(Error::Network); return promise.reject_error(Error::Network, can_gc);
} }
// Step 5.2.4. // Step 5.2.4.
@ -184,7 +184,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
} }
promise.resolve_native(&services, can_gc); promise.resolve_native(&services, can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }

View file

@ -203,7 +203,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
} }
promise.resolve_native(&services, can_gc); promise.resolve_native(&services, can_gc);
}, },
_ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
} }
} }
} }

View file

@ -4291,7 +4291,7 @@ impl Document {
let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
// Step 2 // Step 2
if self.fullscreen_element.get().is_none() { if self.fullscreen_element.get().is_none() {
promise.reject_error(Error::Type(String::from("fullscreen is null"))); promise.reject_error(Error::Type(String::from("fullscreen is null")), can_gc);
return promise; return promise;
} }
// TODO Step 3-6 // TODO Step 3-6

View file

@ -4610,7 +4610,10 @@ impl TaskOnce for ElementPerformFullscreenEnter {
document document
.upcast::<EventTarget>() .upcast::<EventTarget>()
.fire_event(atom!("fullscreenerror"), CanGc::note()); .fire_event(atom!("fullscreenerror"), CanGc::note());
promise.reject_error(Error::Type(String::from("fullscreen is not connected"))); promise.reject_error(
Error::Type(String::from("fullscreen is not connected")),
CanGc::note(),
);
return; return;
} }

View file

@ -191,7 +191,7 @@ impl FontFace {
let font_status_promise = Promise::new(global, can_gc); let font_status_promise = Promise::new(global, can_gc);
// If any of them fail to parse correctly, reject font faces [[FontStatusPromise]] with a // If any of them fail to parse correctly, reject font faces [[FontStatusPromise]] with a
// DOMException named "SyntaxError" // DOMException named "SyntaxError"
font_status_promise.reject_error(Error::Syntax); font_status_promise.reject_error(Error::Syntax, can_gc);
// set font faces corresponding attributes to the empty string, and set font faces status // set font faces corresponding attributes to the empty string, and set font faces status
// attribute to "error" // attribute to "error"
@ -505,7 +505,7 @@ impl FontFaceMethods<crate::DomTypeHolder> for FontFace {
// [[FontStatusPromise]] with a DOMException whose name is "NetworkError" // [[FontStatusPromise]] with a DOMException whose name is "NetworkError"
// and set font faces status attribute to "error". // and set font faces status attribute to "error".
font_face.status.set(FontFaceLoadStatus::Error); font_face.status.set(FontFaceLoadStatus::Error);
font_face.font_status_promise.reject_error(Error::Network); font_face.font_status_promise.reject_error(Error::Network, CanGc::note());
} }
Some(template) => { Some(template) => {
// Step 5.2. Otherwise, font face now represents the loaded font; // Step 5.2. Otherwise, font face now represents the loaded font;

View file

@ -145,38 +145,56 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
// <https://www.w3.org/TR/gamepad/#dfn-valid-dual-rumble-effect> // <https://www.w3.org/TR/gamepad/#dfn-valid-dual-rumble-effect>
GamepadHapticEffectType::Dual_rumble => { GamepadHapticEffectType::Dual_rumble => {
if *params.strongMagnitude < 0.0 || *params.strongMagnitude > 1.0 { if *params.strongMagnitude < 0.0 || *params.strongMagnitude > 1.0 {
playing_effect_promise.reject_error(Error::Type( playing_effect_promise.reject_error(
Error::Type(
"Strong magnitude value is not within range of 0.0 to 1.0.".to_string(), "Strong magnitude value is not within range of 0.0 to 1.0.".to_string(),
)); ),
can_gc,
);
return playing_effect_promise; return playing_effect_promise;
} else if *params.weakMagnitude < 0.0 || *params.weakMagnitude > 1.0 { } else if *params.weakMagnitude < 0.0 || *params.weakMagnitude > 1.0 {
playing_effect_promise.reject_error(Error::Type( playing_effect_promise.reject_error(
Error::Type(
"Weak magnitude value is not within range of 0.0 to 1.0.".to_string(), "Weak magnitude value is not within range of 0.0 to 1.0.".to_string(),
)); ),
can_gc,
);
return playing_effect_promise; return playing_effect_promise;
} }
}, },
// <https://www.w3.org/TR/gamepad/#dfn-valid-trigger-rumble-effect> // <https://www.w3.org/TR/gamepad/#dfn-valid-trigger-rumble-effect>
GamepadHapticEffectType::Trigger_rumble => { GamepadHapticEffectType::Trigger_rumble => {
if *params.strongMagnitude < 0.0 || *params.strongMagnitude > 1.0 { if *params.strongMagnitude < 0.0 || *params.strongMagnitude > 1.0 {
playing_effect_promise.reject_error(Error::Type( playing_effect_promise.reject_error(
Error::Type(
"Strong magnitude value is not within range of 0.0 to 1.0.".to_string(), "Strong magnitude value is not within range of 0.0 to 1.0.".to_string(),
)); ),
can_gc,
);
return playing_effect_promise; return playing_effect_promise;
} else if *params.weakMagnitude < 0.0 || *params.weakMagnitude > 1.0 { } else if *params.weakMagnitude < 0.0 || *params.weakMagnitude > 1.0 {
playing_effect_promise.reject_error(Error::Type( playing_effect_promise.reject_error(
Error::Type(
"Weak magnitude value is not within range of 0.0 to 1.0.".to_string(), "Weak magnitude value is not within range of 0.0 to 1.0.".to_string(),
)); ),
can_gc,
);
return playing_effect_promise; return playing_effect_promise;
} else if *params.leftTrigger < 0.0 || *params.leftTrigger > 1.0 { } else if *params.leftTrigger < 0.0 || *params.leftTrigger > 1.0 {
playing_effect_promise.reject_error(Error::Type( playing_effect_promise.reject_error(
Error::Type(
"Left trigger value is not within range of 0.0 to 1.0.".to_string(), "Left trigger value is not within range of 0.0 to 1.0.".to_string(),
)); ),
can_gc,
);
return playing_effect_promise; return playing_effect_promise;
} else if *params.rightTrigger < 0.0 || *params.rightTrigger > 1.0 { } else if *params.rightTrigger < 0.0 || *params.rightTrigger > 1.0 {
playing_effect_promise.reject_error(Error::Type( playing_effect_promise.reject_error(
Error::Type(
"Right trigger value is not within range of 0.0 to 1.0.".to_string(), "Right trigger value is not within range of 0.0 to 1.0.".to_string(),
)); ),
can_gc,
);
return playing_effect_promise; return playing_effect_promise;
} }
}, },
@ -184,7 +202,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
let document = self.global().as_window().Document(); let document = self.global().as_window().Document();
if !document.is_fully_active() { if !document.is_fully_active() {
playing_effect_promise.reject_error(Error::InvalidState); playing_effect_promise.reject_error(Error::InvalidState, can_gc);
} }
self.sequence_id.set(self.sequence_id.get().wrapping_add(1)); self.sequence_id.set(self.sequence_id.get().wrapping_add(1));
@ -201,7 +219,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
} }
if !self.effects.contains(&type_) { if !self.effects.contains(&type_) {
playing_effect_promise.reject_error(Error::NotSupported); playing_effect_promise.reject_error(Error::NotSupported, can_gc);
return playing_effect_promise; return playing_effect_promise;
} }
@ -251,7 +269,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
let document = self.global().as_window().Document(); let document = self.global().as_window().Document();
if !document.is_fully_active() { if !document.is_fully_active() {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }

View file

@ -2702,12 +2702,12 @@ impl GlobalScope {
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
if options.resizeWidth.is_some_and(|w| w == 0) { if options.resizeWidth.is_some_and(|w| w == 0) {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState, can_gc);
return p; return p;
} }
if options.resizeHeight.is_some_and(|w| w == 0) { if options.resizeHeight.is_some_and(|w| w == 0) {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState, can_gc);
return p; return p;
} }
@ -2715,7 +2715,7 @@ impl GlobalScope {
ImageBitmapSource::HTMLCanvasElement(ref canvas) => { ImageBitmapSource::HTMLCanvasElement(ref canvas) => {
// https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument // https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument
if !canvas.is_valid() { if !canvas.is_valid() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState, can_gc);
return p; return p;
} }
@ -2736,7 +2736,7 @@ impl GlobalScope {
ImageBitmapSource::OffscreenCanvas(ref canvas) => { ImageBitmapSource::OffscreenCanvas(ref canvas) => {
// https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument // https://html.spec.whatwg.org/multipage/#check-the-usability-of-the-image-argument
if !canvas.is_valid() { if !canvas.is_valid() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState, can_gc);
return p; return p;
} }
@ -2754,7 +2754,7 @@ impl GlobalScope {
p p
}, },
_ => { _ => {
p.reject_error(Error::NotSupported); p.reject_error(Error::NotSupported, can_gc);
p p
}, },
} }

View file

@ -1220,7 +1220,7 @@ impl HTMLMediaElement {
for promise in &*promises { for promise in &*promises {
match result { match result {
Ok(ref value) => promise.resolve_native(value, CanGc::note()), Ok(ref value) => promise.resolve_native(value, CanGc::note()),
Err(ref error) => promise.reject_error(error.clone()), Err(ref error) => promise.reject_error(error.clone(), CanGc::note()),
} }
} }
} }
@ -2195,7 +2195,7 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
.get() .get()
.is_some_and(|e| e.Code() == MEDIA_ERR_SRC_NOT_SUPPORTED) .is_some_and(|e| e.Code() == MEDIA_ERR_SRC_NOT_SUPPORTED)
{ {
promise.reject_error(Error::NotSupported); promise.reject_error(Error::NotSupported, can_gc);
return promise; return promise;
} }

View file

@ -146,7 +146,7 @@ impl OfflineAudioContextMethods<crate::DomTypeHolder> for OfflineAudioContext {
fn StartRendering(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> { fn StartRendering(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp, can_gc); let promise = Promise::new_in_current_realm(comp, can_gc);
if self.rendering_started.get() { if self.rendering_started.get() {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }
self.rendering_started.set(true); self.rendering_started.set(true);
@ -221,7 +221,10 @@ impl OfflineAudioContextMethods<crate::DomTypeHolder> for OfflineAudioContext {
.resume() .resume()
.is_err() .is_err()
{ {
promise.reject_error(Error::Type("Could not start offline rendering".to_owned())); promise.reject_error(
Error::Type("Could not start offline rendering".to_owned()),
can_gc,
);
} }
promise promise

View file

@ -104,7 +104,7 @@ impl Permissions {
let root_desc = match Permissions::create_descriptor(cx, permissionDesc) { let root_desc = match Permissions::create_descriptor(cx, permissionDesc) {
Ok(descriptor) => descriptor, Ok(descriptor) => descriptor,
Err(error) => { Err(error) => {
p.reject_error(error); p.reject_error(error, can_gc);
return p; return p;
}, },
}; };
@ -119,7 +119,7 @@ impl Permissions {
let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) { let bluetooth_desc = match Bluetooth::create_descriptor(cx, permissionDesc) {
Ok(descriptor) => descriptor, Ok(descriptor) => descriptor,
Err(error) => { Err(error) => {
p.reject_error(error); p.reject_error(error, can_gc);
return p; return p;
}, },
}; };

View file

@ -221,12 +221,12 @@ impl Promise {
self.reject(cx, v.handle(), can_gc); self.reject(cx, v.handle(), can_gc);
} }
pub(crate) fn reject_error(&self, error: Error) { pub(crate) fn reject_error(&self, error: Error, can_gc: CanGc) {
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());
self.reject(cx, v.handle(), CanGc::note()); self.reject(cx, v.handle(), can_gc);
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]

View file

@ -961,7 +961,7 @@ impl ReadableStreamMethods<crate::DomTypeHolder> for ReadableStream {
// If ! IsReadableStreamLocked(this) is true, // If ! IsReadableStreamLocked(this) is true,
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(&self.global(), can_gc); let promise = Promise::new(&self.global(), can_gc);
promise.reject_error(Error::Type("stream is not locked".to_owned())); promise.reject_error(Error::Type("stream is not locked".to_owned()), can_gc);
promise promise
} else { } else {
// Return ! ReadableStreamCancel(this, reason). // Return ! ReadableStreamCancel(this, reason).

View file

@ -161,7 +161,7 @@ impl ReadableStreamBYOBReader {
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreaderrelease> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreambyobreaderrelease>
pub(crate) fn release(&self, can_gc: CanGc) -> Fallible<()> { pub(crate) fn release(&self, can_gc: CanGc) -> Fallible<()> {
// Perform ! ReadableStreamReaderGenericRelease(reader). // Perform ! ReadableStreamReaderGenericRelease(reader).
self.generic_release()?; self.generic_release(can_gc)?;
// Let e be a new TypeError exception. // Let e be a new TypeError exception.
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut error = UndefinedValue()); rooted!(in(*cx) let mut error = UndefinedValue());
@ -277,26 +277,29 @@ impl ReadableStreamBYOBReaderMethods<crate::DomTypeHolder> for ReadableStreamBYO
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
// If view.[[ByteLength]] is 0, return a promise rejected with a TypeError exception. // If view.[[ByteLength]] is 0, return a promise rejected with a TypeError exception.
if view.byte_length() == 0 { if view.byte_length() == 0 {
promise.reject_error(Error::Type("view byte length is 0".to_owned())); promise.reject_error(Error::Type("view byte length is 0".to_owned()), can_gc);
return promise; return promise;
} }
// If view.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]] is 0, // If view.[[ViewedArrayBuffer]].[[ArrayBufferByteLength]] is 0,
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
if view.viewed_buffer_array_byte_length(cx) == 0 { if view.viewed_buffer_array_byte_length(cx) == 0 {
promise.reject_error(Error::Type("viewed buffer byte length is 0".to_owned())); promise.reject_error(
Error::Type("viewed buffer byte length is 0".to_owned()),
can_gc,
);
return promise; return promise;
} }
// If ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true, // If ! IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true,
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
if view.is_detached_buffer(cx) { if view.is_detached_buffer(cx) {
promise.reject_error(Error::Type("view is detached".to_owned())); promise.reject_error(Error::Type("view is detached".to_owned()), can_gc);
return promise; return promise;
} }
// If options["min"] is 0, return a promise rejected with a TypeError exception. // If options["min"] is 0, return a promise rejected with a TypeError exception.
if options.min == 0 { if options.min == 0 {
promise.reject_error(Error::Type("min is 0".to_owned())); promise.reject_error(Error::Type("min is 0".to_owned()), can_gc);
return promise; return promise;
} }
@ -304,21 +307,30 @@ impl ReadableStreamBYOBReaderMethods<crate::DomTypeHolder> for ReadableStreamBYO
if view.has_typed_array_name() { if view.has_typed_array_name() {
// If options["min"] > view.[[ArrayLength]], return a promise rejected with a RangeError exception. // If options["min"] > view.[[ArrayLength]], return a promise rejected with a RangeError exception.
if options.min > (view.array_length() as u64) { if options.min > (view.array_length() as u64) {
promise.reject_error(Error::Type("min is greater than array length".to_owned())); promise.reject_error(
Error::Type("min is greater than array length".to_owned()),
can_gc,
);
return promise; return promise;
} }
} else { } else {
// Otherwise (i.e., it is a DataView), // Otherwise (i.e., it is a DataView),
// If options["min"] > view.[[ByteLength]], return a promise rejected with a RangeError exception. // If options["min"] > view.[[ByteLength]], return a promise rejected with a RangeError exception.
if options.min > (view.byte_length() as u64) { if options.min > (view.byte_length() as u64) {
promise.reject_error(Error::Type("min is greater than byte length".to_owned())); promise.reject_error(
Error::Type("min is greater than byte length".to_owned()),
can_gc,
);
return promise; return promise;
} }
} }
// If this.[[stream]] is undefined, return a promise rejected with a TypeError exception. // If this.[[stream]] is undefined, return a promise rejected with a TypeError exception.
if self.stream.get().is_none() { if self.stream.get().is_none() {
promise.reject_error(Error::Type("min is greater than byte length".to_owned())); promise.reject_error(
Error::Type("min is greater than byte length".to_owned()),
can_gc,
);
return promise; return promise;
} }

View file

@ -253,7 +253,7 @@ impl ReadableStreamDefaultReader {
/// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease> /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease>
pub(crate) fn release(&self, can_gc: CanGc) -> Fallible<()> { pub(crate) fn release(&self, can_gc: CanGc) -> Fallible<()> {
// Perform ! ReadableStreamReaderGenericRelease(reader). // Perform ! ReadableStreamReaderGenericRelease(reader).
self.generic_release()?; self.generic_release(can_gc)?;
// Let e be a new TypeError exception. // Let e be a new TypeError exception.
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut error = UndefinedValue()); rooted!(in(*cx) let mut error = UndefinedValue());

View file

@ -76,7 +76,7 @@ pub(crate) trait ReadableStreamGenericReader {
/// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-release> /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-release>
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn generic_release(&self) -> Fallible<()> { fn generic_release(&self, can_gc: CanGc) -> Fallible<()> {
// Let stream be reader.[[stream]]. // Let stream be reader.[[stream]].
// Assert: stream is not undefined. // Assert: stream is not undefined.
@ -88,8 +88,10 @@ pub(crate) trait ReadableStreamGenericReader {
if stream.is_readable() { if stream.is_readable() {
// If stream.[[state]] is "readable", reject reader.[[closedPromise]] with a TypeError exception. // If stream.[[state]] is "readable", reject reader.[[closedPromise]] with a TypeError exception.
self.get_closed_promise() self.get_closed_promise().reject_error(
.reject_error(Error::Type("stream state is not readable".to_owned())); Error::Type("stream state is not readable".to_owned()),
can_gc,
);
} else { } else {
// Otherwise, set reader.[[closedPromise]] to a promise rejected with a TypeError exception. // Otherwise, set reader.[[closedPromise]] to a promise rejected with a TypeError exception.
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
@ -104,7 +106,7 @@ pub(crate) trait ReadableStreamGenericReader {
&stream.global(), &stream.global(),
cx, cx,
error.handle(), error.handle(),
CanGc::note(), can_gc,
)); ));
} }
// Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
@ -132,7 +134,7 @@ pub(crate) trait ReadableStreamGenericReader {
// If this.[[stream]] is undefined, // If this.[[stream]] is undefined,
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(Error::Type("stream is undefined".to_owned())); promise.reject_error(Error::Type("stream is undefined".to_owned()), can_gc);
promise promise
} else { } else {
// Return ! ReadableStreamReaderGenericCancel(this, reason). // Return ! ReadableStreamReaderGenericCancel(this, reason).

View file

@ -556,17 +556,19 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
) -> Rc<Promise> { ) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc); let p = Promise::new_in_current_realm(comp, can_gc);
if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() { if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() {
p.reject_error(Error::Type( p.reject_error(
"one of sdpMid and sdpMLineIndex must be set".to_string(), Error::Type("one of sdpMid and sdpMLineIndex must be set".to_string()),
)); can_gc,
);
return p; return p;
} }
// XXXManishearth add support for sdpMid // XXXManishearth add support for sdpMid
if candidate.sdpMLineIndex.is_none() { if candidate.sdpMLineIndex.is_none() {
p.reject_error(Error::Type( p.reject_error(
"servo only supports sdpMLineIndex right now".to_string(), Error::Type("servo only supports sdpMLineIndex right now".to_string()),
)); can_gc,
);
return p; return p;
} }
@ -591,7 +593,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
fn CreateOffer(&self, _options: &RTCOfferOptions, comp: InRealm, can_gc: CanGc) -> Rc<Promise> { fn CreateOffer(&self, _options: &RTCOfferOptions, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc); let p = Promise::new_in_current_realm(comp, can_gc);
if self.closed.get() { if self.closed.get() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState, can_gc);
return p; return p;
} }
self.offer_promises.borrow_mut().push(p.clone()); self.offer_promises.borrow_mut().push(p.clone());
@ -608,7 +610,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
) -> Rc<Promise> { ) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc); let p = Promise::new_in_current_realm(comp, can_gc);
if self.closed.get() { if self.closed.get() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState, can_gc);
return p; return p;
} }
self.answer_promises.borrow_mut().push(p.clone()); self.answer_promises.borrow_mut().push(p.clone());

View file

@ -80,7 +80,7 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
Ok(url) => url, Ok(url) => url,
Err(_) => { Err(_) => {
// B: Step 1 // B: Step 1
promise.reject_error(Error::Type("Invalid script URL".to_owned())); promise.reject_error(Error::Type("Invalid script URL".to_owned()), can_gc);
return promise; return promise;
}, },
}; };
@ -92,7 +92,7 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
match api_base_url.join(inner_scope) { match api_base_url.join(inner_scope) {
Ok(url) => url, Ok(url) => url,
Err(_) => { Err(_) => {
promise.reject_error(Error::Type("Invalid scope URL".to_owned())); promise.reject_error(Error::Type("Invalid scope URL".to_owned()), can_gc);
return promise; return promise;
}, },
} }
@ -106,7 +106,10 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
match script_url.scheme() { match script_url.scheme() {
"https" | "http" => {}, "https" | "http" => {},
_ => { _ => {
promise.reject_error(Error::Type("Only secure origins are allowed".to_owned())); promise.reject_error(
Error::Type("Only secure origins are allowed".to_owned()),
can_gc,
);
return promise; return promise;
}, },
} }
@ -114,9 +117,10 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
if script_url.path().to_ascii_lowercase().contains("%2f") || if script_url.path().to_ascii_lowercase().contains("%2f") ||
script_url.path().to_ascii_lowercase().contains("%5c") script_url.path().to_ascii_lowercase().contains("%5c")
{ {
promise.reject_error(Error::Type( promise.reject_error(
"Script URL contains forbidden characters".to_owned(), Error::Type("Script URL contains forbidden characters".to_owned()),
)); can_gc,
);
return promise; return promise;
} }
@ -124,7 +128,10 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
match scope.scheme() { match scope.scheme() {
"https" | "http" => {}, "https" | "http" => {},
_ => { _ => {
promise.reject_error(Error::Type("Only secure origins are allowed".to_owned())); promise.reject_error(
Error::Type("Only secure origins are allowed".to_owned()),
can_gc,
);
return promise; return promise;
}, },
} }
@ -132,9 +139,10 @@ impl ServiceWorkerContainerMethods<crate::DomTypeHolder> for ServiceWorkerContai
if scope.path().to_ascii_lowercase().contains("%2f") || if scope.path().to_ascii_lowercase().contains("%2f") ||
scope.path().to_ascii_lowercase().contains("%5c") scope.path().to_ascii_lowercase().contains("%5c")
{ {
promise.reject_error(Error::Type( promise.reject_error(
"Scope URL contains forbidden characters".to_owned(), Error::Type("Scope URL contains forbidden characters".to_owned()),
)); can_gc,
);
return promise; return promise;
} }
@ -198,21 +206,23 @@ impl RegisterJobResultHandler {
.expect("No promise to resolve for SW Register job."); .expect("No promise to resolve for SW Register job.");
// Step 1 // Step 1
self.task_source.queue( self.task_source
task!(reject_promise_with_security_error: move || { .queue(task!(reject_promise_with_security_error: move || {
let promise = promise.root(); let promise = promise.root();
let _ac = enter_realm(&*promise.global()); let _ac = enter_realm(&*promise.global());
match error { match error {
JobError::TypeError => { JobError::TypeError => {
promise.reject_error(Error::Type("Failed to register a ServiceWorker".to_string())); promise.reject_error(
Error::Type("Failed to register a ServiceWorker".to_string()),
CanGc::note(),
);
}, },
JobError::SecurityError => { JobError::SecurityError => {
promise.reject_error(Error::Security); promise.reject_error(Error::Security, CanGc::note());
}, },
} }
}) }));
);
// TODO: step 2, handle equivalent jobs. // TODO: step 2, handle equivalent jobs.
}, },

View file

@ -148,7 +148,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
{ {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -171,7 +171,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let key = trusted_key.root(); let key = trusted_key.root();
if !valid_usage || normalized_algorithm.name() != key_alg { if !valid_usage || normalized_algorithm.name() != key_alg {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -186,7 +186,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
array_buffer_ptr.handle_mut(), array_buffer_ptr.handle_mut(),
CanGc::note(), CanGc::note(),
) { ) {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
promise.resolve_native(&*array_buffer_ptr.handle(), CanGc::note()); promise.resolve_native(&*array_buffer_ptr.handle(), CanGc::note());
@ -209,7 +209,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
{ {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -234,7 +234,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
if !valid_usage || normalized_algorithm.name() != key_alg { if !valid_usage || normalized_algorithm.name() != key_alg {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -246,7 +246,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
array_buffer_ptr.handle_mut(), array_buffer_ptr.handle_mut(),
CanGc::note(), CanGc::note(),
) { ) {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
@ -281,7 +281,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
// Step 4. If an error occurred, return a Promise rejected with normalizedAlgorithm. // Step 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -305,14 +305,14 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the // Step 8. If the name member of normalizedAlgorithm is not equal to the name attribute of the
// [[algorithm]] internal slot of key then throw an InvalidAccessError. // [[algorithm]] internal slot of key then throw an InvalidAccessError.
if normalized_algorithm.name() != key.algorithm() { if normalized_algorithm.name() != key.algorithm() {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
// Step 9. If the [[usages]] internal slot of key does not contain an entry that is "sign", // Step 9. If the [[usages]] internal slot of key does not contain an entry that is "sign",
// then throw an InvalidAccessError. // then throw an InvalidAccessError.
if !key.usages().contains(&KeyUsage::Sign) { if !key.usages().contains(&KeyUsage::Sign) {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -322,7 +322,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let result = match normalized_algorithm.sign(cx, &key, &data) { let result = match normalized_algorithm.sign(cx, &key, &data) {
Ok(signature) => signature, Ok(signature) => signature,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -373,7 +373,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
// Step 5. If an error occurred, return a Promise rejected with normalizedAlgorithm. // Step 5. If an error occurred, return a Promise rejected with normalizedAlgorithm.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -397,14 +397,14 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 9. If the name member of normalizedAlgorithm is not equal to the name attribute of the // Step 9. If the name member of normalizedAlgorithm is not equal to the name attribute of the
// [[algorithm]] internal slot of key then throw an InvalidAccessError. // [[algorithm]] internal slot of key then throw an InvalidAccessError.
if normalized_algorithm.name() != key.algorithm() { if normalized_algorithm.name() != key.algorithm() {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
// Step 10. If the [[usages]] internal slot of key does not contain an entry that is "verify", // Step 10. If the [[usages]] internal slot of key does not contain an entry that is "verify",
// then throw an InvalidAccessError. // then throw an InvalidAccessError.
if !key.usages().contains(&KeyUsage::Verify) { if !key.usages().contains(&KeyUsage::Verify) {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -414,7 +414,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let result = match normalized_algorithm.verify(cx, &key, &data, &signature) { let result = match normalized_algorithm.verify(cx, &key, &data, &signature) {
Ok(result) => result, Ok(result) => result,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -451,7 +451,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(normalized_algorithm) => normalized_algorithm, Ok(normalized_algorithm) => normalized_algorithm,
Err(e) => { Err(e) => {
// Step 4. If an error occurred, return a Promise rejected with normalizedAlgorithm. // Step 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -473,7 +473,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let digest = match normalized_algorithm.digest(&data) { let digest = match normalized_algorithm.digest(&data) {
Ok(digest) => digest, Ok(digest) => digest,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -506,7 +506,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let normalized_algorithm = match normalize_algorithm_for_generate_key(cx, &algorithm) { let normalized_algorithm = match normalize_algorithm_for_generate_key(cx, &algorithm) {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -523,7 +523,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
match key { match key {
Ok(key) => promise.resolve_native(&key, CanGc::note()), Ok(key) => promise.resolve_native(&key, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
} }
})); }));
@ -552,7 +552,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
// Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm. // Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -564,7 +564,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
// Step 5. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmImport. // Step 5. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmImport.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -576,7 +576,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
// Step 7. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmLength. // Step 7. If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmLength.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -602,7 +602,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 12. If the [[usages]] internal slot of baseKey does not contain an entry that is // Step 12. If the [[usages]] internal slot of baseKey does not contain an entry that is
// "deriveKey", then throw an InvalidAccessError. // "deriveKey", then throw an InvalidAccessError.
if !base_key.usages().contains(&KeyUsage::DeriveKey) { if !base_key.usages().contains(&KeyUsage::DeriveKey) {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -611,7 +611,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let length = match normalized_derived_key_algorithm_length.get_key_length() { let length = match normalized_derived_key_algorithm_length.get_key_length() {
Ok(length) => length, Ok(length) => length,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -621,7 +621,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let secret = match normalized_algorithm.derive_bits(&base_key, Some(length)){ let secret = match normalized_algorithm.derive_bits(&base_key, Some(length)){
Ok(secret) => secret, Ok(secret) => secret,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -640,7 +640,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let result = match result { let result = match result {
Ok(key) => key, Ok(key) => key,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -648,7 +648,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 17. If the [[type]] internal slot of result is "secret" or "private" and usages // Step 17. If the [[type]] internal slot of result is "secret" or "private" and usages
// is empty, then throw a SyntaxError. // is empty, then throw a SyntaxError.
if matches!(result.Type(), KeyType::Secret | KeyType::Private) && result.usages().is_empty() { if matches!(result.Type(), KeyType::Secret | KeyType::Private) && result.usages().is_empty() {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, CanGc::note());
return; return;
} }
@ -680,7 +680,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
// Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm. // Step 3. If an error occurred, return a Promise rejected with normalizedAlgorithm.
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -707,7 +707,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 8. If the [[usages]] internal slot of baseKey does not contain an entry that // Step 8. If the [[usages]] internal slot of baseKey does not contain an entry that
// is "deriveBits", then throw an InvalidAccessError. // is "deriveBits", then throw an InvalidAccessError.
if !base_key.usages().contains(&KeyUsage::DeriveBits) { if !base_key.usages().contains(&KeyUsage::DeriveBits) {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -718,7 +718,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let result = match normalized_algorithm.derive_bits(&base_key, length) { let result = match normalized_algorithm.derive_bits(&base_key, length) {
Ok(derived_bits) => derived_bits, Ok(derived_bits) => derived_bits,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
}; };
@ -749,7 +749,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let normalized_algorithm = match normalize_algorithm_for_import_key(cx, &algorithm) { let normalized_algorithm = match normalize_algorithm_for_import_key(cx, &algorithm) {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -760,7 +760,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let data_string = match json_web_key.k { let data_string = match json_web_key.k {
Some(s) => s.to_string(), Some(s) => s.to_string(),
None => { None => {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, can_gc);
return promise; return promise;
}, },
}; };
@ -770,7 +770,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
{ {
Ok(data) => data, Ok(data) => data,
Err(_) => { Err(_) => {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, can_gc);
return promise; return promise;
}, },
} }
@ -792,7 +792,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
format, &data, extractable, key_usages, CanGc::note()); format, &data, extractable, key_usages, CanGc::note());
match imported_key { match imported_key {
Ok(k) => promise.resolve_native(&k, CanGc::note()), Ok(k) => promise.resolve_native(&k, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
}; };
})); }));
@ -821,11 +821,11 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
if matches!( if matches!(
alg_name.as_str(), ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2 alg_name.as_str(), ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
) { ) {
promise.reject_error(Error::NotSupported); promise.reject_error(Error::NotSupported, CanGc::note());
return; return;
} }
if !key.Extractable() { if !key.Extractable() {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
let exported_key = match alg_name.as_str() { let exported_key = match alg_name.as_str() {
@ -848,7 +848,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
}, },
} }
}, },
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
} }
}), }),
); );
@ -871,7 +871,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let normalized_algorithm = match normalize_algorithm_for_key_wrap(cx, &wrap_algorithm) { let normalized_algorithm = match normalize_algorithm_for_key_wrap(cx, &wrap_algorithm) {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -892,21 +892,21 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let names_match = normalized_algorithm.name() == wrapping_alg_name.as_str(); let names_match = normalized_algorithm.name() == wrapping_alg_name.as_str();
if !valid_wrap_usage || !names_match || !key.Extractable() { if !valid_wrap_usage || !names_match || !key.Extractable() {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
if matches!( if matches!(
alg_name.as_str(), ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2 alg_name.as_str(), ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
) { ) {
promise.reject_error(Error::NotSupported); promise.reject_error(Error::NotSupported, CanGc::note());
return; return;
} }
let exported_key = match subtle.export_key_aes(format, &key) { let exported_key = match subtle.export_key_aes(format, &key) {
Ok(k) => k, Ok(k) => k,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
}, },
}; };
@ -919,19 +919,19 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// TODO: Support more than just a subset of the JWK dict, or find a way to // TODO: Support more than just a subset of the JWK dict, or find a way to
// stringify via SM internals // stringify via SM internals
let Some(k) = key.k else { let Some(k) = key.k else {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, CanGc::note());
return; return;
}; };
let Some(alg) = key.alg else { let Some(alg) = key.alg else {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, CanGc::note());
return; return;
}; };
let Some(ext) = key.ext else { let Some(ext) = key.ext else {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, CanGc::note());
return; return;
}; };
let Some(key_ops) = key.key_ops else { let Some(key_ops) = key.key_ops else {
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, CanGc::note());
return; return;
}; };
let key_ops_str = key_ops.iter().map(|op| op.to_string()).collect::<Vec<String>>(); let key_ops_str = key_ops.iter().map(|op| op.to_string()).collect::<Vec<String>>();
@ -971,7 +971,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
match result { match result {
Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()), Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
} }
}), }),
); );
@ -1001,7 +1001,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let normalized_algorithm = match normalize_algorithm_for_key_wrap(cx, &unwrap_algorithm) { let normalized_algorithm = match normalize_algorithm_for_key_wrap(cx, &unwrap_algorithm) {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -1009,7 +1009,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
match normalize_algorithm_for_import_key(cx, &unwrapped_key_algorithm) { match normalize_algorithm_for_import_key(cx, &unwrapped_key_algorithm) {
Ok(algorithm) => algorithm, Ok(algorithm) => algorithm,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
}; };
@ -1026,7 +1026,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let valid_usage = unwrapping_key.usages().contains(&KeyUsage::UnwrapKey); let valid_usage = unwrapping_key.usages().contains(&KeyUsage::UnwrapKey);
if !valid_usage || normalized_algorithm.name() != alg_name.as_str() { if !valid_usage || normalized_algorithm.name() != alg_name.as_str() {
promise.reject_error(Error::InvalidAccess); promise.reject_error(Error::InvalidAccess, CanGc::note());
return; return;
} }
@ -1061,7 +1061,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let bytes = match result { let bytes = match result {
Ok(bytes) => bytes, Ok(bytes) => bytes,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
}, },
}; };
@ -1072,7 +1072,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
match parse_jwk(&bytes, normalized_key_algorithm.clone(), extractable, &key_usages) { match parse_jwk(&bytes, normalized_key_algorithm.clone(), extractable, &key_usages) {
Ok(bytes) => bytes, Ok(bytes) => bytes,
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e, CanGc::note());
return; return;
} }
} }
@ -1081,7 +1081,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
match normalized_key_algorithm.import_key(&subtle, format, &import_key_bytes, match normalized_key_algorithm.import_key(&subtle, format, &import_key_bytes,
extractable, key_usages, CanGc::note()) { extractable, key_usages, CanGc::note()) {
Ok(imported_key) => promise.resolve_native(&imported_key, CanGc::note()), Ok(imported_key) => promise.resolve_native(&imported_key, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e, CanGc::note()),
} }
}), }),
); );

View file

@ -988,8 +988,8 @@ impl TestBindingMethods<crate::DomTypeHolder> for TestBinding {
p.reject(cx, v, can_gc); p.reject(cx, v, can_gc);
} }
fn PromiseRejectWithTypeError(&self, p: &Promise, s: USVString) { fn PromiseRejectWithTypeError(&self, p: &Promise, s: USVString, can_gc: CanGc) {
p.reject_error(Error::Type(s.0)); p.reject_error(Error::Type(s.0), can_gc);
} }
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]

View file

@ -132,7 +132,7 @@ impl GPUMethods<crate::DomTypeHolder> for GPU {
)) ))
.is_err() .is_err()
{ {
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation, can_gc);
} }
promise promise
} }

View file

@ -122,10 +122,10 @@ impl GPUAdapterMethods<crate::DomTypeHolder> for GPUAdapter {
if let Some(feature) = gpu_to_wgt_feature(ext) { if let Some(feature) = gpu_to_wgt_feature(ext) {
required_features.insert(feature); required_features.insert(feature);
} else { } else {
promise.reject_error(Error::Type(format!( promise.reject_error(
"{} is not supported feature", Error::Type(format!("{} is not supported feature", ext.as_str())),
ext.as_str() can_gc,
))); );
return promise; return promise;
} }
} }
@ -135,7 +135,7 @@ impl GPUAdapterMethods<crate::DomTypeHolder> for GPUAdapter {
for (limit, value) in (*limits).iter() { for (limit, value) in (*limits).iter() {
if !set_limit(&mut required_limits, limit.as_ref(), *value) { if !set_limit(&mut required_limits, limit.as_ref(), *value) {
warn!("Unknown GPUDevice limit: {limit}"); warn!("Unknown GPUDevice limit: {limit}");
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation, can_gc);
return promise; return promise;
} }
} }
@ -163,7 +163,7 @@ impl GPUAdapterMethods<crate::DomTypeHolder> for GPUAdapter {
}) })
.is_err() .is_err()
{ {
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation, can_gc);
} }
// Step 5 // Step 5
promise promise
@ -225,12 +225,13 @@ impl AsyncWGPUListener for GPUAdapter {
promise.resolve_native(&device, can_gc); promise.resolve_native(&device, can_gc);
}, },
WebGPUResponse::Device((_, _, Err(RequestDeviceError::UnsupportedFeature(f)))) => { WebGPUResponse::Device((_, _, Err(RequestDeviceError::UnsupportedFeature(f)))) => {
promise.reject_error(Error::Type( promise.reject_error(
RequestDeviceError::UnsupportedFeature(f).to_string(), Error::Type(RequestDeviceError::UnsupportedFeature(f).to_string()),
)) can_gc,
)
}, },
WebGPUResponse::Device((_, _, Err(RequestDeviceError::LimitsExceeded(_)))) => { WebGPUResponse::Device((_, _, Err(RequestDeviceError::LimitsExceeded(_)))) => {
promise.reject_error(Error::Operation) promise.reject_error(Error::Operation, can_gc)
}, },
WebGPUResponse::Device((device_id, queue_id, Err(e))) => { WebGPUResponse::Device((device_id, queue_id, Err(e))) => {
let device = GPUDevice::new( let device = GPUDevice::new(

View file

@ -193,7 +193,7 @@ impl GPUBufferMethods<crate::DomTypeHolder> for GPUBuffer {
fn Unmap(&self) { fn Unmap(&self) {
// Step 1 // Step 1
if let Some(promise) = self.pending_map.borrow_mut().take() { if let Some(promise) = self.pending_map.borrow_mut().take() {
promise.reject_error(Error::Abort); promise.reject_error(Error::Abort, CanGc::note());
} }
// Step 2 // Step 2
let mut mapping = self.mapping.borrow_mut().take(); let mut mapping = self.mapping.borrow_mut().take();
@ -251,7 +251,7 @@ impl GPUBufferMethods<crate::DomTypeHolder> for GPUBuffer {
let promise = Promise::new_in_current_realm(comp, can_gc); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 2 // Step 2
if self.pending_map.borrow().is_some() { if self.pending_map.borrow().is_some() {
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation, can_gc);
return promise; return promise;
} }
// Step 4 // Step 4
@ -265,7 +265,7 @@ impl GPUBufferMethods<crate::DomTypeHolder> for GPUBuffer {
.dispatch_error(webgpu::Error::Validation(String::from( .dispatch_error(webgpu::Error::Validation(String::from(
"Invalid MapModeFlags", "Invalid MapModeFlags",
))); )));
self.map_failure(&promise); self.map_failure(&promise, can_gc);
return promise; return promise;
}, },
}; };
@ -283,7 +283,7 @@ impl GPUBufferMethods<crate::DomTypeHolder> for GPUBuffer {
"Failed to send BufferMapAsync ({:?}) ({})", "Failed to send BufferMapAsync ({:?}) ({})",
self.buffer.0, e self.buffer.0, e
); );
self.map_failure(&promise); self.map_failure(&promise, can_gc);
return promise; return promise;
} }
// Step 6 // Step 6
@ -361,7 +361,7 @@ impl GPUBufferMethods<crate::DomTypeHolder> for GPUBuffer {
} }
impl GPUBuffer { impl GPUBuffer {
fn map_failure(&self, p: &Rc<Promise>) { fn map_failure(&self, p: &Rc<Promise>, can_gc: CanGc) {
let mut pending_map = self.pending_map.borrow_mut(); let mut pending_map = self.pending_map.borrow_mut();
// Step 1 // Step 1
if pending_map.as_ref() != Some(p) { if pending_map.as_ref() != Some(p) {
@ -374,9 +374,9 @@ impl GPUBuffer {
pending_map.take(); pending_map.take();
// Step 4 // Step 4
if self.device.is_lost() { if self.device.is_lost() {
p.reject_error(Error::Abort); p.reject_error(Error::Abort, can_gc);
} else { } else {
p.reject_error(Error::Operation); p.reject_error(Error::Operation, can_gc);
} }
} }
@ -404,7 +404,7 @@ impl GPUBuffer {
match mapping { match mapping {
Err(error) => { Err(error) => {
*pending_map = None; *pending_map = None;
p.reject_error(error.clone()); p.reject_error(error.clone(), can_gc);
}, },
Ok(mut mapping) => { Ok(mut mapping) => {
// Step 5 // Step 5
@ -426,7 +426,7 @@ impl AsyncWGPUListener for GPUBuffer {
WebGPUResponse::BufferMapAsync(Ok(mapping)) => { WebGPUResponse::BufferMapAsync(Ok(mapping)) => {
self.map_success(promise, mapping, can_gc) self.map_success(promise, mapping, can_gc)
}, },
WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise), WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise, can_gc),
_ => unreachable!("Wrong response received on AsyncWGPUListener for GPUBuffer"), _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUBuffer"),
} }
} }

View file

@ -588,7 +588,7 @@ impl AsyncWGPUListener for GPUDevice {
Ok(None) | Err(PopError::Lost) => { Ok(None) | Err(PopError::Lost) => {
promise.resolve_native(&None::<Option<GPUError>>, can_gc) promise.resolve_native(&None::<Option<GPUError>>, can_gc)
}, },
Err(PopError::Empty) => promise.reject_error(Error::Operation), Err(PopError::Empty) => promise.reject_error(Error::Operation, can_gc),
Ok(Some(error)) => { Ok(Some(error)) => {
let error = GPUError::from_error(&self.global(), error, can_gc); let error = GPUError::from_error(&self.global(), error, can_gc);
promise.resolve_native(&error, can_gc); promise.resolve_native(&error, can_gc);

View file

@ -228,7 +228,7 @@ impl AsyncWGPUListener for GPUQueue {
}, },
_ => { _ => {
warn!("GPUQueue received wrong WebGPUResponse"); warn!("GPUQueue received wrong WebGPUResponse");
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation, can_gc);
}, },
} }
} }

View file

@ -836,14 +836,14 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
if !self.is_immersive() && if !self.is_immersive() &&
(ty == XRReferenceSpaceType::Bounded_floor || ty == XRReferenceSpaceType::Unbounded) (ty == XRReferenceSpaceType::Bounded_floor || ty == XRReferenceSpaceType::Unbounded)
{ {
p.reject_error(Error::NotSupported); p.reject_error(Error::NotSupported, can_gc);
return p; return p;
} }
match ty { match ty {
XRReferenceSpaceType::Unbounded => { XRReferenceSpaceType::Unbounded => {
// XXXmsub2 figure out how to support this // XXXmsub2 figure out how to support this
p.reject_error(Error::NotSupported) p.reject_error(Error::NotSupported, can_gc)
}, },
ty => { ty => {
if ty != XRReferenceSpaceType::Viewer && if ty != XRReferenceSpaceType::Viewer &&
@ -857,7 +857,7 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
.iter() .iter()
.any(|f| *f == s) .any(|f| *f == s)
{ {
p.reject_error(Error::NotSupported); p.reject_error(Error::NotSupported, can_gc);
return p; return p;
} }
} }
@ -927,7 +927,7 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
.iter() .iter()
.any(|f| f == "hit-test") .any(|f| f == "hit-test")
{ {
p.reject_error(Error::NotSupported); p.reject_error(Error::NotSupported, can_gc);
return p; return p;
} }
@ -1035,12 +1035,15 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
supported_frame_rates.is_empty() || supported_frame_rates.is_empty() ||
self.ended.get() self.ended.get()
{ {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }
if !supported_frame_rates.contains(&*rate) { if !supported_frame_rates.contains(&*rate) {
promise.reject_error(Error::Type("Provided framerate not supported".into())); promise.reject_error(
Error::Type("Provided framerate not supported".into()),
can_gc,
);
return promise; return promise;
} }
} }

View file

@ -171,13 +171,13 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
if pref!(dom_webxr_unsafe_assume_user_intent) { if pref!(dom_webxr_unsafe_assume_user_intent) {
warn!("The dom.webxr.unsafe-assume-user-intent preference assumes user intent to enter WebXR."); warn!("The dom.webxr.unsafe-assume-user-intent preference assumes user intent to enter WebXR.");
} else { } else {
promise.reject_error(Error::Security); promise.reject_error(Error::Security, can_gc);
return promise; return promise;
} }
} }
if self.pending_or_active_session() { if self.pending_or_active_session() {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState, can_gc);
return promise; return promise;
} }
@ -200,7 +200,7 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
if mode != XRSessionMode::Inline { if mode != XRSessionMode::Inline {
self.pending_immersive_session.set(false); self.pending_immersive_session.set(false);
} }
promise.reject_error(Error::NotSupported); promise.reject_error(Error::NotSupported, can_gc);
return promise; return promise;
} }
} }
@ -291,7 +291,7 @@ impl XRSystem {
if mode != XRSessionMode::Inline { if mode != XRSessionMode::Inline {
self.pending_immersive_session.set(false); self.pending_immersive_session.set(false);
} }
promise.reject_error(Error::NotSupported); promise.reject_error(Error::NotSupported, can_gc);
return; return;
}, },
}; };

View file

@ -77,7 +77,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
match get_origin(o) { match get_origin(o) {
Ok(origin) => Some(origin), Ok(origin) => Some(origin),
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return p; return p;
}, },
} }
@ -89,7 +89,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
match get_origin(o) { match get_origin(o) {
Ok(origin) => Some(origin), Ok(origin) => Some(origin),
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return p; return p;
}, },
} }
@ -100,7 +100,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
let views = match get_views(&init.views) { let views = match get_views(&init.views) {
Ok(views) => views, Ok(views) => views,
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return p; return p;
}, },
}; };
@ -115,7 +115,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
let w = match get_world(w) { let w = match get_world(w) {
Ok(w) => w, Ok(w) => w,
Err(e) => { Err(e) => {
p.reject_error(e); p.reject_error(e, can_gc);
return p; return p;
}, },
}; };

View file

@ -141,7 +141,7 @@ impl WorkletMethods<crate::DomTypeHolder> for Worklet {
Err(err) => { Err(err) => {
// Step 4. // Step 4.
debug!("URL {:?} parse error {:?}.", module_url.0, err); debug!("URL {:?} parse error {:?}.", module_url.0, err);
promise.reject_error(Error::Syntax); promise.reject_error(Error::Syntax, can_gc);
return promise; return promise;
}, },
}; };

View file

@ -718,7 +718,10 @@ impl WritableStream {
if self.is_closed() || self.is_errored() { if self.is_closed() || self.is_errored() {
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(Error::Type("Stream is closed or errored.".to_string())); promise.reject_error(
Error::Type("Stream is closed or errored.".to_string()),
can_gc,
);
return promise; return promise;
} }
@ -913,7 +916,7 @@ impl WritableStreamMethods<crate::DomTypeHolder> for WritableStream {
if self.is_locked() { if self.is_locked() {
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_error(Error::Type("Stream is locked.".to_string())); promise.reject_error(Error::Type("Stream is locked.".to_string()), can_gc);
return promise; return promise;
} }
@ -930,7 +933,7 @@ impl WritableStreamMethods<crate::DomTypeHolder> for WritableStream {
if self.is_locked() { if self.is_locked() {
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_error(Error::Type("Stream is locked.".to_string())); promise.reject_error(Error::Type("Stream is locked.".to_string()), can_gc);
return promise; return promise;
} }
@ -938,9 +941,10 @@ impl WritableStreamMethods<crate::DomTypeHolder> for WritableStream {
if self.close_queued_or_in_flight() { if self.close_queued_or_in_flight() {
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_error(Error::Type( promise.reject_error(
"Stream has closed queued or in-flight".to_string(), Error::Type("Stream has closed queued or in-flight".to_string()),
)); can_gc,
);
return promise; return promise;
} }

View file

@ -451,7 +451,7 @@ impl WritableStreamDefaultController {
}; };
result.unwrap_or_else(|e| { result.unwrap_or_else(|e| {
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(e); promise.reject_error(e, can_gc);
promise promise
}) })
} }
@ -477,7 +477,7 @@ impl WritableStreamDefaultController {
}; };
result.unwrap_or_else(|e| { result.unwrap_or_else(|e| {
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(e); promise.reject_error(e, can_gc);
promise promise
}) })
} }
@ -498,7 +498,7 @@ impl WritableStreamDefaultController {
}; };
result.unwrap_or_else(|e| { result.unwrap_or_else(|e| {
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(e); promise.reject_error(e, can_gc);
promise promise
}) })
} }

View file

@ -293,9 +293,10 @@ impl WritableStreamDefaultWriter {
.is_some_and(|current_stream| current_stream == stream) .is_some_and(|current_stream| current_stream == stream)
{ {
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(Error::Type( promise.reject_error(
"Stream is not equal to writer stream".to_string(), Error::Type("Stream is not equal to writer stream".to_string()),
)); can_gc,
);
return promise; return promise;
} }
@ -316,9 +317,10 @@ impl WritableStreamDefaultWriter {
// return a promise rejected with a TypeError exception // return a promise rejected with a TypeError exception
// indicating that the stream is closing or closed // indicating that the stream is closing or closed
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.reject_error(Error::Type( promise.reject_error(
"Stream has been closed, or has close queued or in-flight".to_string(), Error::Type("Stream has been closed, or has close queued or in-flight".to_string()),
)); can_gc,
);
return promise; return promise;
} }
@ -415,7 +417,7 @@ impl WritableStreamDefaultWriterMethods<crate::DomTypeHolder> for WritableStream
if self.stream.get().is_none() { if self.stream.get().is_none() {
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_error(Error::Type("Stream is undefined".to_string())); promise.reject_error(Error::Type("Stream is undefined".to_string()), can_gc);
return promise; return promise;
} }
@ -433,16 +435,17 @@ impl WritableStreamDefaultWriterMethods<crate::DomTypeHolder> for WritableStream
let Some(stream) = self.stream.get() else { let Some(stream) = self.stream.get() else {
// If stream is undefined, // If stream is undefined,
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
promise.reject_error(Error::Type("Stream is undefined".to_string())); promise.reject_error(Error::Type("Stream is undefined".to_string()), can_gc);
return promise; return promise;
}; };
// If ! WritableStreamCloseQueuedOrInFlight(stream) is true // If ! WritableStreamCloseQueuedOrInFlight(stream) is true
if stream.close_queued_or_in_flight() { if stream.close_queued_or_in_flight() {
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
promise.reject_error(Error::Type( promise.reject_error(
"Stream has closed queued or in-flight".to_string(), Error::Type("Stream has closed queued or in-flight".to_string()),
)); can_gc,
);
return promise; return promise;
} }
@ -482,7 +485,7 @@ impl WritableStreamDefaultWriterMethods<crate::DomTypeHolder> for WritableStream
// return a promise rejected with a TypeError exception. // return a promise rejected with a TypeError exception.
let global = GlobalScope::from_safe_context(cx, realm); let global = GlobalScope::from_safe_context(cx, realm);
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.reject_error(Error::Type("Stream is undefined".to_string())); promise.reject_error(Error::Type("Stream is undefined".to_string()), can_gc);
return promise; return promise;
} }

View file

@ -151,7 +151,7 @@ pub(crate) fn Fetch(
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(), can_gc); response.error_stream(e.clone(), can_gc);
promise.reject_error(e); promise.reject_error(e, can_gc);
return promise; return promise;
}, },
Ok(r) => { Ok(r) => {
@ -223,7 +223,10 @@ impl FetchResponseListener for FetchContext {
match fetch_metadata { match fetch_metadata {
// Step 4.1 // Step 4.1
Err(_) => { Err(_) => {
promise.reject_error(Error::Type("Network error occurred".to_string())); promise.reject_error(
Error::Type("Network error occurred".to_string()),
CanGc::note(),
);
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());

View file

@ -485,7 +485,7 @@ DOMInterfaces = {
#FIXME(jdm): This should be 'register': False, but then we don't generate enum types #FIXME(jdm): This should be 'register': False, but then we don't generate enum types
'TestBinding': { 'TestBinding': {
'inRealms': ['PromiseAttribute', 'PromiseNativeHandler'], 'inRealms': ['PromiseAttribute', 'PromiseNativeHandler'],
'canGc': ['InterfaceAttribute', 'GetInterfaceAttributeNullable', 'ReceiveInterface', 'ReceiveInterfaceSequence', 'ReceiveNullableInterface', 'PromiseAttribute', 'PromiseNativeHandler', 'PromiseResolveNative', 'PromiseRejectNative'], 'canGc': ['InterfaceAttribute', 'GetInterfaceAttributeNullable', 'ReceiveInterface', 'ReceiveInterfaceSequence', 'ReceiveNullableInterface', 'PromiseAttribute', 'PromiseNativeHandler', 'PromiseResolveNative', 'PromiseRejectNative', 'PromiseRejectWithTypeError'],
}, },
'TestWorklet': { 'TestWorklet': {