refactor: add CanGc as argument to Promise::resolve (#35616)

Signed-off-by: Yerkebulan Tulibergenov <yerkebulan@gmail.com>
This commit is contained in:
Yerkebulan Tulibergenov 2025-02-23 04:12:21 -08:00 committed by GitHub
parent adb831eefe
commit 0383ba9a5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 330 additions and 294 deletions

View file

@ -632,12 +632,14 @@ impl ConsumeBodyPromiseHandler {
match pkg_data_results { match pkg_data_results {
Ok(results) => { Ok(results) => {
match results { match results {
FetchedData::Text(s) => self.result_promise.resolve_native(&USVString(s)), FetchedData::Text(s) => {
FetchedData::Json(j) => self.result_promise.resolve_native(&j), self.result_promise.resolve_native(&USVString(s), can_gc)
FetchedData::BlobData(b) => self.result_promise.resolve_native(&b), },
FetchedData::FormData(f) => self.result_promise.resolve_native(&f), FetchedData::Json(j) => self.result_promise.resolve_native(&j, can_gc),
FetchedData::Bytes(b) => self.result_promise.resolve_native(&b), FetchedData::BlobData(b) => self.result_promise.resolve_native(&b, can_gc),
FetchedData::ArrayBuffer(a) => self.result_promise.resolve_native(&a), FetchedData::FormData(f) => self.result_promise.resolve_native(&f, can_gc),
FetchedData::Bytes(b) => self.result_promise.resolve_native(&b, can_gc),
FetchedData::ArrayBuffer(a) => self.result_promise.resolve_native(&a, can_gc),
FetchedData::JSException(e) => self.result_promise.reject_native(&e.handle()), FetchedData::JSException(e) => self.result_promise.reject_native(&e.handle()),
}; };
}, },

View file

@ -152,7 +152,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
// Step 3. // Step 3.
if self.context.State() == AudioContextState::Suspended { if self.context.State() == AudioContextState::Suspended {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
return promise; return promise;
} }
@ -167,7 +167,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
let base_context = base_context.root(); let base_context = base_context.root();
let context = context.root(); let context = context.root();
let promise = trusted_promise.root(); let promise = trusted_promise.root();
promise.resolve_native(&()); promise.resolve_native(&(), CanGc::note());
if base_context.State() != AudioContextState::Suspended { if base_context.State() != AudioContextState::Suspended {
base_context.set_state_attribute(AudioContextState::Suspended); base_context.set_state_attribute(AudioContextState::Suspended);
context.global().task_manager().dom_manipulation_task_source().queue_simple_event( context.global().task_manager().dom_manipulation_task_source().queue_simple_event(
@ -208,7 +208,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
// Step 3. // Step 3.
if self.context.State() == AudioContextState::Closed { if self.context.State() == AudioContextState::Closed {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
return promise; return promise;
} }
@ -223,7 +223,7 @@ impl AudioContextMethods<crate::DomTypeHolder> for AudioContext {
let base_context = base_context.root(); let base_context = base_context.root();
let context = context.root(); let context = context.root();
let promise = trusted_promise.root(); let promise = trusted_promise.root();
promise.resolve_native(&()); promise.resolve_native(&(), CanGc::note());
if base_context.State() != AudioContextState::Closed { if base_context.State() != AudioContextState::Closed {
base_context.set_state_attribute(AudioContextState::Closed); base_context.set_state_attribute(AudioContextState::Closed);
context.global().task_manager().dom_manipulation_task_source().queue_simple_event( context.global().task_manager().dom_manipulation_task_source().queue_simple_event(

View file

@ -211,7 +211,7 @@ impl BaseAudioContext {
f(); f();
for promise in &*promises { for promise in &*promises {
match result { match result {
Ok(ref value) => promise.resolve_native(value), 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()),
} }
} }
@ -298,7 +298,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
// Step 3. // Step 3.
if self.state.get() == AudioContextState::Running { if self.state.get() == AudioContextState::Running {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
return promise; return promise;
} }
@ -549,7 +549,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
if let Some(callback) = resolver.success_callback { if let Some(callback) = resolver.success_callback {
let _ = callback.Call__(&buffer, ExceptionHandling::Report); let _ = callback.Call__(&buffer, ExceptionHandling::Report);
} }
resolver.promise.resolve_native(&buffer); resolver.promise.resolve_native(&buffer, CanGc::note());
})); }));
}) })
.error(move |error| { .error(move |error| {

View file

@ -31,6 +31,7 @@ use std::rc::Rc;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use js::jsapi::JSTracer; use js::jsapi::JSTracer;
use script_bindings::script_runtime::CanGc;
use crate::dom::bindings::conversions::ToJSValConvertible; use crate::dom::bindings::conversions::ToJSValConvertible;
use crate::dom::bindings::error::Error; use crate::dom::bindings::error::Error;
@ -151,7 +152,7 @@ impl TrustedPromise {
let this = self; let this = self;
task!(resolve_promise: move || { task!(resolve_promise: move || {
debug!("Resolving promise."); debug!("Resolving promise.");
this.root().resolve_native(&value); this.root().resolve_native(&value, CanGc::note());
}) })
} }
} }

View file

@ -256,7 +256,7 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
Ok(b) => { Ok(b) => {
let (text, _, _) = UTF_8.decode(&b); let (text, _, _) = UTF_8.decode(&b);
let text = DOMString::from(text); let text = DOMString::from(text);
promise.resolve_native(&text); promise.resolve_native(&text, CanGc::note());
}, },
Err(e) => { Err(e) => {
promise.reject_error(e); promise.reject_error(e);
@ -284,7 +284,9 @@ impl BlobMethods<crate::DomTypeHolder> for Blob {
let result = run_array_buffer_data_algorithm(cx, b, CanGc::note()); let result = run_array_buffer_data_algorithm(cx, b, CanGc::note());
match result { match result {
Ok(FetchedData::ArrayBuffer(a)) => promise.resolve_native(&a), Ok(FetchedData::ArrayBuffer(a)) => {
promise.resolve_native(&a, CanGc::note())
},
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e),
_ => panic!("Unexpected result from run_array_buffer_data_algorithm"), _ => panic!("Unexpected result from run_array_buffer_data_algorithm"),
} }

View file

@ -589,7 +589,7 @@ impl AsyncBluetoothListener for Bluetooth {
BluetoothResponse::RequestDevice(device) => { BluetoothResponse::RequestDevice(device) => {
let mut device_instance_map = self.device_instance_map.borrow_mut(); let mut device_instance_map = self.device_instance_map.borrow_mut();
if let Some(existing_device) = device_instance_map.get(&device.id.clone()) { if let Some(existing_device) = device_instance_map.get(&device.id.clone()) {
return promise.resolve_native(&**existing_device); return promise.resolve_native(&**existing_device, can_gc);
} }
let bt_device = BluetoothDevice::new( let bt_device = BluetoothDevice::new(
&self.global(), &self.global(),
@ -609,12 +609,12 @@ impl AsyncBluetoothListener for Bluetooth {
}); });
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
// Step 5. // Step 5.
promise.resolve_native(&bt_device); promise.resolve_native(&bt_device, can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability
// Step 2 - 3. // Step 2 - 3.
BluetoothResponse::GetAvailability(is_available) => { BluetoothResponse::GetAvailability(is_available) => {
promise.resolve_native(&is_available); 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())),
} }
@ -655,7 +655,7 @@ impl PermissionAlgorithm for Bluetooth {
// Step 3. // Step 3.
if let PermissionState::Denied = status.get_state() { if let PermissionState::Denied = status.get_state() {
status.set_devices(Vec::new()); status.set_devices(Vec::new());
return promise.resolve_native(status); return promise.resolve_native(status, CanGc::note());
} }
// Step 4. // Step 4.
@ -727,7 +727,7 @@ impl PermissionAlgorithm for Bluetooth {
// https://w3c.github.io/permissions/#dom-permissions-query // https://w3c.github.io/permissions/#dom-permissions-query
// Step 7. // Step 7.
promise.resolve_native(status); promise.resolve_native(status, CanGc::note());
} }
// https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission // https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission

View file

@ -327,14 +327,14 @@ impl BluetoothDeviceMethods<crate::DomTypeHolder> for BluetoothDevice {
} }
impl AsyncBluetoothListener for BluetoothDevice { impl AsyncBluetoothListener for BluetoothDevice {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, _can_gc: CanGc) { fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, can_gc: CanGc) {
match response { match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements
BluetoothResponse::WatchAdvertisements(_result) => { BluetoothResponse::WatchAdvertisements(_result) => {
// Step 3.1. // Step 3.1.
self.watching_advertisements.set(true); self.watching_advertisements.set(true);
// Step 3.2. // Step 3.2.
promise.resolve_native(&()); 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())),
} }

View file

@ -112,7 +112,7 @@ impl AsyncBluetoothListener for BluetoothPermissionResult {
// https://w3c.github.io/permissions/#dom-permissions-request // https://w3c.github.io/permissions/#dom-permissions-request
// Step 8. // Step 8.
return promise.resolve_native(self); return promise.resolve_native(self, can_gc);
} }
let bt_device = BluetoothDevice::new( let bt_device = BluetoothDevice::new(
&self.global(), &self.global(),
@ -135,7 +135,7 @@ impl AsyncBluetoothListener for BluetoothPermissionResult {
// https://w3c.github.io/permissions/#dom-permissions-request // https://w3c.github.io/permissions/#dom-permissions-request
// Step 8. // Step 8.
promise.resolve_native(self); 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())),
} }

View file

@ -309,11 +309,10 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
// Step 7. // Step 7.
BluetoothResponse::GetDescriptors(descriptors_vec, single) => { BluetoothResponse::GetDescriptors(descriptors_vec, single) => {
if single { if single {
promise.resolve_native(&device.get_or_create_descriptor( promise.resolve_native(
&descriptors_vec[0], &device.get_or_create_descriptor(&descriptors_vec[0], self, can_gc),
self,
can_gc, can_gc,
)); );
return; return;
} }
let mut descriptors = vec![]; let mut descriptors = vec![];
@ -321,7 +320,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
let bt_descriptor = device.get_or_create_descriptor(&descriptor, self, can_gc); let bt_descriptor = device.get_or_create_descriptor(&descriptor, self, can_gc);
descriptors.push(bt_descriptor); descriptors.push(bt_descriptor);
} }
promise.resolve_native(&descriptors); promise.resolve_native(&descriptors, can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
BluetoothResponse::ReadValue(result) => { BluetoothResponse::ReadValue(result) => {
@ -337,7 +336,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
.fire_bubbling_event(atom!("characteristicvaluechanged"), can_gc); .fire_bubbling_event(atom!("characteristicvaluechanged"), can_gc);
// Step 5.5.4. // Step 5.5.4.
promise.resolve_native(&value); promise.resolve_native(&value, can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
BluetoothResponse::WriteValue(result) => { BluetoothResponse::WriteValue(result) => {
@ -348,7 +347,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
*self.value.borrow_mut() = Some(ByteString::new(result)); *self.value.borrow_mut() = Some(ByteString::new(result));
// Step 7.5.3. // Step 7.5.3.
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications
@ -358,7 +357,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
// (StartNotification) Step 11. // (StartNotification) Step 11.
// (StopNotification) Step 5. // (StopNotification) Step 5.
promise.resolve_native(self); 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())),
} }

View file

@ -181,7 +181,7 @@ impl BluetoothRemoteGATTDescriptorMethods<crate::DomTypeHolder> for BluetoothRem
} }
impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor { impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor {
fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, _can_gc: CanGc) { fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, can_gc: CanGc) {
match response { match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
BluetoothResponse::ReadValue(result) => { BluetoothResponse::ReadValue(result) => {
@ -193,7 +193,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor {
*self.value.borrow_mut() = Some(value.clone()); *self.value.borrow_mut() = Some(value.clone());
// Step 5.4.3. // Step 5.4.3.
promise.resolve_native(&value); promise.resolve_native(&value, can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
BluetoothResponse::WriteValue(result) => { BluetoothResponse::WriteValue(result) => {
@ -205,7 +205,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor {
// Step 7.4.3. // Step 7.4.3.
// TODO: Resolve promise with undefined instead of a value. // TODO: Resolve promise with undefined instead of a value.
promise.resolve_native(&()); 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())),
} }

View file

@ -164,18 +164,17 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
self.connected.set(connected); self.connected.set(connected);
// Step 5.2.5. // Step 5.2.5.
promise.resolve_native(self); promise.resolve_native(self, can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
// Step 7. // Step 7.
BluetoothResponse::GetPrimaryServices(services_vec, single) => { BluetoothResponse::GetPrimaryServices(services_vec, single) => {
let device = self.Device(); let device = self.Device();
if single { if single {
promise.resolve_native(&device.get_or_create_service( promise.resolve_native(
&services_vec[0], &device.get_or_create_service(&services_vec[0], self, can_gc),
self,
can_gc, can_gc,
)); );
return; return;
} }
let mut services = vec![]; let mut services = vec![];
@ -183,7 +182,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
let bt_service = device.get_or_create_service(&service, self, can_gc); let bt_service = device.get_or_create_service(&service, self, can_gc);
services.push(bt_service); services.push(bt_service);
} }
promise.resolve_native(&services); 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())),
} }

View file

@ -172,11 +172,10 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
// Step 7. // Step 7.
BluetoothResponse::GetCharacteristics(characteristics_vec, single) => { BluetoothResponse::GetCharacteristics(characteristics_vec, single) => {
if single { if single {
promise.resolve_native(&device.get_or_create_characteristic( promise.resolve_native(
&characteristics_vec[0], &device.get_or_create_characteristic(&characteristics_vec[0], self, can_gc),
self,
can_gc, can_gc,
)); );
return; return;
} }
let mut characteristics = vec![]; let mut characteristics = vec![];
@ -185,17 +184,16 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
device.get_or_create_characteristic(&characteristic, self, can_gc); device.get_or_create_characteristic(&characteristic, self, can_gc);
characteristics.push(bt_characteristic); characteristics.push(bt_characteristic);
} }
promise.resolve_native(&characteristics); promise.resolve_native(&characteristics, can_gc);
}, },
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
// Step 7. // Step 7.
BluetoothResponse::GetIncludedServices(services_vec, single) => { BluetoothResponse::GetIncludedServices(services_vec, single) => {
if single { if single {
return promise.resolve_native(&device.get_or_create_service( return promise.resolve_native(
&services_vec[0], &device.get_or_create_service(&services_vec[0], &device.get_gatt(), can_gc),
&device.get_gatt(),
can_gc, can_gc,
)); );
} }
let mut services = vec![]; let mut services = vec![];
for service in services_vec { for service in services_vec {
@ -203,7 +201,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
device.get_or_create_service(&service, &device.get_gatt(), can_gc); device.get_or_create_service(&service, &device.get_gatt(), can_gc);
services.push(bt_service); services.push(bt_service);
} }
promise.resolve_native(&services); 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())),
} }

View file

@ -343,6 +343,7 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
name: DOMString, name: DOMString,
constructor_: Rc<CustomElementConstructor>, constructor_: Rc<CustomElementConstructor>,
options: &ElementDefinitionOptions, options: &ElementDefinitionOptions,
can_gc: CanGc,
) -> ErrorResult { ) -> ErrorResult {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let constructor = constructor_.callback()); rooted!(in(*cx) let constructor = constructor_.callback());
@ -543,7 +544,7 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
definition definition
.constructor .constructor
.to_jsval(*cx, constructor.handle_mut()); .to_jsval(*cx, constructor.handle_mut());
promise.resolve_native(&constructor.get()); promise.resolve_native(&constructor.get(), can_gc);
} }
} }
Ok(()) Ok(())
@ -595,7 +596,7 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
.constructor .constructor
.to_jsval(*cx, constructor.handle_mut()); .to_jsval(*cx, constructor.handle_mut());
let promise = Promise::new_in_current_realm(comp, can_gc); let promise = Promise::new_in_current_realm(comp, can_gc);
promise.resolve_native(&constructor.get()); promise.resolve_native(&constructor.get(), can_gc);
return promise; return promise;
} }
} }

View file

@ -178,20 +178,20 @@ impl DefaultTeeReadRequest {
} }
} }
/// <https://streams.spec.whatwg.org/#read-request-close-steps> /// <https://streams.spec.whatwg.org/#read-request-close-steps>
pub(crate) fn close_steps(&self) { pub(crate) fn close_steps(&self, can_gc: CanGc) {
// Set reading to false. // Set reading to false.
self.reading.set(false); self.reading.set(false);
// If canceled_1 is false, perform ! ReadableStreamDefaultControllerClose(branch_1.[[controller]]). // If canceled_1 is false, perform ! ReadableStreamDefaultControllerClose(branch_1.[[controller]]).
if !self.canceled_1.get() { if !self.canceled_1.get() {
self.readable_stream_default_controller_close(&self.branch_1); self.readable_stream_default_controller_close(&self.branch_1, can_gc);
} }
// If canceled_2 is false, perform ! ReadableStreamDefaultControllerClose(branch_2.[[controller]]). // If canceled_2 is false, perform ! ReadableStreamDefaultControllerClose(branch_2.[[controller]]).
if !self.canceled_2.get() { if !self.canceled_2.get() {
self.readable_stream_default_controller_close(&self.branch_2); self.readable_stream_default_controller_close(&self.branch_2, can_gc);
} }
// If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined. // If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined.
if !self.canceled_1.get() || !self.canceled_2.get() { if !self.canceled_1.get() || !self.canceled_2.get() {
self.cancel_promise.resolve_native(&()); self.cancel_promise.resolve_native(&(), can_gc);
} }
} }
/// <https://streams.spec.whatwg.org/#read-request-error-steps> /// <https://streams.spec.whatwg.org/#read-request-error-steps>
@ -215,8 +215,8 @@ impl DefaultTeeReadRequest {
/// Call into close of the default controller of a stream, /// Call into close of the default controller of a stream,
/// <https://streams.spec.whatwg.org/#readable-stream-default-controller-close> /// <https://streams.spec.whatwg.org/#readable-stream-default-controller-close>
fn readable_stream_default_controller_close(&self, stream: &ReadableStream) { fn readable_stream_default_controller_close(&self, stream: &ReadableStream, can_gc: CanGc) {
stream.get_default_controller().close(); stream.get_default_controller().close(can_gc);
} }
/// Call into error of the default controller of stream, /// Call into error of the default controller of stream,

View file

@ -213,6 +213,6 @@ impl DefaultTeeUnderlyingSource {
let cancel_result = self.stream.cancel(reasons_value.handle(), can_gc); let cancel_result = self.stream.cancel(reasons_value.handle(), can_gc);
// Resolve cancelPromise with cancelResult. // Resolve cancelPromise with cancelResult.
self.cancel_promise.resolve_native(&cancel_result); self.cancel_promise.resolve_native(&cancel_result, can_gc);
} }
} }

View file

@ -4625,7 +4625,7 @@ impl TaskOnce for ElementPerformFullscreenEnter {
.fire_event(atom!("fullscreenchange"), CanGc::note()); .fire_event(atom!("fullscreenchange"), CanGc::note());
// Step 7.7 // Step 7.7
promise.resolve_native(&()); promise.resolve_native(&(), CanGc::note());
} }
} }
@ -4659,7 +4659,7 @@ impl TaskOnce for ElementPerformFullscreenExit {
.fire_event(atom!("fullscreenchange"), CanGc::note()); .fire_event(atom!("fullscreenchange"), CanGc::note());
// Step 9.10 // Step 9.10
self.promise.root().resolve_native(&()); self.promise.root().resolve_native(&(), CanGc::note());
} }
} }

View file

@ -514,7 +514,7 @@ impl FontFaceMethods<crate::DomTypeHolder> for FontFace {
font_face.status.set(FontFaceLoadStatus::Loaded); font_face.status.set(FontFaceLoadStatus::Loaded);
let old_template = font_face.template.borrow_mut().replace((family_name, template)); let old_template = font_face.template.borrow_mut().replace((family_name, template));
debug_assert!(old_template.is_none(), "FontFace's template must be intialized only once"); debug_assert!(old_template.is_none(), "FontFace's template must be intialized only once");
font_face.font_status_promise.resolve_native(&font_face); font_face.font_status_promise.resolve_native(&font_face, CanGc::note());
} }
} }

View file

@ -69,9 +69,9 @@ impl FontFaceSet {
} }
} }
pub(crate) fn fulfill_ready_promise_if_needed(&self) { pub(crate) fn fulfill_ready_promise_if_needed(&self, can_gc: CanGc) {
if !self.promise.is_fulfilled() { if !self.promise.is_fulfilled() {
self.promise.resolve_native(self); self.promise.resolve_native(self, can_gc);
} }
} }
} }
@ -114,7 +114,7 @@ impl FontFaceSetMethods<crate::DomTypeHolder> for FontFaceSet {
// TODO: Step 4.2. Resolve promise with the result of waiting for all of the // TODO: Step 4.2. Resolve promise with the result of waiting for all of the
// [[FontStatusPromise]]s of each font face in the font face list, in order. // [[FontStatusPromise]]s of each font face in the font face list, in order.
let matched_fonts = Vec::<&FontFace>::new(); let matched_fonts = Vec::<&FontFace>::new();
promise.resolve_native(&matched_fonts); promise.resolve_native(&matched_fonts, CanGc::note());
})); }));
// Step 2. Return promise. Complete the rest of these steps asynchronously. // Step 2. Return promise. Complete the rest of these steps asynchronously.

View file

@ -48,7 +48,7 @@ impl HapticEffectListener {
self.task_source self.task_source
.queue(task!(handle_haptic_effect_completed: move || { .queue(task!(handle_haptic_effect_completed: move || {
let actuator = context.root(); let actuator = context.root();
actuator.handle_haptic_effect_completed(completed_successfully); actuator.handle_haptic_effect_completed(completed_successfully, CanGc::note());
})); }));
} }
} }
@ -195,7 +195,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
task!(preempt_promise: move || { task!(preempt_promise: move || {
let promise = trusted_promise.root(); let promise = trusted_promise.root();
let message = DOMString::from("preempted"); let message = DOMString::from("preempted");
promise.resolve_native(&message); promise.resolve_native(&message, CanGc::note());
}), }),
); );
} }
@ -263,7 +263,7 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
task!(preempt_promise: move || { task!(preempt_promise: move || {
let promise = trusted_promise.root(); let promise = trusted_promise.root();
let message = DOMString::from("preempted"); let message = DOMString::from("preempted");
promise.resolve_native(&message); promise.resolve_native(&message, CanGc::note());
}), }),
); );
} }
@ -302,14 +302,18 @@ impl GamepadHapticActuatorMethods<crate::DomTypeHolder> for GamepadHapticActuato
impl GamepadHapticActuator { impl GamepadHapticActuator {
/// <https://www.w3.org/TR/gamepad/#dom-gamepadhapticactuator-playeffect> /// <https://www.w3.org/TR/gamepad/#dom-gamepadhapticactuator-playeffect>
/// We are in the task queued by the "in-parallel" steps. /// We are in the task queued by the "in-parallel" steps.
pub(crate) fn handle_haptic_effect_completed(&self, completed_successfully: bool) { pub(crate) fn handle_haptic_effect_completed(
&self,
completed_successfully: bool,
can_gc: CanGc,
) {
if self.effect_sequence_id.get() != self.sequence_id.get() || !completed_successfully { if self.effect_sequence_id.get() != self.sequence_id.get() || !completed_successfully {
return; return;
} }
let playing_effect_promise = self.playing_effect_promise.borrow_mut().take(); let playing_effect_promise = self.playing_effect_promise.borrow_mut().take();
if let Some(promise) = playing_effect_promise { if let Some(promise) = playing_effect_promise {
let message = DOMString::from("complete"); let message = DOMString::from("complete");
promise.resolve_native(&message); promise.resolve_native(&message, can_gc);
} }
} }
@ -334,7 +338,7 @@ impl GamepadHapticActuator {
} }
let promise = trusted_promise.root(); let promise = trusted_promise.root();
let message = DOMString::from("complete"); let message = DOMString::from("complete");
promise.resolve_native(&message); promise.resolve_native(&message, CanGc::note());
}) })
); );
} }
@ -354,7 +358,7 @@ impl GamepadHapticActuator {
return; return;
}; };
let message = DOMString::from("preempted"); let message = DOMString::from("preempted");
promise.resolve_native(&message); promise.resolve_native(&message, CanGc::note());
}), }),
); );

View file

@ -591,8 +591,8 @@ fn stream_handle_incoming(stream: &ReadableStream, bytes: Fallible<Vec<u8>>, can
} }
/// Callback used to close streams as part of FileListener. /// Callback used to close streams as part of FileListener.
fn stream_handle_eof(stream: &ReadableStream) { fn stream_handle_eof(stream: &ReadableStream, can_gc: CanGc) {
stream.controller_close_native(); stream.controller_close_native(can_gc);
} }
impl FileListener { impl FileListener {
@ -657,7 +657,7 @@ impl FileListener {
let task = task!(enqueue_stream_chunk: move || { let task = task!(enqueue_stream_chunk: move || {
let stream = trusted.root(); let stream = trusted.root();
stream_handle_eof(&stream); stream_handle_eof(&stream, CanGc::note());
}); });
self.task_source.queue(task); self.task_source.queue(task);
@ -2729,7 +2729,7 @@ impl GlobalScope {
image_bitmap.set_bitmap_data(data); image_bitmap.set_bitmap_data(data);
image_bitmap.set_origin_clean(canvas.origin_is_clean()); image_bitmap.set_origin_clean(canvas.origin_is_clean());
p.resolve_native(&(image_bitmap)); p.resolve_native(&(image_bitmap), can_gc);
} }
p p
}, },
@ -2749,7 +2749,7 @@ impl GlobalScope {
ImageBitmap::new(self, size.width, size.height, can_gc).unwrap(); ImageBitmap::new(self, size.width, size.height, can_gc).unwrap();
image_bitmap.set_bitmap_data(data); image_bitmap.set_bitmap_data(data);
image_bitmap.set_origin_clean(canvas.origin_is_clean()); image_bitmap.set_origin_clean(canvas.origin_is_clean());
p.resolve_native(&(image_bitmap)); p.resolve_native(&(image_bitmap), can_gc);
} }
p p
}, },

View file

@ -450,7 +450,7 @@ impl HTMLImageElement {
LoadBlocker::terminate(&self.current_request.borrow().blocker, can_gc); LoadBlocker::terminate(&self.current_request.borrow().blocker, can_gc);
// Mark the node dirty // Mark the node dirty
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
self.resolve_image_decode_promises(); self.resolve_image_decode_promises(can_gc);
} }
/// Step 24 of <https://html.spec.whatwg.org/multipage/#update-the-image-data> /// Step 24 of <https://html.spec.whatwg.org/multipage/#update-the-image-data>
@ -559,7 +559,7 @@ impl HTMLImageElement {
if matches!(state, State::Broken) { if matches!(state, State::Broken) {
self.reject_image_decode_promises(can_gc); self.reject_image_decode_promises(can_gc);
} else if matches!(state, State::CompletelyAvailable) { } else if matches!(state, State::CompletelyAvailable) {
self.resolve_image_decode_promises(); self.resolve_image_decode_promises(can_gc);
} }
} }
@ -1186,7 +1186,7 @@ impl HTMLImageElement {
State::CompletelyAvailable State::CompletelyAvailable
) { ) {
// this doesn't follow the spec, but it's been discussed in <https://github.com/whatwg/html/issues/4217> // this doesn't follow the spec, but it's been discussed in <https://github.com/whatwg/html/issues/4217>
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
} else { } else {
self.image_decode_promises self.image_decode_promises
.borrow_mut() .borrow_mut()
@ -1194,9 +1194,9 @@ impl HTMLImageElement {
} }
} }
fn resolve_image_decode_promises(&self) { fn resolve_image_decode_promises(&self, can_gc: CanGc) {
for promise in self.image_decode_promises.borrow().iter() { for promise in self.image_decode_promises.borrow().iter() {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
} }
self.image_decode_promises.borrow_mut().clear(); self.image_decode_promises.borrow_mut().clear();
} }

View file

@ -1219,7 +1219,7 @@ impl HTMLMediaElement {
f(); f();
for promise in &*promises { for promise in &*promises {
match result { match result {
Ok(ref value) => promise.resolve_native(value), 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()),
} }
} }

View file

@ -72,7 +72,7 @@ impl MediaDevicesMethods<crate::DomTypeHolder> for MediaDevices {
} }
} }
p.resolve_native(&stream); p.resolve_native(&stream, can_gc);
p p
} }
@ -107,7 +107,7 @@ impl MediaDevicesMethods<crate::DomTypeHolder> for MediaDevices {
Err(_) => Vec::new(), Err(_) => Vec::new(),
}; };
p.resolve_native(&result_list); p.resolve_native(&result_list, can_gc);
// Step 3. // Step 3.
p p

View file

@ -63,7 +63,7 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
.set_navigation_preload_enabled(true); .set_navigation_preload_enabled(true);
// 4. // 4.
promise.resolve_native(&UndefinedValue()); promise.resolve_native(&UndefinedValue(), can_gc);
} }
promise promise
@ -86,7 +86,7 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
.set_navigation_preload_enabled(false); .set_navigation_preload_enabled(false);
// 4. // 4.
promise.resolve_native(&UndefinedValue()); promise.resolve_native(&UndefinedValue(), can_gc);
} }
promise promise
@ -109,7 +109,7 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
.set_navigation_preload_header_value(value); .set_navigation_preload_header_value(value);
// 4. // 4.
promise.resolve_native(&UndefinedValue()); promise.resolve_native(&UndefinedValue(), can_gc);
} }
promise promise
@ -135,7 +135,7 @@ impl NavigationPreloadManagerMethods<crate::DomTypeHolder> for NavigationPreload
.get_navigation_preload_header_value(); .get_navigation_preload_header_value();
// 5. // 5.
promise.resolve_native(&state); promise.resolve_native(&state, can_gc);
promise promise
} }

View file

@ -295,7 +295,7 @@ impl NotificationMethods<crate::DomTypeHolder> for Notification {
} }
// Step 3.2.2: Resolve promise with permissionState. // Step 3.2.2: Resolve promise with permissionState.
promise.resolve_native(&notification_permission); promise.resolve_native(&notification_permission, CanGc::note());
}), }),
); );

View file

@ -179,36 +179,37 @@ impl OfflineAudioContextMethods<crate::DomTypeHolder> for OfflineAudioContext {
.name("OfflineACResolver".to_owned()) .name("OfflineACResolver".to_owned())
.spawn(move || { .spawn(move || {
let _ = receiver.recv(); let _ = receiver.recv();
task_source.queue( task_source.queue(task!(resolve: move || {
task!(resolve: move || { let this = this.root();
let this = this.root(); let processed_audio = processed_audio.lock().unwrap();
let processed_audio = processed_audio.lock().unwrap(); let mut processed_audio: Vec<_> = processed_audio
let mut processed_audio: Vec<_> = processed_audio .chunks(this.length as usize)
.chunks(this.length as usize) .map(|channel| channel.to_vec())
.map(|channel| channel.to_vec()) .collect();
.collect(); // it can end up being empty if the task failed
// it can end up being empty if the task failed if processed_audio.len() != this.length as usize {
if processed_audio.len() != this.length as usize { processed_audio.resize(this.length as usize, Vec::new())
processed_audio.resize(this.length as usize, Vec::new()) }
} let buffer = AudioBuffer::new(
let buffer = AudioBuffer::new( this.global().as_window(),
this.global().as_window(), this.channel_count,
this.channel_count, this.length,
this.length, *this.context.SampleRate(),
*this.context.SampleRate(), Some(processed_audio.as_slice()),
Some(processed_audio.as_slice()), CanGc::note());
CanGc::note()); (*this.pending_rendering_promise.borrow_mut())
(*this.pending_rendering_promise.borrow_mut()).take().unwrap().resolve_native(&buffer); .take()
let global = &this.global(); .unwrap()
let window = global.as_window(); .resolve_native(&buffer, CanGc::note());
let event = OfflineAudioCompletionEvent::new(window, let global = &this.global();
atom!("complete"), let window = global.as_window();
EventBubbles::DoesNotBubble, let event = OfflineAudioCompletionEvent::new(window,
EventCancelable::NotCancelable, atom!("complete"),
&buffer, CanGc::note()); EventBubbles::DoesNotBubble,
event.upcast::<Event>().fire(this.upcast(), CanGc::note()); EventCancelable::NotCancelable,
}) &buffer, CanGc::note());
); event.upcast::<Event>().fire(this.upcast(), CanGc::note());
}));
}) })
.unwrap(); .unwrap();

View file

@ -160,14 +160,14 @@ impl Permissions {
// (Request) Step 7. The default algorithm always resolve // (Request) Step 7. The default algorithm always resolve
// (Request) Step 8. // (Request) Step 8.
p.resolve_native(&status); p.resolve_native(&status, can_gc);
}, },
Operation::Query => { Operation::Query => {
// (Query) Step 6. // (Query) Step 6.
Permissions::permission_query(cx, &p, &root_desc, &status); Permissions::permission_query(cx, &p, &root_desc, &status);
// (Query) Step 7. // (Query) Step 7.
p.resolve_native(&status); p.resolve_native(&status, can_gc);
}, },
Operation::Revoke => { Operation::Revoke => {

View file

@ -184,7 +184,7 @@ impl Promise {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub(crate) fn resolve_native<T>(&self, val: &T) pub(crate) fn resolve_native<T>(&self, val: &T, can_gc: CanGc)
where where
T: ToJSValConvertible, T: ToJSValConvertible,
{ {
@ -194,12 +194,12 @@ impl Promise {
unsafe { unsafe {
val.to_jsval(*cx, v.handle_mut()); val.to_jsval(*cx, v.handle_mut());
} }
self.resolve(cx, v.handle()); self.resolve(cx, v.handle(), can_gc);
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn resolve(&self, cx: SafeJSContext, value: HandleValue) { pub(crate) fn resolve(&self, cx: SafeJSContext, value: HandleValue, _can_gc: CanGc) {
unsafe { unsafe {
if !ResolvePromise(*cx, self.promise_obj(), value) { if !ResolvePromise(*cx, self.promise_obj(), value) {
JS_ClearPendingException(*cx); JS_ClearPendingException(*cx);

View file

@ -62,8 +62,8 @@ impl Callback for SourceCancelPromiseFulfillmentHandler {
/// The fulfillment handler for the reacting to sourceCancelPromise part of /// The fulfillment handler for the reacting to sourceCancelPromise part of
/// <https://streams.spec.whatwg.org/#readable-stream-cancel>. /// <https://streams.spec.whatwg.org/#readable-stream-cancel>.
/// An implementation of <https://webidl.spec.whatwg.org/#dfn-perform-steps-once-promise-is-settled> /// An implementation of <https://webidl.spec.whatwg.org/#dfn-perform-steps-once-promise-is-settled>
fn callback(&self, _cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, _cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
self.result.resolve_native(&()); self.result.resolve_native(&(), can_gc);
} }
} }
@ -251,7 +251,7 @@ impl ReadableStream {
can_gc, can_gc,
)?; )?;
stream.enqueue_native(bytes, can_gc); stream.enqueue_native(bytes, can_gc);
stream.controller_close_native(); stream.controller_close_native(can_gc);
Ok(stream) Ok(stream)
} }
@ -426,13 +426,13 @@ impl ReadableStream {
/// Call into the controller's `Close` method. /// Call into the controller's `Close` method.
/// <https://streams.spec.whatwg.org/#readable-stream-default-controller-close> /// <https://streams.spec.whatwg.org/#readable-stream-default-controller-close>
pub(crate) fn controller_close_native(&self) { pub(crate) fn controller_close_native(&self, can_gc: CanGc) {
match self.controller { match self.controller {
ControllerType::Default(ref controller) => { ControllerType::Default(ref controller) => {
let _ = controller let _ = controller
.get() .get()
.expect("Stream should have controller.") .expect("Stream should have controller.")
.Close(); .Close(can_gc);
}, },
ControllerType::Byte(_) => { ControllerType::Byte(_) => {
unreachable!("Native closing is only done on default controllers.") unreachable!("Native closing is only done on default controllers.")
@ -607,7 +607,7 @@ impl ReadableStream {
/// <https://streams.spec.whatwg.org/#readable-stream-fulfill-read-request> /// <https://streams.spec.whatwg.org/#readable-stream-fulfill-read-request>
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn fulfill_read_request(&self, chunk: SafeHandleValue, done: bool) { pub(crate) fn fulfill_read_request(&self, chunk: SafeHandleValue, done: bool, can_gc: CanGc) {
// step 1 - Assert: ! ReadableStreamHasDefaultReader(stream) is true. // step 1 - Assert: ! ReadableStreamHasDefaultReader(stream) is true.
assert!(self.has_default_reader()); assert!(self.has_default_reader());
match self.reader { match self.reader {
@ -624,12 +624,12 @@ impl ReadableStream {
if done { if done {
// step 6 - If done is true, perform readRequests close steps. // step 6 - If done is true, perform readRequests close steps.
request.close_steps(); request.close_steps(can_gc);
} else { } else {
// step 7 - Otherwise, perform readRequests chunk steps, given chunk. // step 7 - Otherwise, perform readRequests chunk steps, given chunk.
let result = RootedTraceableBox::new(Heap::default()); let result = RootedTraceableBox::new(Heap::default());
result.set(*chunk); result.set(*chunk);
request.chunk_steps(result); request.chunk_steps(result, can_gc);
} }
}, },
ReaderType::BYOB(_) => unreachable!( ReaderType::BYOB(_) => unreachable!(
@ -639,7 +639,7 @@ impl ReadableStream {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-close> /// <https://streams.spec.whatwg.org/#readable-stream-close>
pub(crate) fn close(&self) { pub(crate) fn close(&self, can_gc: CanGc) {
// Assert: stream.[[state]] is "readable". // Assert: stream.[[state]] is "readable".
assert!(self.is_readable()); assert!(self.is_readable());
// Set stream.[[state]] to "closed". // Set stream.[[state]] to "closed".
@ -652,7 +652,7 @@ impl ReadableStream {
return; return;
}; };
// step 5 & 6 // step 5 & 6
reader.close(); reader.close(can_gc);
}, },
ReaderType::BYOB(ref _reader) => {}, ReaderType::BYOB(ref _reader) => {},
} }
@ -680,14 +680,14 @@ impl ReadableStream {
} }
} }
// Perform ! ReadableStreamClose(stream). // Perform ! ReadableStreamClose(stream).
self.close(); self.close(can_gc);
// If reader is not undefined and reader implements ReadableStreamBYOBReader, // If reader is not undefined and reader implements ReadableStreamBYOBReader,
match self.reader { match self.reader {
ReaderType::BYOB(ref reader) => { ReaderType::BYOB(ref reader) => {
if let Some(reader) = reader.get() { if let Some(reader) = reader.get() {
// step 6.1, 6.2 & 6.3 of https://streams.spec.whatwg.org/#readable-stream-cancel // step 6.1, 6.2 & 6.3 of https://streams.spec.whatwg.org/#readable-stream-cancel
reader.close(); reader.close(can_gc);
} }
}, },
ReaderType::Default(ref _reader) => {}, ReaderType::Default(ref _reader) => {},

View file

@ -40,30 +40,36 @@ pub enum ReadIntoRequest {
impl ReadIntoRequest { impl ReadIntoRequest {
/// <https://streams.spec.whatwg.org/#ref-for-read-into-request-chunk-steps> /// <https://streams.spec.whatwg.org/#ref-for-read-into-request-chunk-steps>
pub fn chunk_steps(&self, chunk: RootedTraceableBox<Heap<JSVal>>) { pub fn chunk_steps(&self, chunk: RootedTraceableBox<Heap<JSVal>>, can_gc: CanGc) {
// chunk steps, given chunk // chunk steps, given chunk
// Resolve promise with «[ "value" → chunk, "done" → false ]». // Resolve promise with «[ "value" → chunk, "done" → false ]».
match self { match self {
ReadIntoRequest::Read(promise) => { ReadIntoRequest::Read(promise) => {
promise.resolve_native(&ReadableStreamReadResult { promise.resolve_native(
done: Some(false), &ReadableStreamReadResult {
value: chunk, done: Some(false),
}); value: chunk,
},
can_gc,
);
}, },
} }
} }
/// <https://streams.spec.whatwg.org/#ref-for-read-into-request-close-steps%E2%91%A0> /// <https://streams.spec.whatwg.org/#ref-for-read-into-request-close-steps%E2%91%A0>
pub fn close_steps(&self, chunk: Option<RootedTraceableBox<Heap<JSVal>>>) { pub fn close_steps(&self, chunk: Option<RootedTraceableBox<Heap<JSVal>>>, can_gc: CanGc) {
// close steps, given chunk // close steps, given chunk
// Resolve promise with «[ "value" → chunk, "done" → true ]». // Resolve promise with «[ "value" → chunk, "done" → true ]».
match self { match self {
ReadIntoRequest::Read(promise) => match chunk { ReadIntoRequest::Read(promise) => match chunk {
Some(chunk) => promise.resolve_native(&ReadableStreamReadResult { Some(chunk) => promise.resolve_native(
done: Some(true), &ReadableStreamReadResult {
value: chunk, done: Some(true),
}), value: chunk,
None => promise.resolve_native(&()), },
can_gc,
),
None => promise.resolve_native(&(), can_gc),
}, },
} }
} }
@ -194,7 +200,7 @@ impl ReadableStreamBYOBReader {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-cancel> /// <https://streams.spec.whatwg.org/#readable-stream-cancel>
pub(crate) fn close(&self) { pub(crate) fn close(&self, can_gc: CanGc) {
// If reader is not undefined and reader implements ReadableStreamBYOBReader, // If reader is not undefined and reader implements ReadableStreamBYOBReader,
// Let readIntoRequests be reader.[[readIntoRequests]]. // Let readIntoRequests be reader.[[readIntoRequests]].
let mut read_into_requests = self.take_read_into_requests(); let mut read_into_requests = self.take_read_into_requests();
@ -202,7 +208,7 @@ impl ReadableStreamBYOBReader {
// Perform readIntoRequests close steps, given undefined. // Perform readIntoRequests close steps, given undefined.
for request in read_into_requests.drain(0..) { for request in read_into_requests.drain(0..) {
// Perform readIntoRequests close steps, given undefined. // Perform readIntoRequests close steps, given undefined.
request.close_steps(None); request.close_steps(None, can_gc);
} }
} }

View file

@ -421,7 +421,7 @@ impl ReadableStreamDefaultController {
) )
.unwrap_or_else(|| { .unwrap_or_else(|| {
let promise = Promise::new(global, can_gc); let promise = Promise::new(global, can_gc);
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
Ok(promise) Ok(promise)
}); });
@ -541,7 +541,7 @@ impl ReadableStreamDefaultController {
.call_pull_algorithm(controller, can_gc) .call_pull_algorithm(controller, can_gc)
.unwrap_or_else(|| { .unwrap_or_else(|| {
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
Ok(promise) Ok(promise)
}); });
let promise = result.unwrap_or_else(|error| { let promise = result.unwrap_or_else(|error| {
@ -578,7 +578,7 @@ impl ReadableStreamDefaultController {
.call_cancel_algorithm(reason, can_gc) .call_cancel_algorithm(reason, can_gc)
.unwrap_or_else(|| { .unwrap_or_else(|| {
let promise = Promise::new(&global, can_gc); let promise = Promise::new(&global, can_gc);
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
Ok(promise) Ok(promise)
}); });
let promise = result.unwrap_or_else(|error| { let promise = result.unwrap_or_else(|error| {
@ -622,13 +622,13 @@ impl ReadableStreamDefaultController {
self.clear_algorithms(); self.clear_algorithms();
// Perform ! ReadableStreamClose(stream). // Perform ! ReadableStreamClose(stream).
stream.close(); stream.close(can_gc);
} else { } else {
// Otherwise, perform ! ReadableStreamDefaultControllerCallPullIfNeeded(this). // Otherwise, perform ! ReadableStreamDefaultControllerCallPullIfNeeded(this).
self.call_pull_if_needed(can_gc); self.call_pull_if_needed(can_gc);
} }
// Perform readRequests chunk steps, given chunk. // Perform readRequests chunk steps, given chunk.
read_request.chunk_steps(result); read_request.chunk_steps(result, can_gc);
} else { } else {
// Perform ! ReadableStreamAddReadRequest(stream, readRequest). // Perform ! ReadableStreamAddReadRequest(stream, readRequest).
stream.add_read_request(read_request); stream.add_read_request(read_request);
@ -666,7 +666,7 @@ impl ReadableStreamDefaultController {
// and ! ReadableStreamGetNumReadRequests(stream) > 0, // and ! ReadableStreamGetNumReadRequests(stream) > 0,
// perform ! ReadableStreamFulfillReadRequest(stream, chunk, false). // perform ! ReadableStreamFulfillReadRequest(stream, chunk, false).
if stream.is_locked() && stream.get_num_read_requests() > 0 { if stream.is_locked() && stream.get_num_read_requests() > 0 {
stream.fulfill_read_request(chunk, false); stream.fulfill_read_request(chunk, false, can_gc);
} else { } else {
// Otherwise, // Otherwise,
// Let result be the result of performing controller.[[strategySizeAlgorithm]], // Let result be the result of performing controller.[[strategySizeAlgorithm]],
@ -750,7 +750,7 @@ impl ReadableStreamDefaultController {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
EnqueuedValue::Native(chunk.into_boxed_slice()).to_jsval(cx, rval.handle_mut(), can_gc); EnqueuedValue::Native(chunk.into_boxed_slice()).to_jsval(cx, rval.handle_mut(), can_gc);
stream.fulfill_read_request(rval.handle(), false); stream.fulfill_read_request(rval.handle(), false, can_gc);
} else { } else {
let mut queue = self.queue.borrow_mut(); let mut queue = self.queue.borrow_mut();
queue queue
@ -787,7 +787,7 @@ impl ReadableStreamDefaultController {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-default-controller-close> /// <https://streams.spec.whatwg.org/#readable-stream-default-controller-close>
pub(crate) fn close(&self) { pub(crate) fn close(&self, can_gc: CanGc) {
// If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return. // If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return.
if !self.can_close_or_enqueue() { if !self.can_close_or_enqueue() {
return; return;
@ -805,7 +805,7 @@ impl ReadableStreamDefaultController {
self.clear_algorithms(); self.clear_algorithms();
// Perform ! ReadableStreamClose(stream). // Perform ! ReadableStreamClose(stream).
stream.close(); stream.close(can_gc);
} }
} }
@ -874,7 +874,7 @@ impl ReadableStreamDefaultControllerMethods<crate::DomTypeHolder>
} }
/// <https://streams.spec.whatwg.org/#rs-default-controller-close> /// <https://streams.spec.whatwg.org/#rs-default-controller-close>
fn Close(&self) -> Fallible<()> { fn Close(&self, can_gc: CanGc) -> Fallible<()> {
if !self.can_close_or_enqueue() { if !self.can_close_or_enqueue() {
// If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(this) is false, // If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(this) is false,
// throw a TypeError exception. // throw a TypeError exception.
@ -882,7 +882,7 @@ impl ReadableStreamDefaultControllerMethods<crate::DomTypeHolder>
} }
// Perform ! ReadableStreamDefaultControllerClose(this). // Perform ! ReadableStreamDefaultControllerClose(this).
self.close(); self.close(can_gc);
Ok(()) Ok(())
} }

View file

@ -46,15 +46,18 @@ pub(crate) enum ReadRequest {
impl ReadRequest { impl ReadRequest {
/// <https://streams.spec.whatwg.org/#read-request-chunk-steps> /// <https://streams.spec.whatwg.org/#read-request-chunk-steps>
pub(crate) fn chunk_steps(&self, chunk: RootedTraceableBox<Heap<JSVal>>) { pub(crate) fn chunk_steps(&self, chunk: RootedTraceableBox<Heap<JSVal>>, can_gc: CanGc) {
match self { match self {
ReadRequest::Read(promise) => { ReadRequest::Read(promise) => {
// chunk steps, given chunk // chunk steps, given chunk
// Resolve promise with «[ "value" → chunk, "done" → false ]». // Resolve promise with «[ "value" → chunk, "done" → false ]».
promise.resolve_native(&ReadableStreamReadResult { promise.resolve_native(
done: Some(false), &ReadableStreamReadResult {
value: chunk, done: Some(false),
}); value: chunk,
},
can_gc,
);
}, },
ReadRequest::DefaultTee { tee_read_request } => { ReadRequest::DefaultTee { tee_read_request } => {
tee_read_request.enqueue_chunk_steps(chunk); tee_read_request.enqueue_chunk_steps(chunk);
@ -63,20 +66,23 @@ impl ReadRequest {
} }
/// <https://streams.spec.whatwg.org/#read-request-close-steps> /// <https://streams.spec.whatwg.org/#read-request-close-steps>
pub(crate) fn close_steps(&self) { pub(crate) fn close_steps(&self, can_gc: CanGc) {
match self { match self {
ReadRequest::Read(promise) => { ReadRequest::Read(promise) => {
// close steps // close steps
// Resolve promise with «[ "value" → undefined, "done" → true ]». // Resolve promise with «[ "value" → undefined, "done" → true ]».
let result = RootedTraceableBox::new(Heap::default()); let result = RootedTraceableBox::new(Heap::default());
result.set(UndefinedValue()); result.set(UndefinedValue());
promise.resolve_native(&ReadableStreamReadResult { promise.resolve_native(
done: Some(true), &ReadableStreamReadResult {
value: result, done: Some(true),
}); value: result,
},
can_gc,
);
}, },
ReadRequest::DefaultTee { tee_read_request } => { ReadRequest::DefaultTee { tee_read_request } => {
tee_read_request.close_steps(); tee_read_request.close_steps(can_gc);
}, },
} }
} }
@ -114,7 +120,7 @@ struct ClosedPromiseRejectionHandler {
impl Callback for ClosedPromiseRejectionHandler { impl Callback for ClosedPromiseRejectionHandler {
/// Continuation of <https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed> /// Continuation of <https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed>
/// Upon rejection of `reader.closedPromise` with reason `r``, /// Upon rejection of `reader.closedPromise` with reason `r``,
fn callback(&self, _cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, _cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
let branch_1_controller = &self.branch_1_controller; let branch_1_controller = &self.branch_1_controller;
let branch_2_controller = &self.branch_2_controller; let branch_2_controller = &self.branch_2_controller;
@ -125,7 +131,7 @@ impl Callback for ClosedPromiseRejectionHandler {
// If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined. // If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined.
if !self.canceled_1.get() || !self.canceled_2.get() { if !self.canceled_1.get() || !self.canceled_2.get() {
self.cancel_promise.resolve_native(&()); self.cancel_promise.resolve_native(&(), can_gc);
} }
} }
} }
@ -198,9 +204,9 @@ impl ReadableStreamDefaultReader {
} }
/// <https://streams.spec.whatwg.org/#readable-stream-close> /// <https://streams.spec.whatwg.org/#readable-stream-close>
pub(crate) fn close(&self) { pub(crate) fn close(&self, can_gc: CanGc) {
// Resolve reader.[[closedPromise]] with undefined. // Resolve reader.[[closedPromise]] with undefined.
self.closed_promise.borrow().resolve_native(&()); self.closed_promise.borrow().resolve_native(&(), can_gc);
// If reader implements ReadableStreamDefaultReader, // If reader implements ReadableStreamDefaultReader,
// Let readRequests be reader.[[readRequests]]. // Let readRequests be reader.[[readRequests]].
let mut read_requests = self.take_read_requests(); let mut read_requests = self.take_read_requests();
@ -208,7 +214,7 @@ impl ReadableStreamDefaultReader {
// For each readRequest of readRequests, // For each readRequest of readRequests,
for request in read_requests.drain(0..) { for request in read_requests.drain(0..) {
// Perform readRequests close steps. // Perform readRequests close steps.
request.close_steps(); request.close_steps(can_gc);
} }
} }
@ -290,7 +296,7 @@ impl ReadableStreamDefaultReader {
stream.set_is_disturbed(true); stream.set_is_disturbed(true);
// If stream.[[state]] is "closed", perform readRequests close steps. // If stream.[[state]] is "closed", perform readRequests close steps.
if stream.is_closed() { if stream.is_closed() {
read_request.close_steps(); read_request.close_steps(can_gc);
} else if stream.is_errored() { } else if stream.is_errored() {
// Otherwise, if stream.[[state]] is "errored", // Otherwise, if stream.[[state]] is "errored",
// perform readRequests error steps given stream.[[storedError]]. // perform readRequests error steps given stream.[[storedError]].

View file

@ -464,9 +464,9 @@ impl Response {
} }
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn finish(&self) { pub(crate) fn finish(&self, can_gc: CanGc) {
if let Some(body) = self.body_stream.get() { if let Some(body) = self.body_stream.get() {
body.controller_close_native(); body.controller_close_native(can_gc);
} }
let stream_consumer = self.stream_consumer.borrow_mut().take(); let stream_consumer = self.stream_consumer.borrow_mut().take();
if let Some(stream_consumer) = stream_consumer { if let Some(stream_consumer) = stream_consumer {

View file

@ -457,7 +457,7 @@ impl RTCPeerConnection {
} else { } else {
let init: RTCSessionDescriptionInit = desc.convert(); let init: RTCSessionDescriptionInit = desc.convert();
for promise in this.offer_promises.borrow_mut().drain(..) { for promise in this.offer_promises.borrow_mut().drain(..) {
promise.resolve_native(&init); promise.resolve_native(&init, CanGc::note());
} }
} }
})); }));
@ -486,7 +486,7 @@ impl RTCPeerConnection {
} else { } else {
let init: RTCSessionDescriptionInit = desc.convert(); let init: RTCSessionDescriptionInit = desc.convert();
for promise in this.answer_promises.borrow_mut().drain(..) { for promise in this.answer_promises.borrow_mut().drain(..) {
promise.resolve_native(&init); promise.resolve_native(&init, CanGc::note());
} }
} }
})); }));
@ -583,7 +583,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
}); });
// XXXManishearth add_ice_candidate should have a callback // XXXManishearth add_ice_candidate should have a callback
p.resolve_native(&()); p.resolve_native(&(), can_gc);
p p
} }
@ -662,7 +662,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
&desc, &desc,
).unwrap(); ).unwrap();
this.local_description.set(Some(&desc)); this.local_description.set(Some(&desc));
trusted_promise.root().resolve_native(&()) trusted_promise.root().resolve_native(&(), CanGc::note())
})); }));
}), }),
); );
@ -705,7 +705,7 @@ impl RTCPeerConnectionMethods<crate::DomTypeHolder> for RTCPeerConnection {
&desc, &desc,
).unwrap(); ).unwrap();
this.remote_description.set(Some(&desc)); this.remote_description.set(Some(&desc));
trusted_promise.root().resolve_native(&()) trusted_promise.root().resolve_native(&(), CanGc::note())
})); }));
}), }),
); );

View file

@ -53,7 +53,7 @@ impl RTCRtpSenderMethods<crate::DomTypeHolder> for RTCRtpSender {
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-setparameters // https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-setparameters
fn SetParameters(&self, _parameters: &RTCRtpSendParameters, can_gc: CanGc) -> Rc<Promise> { fn SetParameters(&self, _parameters: &RTCRtpSendParameters, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new(&self.global(), can_gc); let promise = Promise::new(&self.global(), can_gc);
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
promise promise
} }
} }

View file

@ -248,7 +248,7 @@ impl RegisterJobResultHandler {
); );
// Step 1.4 // Step 1.4
promise.resolve_native(&*registration); promise.resolve_native(&*registration, CanGc::note());
})); }));
// TODO: step 2, handle equivalent jobs. // TODO: step 2, handle equivalent jobs.

View file

@ -181,7 +181,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
promise.reject_error(e); promise.reject_error(e);
return; return;
} }
promise.resolve_native(&*array_buffer_ptr.handle()); promise.resolve_native(&*array_buffer_ptr.handle(), CanGc::note());
}) })
); );
@ -236,7 +236,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
return; return;
} }
promise.resolve_native(&*array_buffer_ptr.handle()); promise.resolve_native(&*array_buffer_ptr.handle(), CanGc::note());
}) })
); );
@ -320,7 +320,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
.expect("failed to create buffer source for exported key."); .expect("failed to create buffer source for exported key.");
// Step 9. Resolve promise with result. // Step 9. Resolve promise with result.
promise.resolve_native(&*array_buffer_ptr); promise.resolve_native(&*array_buffer_ptr, CanGc::note());
})); }));
promise promise
@ -408,7 +408,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
}; };
// Step 9. Resolve promise with result. // Step 9. Resolve promise with result.
promise.resolve_native(&result); promise.resolve_native(&result, CanGc::note());
})); }));
promise promise
@ -473,7 +473,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
// Step 9. Resolve promise with result. // Step 9. Resolve promise with result.
promise.resolve_native(&*array_buffer_ptr); promise.resolve_native(&*array_buffer_ptr, CanGc::note());
}) })
); );
@ -510,7 +510,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let key = normalized_algorithm.generate_key(&subtle, key_usages, extractable); let key = normalized_algorithm.generate_key(&subtle, key_usages, extractable);
match key { match key {
Ok(key) => promise.resolve_native(&key), Ok(key) => promise.resolve_native(&key, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e),
} }
})); }));
@ -641,7 +641,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
} }
// Step 17. Resolve promise with result. // Step 17. Resolve promise with result.
promise.resolve_native(&*result); promise.resolve_native(&*result, CanGc::note());
}), }),
); );
@ -715,7 +715,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
.expect("failed to create buffer source for derived bits."); .expect("failed to create buffer source for derived bits.");
// Step 10. Resolve promise with result. // Step 10. Resolve promise with result.
promise.resolve_native(&*array_buffer_ptr); promise.resolve_native(&*array_buffer_ptr, CanGc::note());
})); }));
promise promise
@ -779,7 +779,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
let imported_key = normalized_algorithm.import_key(&subtle, let imported_key = normalized_algorithm.import_key(&subtle,
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), Ok(k) => promise.resolve_native(&k, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e),
}; };
})); }));
@ -829,10 +829,10 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
create_buffer_source::<ArrayBufferU8>(cx, &k, array_buffer_ptr.handle_mut(), create_buffer_source::<ArrayBufferU8>(cx, &k, array_buffer_ptr.handle_mut(),
CanGc::note()) CanGc::note())
.expect("failed to create buffer source for exported key."); .expect("failed to create buffer source for exported key.");
promise.resolve_native(&array_buffer_ptr.get()) promise.resolve_native(&array_buffer_ptr.get(), CanGc::note())
}, },
AesExportedKey::Jwk(k) => { AesExportedKey::Jwk(k) => {
promise.resolve_native(&k) promise.resolve_native(&k, CanGc::note())
}, },
} }
}, },
@ -958,7 +958,7 @@ impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
}; };
match result { match result {
Ok(_) => promise.resolve_native(&*array_buffer_ptr), Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e),
} }
}), }),
@ -1068,7 +1068,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), Ok(imported_key) => promise.resolve_native(&imported_key, CanGc::note()),
Err(e) => promise.reject_error(e), Err(e) => promise.reject_error(e),
} }
}), }),

View file

@ -980,8 +980,8 @@ impl TestBindingMethods<crate::DomTypeHolder> for TestBinding {
Promise::new_rejected(&self.global(), cx, v, CanGc::note()) Promise::new_rejected(&self.global(), cx, v, CanGc::note())
} }
fn PromiseResolveNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) { fn PromiseResolveNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue, can_gc: CanGc) {
p.resolve(cx, v); p.resolve(cx, v, can_gc);
} }
fn PromiseRejectNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) { fn PromiseRejectNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) {
@ -1163,6 +1163,8 @@ pub(crate) struct TestBindingCallback {
impl TestBindingCallback { impl TestBindingCallback {
#[cfg_attr(crown, allow(crown::unrooted_must_root))] #[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn invoke(self) { pub(crate) fn invoke(self) {
self.promise.root().resolve_native(&self.value); self.promise
.root()
.resolve_native(&self.value, CanGc::note());
} }
} }

View file

@ -203,7 +203,7 @@ impl UnderlyingSourceContainer {
promise promise
} else { } else {
let promise = Promise::new(&self.global(), can_gc); let promise = Promise::new(&self.global(), can_gc);
promise.resolve_native(&result.get()); promise.resolve_native(&result.get(), can_gc);
promise promise
}; };
return Some(Ok(promise)); return Some(Ok(promise));

View file

@ -4691,7 +4691,7 @@ impl WebGL2RenderingContextMethods<crate::DomTypeHolder> for WebGL2RenderingCont
fn MakeXRCompatible(&self, can_gc: CanGc) -> Rc<Promise> { fn MakeXRCompatible(&self, can_gc: CanGc) -> Rc<Promise> {
// XXXManishearth Fill in with compatibility checks when rust-webxr supports this // XXXManishearth Fill in with compatibility checks when rust-webxr supports this
let p = Promise::new(&self.global(), can_gc); let p = Promise::new(&self.global(), can_gc);
p.resolve_native(&()); p.resolve_native(&(), can_gc);
p p
} }
} }

View file

@ -4818,7 +4818,7 @@ impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContex
fn MakeXRCompatible(&self, can_gc: CanGc) -> Rc<Promise> { fn MakeXRCompatible(&self, can_gc: CanGc) -> Rc<Promise> {
// XXXManishearth Fill in with compatibility checks when rust-webxr supports this // XXXManishearth Fill in with compatibility checks when rust-webxr supports this
let p = Promise::new(&self.global(), can_gc); let p = Promise::new(&self.global(), can_gc);
p.resolve_native(&()); p.resolve_native(&(), can_gc);
p p
} }
} }

View file

@ -168,15 +168,15 @@ impl AsyncWGPUListener for GPU {
adapter.adapter_id, adapter.adapter_id,
can_gc, can_gc,
); );
promise.resolve_native(&adapter); promise.resolve_native(&adapter, can_gc);
}, },
WebGPUResponse::Adapter(Err(e)) => { WebGPUResponse::Adapter(Err(e)) => {
warn!("Could not get GPUAdapter ({:?})", e); warn!("Could not get GPUAdapter ({:?})", e);
promise.resolve_native(&None::<GPUAdapter>); promise.resolve_native(&None::<GPUAdapter>, can_gc);
}, },
WebGPUResponse::None => { WebGPUResponse::None => {
warn!("Couldn't get a response, because WebGPU is disabled"); warn!("Couldn't get a response, because WebGPU is disabled");
promise.resolve_native(&None::<GPUAdapter>); promise.resolve_native(&None::<GPUAdapter>, can_gc);
}, },
_ => unreachable!("GPU received wrong WebGPUResponse"), _ => unreachable!("GPU received wrong WebGPUResponse"),
} }

View file

@ -189,7 +189,7 @@ impl GPUAdapterMethods<crate::DomTypeHolder> for GPUAdapter {
if !unmask_hints.is_empty() { if !unmask_hints.is_empty() {
todo!("unmaskHints on RequestAdapterInfo"); todo!("unmaskHints on RequestAdapterInfo");
} }
promise.resolve_native(&*self.info); promise.resolve_native(&*self.info, can_gc);
// Step 5 // Step 5
promise promise
} }
@ -222,7 +222,7 @@ impl AsyncWGPUListener for GPUAdapter {
can_gc, can_gc,
); );
self.global().add_gpu_device(&device); self.global().add_gpu_device(&device);
promise.resolve_native(&device); 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(Error::Type(
@ -246,7 +246,7 @@ impl AsyncWGPUListener for GPUAdapter {
can_gc, can_gc,
); );
device.lose(GPUDeviceLostReason::Unknown, e.to_string(), can_gc); device.lose(GPUDeviceLostReason::Unknown, e.to_string(), can_gc);
promise.resolve_native(&device); promise.resolve_native(&device, can_gc);
}, },
WebGPUResponse::None => unreachable!("Failed to get a response for RequestDevice"), WebGPUResponse::None => unreachable!("Failed to get a response for RequestDevice"),
_ => unreachable!("GPUAdapter received wrong WebGPUResponse"), _ => unreachable!("GPUAdapter received wrong WebGPUResponse"),

View file

@ -380,7 +380,7 @@ impl GPUBuffer {
} }
} }
fn map_success(&self, p: &Rc<Promise>, wgpu_mapping: Mapping) { fn map_success(&self, p: &Rc<Promise>, wgpu_mapping: Mapping, 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
@ -413,7 +413,7 @@ impl GPUBuffer {
self.mapping.borrow_mut().replace(mapping); self.mapping.borrow_mut().replace(mapping);
// Step 7 // Step 7
pending_map.take(); pending_map.take();
p.resolve_native(&()); p.resolve_native(&(), can_gc);
}, },
} }
} }
@ -421,9 +421,11 @@ impl GPUBuffer {
impl AsyncWGPUListener for GPUBuffer { impl AsyncWGPUListener for GPUBuffer {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, _can_gc: CanGc) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, can_gc: CanGc) {
match response { match response {
WebGPUResponse::BufferMapAsync(Ok(mapping)) => self.map_success(promise, mapping), WebGPUResponse::BufferMapAsync(Ok(mapping)) => {
self.map_success(promise, mapping, can_gc)
},
WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise), WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise),
_ => unreachable!("Wrong response received on AsyncWGPUListener for GPUBuffer"), _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUBuffer"),
} }

View file

@ -373,7 +373,7 @@ impl GPUDevice {
let lost_promise = &(*self.lost_promise.borrow()); let lost_promise = &(*self.lost_promise.borrow());
let global = &self.global(); let global = &self.global();
let lost = GPUDeviceLostInfo::new(global, msg.into(), reason, can_gc); let lost = GPUDeviceLostInfo::new(global, msg.into(), reason, can_gc);
lost_promise.resolve_native(&*lost); lost_promise.resolve_native(&*lost, can_gc);
} }
} }
@ -585,21 +585,26 @@ impl AsyncWGPUListener for GPUDevice {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, can_gc: CanGc) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, can_gc: CanGc) {
match response { match response {
WebGPUResponse::PoppedErrorScope(result) => match result { WebGPUResponse::PoppedErrorScope(result) => match result {
Ok(None) | Err(PopError::Lost) => promise.resolve_native(&None::<Option<GPUError>>), Ok(None) | Err(PopError::Lost) => {
promise.resolve_native(&None::<Option<GPUError>>, can_gc)
},
Err(PopError::Empty) => promise.reject_error(Error::Operation), Err(PopError::Empty) => promise.reject_error(Error::Operation),
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); promise.resolve_native(&error, can_gc);
}, },
}, },
WebGPUResponse::ComputePipeline(result) => match result { WebGPUResponse::ComputePipeline(result) => match result {
Ok(pipeline) => promise.resolve_native(&GPUComputePipeline::new( Ok(pipeline) => promise.resolve_native(
&self.global(), &GPUComputePipeline::new(
WebGPUComputePipeline(pipeline.id), &self.global(),
pipeline.label.into(), WebGPUComputePipeline(pipeline.id),
self, pipeline.label.into(),
self,
can_gc,
),
can_gc, can_gc,
)), ),
Err(webgpu::Error::Validation(msg)) => { Err(webgpu::Error::Validation(msg)) => {
promise.reject_native(&GPUPipelineError::new( promise.reject_native(&GPUPipelineError::new(
&self.global(), &self.global(),
@ -617,13 +622,16 @@ impl AsyncWGPUListener for GPUDevice {
)), )),
}, },
WebGPUResponse::RenderPipeline(result) => match result { WebGPUResponse::RenderPipeline(result) => match result {
Ok(pipeline) => promise.resolve_native(&GPURenderPipeline::new( Ok(pipeline) => promise.resolve_native(
&self.global(), &GPURenderPipeline::new(
WebGPURenderPipeline(pipeline.id), &self.global(),
pipeline.label.into(), WebGPURenderPipeline(pipeline.id),
self, pipeline.label.into(),
self,
can_gc,
),
can_gc, can_gc,
)), ),
Err(webgpu::Error::Validation(msg)) => { Err(webgpu::Error::Validation(msg)) => {
promise.reject_native(&GPUPipelineError::new( promise.reject_native(&GPUPipelineError::new(
&self.global(), &self.global(),

View file

@ -220,11 +220,11 @@ impl AsyncWGPUListener for GPUQueue {
&self, &self,
response: webgpu::WebGPUResponse, response: webgpu::WebGPUResponse,
promise: &Rc<Promise>, promise: &Rc<Promise>,
_can_gc: CanGc, can_gc: CanGc,
) { ) {
match response { match response {
WebGPUResponse::SubmittedWorkDone => { WebGPUResponse::SubmittedWorkDone => {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
}, },
_ => { _ => {
warn!("GPUQueue received wrong WebGPUResponse"); warn!("GPUQueue received wrong WebGPUResponse");

View file

@ -134,7 +134,7 @@ impl AsyncWGPUListener for GPUShaderModule {
match response { match response {
WebGPUResponse::CompilationInfo(info) => { WebGPUResponse::CompilationInfo(info) => {
let info = GPUCompilationInfo::from(&self.global(), info, can_gc); let info = GPUCompilationInfo::from(&self.global(), info, can_gc);
promise.resolve_native(&info); promise.resolve_native(&info, can_gc);
}, },
_ => unreachable!("Wrong response received on AsyncWGPUListener for GPUShaderModule"), _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUShaderModule"),
} }

View file

@ -214,7 +214,7 @@ impl XRSession {
let time = CrossProcessInstant::now(); let time = CrossProcessInstant::now();
let this = this.clone(); let this = this.clone();
task_source.queue(task!(xr_raf_callback: move || { task_source.queue(task!(xr_raf_callback: move || {
this.root().raf_callback(frame, time); this.root().raf_callback(frame, time, CanGc::note());
})); }));
}), }),
); );
@ -286,7 +286,7 @@ impl XRSession {
// Step 6 is happening n the XR session // Step 6 is happening n the XR session
// https://immersive-web.github.io/webxr/#dom-xrsession-end step 3 // https://immersive-web.github.io/webxr/#dom-xrsession-end step 3
for promise in self.end_promises.borrow_mut().drain(..) { for promise in self.end_promises.borrow_mut().drain(..) {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
} }
// Step 7 // Step 7
let event = let event =
@ -410,7 +410,7 @@ impl XRSession {
} }
/// <https://immersive-web.github.io/webxr/#xr-animation-frame> /// <https://immersive-web.github.io/webxr/#xr-animation-frame>
fn raf_callback(&self, mut frame: Frame, time: CrossProcessInstant) { fn raf_callback(&self, mut frame: Frame, time: CrossProcessInstant, can_gc: CanGc) {
debug!("WebXR RAF callback {:?}", frame); debug!("WebXR RAF callback {:?}", frame);
// Step 1-2 happen in the xebxr device thread // Step 1-2 happen in the xebxr device thread
@ -430,7 +430,7 @@ impl XRSession {
// TODO: how does this fit the webxr spec? // TODO: how does this fit the webxr spec?
for event in frame.events.drain(..) { for event in frame.events.drain(..) {
self.handle_frame_event(event); self.handle_frame_event(event, can_gc);
} }
// Step 4 // Step 4
@ -575,16 +575,14 @@ impl XRSession {
} }
} }
fn handle_frame_event(&self, event: FrameUpdateEvent) { fn handle_frame_event(&self, event: FrameUpdateEvent, can_gc: CanGc) {
match event { match event {
FrameUpdateEvent::HitTestSourceAdded(id) => { FrameUpdateEvent::HitTestSourceAdded(id) => {
if let Some(promise) = self.pending_hit_test_promises.borrow_mut().remove(&id) { if let Some(promise) = self.pending_hit_test_promises.borrow_mut().remove(&id) {
promise.resolve_native(&XRHitTestSource::new( promise.resolve_native(
&self.global(), &XRHitTestSource::new(&self.global(), id, self, can_gc),
id, can_gc,
self, );
CanGc::note(),
));
} else { } else {
warn!( warn!(
"received hit test add request for unknown hit test {:?}", "received hit test add request for unknown hit test {:?}",
@ -868,13 +866,13 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
self.reference_spaces self.reference_spaces
.borrow_mut() .borrow_mut()
.push(Dom::from_ref(space.reference_space())); .push(Dom::from_ref(space.reference_space()));
p.resolve_native(&space); p.resolve_native(&space, can_gc);
} else { } else {
let space = XRReferenceSpace::new(&self.global(), self, ty, can_gc); let space = XRReferenceSpace::new(&self.global(), self, ty, can_gc);
self.reference_spaces self.reference_spaces
.borrow_mut() .borrow_mut()
.push(Dom::from_ref(&*space)); .push(Dom::from_ref(&*space));
p.resolve_native(&space); p.resolve_native(&space, can_gc);
} }
}, },
} }
@ -900,7 +898,7 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
// //
// However, if end_promises is empty, then all end() promises have already resolved, // However, if end_promises is empty, then all end() promises have already resolved,
// so the session has completely shut down and we should not queue up more promises // so the session has completely shut down and we should not queue up more promises
p.resolve_native(&()); p.resolve_native(&(), can_gc);
return p; return p;
} }
self.end_promises.borrow_mut().push(p.clone()); self.end_promises.borrow_mut().push(p.clone());
@ -1065,7 +1063,7 @@ impl XRSessionMethods<crate::DomTypeHolder> for XRSession {
let session = this.root(); let session = this.root();
session.apply_nominal_framerate(message.unwrap(), CanGc::note()); session.apply_nominal_framerate(message.unwrap(), CanGc::note());
if let Some(promise) = session.update_framerate_promise.borrow_mut().take() { if let Some(promise) = session.update_framerate_promise.borrow_mut().take() {
promise.resolve_native(&()); promise.resolve_native(&(), CanGc::note());
}; };
})); }));
}), }),

View file

@ -258,7 +258,7 @@ impl XRSystemMethods<crate::DomTypeHolder> for XRSystem {
return; return;
}; };
task_source.queue(task!(request_session: move || { task_source.queue(task!(request_session: move || {
this.root().session_obtained(message, trusted.root(), mode, frame_receiver); this.root().session_obtained(message, trusted.root(), mode, frame_receiver, CanGc::note());
})); }));
}), }),
); );
@ -282,6 +282,7 @@ impl XRSystem {
promise: Rc<Promise>, promise: Rc<Promise>,
mode: XRSessionMode, mode: XRSessionMode,
frame_receiver: IpcReceiver<Frame>, frame_receiver: IpcReceiver<Frame>,
can_gc: CanGc,
) { ) {
let session = match response { let session = match response {
Ok(session) => session, Ok(session) => session,
@ -302,7 +303,7 @@ impl XRSystem {
} else { } else {
self.set_active_immersive_session(&session); self.set_active_immersive_session(&session);
} }
promise.resolve_native(&session); promise.resolve_native(&session, can_gc);
// https://github.com/immersive-web/webxr/issues/961 // https://github.com/immersive-web/webxr/issues/961
// This must be called _after_ the promise is resolved // This must be called _after_ the promise is resolved
session.setup_initial_inputs(); session.setup_initial_inputs();

View file

@ -51,6 +51,7 @@ impl XRTest {
&self, &self,
response: Result<IpcSender<MockDeviceMsg>, XRError>, response: Result<IpcSender<MockDeviceMsg>, XRError>,
trusted: TrustedPromise, trusted: TrustedPromise,
can_gc: CanGc,
) { ) {
let promise = trusted.root(); let promise = trusted.root();
if let Ok(sender) = response { if let Ok(sender) = response {
@ -58,7 +59,7 @@ impl XRTest {
self.devices_connected self.devices_connected
.borrow_mut() .borrow_mut()
.push(Dom::from_ref(&device)); .push(Dom::from_ref(&device));
promise.resolve_native(&device); promise.resolve_native(&device, can_gc);
} else { } else {
promise.reject_native(&()); promise.reject_native(&());
} }
@ -167,7 +168,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
message.expect("SimulateDeviceConnection callback given incorrect payload"); message.expect("SimulateDeviceConnection callback given incorrect payload");
task_source.queue(task!(request_session: move || { task_source.queue(task!(request_session: move || {
this.root().device_obtained(message, trusted); this.root().device_obtained(message, trusted, CanGc::note());
})); }));
}), }),
); );
@ -193,7 +194,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
let p = Promise::new(&global, can_gc); let p = Promise::new(&global, can_gc);
let mut devices = self.devices_connected.borrow_mut(); let mut devices = self.devices_connected.borrow_mut();
if devices.is_empty() { if devices.is_empty() {
p.resolve_native(&()); p.resolve_native(&(), can_gc);
} else { } else {
let mut len = devices.len(); let mut len = devices.len();

View file

@ -2058,7 +2058,7 @@ impl Window {
// a "rendering opportunity" in `ScriptThread::handle_web_font_loaded, which should also // a "rendering opportunity" in `ScriptThread::handle_web_font_loaded, which should also
// make sure a microtask checkpoint happens, triggering the promise callback. // make sure a microtask checkpoint happens, triggering the promise callback.
if !waiting_for_web_fonts_to_load && is_ready_state_complete { if !waiting_for_web_fonts_to_load && is_ready_state_complete {
font_face_set.fulfill_ready_promise_if_needed(); font_face_set.fulfill_ready_promise_if_needed(can_gc);
} }
// If writing a screenshot, check if the script has reached a state // If writing a screenshot, check if the script has reached a state

View file

@ -47,9 +47,9 @@ struct AbortAlgorithmFulfillmentHandler {
} }
impl Callback for AbortAlgorithmFulfillmentHandler { impl Callback for AbortAlgorithmFulfillmentHandler {
fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
// Resolve abortRequests promise with undefined. // Resolve abortRequests promise with undefined.
self.abort_request_promise.resolve_native(&()); self.abort_request_promise.resolve_native(&(), can_gc);
// Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream). // Perform ! WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
self.stream self.stream
@ -366,14 +366,14 @@ impl WritableStream {
} }
/// <https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-write> /// <https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-write>
pub(crate) fn finish_in_flight_write(&self) { pub(crate) fn finish_in_flight_write(&self, can_gc: CanGc) {
let Some(in_flight_write_request) = self.in_flight_write_request.borrow_mut().take() else { let Some(in_flight_write_request) = self.in_flight_write_request.borrow_mut().take() else {
// Assert: stream.[[inFlightWriteRequest]] is not undefined. // Assert: stream.[[inFlightWriteRequest]] is not undefined.
unreachable!("Stream should have a write request"); unreachable!("Stream should have a write request");
}; };
// Resolve stream.[[inFlightWriteRequest]] with undefined. // Resolve stream.[[inFlightWriteRequest]] with undefined.
in_flight_write_request.resolve_native(&()); in_flight_write_request.resolve_native(&(), can_gc);
// Set stream.[[inFlightWriteRequest]] to undefined. // Set stream.[[inFlightWriteRequest]] to undefined.
// Done above with `take`. // Done above with `take`.
@ -483,14 +483,14 @@ impl WritableStream {
} }
/// <https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-close> /// <https://streams.spec.whatwg.org/#writable-stream-finish-in-flight-close>
pub(crate) fn finish_in_flight_close(&self, cx: SafeJSContext) { pub(crate) fn finish_in_flight_close(&self, cx: SafeJSContext, can_gc: CanGc) {
let Some(in_flight_close_request) = self.in_flight_close_request.borrow_mut().take() else { let Some(in_flight_close_request) = self.in_flight_close_request.borrow_mut().take() else {
// Assert: stream.[[inFlightCloseRequest]] is not undefined. // Assert: stream.[[inFlightCloseRequest]] is not undefined.
unreachable!("in_flight_close_request must be Some"); unreachable!("in_flight_close_request must be Some");
}; };
// Resolve stream.[[inFlightCloseRequest]] with undefined. // Resolve stream.[[inFlightCloseRequest]] with undefined.
in_flight_close_request.resolve_native(&()); in_flight_close_request.resolve_native(&(), can_gc);
// Set stream.[[inFlightCloseRequest]] to undefined. // Set stream.[[inFlightCloseRequest]] to undefined.
// Done with take above. // Done with take above.
@ -507,7 +507,7 @@ impl WritableStream {
rooted!(in(*cx) let pending_abort_request = self.pending_abort_request.borrow_mut().take()); rooted!(in(*cx) let pending_abort_request = self.pending_abort_request.borrow_mut().take());
if let Some(pending_abort_request) = &*pending_abort_request { if let Some(pending_abort_request) = &*pending_abort_request {
// Resolve stream.[[pendingAbortRequest]]'s promise with undefined. // Resolve stream.[[pendingAbortRequest]]'s promise with undefined.
pending_abort_request.promise.resolve_native(&()); pending_abort_request.promise.resolve_native(&(), can_gc);
// Set stream.[[pendingAbortRequest]] to undefined. // Set stream.[[pendingAbortRequest]] to undefined.
// Done above with `take`. // Done above with `take`.
@ -521,7 +521,7 @@ impl WritableStream {
if let Some(writer) = self.writer.get() { if let Some(writer) = self.writer.get() {
// If writer is not undefined, // If writer is not undefined,
// resolve writer.[[closedPromise]] with undefined. // resolve writer.[[closedPromise]] with undefined.
writer.resolve_closed_promise_with_undefined(); writer.resolve_closed_promise_with_undefined(can_gc);
} }
// Assert: stream.[[pendingAbortRequest]] is undefined. // Assert: stream.[[pendingAbortRequest]] is undefined.
@ -747,7 +747,7 @@ impl WritableStream {
// and state is "writable", // and state is "writable",
if self.get_backpressure() && self.is_writable() { if self.get_backpressure() && self.is_writable() {
// resolve writer.[[readyPromise]] with undefined. // resolve writer.[[readyPromise]] with undefined.
writer.resolve_ready_promise_with_undefined(); writer.resolve_ready_promise_with_undefined(can_gc);
} }
} }
@ -795,7 +795,7 @@ impl WritableStream {
let writer = WritableStreamDefaultWriter::new(global, None, can_gc); let writer = WritableStreamDefaultWriter::new(global, None, can_gc);
// Perform ? SetUpWritableStreamDefaultWriter(writer, stream). // Perform ? SetUpWritableStreamDefaultWriter(writer, stream).
writer.setup(cx, self)?; writer.setup(cx, self, can_gc)?;
// Return writer. // Return writer.
Ok(writer) Ok(writer)
@ -829,7 +829,7 @@ impl WritableStream {
// Assert: backpressure is false. // Assert: backpressure is false.
assert!(!backpressure); assert!(!backpressure);
// Resolve writer.[[readyPromise]] with undefined. // Resolve writer.[[readyPromise]] with undefined.
writer.resolve_ready_promise_with_undefined(); writer.resolve_ready_promise_with_undefined(can_gc);
} }
}; };

View file

@ -40,11 +40,11 @@ struct CloseAlgorithmFulfillmentHandler {
} }
impl Callback for CloseAlgorithmFulfillmentHandler { impl Callback for CloseAlgorithmFulfillmentHandler {
fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, _can_gc: CanGc) { fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
let stream = self.stream.as_rooted(); let stream = self.stream.as_rooted();
// Perform ! WritableStreamFinishInFlightClose(stream). // Perform ! WritableStreamFinishInFlightClose(stream).
stream.finish_in_flight_close(cx); stream.finish_in_flight_close(cx, can_gc);
} }
} }
@ -154,7 +154,7 @@ impl Callback for WriteAlgorithmFulfillmentHandler {
.expect("Controller should have a stream."); .expect("Controller should have a stream.");
// Perform ! WritableStreamFinishInFlightWrite(stream). // Perform ! WritableStreamFinishInFlightWrite(stream).
stream.finish_in_flight_write(); stream.finish_in_flight_write(can_gc);
// Let state be stream.[[state]]. // Let state be stream.[[state]].
// Assert: state is "writable" or "erroring". // Assert: state is "writable" or "erroring".

View file

@ -63,7 +63,12 @@ impl WritableStreamDefaultWriter {
/// <https://streams.spec.whatwg.org/#set-up-writable-stream-default-writer> /// <https://streams.spec.whatwg.org/#set-up-writable-stream-default-writer>
/// Continuing from `new_inherited`, the rest. /// Continuing from `new_inherited`, the rest.
pub(crate) fn setup(&self, cx: SafeJSContext, stream: &WritableStream) -> Result<(), Error> { pub(crate) fn setup(
&self,
cx: SafeJSContext,
stream: &WritableStream,
can_gc: CanGc,
) -> Result<(), Error> {
// If ! IsWritableStreamLocked(stream) is true, throw a TypeError exception. // If ! IsWritableStreamLocked(stream) is true, throw a TypeError exception.
if stream.is_locked() { if stream.is_locked() {
return Err(Error::Type("Stream is locked".to_string())); return Err(Error::Type("Stream is locked".to_string()));
@ -87,7 +92,7 @@ impl WritableStreamDefaultWriter {
} else { } else {
// Otherwise, set writer.[[readyPromise]] to a promise resolved with undefined. // Otherwise, set writer.[[readyPromise]] to a promise resolved with undefined.
// Note: new promise created in `new_inherited`. // Note: new promise created in `new_inherited`.
self.ready_promise.borrow().resolve_native(&()); self.ready_promise.borrow().resolve_native(&(), can_gc);
} }
// Set writer.[[closedPromise]] to a new promise. // Set writer.[[closedPromise]] to a new promise.
@ -116,11 +121,11 @@ impl WritableStreamDefaultWriter {
if stream.is_closed() { if stream.is_closed() {
// Set writer.[[readyPromise]] to a promise resolved with undefined. // Set writer.[[readyPromise]] to a promise resolved with undefined.
// Note: new promise created in `new_inherited`. // Note: new promise created in `new_inherited`.
self.ready_promise.borrow().resolve_native(&()); self.ready_promise.borrow().resolve_native(&(), can_gc);
// Set writer.[[closedPromise]] to a promise resolved with undefined. // Set writer.[[closedPromise]] to a promise resolved with undefined.
// Note: new promise created in `new_inherited`. // Note: new promise created in `new_inherited`.
self.closed_promise.borrow().resolve_native(&()); self.closed_promise.borrow().resolve_native(&(), can_gc);
return Ok(()); return Ok(());
} }
@ -161,12 +166,12 @@ impl WritableStreamDefaultWriter {
*self.ready_promise.borrow_mut() = promise; *self.ready_promise.borrow_mut() = promise;
} }
pub(crate) fn resolve_ready_promise_with_undefined(&self) { pub(crate) fn resolve_ready_promise_with_undefined(&self, can_gc: CanGc) {
self.ready_promise.borrow().resolve_native(&()); self.ready_promise.borrow().resolve_native(&(), can_gc);
} }
pub(crate) fn resolve_closed_promise_with_undefined(&self) { pub(crate) fn resolve_closed_promise_with_undefined(&self, can_gc: CanGc) {
self.closed_promise.borrow().resolve_native(&()); self.closed_promise.borrow().resolve_native(&(), can_gc);
} }
/// <https://streams.spec.whatwg.org/#writable-stream-default-writer-ensure-ready-promise-rejected> /// <https://streams.spec.whatwg.org/#writable-stream-default-writer-ensure-ready-promise-rejected>
@ -493,7 +498,7 @@ impl WritableStreamDefaultWriterMethods<crate::DomTypeHolder> for WritableStream
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
// Perform ? SetUpWritableStreamDefaultWriter(this, stream). // Perform ? SetUpWritableStreamDefaultWriter(this, stream).
writer.setup(cx, stream)?; writer.setup(cx, stream, can_gc)?;
Ok(writer) Ok(writer)
} }

View file

@ -266,7 +266,7 @@ impl FetchResponseListener for FetchContext {
} }
// Step 4.3 // Step 4.3
promise.resolve_native(&self.response_object.root()); promise.resolve_native(&self.response_object.root(), CanGc::note());
self.fetch_promise = Some(TrustedPromise::new(promise)); self.fetch_promise = Some(TrustedPromise::new(promise));
} }
@ -282,7 +282,7 @@ impl FetchResponseListener for FetchContext {
) { ) {
let response = self.response_object.root(); let response = self.response_object.root();
let _ac = enter_realm(&*response); let _ac = enter_realm(&*response);
response.finish(); response.finish(CanGc::note());
// TODO // TODO
// ... trailerObject is not supported in Servo yet. // ... trailerObject is not supported in Servo yet.
} }

View file

@ -776,7 +776,7 @@ impl ModuleTree {
// Step 3. // Step 3.
Ok(valid_specifier_urls) if valid_specifier_urls.is_empty() => { Ok(valid_specifier_urls) if valid_specifier_urls.is_empty() => {
debug!("Module {} doesn't have any dependencies.", self.url); debug!("Module {} doesn't have any dependencies.", self.url);
self.advance_finished_and_link(&global); self.advance_finished_and_link(&global, can_gc);
}, },
Ok(valid_specifier_urls) => { Ok(valid_specifier_urls) => {
self.descendant_urls self.descendant_urls
@ -807,7 +807,7 @@ impl ModuleTree {
"After checking with visited urls, module {} doesn't have dependencies to load.", "After checking with visited urls, module {} doesn't have dependencies to load.",
&self.url &self.url
); );
self.advance_finished_and_link(&global); self.advance_finished_and_link(&global, can_gc);
return; return;
} }
@ -837,14 +837,14 @@ impl ModuleTree {
}, },
Err(error) => { Err(error) => {
self.set_rethrow_error(error); self.set_rethrow_error(error);
self.advance_finished_and_link(&global); self.advance_finished_and_link(&global, can_gc);
}, },
} }
} }
/// <https://html.spec.whatwg.org/multipage/#fetch-the-descendants-of-and-link-a-module-script> /// <https://html.spec.whatwg.org/multipage/#fetch-the-descendants-of-and-link-a-module-script>
/// step 4-7. /// step 4-7.
fn advance_finished_and_link(&self, global: &GlobalScope) { fn advance_finished_and_link(&self, global: &GlobalScope, can_gc: CanGc) {
{ {
if !self.has_all_ready_descendants(global) { if !self.has_all_ready_descendants(global) {
return; return;
@ -871,7 +871,7 @@ impl ModuleTree {
if incomplete_count_before_remove > 0 { if incomplete_count_before_remove > 0 {
parent_tree.remove_incomplete_fetch_url(&self.url); parent_tree.remove_incomplete_fetch_url(&self.url);
parent_tree.advance_finished_and_link(global); parent_tree.advance_finished_and_link(global, can_gc);
} }
} }
} }
@ -901,7 +901,7 @@ impl ModuleTree {
let promise = self.promise.borrow(); let promise = self.promise.borrow();
if let Some(promise) = promise.as_ref() { if let Some(promise) = promise.as_ref() {
promise.resolve_native(&()); promise.resolve_native(&(), can_gc);
} }
} }
} }
@ -1221,7 +1221,7 @@ impl FetchResponseListener for ModuleContext {
Err(err) => { Err(err) => {
error!("Failed to fetch {} with error {:?}", &self.url, err); error!("Failed to fetch {} with error {:?}", &self.url, err);
module_tree.set_network_error(err); module_tree.set_network_error(err);
module_tree.advance_finished_and_link(&global); module_tree.advance_finished_and_link(&global, CanGc::note());
}, },
Ok(ref resp_mod_script) => { Ok(ref resp_mod_script) => {
module_tree.set_text(resp_mod_script.text()); module_tree.set_text(resp_mod_script.text());
@ -1242,7 +1242,7 @@ impl FetchResponseListener for ModuleContext {
match compiled_module_result { match compiled_module_result {
Err(exception) => { Err(exception) => {
module_tree.set_rethrow_error(exception); module_tree.set_rethrow_error(exception);
module_tree.advance_finished_and_link(&global); module_tree.advance_finished_and_link(&global, CanGc::note());
}, },
Ok(_) => { Ok(_) => {
module_tree.set_record(ModuleObject::new(compiled_module.handle())); module_tree.set_record(ModuleObject::new(compiled_module.handle()));
@ -1691,7 +1691,7 @@ fn fetch_single_module_script(
ModuleStatus::Fetching => {}, ModuleStatus::Fetching => {},
// Step 3. // Step 3.
ModuleStatus::FetchingDescendants | ModuleStatus::Finished => { ModuleStatus::FetchingDescendants | ModuleStatus::Finished => {
module_tree.advance_finished_and_link(&global); module_tree.advance_finished_and_link(&global, can_gc);
}, },
} }

View file

@ -92,7 +92,7 @@ DOMInterfaces = {
'CustomElementRegistry': { 'CustomElementRegistry': {
'inRealms': ['WhenDefined'], 'inRealms': ['WhenDefined'],
'canGc': ['WhenDefined'], 'canGc': ['Define', 'WhenDefined'],
}, },
'DataTransfer': { 'DataTransfer': {
@ -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'], 'canGc': ['InterfaceAttribute', 'GetInterfaceAttributeNullable', 'ReceiveInterface', 'ReceiveInterfaceSequence', 'ReceiveNullableInterface', 'PromiseAttribute', 'PromiseNativeHandler', 'PromiseResolveNative'],
}, },
'TestWorklet': { 'TestWorklet': {
@ -593,7 +593,7 @@ DOMInterfaces = {
}, },
"ReadableStreamDefaultController": { "ReadableStreamDefaultController": {
"canGc": ["Enqueue"] "canGc": ["Close", "Enqueue"]
}, },
"ReadableStreamBYOBReader": { "ReadableStreamBYOBReader": {