Mark promise creation methods with CanGc (#33928)

* Add CanGc annotations to promise constructor.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

* Propagate CanGc arguments for Promise::new_in_current_realm.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

* Fix out-of-order entries.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

* Propagate CanGc from Promise::new.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

* Suppress clippy warning.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

* Formatting.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2024-10-22 05:35:20 -04:00 committed by GitHub
parent edc304854f
commit 575e885529
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 422 additions and 221 deletions

View file

@ -264,7 +264,7 @@ impl TransmitBodyConnectHandler {
let realm = enter_realm(&*global); let realm = enter_realm(&*global);
let comp = InRealm::Entered(&realm); let comp = InRealm::Entered(&realm);
promise.append_native_handler(&handler, comp); promise.append_native_handler(&handler, comp, CanGc::note());
}), }),
&self.canceller, &self.canceller,
); );
@ -708,7 +708,7 @@ impl Callback for ConsumeBodyPromiseHandler {
let realm = enter_realm(&*global); let realm = enter_realm(&*global);
let comp = InRealm::Entered(&realm); let comp = InRealm::Entered(&realm);
read_promise.append_native_handler(&handler, comp); read_promise.append_native_handler(&handler, comp, CanGc::note());
} }
} }
} }
@ -721,7 +721,7 @@ pub fn consume_body<T: BodyMixin + DomObject>(
can_gc: CanGc, can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
// Step 1 // Step 1
if object.is_disturbed() || object.is_locked() { if object.is_disturbed() || object.is_locked() {
@ -792,7 +792,7 @@ fn consume_body_with_promise<T: BodyMixin + DomObject>(
Some(rejection_handler), Some(rejection_handler),
); );
// We are already in a realm and a script. // We are already in a realm and a script.
read_promise.append_native_handler(&handler, comp); read_promise.append_native_handler(&handler, comp, can_gc);
} }
// https://fetch.spec.whatwg.org/#concept-body-package-data // https://fetch.spec.whatwg.org/#concept-body-package-data

View file

@ -140,9 +140,9 @@ impl AudioContextMethods for AudioContext {
} }
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend // https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend
fn Suspend(&self, comp: InRealm) -> Rc<Promise> { fn Suspend(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 2. // Step 2.
if self.context.control_thread_state() == ProcessingState::Closed { if self.context.control_thread_state() == ProcessingState::Closed {
@ -201,9 +201,9 @@ impl AudioContextMethods for AudioContext {
} }
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-close // https://webaudio.github.io/web-audio-api/#dom-audiocontext-close
fn Close(&self, comp: InRealm) -> Rc<Promise> { fn Close(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 2. // Step 2.
if self.context.control_thread_state() == ProcessingState::Closed { if self.context.control_thread_state() == ProcessingState::Closed {

View file

@ -294,9 +294,9 @@ impl BaseAudioContextMethods for BaseAudioContext {
} }
/// <https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-resume> /// <https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-resume>
fn Resume(&self, comp: InRealm) -> Rc<Promise> { fn Resume(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 2. // Step 2.
if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed { if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed {
@ -480,9 +480,10 @@ impl BaseAudioContextMethods for BaseAudioContext {
decode_success_callback: Option<Rc<DecodeSuccessCallback>>, decode_success_callback: Option<Rc<DecodeSuccessCallback>>,
decode_error_callback: Option<Rc<DecodeErrorCallback>>, decode_error_callback: Option<Rc<DecodeErrorCallback>>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let global = self.global(); let global = self.global();
let window = global.as_window(); let window = global.as_window();

View file

@ -20,41 +20,46 @@ DOMInterfaces = {
'AudioContext': { 'AudioContext': {
'inRealms': ['Close', 'Suspend'], 'inRealms': ['Close', 'Suspend'],
'canGc':['CreateMediaStreamDestination', 'CreateMediaElementSource', 'CreateMediaStreamSource', 'CreateMediaStreamTrackSource'], 'canGc':['CreateMediaStreamDestination', 'CreateMediaElementSource', 'CreateMediaStreamSource', 'CreateMediaStreamTrackSource', 'Suspend', 'Close'],
}, },
'BaseAudioContext': { 'BaseAudioContext': {
'inRealms': ['DecodeAudioData', 'Resume', 'ParseFromString', 'GetBounds', 'GetClientRects'], 'inRealms': ['DecodeAudioData', 'Resume', 'ParseFromString', 'GetBounds', 'GetClientRects'],
'canGc': ['CreateChannelMerger', 'CreateOscillator', 'CreateStereoPanner', 'CreateGain', 'CreateIIRFilter', 'CreateBiquadFilter', 'CreateBufferSource', 'CreateAnalyser', 'CreatePanner', 'CreateChannelSplitter', 'CreateBuffer', 'CreateConstantSource'], 'canGc': ['CreateChannelMerger', 'CreateOscillator', 'CreateStereoPanner', 'CreateGain', 'CreateIIRFilter', 'CreateBiquadFilter', 'CreateBufferSource', 'CreateAnalyser', 'CreatePanner', 'CreateChannelSplitter', 'CreateBuffer', 'CreateConstantSource', 'Resume', 'DecodeAudioData'],
}, },
'Blob': { 'Blob': {
'weakReferenceable': True, 'weakReferenceable': True,
'canGc': ['Slice'], 'canGc': ['Slice', 'Text', 'ArrayBuffer'],
}, },
'Bluetooth': { 'Bluetooth': {
'inRealms': ['GetAvailability', 'RequestDevice'], 'inRealms': ['GetAvailability', 'RequestDevice'],
'canGc': ['RequestDevice', 'GetAvailability'],
}, },
'BluetoothDevice': { 'BluetoothDevice': {
'inRealms': ['WatchAdvertisements'], 'inRealms': ['WatchAdvertisements'],
'canGc': ['WatchAdvertisements'],
}, },
'BluetoothRemoteGATTCharacteristic': { 'BluetoothRemoteGATTCharacteristic': {
'inRealms': ['ReadValue', 'StartNotifications', 'StopNotifications', 'WriteValue'], 'inRealms': ['ReadValue', 'StartNotifications', 'StopNotifications', 'WriteValue'],
'canGc': ['GetDescriptor', 'GetDescriptors', 'ReadValue', 'StartNotifications', 'StopNotifications', 'WriteValue'],
}, },
'BluetoothRemoteGATTDescriptor': { 'BluetoothRemoteGATTDescriptor': {
'inRealms': ['ReadValue', 'WriteValue'], 'inRealms': ['ReadValue', 'WriteValue'],
'canGc': ['ReadValue', 'WriteValue'],
}, },
'BluetoothRemoteGATTServer': { 'BluetoothRemoteGATTServer': {
'inRealms': ['Connect'], 'inRealms': ['Connect'],
'canGc': ['GetPrimaryService', 'GetPrimaryServices', 'Connect'],
}, },
'CustomElementRegistry': { 'BluetoothRemoteGATTService': {
'inRealms': ['WhenDefined'], 'canGc': ['GetCharacteristic', 'GetCharacteristics', 'GetIncludedService', 'GetIncludedServices'],
}, },
'CanvasRenderingContext2D': { 'CanvasRenderingContext2D': {
@ -65,20 +70,25 @@ DOMInterfaces = {
'canGc': ['AddColorStop'], 'canGc': ['AddColorStop'],
}, },
'DOMImplementation': { 'CustomElementRegistry': {
'canGc': ['CreateDocument', 'CreateHTMLDocument'], 'inRealms': ['WhenDefined'],
'canGc': ['WhenDefined'],
}, },
'DOMParser': { 'DOMImplementation': {
'canGc': ['ParseFromString'], 'canGc': ['CreateDocument', 'CreateHTMLDocument'],
}, },
'DOMMatrix': { 'DOMMatrix': {
'canGc': ['FromMatrix', 'FromFloat32Array', 'FromFloat64Array'], 'canGc': ['FromMatrix', 'FromFloat32Array', 'FromFloat64Array'],
}, },
'DOMQuad': { 'DOMMatrixReadOnly': {
'canGc': ['FromRect', 'FromQuad', 'GetBounds'], 'canGc': ['Multiply', 'Inverse', 'Scale', 'Translate', 'Rotate', 'RotateFromVector','FlipY', 'ScaleNonUniform', 'Scale3d', 'RotateAxisAngle', 'SkewX', 'SkewY', 'FlipX', 'TransformPoint', 'FromFloat32Array', 'FromFloat64Array','FromMatrix'],
},
'DOMParser': {
'canGc': ['ParseFromString'],
}, },
'DOMPoint': { 'DOMPoint': {
@ -89,12 +99,12 @@ DOMInterfaces = {
'canGc': ['FromPoint'], 'canGc': ['FromPoint'],
}, },
'DOMMatrixReadOnly': { 'DOMQuad': {
'canGc': ['Multiply', 'Inverse', 'Scale', 'Translate', 'Rotate', 'RotateFromVector','FlipY', 'ScaleNonUniform', 'Scale3d', 'RotateAxisAngle', 'SkewX', 'SkewY', 'FlipX', 'TransformPoint', 'FromFloat32Array', 'FromFloat64Array','FromMatrix'], 'canGc': ['FromRect', 'FromQuad', 'GetBounds'],
}, },
'Document': { 'Document': {
'canGc': ['Close', 'CreateElement', 'CreateElementNS', 'ImportNode', 'SetTitle', 'Write', 'Writeln', 'CreateEvent', 'CreateRange', 'Open', 'Open_', 'Fonts', 'ElementFromPoint', 'ElementsFromPoint'], 'canGc': ['Close', 'CreateElement', 'CreateElementNS', 'ImportNode', 'SetTitle', 'Write', 'Writeln', 'CreateEvent', 'CreateRange', 'Open', 'Open_', 'Fonts', 'ElementFromPoint', 'ElementsFromPoint', 'ExitFullscreen'],
}, },
'DynamicModuleOwner': { 'DynamicModuleOwner': {
@ -102,7 +112,7 @@ DOMInterfaces = {
}, },
'Element': { 'Element': {
'canGc': ['SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML', 'GetClientRects', 'GetBoundingClientRect', 'SetScrollTop', 'SetScrollLeft', 'Scroll', 'Scroll_', 'ScrollBy', 'ScrollBy_', 'ScrollWidth', 'ScrollHeight', 'ScrollTop', 'ScrollLeft', 'ClientTop', 'ClientLeft', 'ClientWidth', 'ClientHeight'], 'canGc': ['SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML', 'GetClientRects', 'GetBoundingClientRect', 'SetScrollTop', 'SetScrollLeft', 'Scroll', 'Scroll_', 'ScrollBy', 'ScrollBy_', 'ScrollWidth', 'ScrollHeight', 'ScrollTop', 'ScrollLeft', 'ClientTop', 'ClientLeft', 'ClientWidth', 'ClientHeight', 'RequestFullscreen'],
}, },
'ElementInternals': { 'ElementInternals': {
@ -117,6 +127,10 @@ DOMInterfaces = {
'canGc': ['DispatchEvent'], 'canGc': ['DispatchEvent'],
}, },
'FakeXRDevice': {
'canGc': ['Disconnect'],
},
'File': { 'File': {
'weakReferenceable': True, 'weakReferenceable': True,
}, },
@ -127,14 +141,17 @@ DOMInterfaces = {
'GPU': { 'GPU': {
'inRealms': ['RequestAdapter'], 'inRealms': ['RequestAdapter'],
'canGc': ['RequestAdapter'],
}, },
'GPUAdapter': { 'GPUAdapter': {
'inRealms': ['RequestAdapterInfo', 'RequestDevice'], 'inRealms': ['RequestAdapterInfo', 'RequestDevice'],
'canGc': ['RequestAdapterInfo', 'RequestDevice'],
}, },
'GPUBuffer': { 'GPUBuffer': {
'inRealms': ['MapAsync'], 'inRealms': ['MapAsync'],
'canGc': ['MapAsync'],
}, },
'GPUDevice': { 'GPUDevice': {
@ -144,11 +161,22 @@ DOMInterfaces = {
'CreateShaderModule', # Creates promise for compilation info 'CreateShaderModule', # Creates promise for compilation info
'PopErrorScope' 'PopErrorScope'
], ],
'canGc': [
'CreateComputePipelineAsync',
'CreateRenderPipelineAsync',
'CreateShaderModule',
'PopErrorScope'
],
'weakReferenceable': True, # for usage in GlobalScope https://github.com/servo/servo/issues/32519 'weakReferenceable': True, # for usage in GlobalScope https://github.com/servo/servo/issues/32519
}, },
'GPUQueue': {
'canGc': ['OnSubmittedWorkDone'],
},
'GamepadHapticActuator': { 'GamepadHapticActuator': {
'inRealms': ['PlayEffect', 'Reset'] 'inRealms': ['PlayEffect', 'Reset'],
'canGc': ['PlayEffect', 'Reset'],
}, },
'History': { 'History': {
@ -159,8 +187,12 @@ DOMInterfaces = {
'canGc': ['ReportValidity'], 'canGc': ['ReportValidity'],
}, },
'HTMLCanvasElement': {
'canGc': ['CaptureStream', 'GetContext'],
},
'HTMLElement': { 'HTMLElement': {
'canGc': ['Focus', 'Blur', 'Click'], 'canGc': ['GetOffsetParent', 'OffsetTop', 'OffsetLeft', 'OffsetWidth', 'OffsetHeight', 'InnerText', 'GetOuterText', 'Focus', 'Blur', 'Click'],
}, },
'HTMLFieldSetElement': { 'HTMLFieldSetElement': {
@ -175,6 +207,10 @@ DOMInterfaces = {
'canGc': ['ReportValidity', 'SelectFiles'], 'canGc': ['ReportValidity', 'SelectFiles'],
}, },
'HTMLImageElement': {
'canGc': ['Width', 'Height', 'Decode'],
},
'HTMLMediaElement': { 'HTMLMediaElement': {
'canGc': ['Load', 'Pause', 'Play', 'SetSrcObject'], 'canGc': ['Load', 'Pause', 'Play', 'SetSrcObject'],
'inRealms': ['Play'], 'inRealms': ['Play'],
@ -188,10 +224,6 @@ DOMInterfaces = {
'canGc': ['ReportValidity'], 'canGc': ['ReportValidity'],
}, },
'HTMLCanvasElement': {
'canGc': ['CaptureStream', 'GetContext'],
},
'HTMLSelectElement': { 'HTMLSelectElement': {
'canGc': ['ReportValidity'], 'canGc': ['ReportValidity'],
}, },
@ -200,14 +232,6 @@ DOMInterfaces = {
'canGc': ['Content'], 'canGc': ['Content'],
}, },
'HTMLElement': {
'canGc': ['GetOffsetParent', 'OffsetTop', 'OffsetLeft', 'OffsetWidth', 'OffsetHeight', 'InnerText', 'GetOuterText', 'Focus', 'Blur', 'Click'],
},
'HTMLImageElement': {
'canGc': ['Width', 'Height'],
},
'HTMLTextAreaElement': { 'HTMLTextAreaElement': {
'canGc': ['ReportValidity'], 'canGc': ['ReportValidity'],
}, },
@ -217,7 +241,7 @@ DOMInterfaces = {
}, },
'MediaDevices': { 'MediaDevices': {
'canGc': ['GetUserMedia'], 'canGc': ['GetUserMedia', 'EnumerateDevices'],
'inRealms': ['GetUserMedia', 'GetClientRects', 'GetBoundingClientRect'], 'inRealms': ['GetUserMedia', 'GetClientRects', 'GetBoundingClientRect'],
}, },
@ -243,6 +267,7 @@ DOMInterfaces = {
'NavigationPreloadManager': { 'NavigationPreloadManager': {
'inRealms': ['Disable', 'Enable', 'GetState', 'SetHeaderValue'], 'inRealms': ['Disable', 'Enable', 'GetState', 'SetHeaderValue'],
'canGc': ['Disable', 'Enable', 'GetState', 'SetHeaderValue'],
}, },
'Navigator': { 'Navigator': {
@ -255,6 +280,7 @@ DOMInterfaces = {
'OfflineAudioContext': { 'OfflineAudioContext': {
'inRealms': ['StartRendering'], 'inRealms': ['StartRendering'],
'canGc': ['StartRendering'],
}, },
'OffscreenCanvasRenderingContext2D': { 'OffscreenCanvasRenderingContext2D': {
@ -265,13 +291,21 @@ DOMInterfaces = {
'canGc': ['GetTransform', 'SetStrokeStyle', 'SetFillStyle', 'SetShadowColor'], 'canGc': ['GetTransform', 'SetStrokeStyle', 'SetFillStyle', 'SetShadowColor'],
}, },
'Permissions': {
'canGc': ['Query', 'Request', 'Revoke'],
},
'Promise': { 'Promise': {
'spiderMonkeyInterface': True, 'spiderMonkeyInterface': True,
}, },
'RTCPeerConnection': { 'RTCPeerConnection': {
'inRealms': ['AddIceCandidate', 'CreateAnswer', 'CreateOffer', 'SetLocalDescription', 'SetRemoteDescription'], 'inRealms': ['AddIceCandidate', 'CreateAnswer', 'CreateOffer', 'SetLocalDescription', 'SetRemoteDescription'],
'canGc': ['Close'], 'canGc': ['Close', 'AddIceCandidate', 'CreateAnswer', 'CreateOffer', 'SetLocalDescription', 'SetRemoteDescription'],
},
'RTCRtpSender': {
'canGc': ['SetParameters'],
}, },
'Range': { 'Range': {
@ -279,42 +313,46 @@ DOMInterfaces = {
'weakReferenceable': True, 'weakReferenceable': True,
}, },
'Response': {
'canGc': ['Error', 'Redirect', 'Clone', 'Text', 'Blob', 'FormData', 'Json', 'ArrayBuffer', 'Headers'],
},
'Request': { 'Request': {
'canGc': ['Headers', 'Text', 'Blob', 'FormData', 'Json', 'ArrayBuffer', 'Clone'], 'canGc': ['Headers', 'Text', 'Blob', 'FormData', 'Json', 'ArrayBuffer', 'Clone'],
}, },
'Response': {
'canGc': ['Error', 'Redirect', 'Clone', 'Text', 'Blob', 'FormData', 'Json', 'ArrayBuffer', 'Headers'],
},
'Selection': { 'Selection': {
'canGc': ['Collapse', 'CollapseToEnd', 'CollapseToStart', 'Extend', 'SelectAllChildren', 'SetBaseAndExtent', 'SetPosition'], 'canGc': ['Collapse', 'CollapseToEnd', 'CollapseToStart', 'Extend', 'SelectAllChildren', 'SetBaseAndExtent', 'SetPosition'],
}, },
'ServiceWorkerContainer': { 'ServiceWorkerContainer': {
'inRealms': ['Register'], 'inRealms': ['Register'],
}, 'canGc': ['Register'],
'StaticRange': {
'weakReferenceable': True,
}, },
'ShadowRoot': { 'ShadowRoot': {
'canGc': ['ElementFromPoint', 'ElementsFromPoint'], 'canGc': ['ElementFromPoint', 'ElementsFromPoint'],
}, },
'StaticRange': {
'weakReferenceable': True,
},
'SubtleCrypto': { 'SubtleCrypto': {
'inRealms': ['Encrypt', 'Decrypt', 'GenerateKey', 'ImportKey', 'ExportKey'] 'inRealms': ['Encrypt', 'Decrypt', 'GenerateKey', 'ImportKey', 'ExportKey'],
'canGc': ['Encrypt', 'Decrypt', 'GenerateKey', 'ImportKey', 'ExportKey'],
}, },
#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'], 'canGc': ['InterfaceAttribute', 'GetInterfaceAttributeNullable', 'ReceiveInterface', 'ReceiveInterfaceSequence', 'ReceiveNullableInterface', 'PromiseAttribute', 'PromiseNativeHandler'],
}, },
'TestWorklet': { 'TestWorklet': {
'inRealms': ['AddModule'], 'inRealms': ['AddModule'],
'canGc': ['AddModule'],
}, },
'URL': { 'URL': {
@ -322,12 +360,16 @@ DOMInterfaces = {
'canGc': ['Parse', 'SearchParams'], 'canGc': ['Parse', 'SearchParams'],
}, },
'VRDisplay': { 'WebGLRenderingContext': {
'inRealms': ['ExitPresent', 'RequestPresent'], 'canGc': ['MakeXRCompatible'],
},
'WebGL2RenderingContext': {
'canGc': ['MakeXRCompatible'],
}, },
'Window': { 'Window': {
'canGc': ['Stop', 'Fetch', 'Scroll', 'Scroll_','ScrollBy', 'ScrollBy_', 'Stop', 'Fetch', 'Open'], 'canGc': ['Stop', 'Fetch', 'Scroll', 'Scroll_','ScrollBy', 'ScrollBy_', 'Stop', 'Fetch', 'Open', 'CreateImageBitmap'],
'inRealms': ['Fetch', 'GetOpener'], 'inRealms': ['Fetch', 'GetOpener'],
}, },
@ -338,11 +380,12 @@ DOMInterfaces = {
'WorkerGlobalScope': { 'WorkerGlobalScope': {
'inRealms': ['Fetch'], 'inRealms': ['Fetch'],
'canGc': ['Fetch'], 'canGc': ['Fetch', 'CreateImageBitmap'],
}, },
'Worklet': { 'Worklet': {
'inRealms': ['AddModule'], 'inRealms': ['AddModule'],
'canGc': ['AddModule'],
}, },
'XMLHttpRequest': { 'XMLHttpRequest': {
@ -375,11 +418,16 @@ DOMInterfaces = {
'XRSession': { 'XRSession': {
'inRealms': ['RequestReferenceSpace', 'UpdateRenderState', 'UpdateTargetFrameRate'], 'inRealms': ['RequestReferenceSpace', 'UpdateRenderState', 'UpdateTargetFrameRate'],
'canGc': ['End', 'RequestReferenceSpace'], 'canGc': ['End', 'RequestReferenceSpace', 'UpdateTargetFrameRate', 'RequestHitTestSource'],
}, },
'XRSystem': { 'XRSystem': {
'inRealms': ['RequestSession', 'SupportsSessionMode'], 'inRealms': ['RequestSession'],
'canGc': ['RequestSession', 'IsSessionSupported'],
},
'XRTest': {
'canGc': ['SimulateDeviceConnection', 'DisconnectAllDevices'],
}, },
} }

View file

@ -257,10 +257,10 @@ impl BlobMethods for Blob {
} }
// https://w3c.github.io/FileAPI/#text-method-algo // https://w3c.github.io/FileAPI/#text-method-algo
fn Text(&self) -> Rc<Promise> { fn Text(&self, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
let id = self.get_blob_url_id(); let id = self.get_blob_url_id();
global.read_file_async( global.read_file_async(
id, id,
@ -280,10 +280,10 @@ impl BlobMethods for Blob {
} }
// https://w3c.github.io/FileAPI/#arraybuffer-method-algo // https://w3c.github.io/FileAPI/#arraybuffer-method-algo
fn ArrayBuffer(&self) -> Rc<Promise> { fn ArrayBuffer(&self, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
let id = self.get_blob_url_id(); let id = self.get_blob_url_id();

View file

@ -30,7 +30,7 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::permissions::{get_descriptor_permission_state, PermissionAlgorithm}; use crate::dom::permissions::{get_descriptor_permission_state, PermissionAlgorithm};
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::JSContext; use crate::script_runtime::{CanGc, JSContext};
use crate::task::TaskOnce; use crate::task::TaskOnce;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
@ -278,6 +278,7 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(
} }
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
#[allow(clippy::too_many_arguments)]
pub fn get_gatt_children<T, F>( pub fn get_gatt_children<T, F>(
attribute: &T, attribute: &T,
single: bool, single: bool,
@ -286,13 +287,14 @@ pub fn get_gatt_children<T, F>(
instance_id: String, instance_id: String,
connected: bool, connected: bool,
child_type: GATTType, child_type: GATTType,
can_gc: CanGc,
) -> Rc<Promise> ) -> Rc<Promise>
where where
T: AsyncBluetoothListener + DomObject + 'static, T: AsyncBluetoothListener + DomObject + 'static,
F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>, F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>,
{ {
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
let result_uuid = if let Some(u) = uuid { let result_uuid = if let Some(u) = uuid {
// Step 1. // Step 1.
@ -531,8 +533,13 @@ impl From<BluetoothError> for Error {
impl BluetoothMethods for Bluetooth { impl BluetoothMethods for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
fn RequestDevice(&self, option: &RequestDeviceOptions, comp: InRealm) -> Rc<Promise> { fn RequestDevice(
let p = Promise::new_in_current_realm(comp); &self,
option: &RequestDeviceOptions,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
if (option.filters.is_some() && option.acceptAllDevices) || if (option.filters.is_some() && option.acceptAllDevices) ||
(option.filters.is_none() && !option.acceptAllDevices) (option.filters.is_none() && !option.acceptAllDevices)
@ -549,8 +556,8 @@ impl BluetoothMethods for Bluetooth {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability
fn GetAvailability(&self, comp: InRealm) -> Rc<Promise> { fn GetAvailability(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. We did not override the method // Step 1. We did not override the method
// Step 2 - 3. in handle_response // Step 2 - 3. in handle_response
let sender = response_async(&p, self); let sender = response_async(&p, self);

View file

@ -32,6 +32,7 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
#[crown::unrooted_must_root_lint::must_root] #[crown::unrooted_must_root_lint::must_root]
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
@ -280,8 +281,8 @@ impl BluetoothDeviceMethods for BluetoothDevice {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements
fn WatchAdvertisements(&self, comp: InRealm) -> Rc<Promise> { fn WatchAdvertisements(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&p, self); let sender = response_async(&p, self);
// TODO: Step 1. // TODO: Step 1.
// Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function // Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function

View file

@ -30,6 +30,7 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
// Maximum length of an attribute value. // Maximum length of an attribute value.
// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 2169) // https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 2169)
@ -107,7 +108,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> { fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID, can_gc: CanGc) -> Rc<Promise> {
get_gatt_children( get_gatt_children(
self, self,
true, true,
@ -116,11 +117,16 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
self.get_instance_id(), self.get_instance_id(),
self.Service().Device().get_gatt().Connected(), self.Service().Device().get_gatt().Connected(),
GATTType::Descriptor, GATTType::Descriptor,
can_gc,
) )
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
fn GetDescriptors(&self, descriptor: Option<BluetoothDescriptorUUID>) -> Rc<Promise> { fn GetDescriptors(
&self,
descriptor: Option<BluetoothDescriptorUUID>,
can_gc: CanGc,
) -> Rc<Promise> {
get_gatt_children( get_gatt_children(
self, self,
false, false,
@ -129,6 +135,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
self.get_instance_id(), self.get_instance_id(),
self.Service().Device().get_gatt().Connected(), self.Service().Device().get_gatt().Connected(),
GATTType::Descriptor, GATTType::Descriptor,
can_gc,
) )
} }
@ -138,8 +145,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
fn ReadValue(&self, comp: InRealm) -> Rc<Promise> { fn ReadValue(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@ -171,8 +178,13 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer, comp: InRealm) -> Rc<Promise> { fn WriteValue(
let p = Promise::new_in_current_realm(comp); &self,
value: ArrayBufferViewOrArrayBuffer,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {
@ -222,8 +234,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications
fn StartNotifications(&self, comp: InRealm) -> Rc<Promise> { fn StartNotifications(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@ -259,8 +271,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications
fn StopNotifications(&self, comp: InRealm) -> Rc<Promise> { fn StopNotifications(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&p, self); let sender = response_async(&p, self);
// TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic, // TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic,

View file

@ -26,6 +26,7 @@ use crate::dom::bluetoothremotegattcharacteristic::{
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor // http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
#[dom_struct] #[dom_struct]
@ -94,8 +95,8 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
fn ReadValue(&self, comp: InRealm) -> Rc<Promise> { fn ReadValue(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@ -126,8 +127,13 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer, comp: InRealm) -> Rc<Promise> { fn WriteValue(
let p = Promise::new_in_current_realm(comp); &self,
value: ArrayBufferViewOrArrayBuffer,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {

View file

@ -20,6 +20,7 @@ use crate::dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver
#[dom_struct] #[dom_struct]
@ -70,9 +71,9 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Connect(&self, comp: InRealm) -> Rc<Promise> { fn Connect(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
// Step 1. // Step 1.
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&p, self); let sender = response_async(&p, self);
// TODO: Step 3: Check if the UA is currently using the Bluetooth system. // TODO: Step 3: Check if the UA is currently using the Bluetooth system.
@ -110,7 +111,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> { fn GetPrimaryService(&self, service: BluetoothServiceUUID, can_gc: CanGc) -> Rc<Promise> {
// Step 1 - 2. // Step 1 - 2.
get_gatt_children( get_gatt_children(
self, self,
@ -120,11 +121,16 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
String::from(self.Device().Id()), String::from(self.Device().Id()),
self.Device().get_gatt().Connected(), self.Device().get_gatt().Connected(),
GATTType::PrimaryService, GATTType::PrimaryService,
can_gc,
) )
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> { fn GetPrimaryServices(
&self,
service: Option<BluetoothServiceUUID>,
can_gc: CanGc,
) -> Rc<Promise> {
// Step 1 - 2. // Step 1 - 2.
get_gatt_children( get_gatt_children(
self, self,
@ -134,6 +140,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
String::from(self.Device().Id()), String::from(self.Device().Id()),
self.Connected(), self.Connected(),
GATTType::PrimaryService, GATTType::PrimaryService,
can_gc,
) )
} }
} }

View file

@ -19,6 +19,7 @@ use crate::dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUI
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::CanGc;
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
#[dom_struct] #[dom_struct]
@ -84,7 +85,11 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
fn GetCharacteristic(&self, characteristic: BluetoothCharacteristicUUID) -> Rc<Promise> { fn GetCharacteristic(
&self,
characteristic: BluetoothCharacteristicUUID,
can_gc: CanGc,
) -> Rc<Promise> {
get_gatt_children( get_gatt_children(
self, self,
true, true,
@ -93,6 +98,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
self.get_instance_id(), self.get_instance_id(),
self.Device().get_gatt().Connected(), self.Device().get_gatt().Connected(),
GATTType::Characteristic, GATTType::Characteristic,
can_gc,
) )
} }
@ -100,6 +106,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
fn GetCharacteristics( fn GetCharacteristics(
&self, &self,
characteristic: Option<BluetoothCharacteristicUUID>, characteristic: Option<BluetoothCharacteristicUUID>,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
get_gatt_children( get_gatt_children(
self, self,
@ -109,11 +116,12 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
self.get_instance_id(), self.get_instance_id(),
self.Device().get_gatt().Connected(), self.Device().get_gatt().Connected(),
GATTType::Characteristic, GATTType::Characteristic,
can_gc,
) )
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
fn GetIncludedService(&self, service: BluetoothServiceUUID) -> Rc<Promise> { fn GetIncludedService(&self, service: BluetoothServiceUUID, can_gc: CanGc) -> Rc<Promise> {
get_gatt_children( get_gatt_children(
self, self,
false, false,
@ -122,11 +130,16 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
self.get_instance_id(), self.get_instance_id(),
self.Device().get_gatt().Connected(), self.Device().get_gatt().Connected(),
GATTType::IncludedService, GATTType::IncludedService,
can_gc,
) )
} }
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
fn GetIncludedServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> { fn GetIncludedServices(
&self,
service: Option<BluetoothServiceUUID>,
can_gc: CanGc,
) -> Rc<Promise> {
get_gatt_children( get_gatt_children(
self, self,
false, false,
@ -135,6 +148,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
self.get_instance_id(), self.get_instance_id(),
self.Device().get_gatt().Connected(), self.Device().get_gatt().Connected(),
GATTType::IncludedService, GATTType::IncludedService,
can_gc,
) )
} }

View file

@ -573,13 +573,13 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-whendefined> /// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-whendefined>
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn WhenDefined(&self, name: DOMString, comp: InRealm) -> Rc<Promise> { fn WhenDefined(&self, name: DOMString, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let global_scope = self.window.upcast::<GlobalScope>(); let global_scope = self.window.upcast::<GlobalScope>();
let name = LocalName::from(&*name); let name = LocalName::from(&*name);
// Step 1 // Step 1
if !is_valid_custom_element_name(&name) { if !is_valid_custom_element_name(&name) {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
promise.reject_native(&DOMException::new(global_scope, DOMErrorName::SyntaxError)); promise.reject_native(&DOMException::new(global_scope, DOMErrorName::SyntaxError));
return promise; return promise;
} }
@ -592,7 +592,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
definition definition
.constructor .constructor
.to_jsval(*cx, constructor.handle_mut()); .to_jsval(*cx, constructor.handle_mut());
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
promise.resolve_native(&constructor.get()); promise.resolve_native(&constructor.get());
return promise; return promise;
} }
@ -603,7 +603,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
// Steps 4, 5 // Steps 4, 5
let promise = map.get(&name).cloned().unwrap_or_else(|| { let promise = map.get(&name).cloned().unwrap_or_else(|| {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
map.insert(name, promise.clone()); map.insert(name, promise.clone());
promise promise
}); });

View file

@ -3894,10 +3894,10 @@ impl Document {
} }
// https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen
pub fn enter_fullscreen(&self, pending: &Element) -> Rc<Promise> { pub fn enter_fullscreen(&self, pending: &Element, can_gc: CanGc) -> Rc<Promise> {
// Step 1 // Step 1
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
let mut error = false; let mut error = false;
// Step 4 // Step 4
@ -3961,11 +3961,11 @@ impl Document {
} }
// https://fullscreen.spec.whatwg.org/#exit-fullscreen // https://fullscreen.spec.whatwg.org/#exit-fullscreen
pub fn exit_fullscreen(&self) -> Rc<Promise> { pub fn exit_fullscreen(&self, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
// Step 1 // Step 1
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
// Step 2 // Step 2
if self.fullscreen_element.get().is_none() { if self.fullscreen_element.get().is_none() {
promise.reject_error(Error::Type(String::from("fullscreen is null"))); promise.reject_error(Error::Type(String::from("fullscreen is null")));
@ -5557,8 +5557,8 @@ impl DocumentMethods for Document {
} }
// https://fullscreen.spec.whatwg.org/#dom-document-exitfullscreen // https://fullscreen.spec.whatwg.org/#dom-document-exitfullscreen
fn ExitFullscreen(&self) -> Rc<Promise> { fn ExitFullscreen(&self, can_gc: CanGc) -> Rc<Promise> {
self.exit_fullscreen() self.exit_fullscreen(can_gc)
} }
// check-tidy: no specs after this line // check-tidy: no specs after this line

View file

@ -2954,9 +2954,9 @@ impl ElementMethods for Element {
} }
// https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen
fn RequestFullscreen(&self) -> Rc<Promise> { fn RequestFullscreen(&self, can_gc: CanGc) -> Rc<Promise> {
let doc = document_from_node(self); let doc = document_from_node(self);
doc.enter_fullscreen(self) doc.enter_fullscreen(self, can_gc)
} }
// XXX Hidden under dom.shadowdom.enabled pref. Only exposed to be able // XXX Hidden under dom.shadowdom.enabled pref. Only exposed to be able
@ -3557,7 +3557,7 @@ impl VirtualMethods for Element {
let fullscreen = doc.GetFullscreenElement(); let fullscreen = doc.GetFullscreenElement();
if fullscreen.as_deref() == Some(self) { if fullscreen.as_deref() == Some(self) {
doc.exit_fullscreen(); doc.exit_fullscreen(CanGc::note());
} }
if let Some(ref value) = *self.id_attribute.borrow() { if let Some(ref value) = *self.id_attribute.borrow() {
doc.unregister_element_id(self, value.clone()); doc.unregister_element_id(self, value.clone());

View file

@ -33,6 +33,7 @@ use crate::dom::bindings::root::DomRoot;
use crate::dom::fakexrinputcontroller::{init_to_mock_buttons, FakeXRInputController}; use crate::dom::fakexrinputcontroller::{init_to_mock_buttons, FakeXRInputController};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::CanGc;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
#[dom_struct] #[dom_struct]
@ -297,9 +298,9 @@ impl FakeXRDeviceMethods for FakeXRDevice {
} }
/// <https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-disconnect> /// <https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-disconnect>
fn Disconnect(&self) -> Rc<Promise> { fn Disconnect(&self, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let p = Promise::new(&global); let p = Promise::new(&global, can_gc);
let mut trusted = Some(TrustedPromise::new(p.clone())); let mut trusted = Some(TrustedPromise::new(p.clone()));
let (task_source, canceller) = global let (task_source, canceller) = global
.as_window() .as_window()

View file

@ -27,7 +27,7 @@ impl FontFaceSet {
pub fn new_inherited(global: &GlobalScope) -> Self { pub fn new_inherited(global: &GlobalScope) -> Self {
FontFaceSet { FontFaceSet {
target: EventTarget::new_inherited(), target: EventTarget::new_inherited(),
promise: Promise::new(global), promise: Promise::new(global, CanGc::note()),
} }
} }

View file

@ -144,8 +144,9 @@ impl GamepadHapticActuatorMethods for GamepadHapticActuator {
type_: GamepadHapticEffectType, type_: GamepadHapticEffectType,
params: &GamepadEffectParameters, params: &GamepadEffectParameters,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let playing_effect_promise = Promise::new_in_current_realm(comp); let playing_effect_promise = Promise::new_in_current_realm(comp, can_gc);
// <https://www.w3.org/TR/gamepad/#dfn-valid-effect> // <https://www.w3.org/TR/gamepad/#dfn-valid-effect>
match type_ { match type_ {
@ -258,8 +259,8 @@ impl GamepadHapticActuatorMethods for GamepadHapticActuator {
} }
/// <https://www.w3.org/TR/gamepad/#dom-gamepadhapticactuator-reset> /// <https://www.w3.org/TR/gamepad/#dom-gamepadhapticactuator-reset>
fn Reset(&self, comp: InRealm) -> Rc<Promise> { fn Reset(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let document = self.global().as_window().Document(); let document = self.global().as_window().Document();
if !document.is_fully_active() { if !document.is_fully_active() {

View file

@ -2810,9 +2810,10 @@ impl GlobalScope {
&self, &self,
image: ImageBitmapSource, image: ImageBitmapSource,
options: &ImageBitmapOptions, options: &ImageBitmapOptions,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
if options.resizeWidth.is_some_and(|w| w == 0) { if options.resizeWidth.is_some_and(|w| w == 0) {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState);
return p; return p;

View file

@ -106,9 +106,14 @@ pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
impl GPUMethods for GPU { impl GPUMethods for GPU {
// https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter // https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter
fn RequestAdapter(&self, options: &GPURequestAdapterOptions, comp: InRealm) -> Rc<Promise> { fn RequestAdapter(
&self,
options: &GPURequestAdapterOptions,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let global = &self.global(); let global = &self.global();
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let power_preference = match options.powerPreference { let power_preference = match options.powerPreference {
Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower, Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower,

View file

@ -108,9 +108,14 @@ impl Drop for GPUAdapter {
impl GPUAdapterMethods for GPUAdapter { impl GPUAdapterMethods for GPUAdapter {
/// <https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice> /// <https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice>
fn RequestDevice(&self, descriptor: &GPUDeviceDescriptor, comp: InRealm) -> Rc<Promise> { fn RequestDevice(
&self,
descriptor: &GPUDeviceDescriptor,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
// Step 2 // Step 2
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let mut required_features = wgt::Features::empty(); let mut required_features = wgt::Features::empty();
for &ext in descriptor.requiredFeatures.iter() { for &ext in descriptor.requiredFeatures.iter() {
@ -171,10 +176,15 @@ impl GPUAdapterMethods for GPUAdapter {
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestadapterinfo> /// <https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestadapterinfo>
fn RequestAdapterInfo(&self, unmask_hints: Vec<DOMString>, comp: InRealm) -> Rc<Promise> { fn RequestAdapterInfo(
&self,
unmask_hints: Vec<DOMString>,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
// XXX: Adapter info should be generated here ... // XXX: Adapter info should be generated here ...
// Step 1 // Step 1
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 4 // Step 4
if !unmask_hints.is_empty() { if !unmask_hints.is_empty() {
todo!("unmaskHints on RequestAdapterInfo"); todo!("unmaskHints on RequestAdapterInfo");

View file

@ -238,8 +238,9 @@ impl GPUBufferMethods for GPUBuffer {
offset: GPUSize64, offset: GPUSize64,
size: Option<GPUSize64>, size: Option<GPUSize64>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 2 // Step 2
if self.pending_map.borrow().is_some() { if self.pending_map.borrow().is_some() {
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation);

View file

@ -153,7 +153,7 @@ impl GPUDevice {
let queue = GPUQueue::new(global, channel.clone(), queue); let queue = GPUQueue::new(global, channel.clone(), queue);
let limits = GPUSupportedLimits::new(global, limits); let limits = GPUSupportedLimits::new(global, limits);
let features = GPUSupportedFeatures::Constructor(global, None, features, can_gc).unwrap(); let features = GPUSupportedFeatures::Constructor(global, None, features, can_gc).unwrap();
let lost_promise = Promise::new(global); let lost_promise = Promise::new(global, can_gc);
let device = reflect_dom_object( let device = reflect_dom_object(
Box::new(GPUDevice::new_inherited( Box::new(GPUDevice::new_inherited(
channel, channel,
@ -440,8 +440,9 @@ impl GPUDeviceMethods for GPUDevice {
&self, &self,
descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>, descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> DomRoot<GPUShaderModule> { ) -> DomRoot<GPUShaderModule> {
GPUShaderModule::create(self, descriptor, comp) GPUShaderModule::create(self, descriptor, comp, can_gc)
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcomputepipeline> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcomputepipeline>
@ -463,8 +464,9 @@ impl GPUDeviceMethods for GPUDevice {
&self, &self,
descriptor: &GPUComputePipelineDescriptor, descriptor: &GPUComputePipelineDescriptor,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
GPUComputePipeline::create(self, descriptor, Some(sender)); GPUComputePipeline::create(self, descriptor, Some(sender));
promise promise
@ -508,9 +510,10 @@ impl GPUDeviceMethods for GPUDevice {
&self, &self,
descriptor: &GPURenderPipelineDescriptor, descriptor: &GPURenderPipelineDescriptor,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Fallible<Rc<Promise>> { ) -> Fallible<Rc<Promise>> {
let (implicit_ids, desc) = self.parse_render_pipeline(descriptor)?; let (implicit_ids, desc) = self.parse_render_pipeline(descriptor)?;
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
GPURenderPipeline::create(self, implicit_ids, desc, Some(sender))?; GPURenderPipeline::create(self, implicit_ids, desc, Some(sender))?;
Ok(promise) Ok(promise)
@ -540,8 +543,8 @@ impl GPUDeviceMethods for GPUDevice {
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-poperrorscope> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-poperrorscope>
fn PopErrorScope(&self, comp: InRealm) -> Rc<Promise> { fn PopErrorScope(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
if self if self
.channel .channel

View file

@ -188,9 +188,9 @@ impl GPUQueueMethods for GPUQueue {
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpuqueue-onsubmittedworkdone> /// <https://gpuweb.github.io/gpuweb/#dom-gpuqueue-onsubmittedworkdone>
fn OnSubmittedWorkDone(&self) -> Rc<Promise> { fn OnSubmittedWorkDone(&self, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let promise = Promise::new(&global); let promise = Promise::new(&global, can_gc);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
if let Err(e) = self if let Err(e) = self
.channel .channel

View file

@ -82,9 +82,10 @@ impl GPUShaderModule {
device: &GPUDevice, device: &GPUDevice,
descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>, descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> DomRoot<GPUShaderModule> { ) -> DomRoot<GPUShaderModule> {
let program_id = device.global().wgpu_id_hub().create_shader_module_id(); let program_id = device.global().wgpu_id_hub().create_shader_module_id();
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let shader_module = GPUShaderModule::new( let shader_module = GPUShaderModule::new(
&device.global(), &device.global(),
device.channel().clone(), device.channel().clone(),

View file

@ -1703,9 +1703,9 @@ impl HTMLImageElementMethods for HTMLImageElement {
} }
/// <https://html.spec.whatwg.org/multipage/#dom-img-decode> /// <https://html.spec.whatwg.org/multipage/#dom-img-decode>
fn Decode(&self) -> Rc<Promise> { fn Decode(&self, can_gc: CanGc) -> Rc<Promise> {
// Step 1 // Step 1
let promise = Promise::new(&self.global()); let promise = Promise::new(&self.global(), can_gc);
// Step 2 // Step 2
let task = ImageElementMicrotask::Decode { let task = ImageElementMicrotask::Decode {

View file

@ -2158,7 +2158,7 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
// https://html.spec.whatwg.org/multipage/#dom-media-play // https://html.spec.whatwg.org/multipage/#dom-media-play
fn Play(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> { fn Play(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 1. // Step 1.
// FIXME(nox): Reject promise if not allowed to play. // FIXME(nox): Reject promise if not allowed to play.

View file

@ -572,7 +572,7 @@ fn fetch_a_classic_script(
impl HTMLScriptElement { impl HTMLScriptElement {
/// <https://html.spec.whatwg.org/multipage/#prepare-a-script> /// <https://html.spec.whatwg.org/multipage/#prepare-a-script>
pub fn prepare(&self) { pub fn prepare(&self, can_gc: CanGc) {
// Step 1. // Step 1.
if self.already_started.get() { if self.already_started.get() {
return; return;
@ -784,6 +784,7 @@ impl HTMLScriptElement {
url.clone(), url.clone(),
Destination::Script, Destination::Script,
options, options,
can_gc,
); );
if !asynch && was_parser_inserted { if !asynch && was_parser_inserted {
@ -842,6 +843,7 @@ impl HTMLScriptElement {
base_url.clone(), base_url.clone(),
self.id, self.id,
options, options,
can_gc,
); );
}, },
} }
@ -1236,7 +1238,7 @@ impl VirtualMethods for HTMLScriptElement {
if *attr.local_name() == local_name!("src") { if *attr.local_name() == local_name!("src") {
if let AttributeMutation::Set(_) = mutation { if let AttributeMutation::Set(_) = mutation {
if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() { if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() {
self.prepare(); self.prepare(CanGc::note());
} }
} }
} }
@ -1247,7 +1249,7 @@ impl VirtualMethods for HTMLScriptElement {
s.children_changed(mutation); s.children_changed(mutation);
} }
if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() { if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() {
self.prepare(); self.prepare(CanGc::note());
} }
} }
@ -1259,7 +1261,7 @@ impl VirtualMethods for HTMLScriptElement {
if context.tree_connected && !self.parser_inserted.get() { if context.tree_connected && !self.parser_inserted.get() {
let script = Trusted::new(self); let script = Trusted::new(self);
document_from_node(self).add_delayed_task(task!(ScriptDelayedInitialize: move || { document_from_node(self).add_delayed_task(task!(ScriptDelayedInitialize: move || {
script.root().prepare(); script.root().prepare(CanGc::note());
})); }));
} }
} }

View file

@ -53,7 +53,7 @@ impl MediaDevicesMethods for MediaDevices {
comp: InRealm, comp: InRealm,
can_gc: CanGc, can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
let media = ServoMedia::get().unwrap(); let media = ServoMedia::get().unwrap();
let stream = MediaStream::new(&self.global(), can_gc); let stream = MediaStream::new(&self.global(), can_gc);
if let Some(constraints) = convert_constraints(&constraints.audio) { if let Some(constraints) = convert_constraints(&constraints.audio) {
@ -74,10 +74,10 @@ impl MediaDevicesMethods for MediaDevices {
} }
/// <https://w3c.github.io/mediacapture-main/#dom-mediadevices-enumeratedevices> /// <https://w3c.github.io/mediacapture-main/#dom-mediadevices-enumeratedevices>
fn EnumerateDevices(&self) -> Rc<Promise> { fn EnumerateDevices(&self, can_gc: CanGc) -> Rc<Promise> {
// Step 1. // Step 1.
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc);
// Step 2. // Step 2.
// XXX These steps should be run in parallel. // XXX These steps should be run in parallel.

View file

@ -18,6 +18,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration; use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct NavigationPreloadManager { pub struct NavigationPreloadManager {
@ -45,8 +46,8 @@ impl NavigationPreloadManager {
impl NavigationPreloadManagerMethods for NavigationPreloadManager { impl NavigationPreloadManagerMethods for NavigationPreloadManager {
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-enable // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-enable
fn Enable(&self, comp: InRealm) -> Rc<Promise> { fn Enable(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
@ -67,8 +68,8 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
} }
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-disable // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-disable
fn Disable(&self, comp: InRealm) -> Rc<Promise> { fn Disable(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
@ -89,8 +90,8 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
} }
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-setheadervalue // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-setheadervalue
fn SetHeaderValue(&self, value: ByteString, comp: InRealm) -> Rc<Promise> { fn SetHeaderValue(&self, value: ByteString, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
@ -111,8 +112,8 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
} }
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-getstate // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-getstate
fn GetState(&self, comp: InRealm) -> Rc<Promise> { fn GetState(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// 2. // 2.
let mut state = NavigationPreloadState::empty(); let mut state = NavigationPreloadState::empty();

View file

@ -144,8 +144,8 @@ impl OfflineAudioContextMethods for OfflineAudioContext {
} }
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering // https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering
fn StartRendering(&self, comp: InRealm) -> Rc<Promise> { fn StartRendering(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
if self.rendering_started.get() { if self.rendering_started.get() {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState);
return promise; return promise;

View file

@ -25,7 +25,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::permissionstatus::PermissionStatus; use crate::dom::permissionstatus::PermissionStatus;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::{AlreadyInRealm, InRealm}; use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext; use crate::script_runtime::{CanGc, JSContext};
pub trait PermissionAlgorithm { pub trait PermissionAlgorithm {
type Descriptor; type Descriptor;
@ -82,13 +82,14 @@ impl Permissions {
cx: JSContext, cx: JSContext,
permissionDesc: *mut JSObject, permissionDesc: *mut JSObject,
promise: Option<Rc<Promise>>, promise: Option<Rc<Promise>>,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
// (Query, Request) Step 3. // (Query, Request) Step 3.
let p = match promise { let p = match promise {
Some(promise) => promise, Some(promise) => promise,
None => { None => {
let in_realm_proof = AlreadyInRealm::assert(); let in_realm_proof = AlreadyInRealm::assert();
Promise::new_in_current_realm(InRealm::Already(&in_realm_proof)) Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc)
}, },
}; };
@ -177,7 +178,9 @@ impl Permissions {
}; };
match op { match op {
// (Revoke) Step 5. // (Revoke) Step 5.
Operation::Revoke => self.manipulate(Operation::Query, cx, permissionDesc, Some(p)), Operation::Revoke => {
self.manipulate(Operation::Query, cx, permissionDesc, Some(p), can_gc)
},
// (Query, Request) Step 4. // (Query, Request) Step 4.
_ => p, _ => p,
@ -188,18 +191,18 @@ impl Permissions {
#[allow(non_snake_case)] #[allow(non_snake_case)]
impl PermissionsMethods for Permissions { impl PermissionsMethods for Permissions {
// https://w3c.github.io/permissions/#dom-permissions-query // https://w3c.github.io/permissions/#dom-permissions-query
fn Query(&self, cx: JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> { fn Query(&self, cx: JSContext, permissionDesc: *mut JSObject, can_gc: CanGc) -> Rc<Promise> {
self.manipulate(Operation::Query, cx, permissionDesc, None) self.manipulate(Operation::Query, cx, permissionDesc, None, can_gc)
} }
// https://w3c.github.io/permissions/#dom-permissions-request // https://w3c.github.io/permissions/#dom-permissions-request
fn Request(&self, cx: JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> { fn Request(&self, cx: JSContext, permissionDesc: *mut JSObject, can_gc: CanGc) -> Rc<Promise> {
self.manipulate(Operation::Request, cx, permissionDesc, None) self.manipulate(Operation::Request, cx, permissionDesc, None, can_gc)
} }
// https://w3c.github.io/permissions/#dom-permissions-revoke // https://w3c.github.io/permissions/#dom-permissions-revoke
fn Revoke(&self, cx: JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> { fn Revoke(&self, cx: JSContext, permissionDesc: *mut JSObject, can_gc: CanGc) -> Rc<Promise> {
self.manipulate(Operation::Revoke, cx, permissionDesc, None) self.manipulate(Operation::Revoke, cx, permissionDesc, None, can_gc)
} }
} }

View file

@ -86,16 +86,16 @@ impl Drop for Promise {
} }
impl Promise { impl Promise {
pub fn new(global: &GlobalScope) -> Rc<Promise> { pub fn new(global: &GlobalScope, can_gc: CanGc) -> Rc<Promise> {
let realm = enter_realm(global); let realm = enter_realm(global);
let comp = InRealm::Entered(&realm); let comp = InRealm::Entered(&realm);
Promise::new_in_current_realm(comp) Promise::new_in_current_realm(comp, can_gc)
} }
pub fn new_in_current_realm(_comp: InRealm) -> Rc<Promise> { pub fn new_in_current_realm(_comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>());
Promise::create_js_promise(cx, obj.handle_mut()); Promise::create_js_promise(cx, obj.handle_mut(), can_gc);
Promise::new_with_js_promise(obj.handle(), cx) Promise::new_with_js_promise(obj.handle(), cx)
} }
@ -121,7 +121,9 @@ impl Promise {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn create_js_promise(cx: SafeJSContext, mut obj: MutableHandleObject) { // The apparently-unused CanGc parameter reflects the fact that the JS API calls
// like JS_NewFunction can trigger a GC.
fn create_js_promise(cx: SafeJSContext, mut obj: MutableHandleObject, _can_gc: CanGc) {
unsafe { unsafe {
let do_nothing_func = JS_NewFunction( let do_nothing_func = JS_NewFunction(
*cx, *cx,
@ -253,18 +255,25 @@ impl Promise {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn append_native_handler(&self, handler: &PromiseNativeHandler, _comp: InRealm) { pub fn append_native_handler(
&self,
handler: &PromiseNativeHandler,
_comp: InRealm,
can_gc: CanGc,
) {
let _ais = AutoEntryScript::new(&handler.global()); let _ais = AutoEntryScript::new(&handler.global());
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let resolve_func = rooted!(in(*cx) let resolve_func =
create_native_handler_function(*cx, create_native_handler_function(*cx,
handler.reflector().get_jsobject(), handler.reflector().get_jsobject(),
NativeHandlerTask::Resolve)); NativeHandlerTask::Resolve,
can_gc));
rooted!(in(*cx) let reject_func = rooted!(in(*cx) let reject_func =
create_native_handler_function(*cx, create_native_handler_function(*cx,
handler.reflector().get_jsobject(), handler.reflector().get_jsobject(),
NativeHandlerTask::Reject)); NativeHandlerTask::Reject,
can_gc));
unsafe { unsafe {
let ok = AddPromiseReactions( let ok = AddPromiseReactions(
@ -335,10 +344,13 @@ unsafe extern "C" fn native_handler_callback(
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
// The apparently-unused CanGc argument reflects the fact that the JS API calls
// like NewFunctionWithReserved can trigger a GC.
fn create_native_handler_function( fn create_native_handler_function(
cx: *mut JSContext, cx: *mut JSContext,
holder: HandleObject, holder: HandleObject,
task: NativeHandlerTask, task: NativeHandlerTask,
_can_gc: CanGc,
) -> *mut JSObject { ) -> *mut JSObject {
unsafe { unsafe {
let func = NewFunctionWithReserved(cx, Some(native_handler_callback), 1, 0, ptr::null()); let func = NewFunctionWithReserved(cx, Some(native_handler_callback), 1, 0, ptr::null());

View file

@ -583,8 +583,13 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
event_handler!(datachannel, GetOndatachannel, SetOndatachannel); event_handler!(datachannel, GetOndatachannel, SetOndatachannel);
/// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate> /// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate>
fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit, comp: InRealm) -> Rc<Promise> { fn AddIceCandidate(
let p = Promise::new_in_current_realm(comp); &self,
candidate: &RTCIceCandidateInit,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc);
if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() { if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() {
p.reject_error(Error::Type( p.reject_error(Error::Type(
"one of sdpMid and sdpMLineIndex must be set".to_string(), "one of sdpMid and sdpMLineIndex must be set".to_string(),
@ -618,8 +623,8 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
} }
/// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer> /// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer>
fn CreateOffer(&self, _options: &RTCOfferOptions, comp: InRealm) -> Rc<Promise> { fn CreateOffer(&self, _options: &RTCOfferOptions, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
if self.closed.get() { if self.closed.get() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState);
return p; return p;
@ -630,8 +635,13 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
} }
/// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer> /// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer>
fn CreateAnswer(&self, _options: &RTCAnswerOptions, comp: InRealm) -> Rc<Promise> { fn CreateAnswer(
let p = Promise::new_in_current_realm(comp); &self,
_options: &RTCAnswerOptions,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp, can_gc);
if self.closed.get() { if self.closed.get() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState);
return p; return p;
@ -652,9 +662,14 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
} }
/// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setlocaldescription> /// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setlocaldescription>
fn SetLocalDescription(&self, desc: &RTCSessionDescriptionInit, comp: InRealm) -> Rc<Promise> { fn SetLocalDescription(
&self,
desc: &RTCSessionDescriptionInit,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
// XXXManishearth validate the current state // XXXManishearth validate the current state
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
let this = Trusted::new(self); let this = Trusted::new(self);
let desc: SessionDescription = desc.into(); let desc: SessionDescription = desc.into();
let trusted_promise = TrustedPromise::new(p.clone()); let trusted_promise = TrustedPromise::new(p.clone());
@ -693,9 +708,14 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
} }
/// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setremotedescription> /// <https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setremotedescription>
fn SetRemoteDescription(&self, desc: &RTCSessionDescriptionInit, comp: InRealm) -> Rc<Promise> { fn SetRemoteDescription(
&self,
desc: &RTCSessionDescriptionInit,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
// XXXManishearth validate the current state // XXXManishearth validate the current state
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
let this = Trusted::new(self); let this = Trusted::new(self);
let desc: SessionDescription = desc.into(); let desc: SessionDescription = desc.into();
let trusted_promise = TrustedPromise::new(p.clone()); let trusted_promise = TrustedPromise::new(p.clone());

View file

@ -14,6 +14,7 @@ use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct RTCRtpSender { pub struct RTCRtpSender {
@ -50,8 +51,8 @@ impl RTCRtpSenderMethods 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) -> Rc<Promise> { fn SetParameters(&self, _parameters: &RTCRtpSendParameters, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new(&self.global()); let promise = Promise::new(&self.global(), can_gc);
promise.resolve_native(&()); promise.resolve_native(&());
promise promise
} }

View file

@ -25,6 +25,7 @@ use crate::dom::promise::Promise;
use crate::dom::serviceworker::ServiceWorker; use crate::dom::serviceworker::ServiceWorker;
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration; use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
use crate::realms::{enter_realm, InRealm}; use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::CanGc;
use crate::task::TaskCanceller; use crate::task::TaskCanceller;
use crate::task_source::dom_manipulation::DOMManipulationTaskSource; use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
use crate::task_source::{TaskSource, TaskSourceName}; use crate::task_source::{TaskSource, TaskSourceName};
@ -66,12 +67,13 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
script_url: USVString, script_url: USVString,
options: &RegistrationOptions, options: &RegistrationOptions,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
// A: Step 2. // A: Step 2.
let global = self.client.global(); let global = self.client.global();
// A: Step 1 // A: Step 1
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let USVString(ref script_url) = script_url; let USVString(ref script_url) = script_url;
// A: Step 3 // A: Step 3

View file

@ -610,7 +610,7 @@ impl ServoParser {
let script_nesting_level = self.script_nesting_level.get(); let script_nesting_level = self.script_nesting_level.get();
self.script_nesting_level.set(script_nesting_level + 1); self.script_nesting_level.set(script_nesting_level + 1);
script.prepare(); script.prepare(can_gc);
self.script_nesting_level.set(script_nesting_level); self.script_nesting_level.set(script_nesting_level);
if self.document.has_pending_parsing_blocking_script() { if self.document.has_pending_parsing_blocking_script() {

View file

@ -43,7 +43,7 @@ use crate::dom::promise::Promise;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope; use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::JSContext; use crate::script_runtime::{CanGc, JSContext};
use crate::task::TaskCanceller; use crate::task::TaskCanceller;
use crate::task_source::dom_manipulation::DOMManipulationTaskSource; use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
@ -141,9 +141,10 @@ impl SubtleCryptoMethods for SubtleCrypto {
key: &CryptoKey, key: &CryptoKey,
data: ArrayBufferViewOrArrayBuffer, data: ArrayBufferViewOrArrayBuffer,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let normalized_algorithm = normalize_algorithm(cx, algorithm, "encrypt"); let normalized_algorithm = normalize_algorithm(cx, algorithm, "encrypt");
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let data = match data { let data = match data {
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(), ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(), ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
@ -197,9 +198,10 @@ impl SubtleCryptoMethods for SubtleCrypto {
key: &CryptoKey, key: &CryptoKey,
data: ArrayBufferViewOrArrayBuffer, data: ArrayBufferViewOrArrayBuffer,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let normalized_algorithm = normalize_algorithm(cx, algorithm, "decrypt"); let normalized_algorithm = normalize_algorithm(cx, algorithm, "decrypt");
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
let data = match data { let data = match data {
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(), ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(), ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
@ -253,9 +255,10 @@ impl SubtleCryptoMethods for SubtleCrypto {
extractable: bool, extractable: bool,
key_usages: Vec<KeyUsage>, key_usages: Vec<KeyUsage>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let normalized_algorithm = normalize_algorithm(cx, algorithm, "generateKey"); let normalized_algorithm = normalize_algorithm(cx, algorithm, "generateKey");
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
if let Err(e) = normalized_algorithm { if let Err(e) = normalized_algorithm {
promise.reject_error(e); promise.reject_error(e);
return promise; return promise;
@ -296,9 +299,10 @@ impl SubtleCryptoMethods for SubtleCrypto {
extractable: bool, extractable: bool,
key_usages: Vec<KeyUsage>, key_usages: Vec<KeyUsage>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let normalized_algorithm = normalize_algorithm(cx, algorithm, "importKey"); let normalized_algorithm = normalize_algorithm(cx, algorithm, "importKey");
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
if let Err(e) = normalized_algorithm { if let Err(e) = normalized_algorithm {
promise.reject_error(e); promise.reject_error(e);
return promise; return promise;
@ -360,8 +364,14 @@ impl SubtleCryptoMethods for SubtleCrypto {
} }
/// <https://w3c.github.io/webcrypto/#SubtleCrypto-method-exportKey> /// <https://w3c.github.io/webcrypto/#SubtleCrypto-method-exportKey>
fn ExportKey(&self, format: KeyFormat, key: &CryptoKey, comp: InRealm) -> Rc<Promise> { fn ExportKey(
let promise = Promise::new_in_current_realm(comp); &self,
format: KeyFormat,
key: &CryptoKey,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp, can_gc);
let (task_source, canceller) = self.task_source_with_canceller(); let (task_source, canceller) = self.task_source_with_canceller();
let this = Trusted::new(self); let this = Trusted::new(self);

View file

@ -1013,6 +1013,7 @@ impl TestBindingMethods for TestBinding {
resolve: Option<Rc<SimpleCallback>>, resolve: Option<Rc<SimpleCallback>>,
reject: Option<Rc<SimpleCallback>>, reject: Option<Rc<SimpleCallback>>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let handler = PromiseNativeHandler::new( let handler = PromiseNativeHandler::new(
@ -1020,8 +1021,8 @@ impl TestBindingMethods for TestBinding {
resolve.map(SimpleHandler::new_boxed), resolve.map(SimpleHandler::new_boxed),
reject.map(SimpleHandler::new_boxed), reject.map(SimpleHandler::new_boxed),
); );
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
p.append_native_handler(&handler, comp); p.append_native_handler(&handler, comp, can_gc);
return p; return p;
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
@ -1042,8 +1043,8 @@ impl TestBindingMethods for TestBinding {
} }
} }
fn PromiseAttribute(&self, comp: InRealm) -> Rc<Promise> { fn PromiseAttribute(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
Promise::new_in_current_realm(comp) Promise::new_in_current_realm(comp, can_gc)
} }
fn AcceptPromise(&self, _promise: &Promise) {} fn AcceptPromise(&self, _promise: &Promise) {}

View file

@ -63,8 +63,9 @@ impl TestWorkletMethods for TestWorklet {
moduleURL: USVString, moduleURL: USVString,
options: &WorkletOptions, options: &WorkletOptions,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
self.worklet.AddModule(moduleURL, options, comp) self.worklet.AddModule(moduleURL, options, comp, can_gc)
} }
fn Lookup(&self, key: DOMString) -> Option<DOMString> { fn Lookup(&self, key: DOMString) -> Option<DOMString> {

View file

@ -4479,9 +4479,9 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
} }
/// <https://immersive-web.github.io/webxr/#dom-webglrenderingcontextbase-makexrcompatible> /// <https://immersive-web.github.io/webxr/#dom-webglrenderingcontextbase-makexrcompatible>
fn MakeXRCompatible(&self) -> 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()); let p = Promise::new(&self.global(), can_gc);
p.resolve_native(&()); p.resolve_native(&());
p p
} }

View file

@ -4688,9 +4688,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
} }
/// <https://immersive-web.github.io/webxr/#dom-webglrenderingcontextbase-makexrcompatible> /// <https://immersive-web.github.io/webxr/#dom-webglrenderingcontextbase-makexrcompatible>
fn MakeXRCompatible(&self) -> 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()); let p = Promise::new(&self.global(), can_gc);
p.resolve_native(&()); p.resolve_native(&());
p p
} }

View file

@ -932,10 +932,11 @@ impl WindowMethods for Window {
&self, &self,
image: ImageBitmapSource, image: ImageBitmapSource,
options: &ImageBitmapOptions, options: &ImageBitmapOptions,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let p = self let p = self
.upcast::<GlobalScope>() .upcast::<GlobalScope>()
.create_image_bitmap(image, options); .create_image_bitmap(image, options, can_gc);
p p
} }

View file

@ -389,10 +389,11 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
&self, &self,
image: ImageBitmapSource, image: ImageBitmapSource,
options: &ImageBitmapOptions, options: &ImageBitmapOptions,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let p = self let p = self
.upcast::<GlobalScope>() .upcast::<GlobalScope>()
.create_image_bitmap(image, options); .create_image_bitmap(image, options, can_gc);
p p
} }

View file

@ -49,7 +49,7 @@ use crate::dom::workletglobalscope::{
}; };
use crate::fetch::load_whole_resource; use crate::fetch::load_whole_resource;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::{CommonScriptMsg, Runtime, ScriptThreadEventCategory}; use crate::script_runtime::{CanGc, CommonScriptMsg, Runtime, ScriptThreadEventCategory};
use crate::script_thread::{MainThreadScriptMsg, ScriptThread}; use crate::script_thread::{MainThreadScriptMsg, ScriptThread};
use crate::task::TaskBox; use crate::task::TaskBox;
use crate::task_source::TaskSourceName; use crate::task_source::TaskSourceName;
@ -123,9 +123,10 @@ impl WorkletMethods for Worklet {
module_url: USVString, module_url: USVString,
options: &WorkletOptions, options: &WorkletOptions,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 3. // Step 3.
let module_url_record = match self.window.Document().base_url().join(&module_url.0) { let module_url_record = match self.window.Document().base_url().join(&module_url.0) {

View file

@ -831,7 +831,7 @@ impl XRSessionMethods for XRSession {
comp: InRealm, comp: InRealm,
can_gc: CanGc, can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let p = Promise::new_in_current_realm(comp); let p = Promise::new_in_current_realm(comp, can_gc);
// https://immersive-web.github.io/webxr/#create-a-reference-space // https://immersive-web.github.io/webxr/#create-a-reference-space
@ -892,7 +892,7 @@ impl XRSessionMethods for XRSession {
/// <https://immersive-web.github.io/webxr/#dom-xrsession-end> /// <https://immersive-web.github.io/webxr/#dom-xrsession-end>
fn End(&self, can_gc: CanGc) -> Rc<Promise> { fn End(&self, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let p = Promise::new(&global); let p = Promise::new(&global, can_gc);
if self.ended.get() && self.end_promises.borrow().is_empty() { if self.ended.get() && self.end_promises.borrow().is_empty() {
// If the session has completely ended and all end promises have been resolved, // If the session has completely ended and all end promises have been resolved,
// don't queue up more end promises // don't queue up more end promises
@ -922,8 +922,8 @@ impl XRSessionMethods for XRSession {
} }
// https://immersive-web.github.io/hit-test/#dom-xrsession-requesthittestsource // https://immersive-web.github.io/hit-test/#dom-xrsession-requesthittestsource
fn RequestHitTestSource(&self, options: &XRHitTestOptionsInit) -> Rc<Promise> { fn RequestHitTestSource(&self, options: &XRHitTestOptionsInit, can_gc: CanGc) -> Rc<Promise> {
let p = Promise::new(&self.global()); let p = Promise::new(&self.global(), can_gc);
if !self if !self
.session .session
@ -1025,10 +1025,15 @@ impl XRSessionMethods for XRSession {
} }
/// <https://www.w3.org/TR/webxr/#dom-xrsession-updatetargetframerate> /// <https://www.w3.org/TR/webxr/#dom-xrsession-updatetargetframerate>
fn UpdateTargetFrameRate(&self, rate: Finite<f32>, comp: InRealm) -> Rc<Promise> { fn UpdateTargetFrameRate(
&self,
rate: Finite<f32>,
comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> {
let mut session = self.session.borrow_mut(); let mut session = self.session.borrow_mut();
let supported_frame_rates = session.supported_frame_rates(); let supported_frame_rates = session.supported_frame_rates();
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
if self.mode == XRSessionMode::Inline || if self.mode == XRSessionMode::Inline ||
supported_frame_rates.is_empty() || supported_frame_rates.is_empty() ||

View file

@ -32,6 +32,7 @@ use crate::dom::window::Window;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use crate::dom::xrtest::XRTest; use crate::dom::xrtest::XRTest;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
@ -111,9 +112,9 @@ impl From<XRSessionMode> for SessionMode {
impl XRSystemMethods for XRSystem { impl XRSystemMethods for XRSystem {
/// <https://immersive-web.github.io/webxr/#dom-xr-issessionsupported> /// <https://immersive-web.github.io/webxr/#dom-xr-issessionsupported>
fn IsSessionSupported(&self, mode: XRSessionMode) -> Rc<Promise> { fn IsSessionSupported(&self, mode: XRSessionMode, can_gc: CanGc) -> Rc<Promise> {
// XXXManishearth this should select an XR device first // XXXManishearth this should select an XR device first
let promise = Promise::new(&self.global()); let promise = Promise::new(&self.global(), can_gc);
let mut trusted = Some(TrustedPromise::new(promise.clone())); let mut trusted = Some(TrustedPromise::new(promise.clone()));
let global = self.global(); let global = self.global();
let window = global.as_window(); let window = global.as_window();
@ -160,10 +161,11 @@ impl XRSystemMethods for XRSystem {
mode: XRSessionMode, mode: XRSessionMode,
init: RootedTraceableBox<XRSessionInit>, init: RootedTraceableBox<XRSessionInit>,
comp: InRealm, comp: InRealm,
can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let window = global.as_window(); let window = global.as_window();
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
if mode != XRSessionMode::Inline { if mode != XRSessionMode::Inline {
if !ScriptThread::is_user_interacting() { if !ScriptThread::is_user_interacting() {

View file

@ -25,6 +25,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::fakexrdevice::{get_origin, get_views, get_world, FakeXRDevice}; use crate::dom::fakexrdevice::{get_origin, get_views, get_world, FakeXRDevice};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
@ -67,9 +68,9 @@ impl XRTest {
impl XRTestMethods for XRTest { impl XRTestMethods for XRTest {
/// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md> /// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md>
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn SimulateDeviceConnection(&self, init: &FakeXRDeviceInit) -> Rc<Promise> { fn SimulateDeviceConnection(&self, init: &FakeXRDeviceInit, can_gc: CanGc) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let p = Promise::new(&global); let p = Promise::new(&global, can_gc);
let origin = if let Some(ref o) = init.viewerOrigin { let origin = if let Some(ref o) = init.viewerOrigin {
match get_origin(o) { match get_origin(o) {
@ -188,10 +189,10 @@ impl XRTestMethods for XRTest {
} }
/// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md> /// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md>
fn DisconnectAllDevices(&self) -> Rc<Promise> { fn DisconnectAllDevices(&self, can_gc: CanGc) -> Rc<Promise> {
// XXXManishearth implement device disconnection and session ending // XXXManishearth implement device disconnection and session ending
let global = self.global(); let global = self.global();
let p = Promise::new(&global); 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(&());

View file

@ -144,7 +144,7 @@ pub fn Fetch(
can_gc: CanGc, can_gc: CanGc,
) -> Rc<Promise> { ) -> Rc<Promise> {
// Step 1. Let p be a new promise. // Step 1. Let p be a new promise.
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp, can_gc);
// Step 7. Let responseObject be null. // Step 7. Let responseObject be null.
// NOTE: We do initialize the object earlier earlier so we can use it to track errors // NOTE: We do initialize the object earlier earlier so we can use it to track errors

View file

@ -338,6 +338,7 @@ impl ModuleTree {
owner: ModuleOwner, owner: ModuleOwner,
module_identity: ModuleIdentity, module_identity: ModuleIdentity,
fetch_options: ScriptFetchOptions, fetch_options: ScriptFetchOptions,
can_gc: CanGc,
) { ) {
let this = owner.clone(); let this = owner.clone();
let identity = module_identity.clone(); let identity = module_identity.clone();
@ -359,10 +360,10 @@ impl ModuleTree {
let mut promise = self.promise.borrow_mut(); let mut promise = self.promise.borrow_mut();
match promise.as_ref() { match promise.as_ref() {
Some(promise) => promise.append_native_handler(&handler, comp), Some(promise) => promise.append_native_handler(&handler, comp, can_gc),
None => { None => {
let new_promise = Promise::new_in_current_realm(comp); let new_promise = Promise::new_in_current_realm(comp, can_gc);
new_promise.append_native_handler(&handler, comp); new_promise.append_native_handler(&handler, comp, can_gc);
*promise = Some(new_promise); *promise = Some(new_promise);
}, },
} }
@ -373,6 +374,7 @@ impl ModuleTree {
owner: ModuleOwner, owner: ModuleOwner,
module_identity: ModuleIdentity, module_identity: ModuleIdentity,
dynamic_module: RootedTraceableBox<DynamicModule>, dynamic_module: RootedTraceableBox<DynamicModule>,
can_gc: CanGc,
) { ) {
let this = owner.clone(); let this = owner.clone();
let identity = module_identity.clone(); let identity = module_identity.clone();
@ -395,10 +397,10 @@ impl ModuleTree {
let mut promise = self.promise.borrow_mut(); let mut promise = self.promise.borrow_mut();
match promise.as_ref() { match promise.as_ref() {
Some(promise) => promise.append_native_handler(&handler, comp), Some(promise) => promise.append_native_handler(&handler, comp, can_gc),
None => { None => {
let new_promise = Promise::new_in_current_realm(comp); let new_promise = Promise::new_in_current_realm(comp, can_gc);
new_promise.append_native_handler(&handler, comp); new_promise.append_native_handler(&handler, comp, can_gc);
*promise = Some(new_promise); *promise = Some(new_promise);
}, },
} }
@ -692,6 +694,7 @@ impl ModuleTree {
destination: Destination, destination: Destination,
options: &ScriptFetchOptions, options: &ScriptFetchOptions,
parent_identity: ModuleIdentity, parent_identity: ModuleIdentity,
can_gc: CanGc,
) { ) {
debug!("Start to load dependencies of {}", self.url); debug!("Start to load dependencies of {}", self.url);
@ -775,6 +778,7 @@ impl ModuleTree {
Some(parent_identity.clone()), Some(parent_identity.clone()),
false, false,
None, None,
can_gc,
); );
} }
}, },
@ -1173,6 +1177,7 @@ impl FetchResponseListener for ModuleContext {
self.destination, self.destination,
&self.options, &self.options,
ModuleIdentity::ModuleUrl(self.url.clone()), ModuleIdentity::ModuleUrl(self.url.clone()),
CanGc::note(),
); );
}, },
} }
@ -1272,6 +1277,7 @@ pub unsafe extern "C" fn host_import_module_dynamically(
base_url, base_url,
options, options,
promise, promise,
CanGc::note(),
) { ) {
JS_SetPendingException(*cx, e.handle(), ExceptionStackBehavior::Capture); JS_SetPendingException(*cx, e.handle(), ExceptionStackBehavior::Capture);
return false; return false;
@ -1340,6 +1346,7 @@ fn fetch_an_import_module_script_graph(
base_url: ServoUrl, base_url: ServoUrl,
options: ScriptFetchOptions, options: ScriptFetchOptions,
promise: Rc<Promise>, promise: Rc<Promise>,
can_gc: CanGc,
) -> Result<(), RethrowError> { ) -> Result<(), RethrowError> {
// Step 1. // Step 1.
let cx = GlobalScope::get_cx(); let cx = GlobalScope::get_cx();
@ -1390,6 +1397,7 @@ fn fetch_an_import_module_script_graph(
None, None,
true, true,
Some(dynamic_module), Some(dynamic_module),
can_gc,
); );
Ok(()) Ok(())
} }
@ -1487,6 +1495,7 @@ pub(crate) fn fetch_external_module_script(
url: ServoUrl, url: ServoUrl,
destination: Destination, destination: Destination,
options: ScriptFetchOptions, options: ScriptFetchOptions,
can_gc: CanGc,
) { ) {
let mut visited_urls = HashSet::new(); let mut visited_urls = HashSet::new();
visited_urls.insert(url.clone()); visited_urls.insert(url.clone());
@ -1501,6 +1510,7 @@ pub(crate) fn fetch_external_module_script(
None, None,
true, true,
None, None,
can_gc,
) )
} }
@ -1563,6 +1573,7 @@ fn fetch_single_module_script(
parent_identity: Option<ModuleIdentity>, parent_identity: Option<ModuleIdentity>,
top_level_module_fetch: bool, top_level_module_fetch: bool,
dynamic_module: Option<RootedTraceableBox<DynamicModule>>, dynamic_module: Option<RootedTraceableBox<DynamicModule>>,
can_gc: CanGc,
) { ) {
{ {
// Step 1. // Step 1.
@ -1581,11 +1592,13 @@ fn fetch_single_module_script(
owner.clone(), owner.clone(),
ModuleIdentity::ModuleUrl(url.clone()), ModuleIdentity::ModuleUrl(url.clone()),
module, module,
can_gc,
), ),
None if top_level_module_fetch => module_tree.append_handler( None if top_level_module_fetch => module_tree.append_handler(
owner.clone(), owner.clone(),
ModuleIdentity::ModuleUrl(url.clone()), ModuleIdentity::ModuleUrl(url.clone()),
options, options,
can_gc,
), ),
// do nothing if it's neither a dynamic module nor a top level module // do nothing if it's neither a dynamic module nor a top level module
None => {}, None => {},
@ -1621,11 +1634,13 @@ fn fetch_single_module_script(
owner.clone(), owner.clone(),
ModuleIdentity::ModuleUrl(url.clone()), ModuleIdentity::ModuleUrl(url.clone()),
module, module,
can_gc,
), ),
None if top_level_module_fetch => module_tree.append_handler( None if top_level_module_fetch => module_tree.append_handler(
owner.clone(), owner.clone(),
ModuleIdentity::ModuleUrl(url.clone()), ModuleIdentity::ModuleUrl(url.clone()),
options.clone(), options.clone(),
can_gc,
), ),
// do nothing if it's neither a dynamic module nor a top level module // do nothing if it's neither a dynamic module nor a top level module
None => {}, None => {},
@ -1702,6 +1717,7 @@ pub(crate) fn fetch_inline_module_script(
url: ServoUrl, url: ServoUrl,
script_id: ScriptId, script_id: ScriptId,
options: ScriptFetchOptions, options: ScriptFetchOptions,
can_gc: CanGc,
) { ) {
let global = owner.global(); let global = owner.global();
let is_external = false; let is_external = false;
@ -1721,6 +1737,7 @@ pub(crate) fn fetch_inline_module_script(
owner.clone(), owner.clone(),
ModuleIdentity::ScriptId(script_id), ModuleIdentity::ScriptId(script_id),
options.clone(), options.clone(),
can_gc,
); );
module_tree.set_record(record); module_tree.set_record(record);
@ -1740,6 +1757,7 @@ pub(crate) fn fetch_inline_module_script(
Destination::Script, Destination::Script,
&options, &options,
ModuleIdentity::ScriptId(script_id), ModuleIdentity::ScriptId(script_id),
can_gc,
); );
}, },
Err(exception) => { Err(exception) => {

View file

@ -1939,7 +1939,7 @@ impl ScriptThread {
}, },
FromConstellation(ConstellationControlMsg::ExitFullScreen(id)) => self FromConstellation(ConstellationControlMsg::ExitFullScreen(id)) => self
.profile_event(ScriptThreadEventCategory::ExitFullscreen, Some(id), || { .profile_event(ScriptThreadEventCategory::ExitFullscreen, Some(id), || {
self.handle_exit_fullscreen(id); self.handle_exit_fullscreen(id, can_gc);
}), }),
_ => { _ => {
sequential.push(event); sequential.push(event);
@ -2914,11 +2914,11 @@ impl ScriptThread {
} }
// exit_fullscreen creates a new JS promise object, so we need to have entered a realm // exit_fullscreen creates a new JS promise object, so we need to have entered a realm
fn handle_exit_fullscreen(&self, id: PipelineId) { fn handle_exit_fullscreen(&self, id: PipelineId, can_gc: CanGc) {
let document = self.documents.borrow().find_document(id); let document = self.documents.borrow().find_document(id);
if let Some(document) = document { if let Some(document) = document {
let _ac = enter_realm(&*document); let _ac = enter_realm(&*document);
document.exit_fullscreen(); document.exit_fullscreen(can_gc);
} }
} }