diff options
Diffstat (limited to 'components/script/dom')
29 files changed, 219 insertions, 88 deletions
diff --git a/components/script/dom/audiocontext.rs b/components/script/dom/audiocontext.rs index 0d980a8f729..52695f8ae54 100644 --- a/components/script/dom/audiocontext.rs +++ b/components/script/dom/audiocontext.rs @@ -107,9 +107,10 @@ impl AudioContextMethods for AudioContext { } // https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend + #[allow(unsafe_code)] fn Suspend(&self) -> Rc<Promise> { // Step 1. - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 2. if self.context.control_thread_state() == ProcessingState::Closed { @@ -168,9 +169,10 @@ impl AudioContextMethods for AudioContext { } // https://webaudio.github.io/web-audio-api/#dom-audiocontext-close + #[allow(unsafe_code)] fn Close(&self) -> Rc<Promise> { // Step 1. - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 2. if self.context.control_thread_state() == ProcessingState::Closed { diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs index 96f21eeddfc..cebda5a26dd 100644 --- a/components/script/dom/baseaudiocontext.rs +++ b/components/script/dom/baseaudiocontext.rs @@ -273,9 +273,10 @@ impl BaseAudioContextMethods for BaseAudioContext { } /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-resume + #[allow(unsafe_code)] fn Resume(&self) -> Rc<Promise> { // Step 1. - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 2. if self.audio_context_impl.state() == ProcessingState::Closed { @@ -405,6 +406,7 @@ impl BaseAudioContextMethods for BaseAudioContext { } // https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-decodeaudiodata + #[allow(unsafe_code)] fn DecodeAudioData( &self, audio_data: CustomAutoRooterGuard<ArrayBuffer>, @@ -412,7 +414,7 @@ impl BaseAudioContextMethods for BaseAudioContext { decode_error_callback: Option<Rc<DecodeErrorCallback>>, ) -> Rc<Promise> { // Step 1. - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; let global = self.global(); let window = global.as_window(); diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 4b541d4b60a..c218fbce27a 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -278,6 +278,7 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>( } // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren +#[allow(unsafe_code)] pub fn get_gatt_children<T, F>( attribute: &T, single: bool, @@ -291,7 +292,7 @@ where T: AsyncBluetoothListener + DomObject + 'static, F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>, { - let p = Promise::new(&attribute.global()); + let p = unsafe { Promise::new_in_current_compartment(&attribute.global()) }; let result_uuid = if let Some(u) = uuid { // Step 1. @@ -530,8 +531,9 @@ impl From<BluetoothError> for Error { impl BluetoothMethods for Bluetooth { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice + #[allow(unsafe_code)] fn RequestDevice(&self, option: &RequestDeviceOptions) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. if (option.filters.is_some() && option.acceptAllDevices) || (option.filters.is_none() && !option.acceptAllDevices) @@ -548,8 +550,9 @@ impl BluetoothMethods for Bluetooth { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability + #[allow(unsafe_code)] fn GetAvailability(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. We did not override the method // Step 2 - 3. in handle_response let sender = response_async(&p, self); diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index 8e65b1b6723..9a40a1a44cf 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -277,8 +277,9 @@ impl BluetoothDeviceMethods for BluetoothDevice { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements + #[allow(unsafe_code)] fn WatchAdvertisements(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; let sender = response_async(&p, self); // TODO: Step 1. // Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index 7e355749811..812c16d1040 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -134,8 +134,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue + #[allow(unsafe_code)] fn ReadValue(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { @@ -167,8 +168,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue + #[allow(unsafe_code)] fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { @@ -218,8 +220,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications + #[allow(unsafe_code)] fn StartNotifications(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { @@ -255,8 +258,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications + #[allow(unsafe_code)] fn StopNotifications(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; let sender = response_async(&p, self); // TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic, diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs index 983ee355de4..000acdecb6c 100644 --- a/components/script/dom/bluetoothremotegattdescriptor.rs +++ b/components/script/dom/bluetoothremotegattdescriptor.rs @@ -93,8 +93,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue + #[allow(unsafe_code)] fn ReadValue(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { @@ -125,8 +126,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue + #[allow(unsafe_code)] fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index 62810f04091..005f0dad2ca 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -69,9 +69,10 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect + #[allow(unsafe_code)] fn Connect(&self) -> Rc<Promise> { // Step 1. - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; let sender = response_async(&p, self); // TODO: Step 3: Check if the UA is currently using the Bluetooth system. diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 4080731a534..abefc4eca58 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -399,20 +399,21 @@ impl CustomElementRegistryMethods for CustomElementRegistry { } /// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-whendefined> + #[allow(unsafe_code)] fn WhenDefined(&self, name: DOMString) -> Rc<Promise> { let global_scope = self.window.upcast::<GlobalScope>(); let name = LocalName::from(&*name); // Step 1 if !is_valid_custom_element_name(&name) { - let promise = Promise::new(global_scope); + let promise = unsafe { Promise::new_in_current_compartment(global_scope) }; promise.reject_native(&DOMException::new(global_scope, DOMErrorName::SyntaxError)); return promise; } // Step 2 if self.definitions.borrow().contains_key(&name) { - let promise = Promise::new(global_scope); + let promise = unsafe { Promise::new_in_current_compartment(global_scope) }; promise.resolve_native(&UndefinedValue()); return promise; } @@ -422,7 +423,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry { // Steps 4, 5 let promise = map.get(&name).cloned().unwrap_or_else(|| { - let promise = Promise::new(global_scope); + let promise = unsafe { Promise::new_in_current_compartment(global_scope) }; map.insert(name, promise.clone()); promise }); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index b3f08964502..3d890357e16 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -3129,9 +3129,10 @@ impl Document { } // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen + #[allow(unsafe_code)] pub fn enter_fullscreen(&self, pending: &Element) -> Rc<Promise> { // Step 1 - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; let mut error = false; // Step 4 @@ -3195,10 +3196,11 @@ impl Document { } // https://fullscreen.spec.whatwg.org/#exit-fullscreen + #[allow(unsafe_code)] pub fn exit_fullscreen(&self) -> Rc<Promise> { let global = self.global(); // Step 1 - let promise = Promise::new(&global); + let promise = unsafe { Promise::new_in_current_compartment(&global) }; // Step 2 if self.fullscreen_element.get().is_none() { promise.reject_error(Error::Type(String::from("fullscreen is null"))); diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index dbc952688b1..f20a9d3ff7f 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -1651,8 +1651,9 @@ impl HTMLMediaElementMethods for HTMLMediaElement { } // https://html.spec.whatwg.org/multipage/#dom-media-play + #[allow(unsafe_code)] fn Play(&self) -> Rc<Promise> { - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; // Step 1. // FIXME(nox): Reject promise if not allowed to play. diff --git a/components/script/dom/mediadevices.rs b/components/script/dom/mediadevices.rs index 808ce22c2af..0c8049ff4d1 100644 --- a/components/script/dom/mediadevices.rs +++ b/components/script/dom/mediadevices.rs @@ -44,8 +44,9 @@ impl MediaDevices { impl MediaDevicesMethods for MediaDevices { /// https://w3c.github.io/mediacapture-main/#dom-mediadevices-getusermedia + #[allow(unsafe_code)] fn GetUserMedia(&self, constraints: &MediaStreamConstraints) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; let media = ServoMedia::get().unwrap(); let mut tracks = vec![]; if let Some(constraints) = convert_constraints(&constraints.audio) { diff --git a/components/script/dom/navigationpreloadmanager.rs b/components/script/dom/navigationpreloadmanager.rs index 5eca51a5226..d07be1b070e 100644 --- a/components/script/dom/navigationpreloadmanager.rs +++ b/components/script/dom/navigationpreloadmanager.rs @@ -43,8 +43,9 @@ impl NavigationPreloadManager { impl NavigationPreloadManagerMethods for NavigationPreloadManager { // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-enable + #[allow(unsafe_code)] fn Enable(&self) -> Rc<Promise> { - let promise = Promise::new(&*self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&*self.global()) }; // 2. if self.serviceworker_registration.active().is_none() { @@ -65,8 +66,9 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager { } // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-disable + #[allow(unsafe_code)] fn Disable(&self) -> Rc<Promise> { - let promise = Promise::new(&*self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&*self.global()) }; // 2. if self.serviceworker_registration.active().is_none() { @@ -87,8 +89,9 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager { } // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-setheadervalue + #[allow(unsafe_code)] fn SetHeaderValue(&self, value: ByteString) -> Rc<Promise> { - let promise = Promise::new(&*self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&*self.global()) }; // 2. if self.serviceworker_registration.active().is_none() { @@ -109,8 +112,9 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager { } // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-getstate + #[allow(unsafe_code)] fn GetState(&self) -> Rc<Promise> { - let promise = Promise::new(&*self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&*self.global()) }; // 2. let mut state = NavigationPreloadState::empty(); diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index 03899baf97e..254b55a1113 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -150,8 +150,9 @@ impl NavigatorMethods for Navigator { } // https://w3c.github.io/webvr/spec/1.1/#navigator-getvrdisplays-attribute + #[allow(unsafe_code)] fn GetVRDisplays(&self) -> Rc<Promise> { - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; let displays = self.Xr().get_displays(); match displays { Ok(displays) => promise.resolve_native(&displays), diff --git a/components/script/dom/offlineaudiocontext.rs b/components/script/dom/offlineaudiocontext.rs index b17b0ff73d8..2fba02bc88a 100644 --- a/components/script/dom/offlineaudiocontext.rs +++ b/components/script/dom/offlineaudiocontext.rs @@ -113,8 +113,9 @@ impl OfflineAudioContextMethods for OfflineAudioContext { } // https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering + #[allow(unsafe_code)] fn StartRendering(&self) -> Rc<Promise> { - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; if self.rendering_started.get() { promise.reject_error(Error::InvalidState); return promise; diff --git a/components/script/dom/permissions.rs b/components/script/dom/permissions.rs index 3732c60d191..6886532d1ab 100644 --- a/components/script/dom/permissions.rs +++ b/components/script/dom/permissions.rs @@ -87,6 +87,7 @@ impl Permissions { // https://w3c.github.io/permissions/#dom-permissions-query // https://w3c.github.io/permissions/#dom-permissions-request // https://w3c.github.io/permissions/#dom-permissions-revoke + #[allow(unsafe_code)] fn manipulate( &self, op: Operation, @@ -97,7 +98,7 @@ impl Permissions { // (Query, Request) Step 3. let p = match promise { Some(promise) => promise, - None => Promise::new(&self.global()), + None => unsafe { Promise::new_in_current_compartment(&self.global()) }, }; // (Query, Request, Revoke) Step 1. diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index 734c440f414..9ff4adfe397 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -80,13 +80,16 @@ impl Drop for Promise { impl Promise { #[allow(unsafe_code)] - pub fn new(global: &GlobalScope) -> Rc<Promise> { + pub fn new(global: &GlobalScope, _comp: &JSAutoCompartment) -> Rc<Promise> { + unsafe { Promise::new_in_current_compartment(global) } + } + + #[allow(unsafe_code)] + pub unsafe fn new_in_current_compartment(global: &GlobalScope) -> Rc<Promise> { let cx = global.get_cx(); rooted!(in(cx) let mut obj = ptr::null_mut::<JSObject>()); - unsafe { - Promise::create_js_promise(cx, HandleObject::null(), obj.handle_mut()); - Promise::new_with_js_promise(obj.handle(), cx) - } + Promise::create_js_promise(cx, HandleObject::null(), obj.handle_mut()); + Promise::new_with_js_promise(obj.handle(), cx) } #[allow(unsafe_code)] diff --git a/components/script/dom/rtcpeerconnection.rs b/components/script/dom/rtcpeerconnection.rs index e4948e08d8e..a0a1cfbb6e9 100644 --- a/components/script/dom/rtcpeerconnection.rs +++ b/components/script/dom/rtcpeerconnection.rs @@ -429,8 +429,9 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { ); /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate + #[allow(unsafe_code)] fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() { p.reject_error(Error::Type(format!( "one of sdpMid and sdpMLineIndex must be set" @@ -464,8 +465,9 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { } /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer + #[allow(unsafe_code)] fn CreateOffer(&self, _options: &RTCOfferOptions) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; if self.closed.get() { p.reject_error(Error::InvalidState); return p; @@ -476,8 +478,9 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { } /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer + #[allow(unsafe_code)] fn CreateAnswer(&self, _options: &RTCAnswerOptions) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; if self.closed.get() { p.reject_error(Error::InvalidState); return p; @@ -498,9 +501,10 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { } /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setlocaldescription + #[allow(unsafe_code)] fn SetLocalDescription(&self, desc: &RTCSessionDescriptionInit) -> Rc<Promise> { // XXXManishearth validate the current state - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; let this = Trusted::new(self); let desc: SessionDescription = desc.into(); let trusted_promise = TrustedPromise::new(p.clone()); @@ -531,9 +535,10 @@ impl RTCPeerConnectionMethods for RTCPeerConnection { } /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setremotedescription + #[allow(unsafe_code)] fn SetRemoteDescription(&self, desc: &RTCSessionDescriptionInit) -> Rc<Promise> { // XXXManishearth validate the current state - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; let this = Trusted::new(self); let desc: SessionDescription = desc.into(); let trusted_promise = TrustedPromise::new(p.clone()); diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs index 9ddd5a37922..74458548efe 100644 --- a/components/script/dom/serviceworkercontainer.rs +++ b/components/script/dom/serviceworkercontainer.rs @@ -54,9 +54,10 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer { #[allow(unrooted_must_root)] // Job is unrooted /// https://w3c.github.io/ServiceWorker/#service-worker-container-register-method and - A /// https://w3c.github.io/ServiceWorker/#start-register-algorithm - B + #[allow(unsafe_code)] fn Register(&self, script_url: USVString, options: &RegistrationOptions) -> Rc<Promise> { // A: Step 1 - let promise = Promise::new(&*self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&*self.global()) }; let USVString(ref script_url) = script_url; let api_base_url = self.global().api_base_url(); // A: Step 3-5 diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index 505e51325a9..f5d64a478de 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -1009,6 +1009,7 @@ impl TestBindingMethods for TestBinding { ); } + #[allow(unsafe_code)] fn PromiseNativeHandler( &self, resolve: Option<Rc<SimpleCallback>>, @@ -1020,7 +1021,7 @@ impl TestBindingMethods for TestBinding { resolve.map(SimpleHandler::new), reject.map(SimpleHandler::new), ); - let p = Promise::new(&global); + let p = unsafe { Promise::new_in_current_compartment(&global) }; p.append_native_handler(&handler); return p; @@ -1043,8 +1044,9 @@ impl TestBindingMethods for TestBinding { } } + #[allow(unsafe_code)] fn PromiseAttribute(&self) -> Rc<Promise> { - Promise::new(&self.global()) + unsafe { Promise::new_in_current_compartment(&self.global()) } } fn AcceptPromise(&self, _promise: &Promise) {} diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 3bcfbddd3b9..723e7d3935d 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -341,8 +341,9 @@ impl VRDisplayMethods for VRDisplay { } // https://w3c.github.io/webvr/#dom-vrdisplay-requestpresent + #[allow(unsafe_code)] fn RequestPresent(&self, layers: Vec<VRLayer>) -> Rc<Promise> { - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; // TODO: WebVR spec: this method must be called in response to a user gesture // WebVR spec: If canPresent is false the promise MUST be rejected @@ -405,8 +406,9 @@ impl VRDisplayMethods for VRDisplay { } // https://w3c.github.io/webvr/#dom-vrdisplay-exitpresent + #[allow(unsafe_code)] fn ExitPresent(&self) -> Rc<Promise> { - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; // WebVR spec: If the VRDisplay is not presenting the promise MUST be rejected. if !self.presenting.get() { diff --git a/components/script/dom/webidls/XRFrame.webidl b/components/script/dom/webidls/XRFrame.webidl index 24f714fcb76..a393acbc588 100644 --- a/components/script/dom/webidls/XRFrame.webidl +++ b/components/script/dom/webidls/XRFrame.webidl @@ -8,6 +8,7 @@ interface XRFrame { readonly attribute XRSession session; - XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); + [Throws] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); + [Throws] XRPose? getPose(XRSpace space, XRSpace relativeTo); // XRInputPose? getInputPose(XRInputSource inputSource, optional XRReferenceSpace referenceSpace); }; diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index 5f2cfb23929..f22918d469d 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -20,6 +20,7 @@ interface XRSession : EventTarget { readonly attribute XREnvironmentBlendMode environmentBlendMode; readonly attribute XRRenderState renderState; + readonly attribute XRSpace viewerSpace; // // Methods Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceOptions options); diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index 16d7ccb5f6b..abca41f787c 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -110,9 +110,10 @@ impl Worklet { impl WorkletMethods for Worklet { /// <https://drafts.css-houdini.org/worklets/#dom-worklet-addmodule> + #[allow(unsafe_code)] fn AddModule(&self, module_url: USVString, options: &WorkletOptions) -> Rc<Promise> { // Step 1. - let promise = Promise::new(self.window.upcast()); + let promise = unsafe { Promise::new_in_current_compartment(self.window.upcast()) }; // Step 3. let module_url_record = match self.window.Document().base_url().join(&module_url.0) { diff --git a/components/script/dom/xr.rs b/components/script/dom/xr.rs index 13838ac2b20..95fc5003c2a 100644 --- a/components/script/dom/xr.rs +++ b/components/script/dom/xr.rs @@ -83,9 +83,10 @@ impl Drop for XR { impl XRMethods for XR { /// https://immersive-web.github.io/webxr/#dom-xr-supportssessionmode + #[allow(unsafe_code)] fn SupportsSessionMode(&self, mode: XRSessionMode) -> Rc<Promise> { // XXXManishearth this should select an XR device first - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; if mode == XRSessionMode::Immersive_vr { promise.resolve_native(&()); } else { @@ -97,8 +98,9 @@ impl XRMethods for XR { } /// https://immersive-web.github.io/webxr/#dom-xr-requestsession + #[allow(unsafe_code)] fn RequestSession(&self, options: &XRSessionCreationOptions) -> Rc<Promise> { - let promise = Promise::new(&self.global()); + let promise = unsafe { Promise::new_in_current_compartment(&self.global()) }; if options.mode != XRSessionMode::Immersive_vr { promise.reject_error(Error::NotSupported); return promise; diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index c9bb240a3bf..67602709d9b 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -4,11 +4,15 @@ use crate::dom::bindings::codegen::Bindings::XRFrameBinding; use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods; +use crate::dom::bindings::error::Error; +use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; +use crate::dom::xrpose::XRPose; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; +use crate::dom::xrspace::XRSpace; use crate::dom::xrviewerpose::XRViewerPose; use dom_struct::dom_struct; use webvr_traits::WebVRFrameData; @@ -50,13 +54,34 @@ impl XRFrameMethods for XRFrame { } /// https://immersive-web.github.io/webxr/#dom-xrframe-getviewerpose - fn GetViewerPose(&self, reference: &XRReferenceSpace) -> Option<DomRoot<XRViewerPose>> { + fn GetViewerPose( + &self, + reference: &XRReferenceSpace, + ) -> Result<Option<DomRoot<XRViewerPose>>, Error> { + if self.session != reference.upcast::<XRSpace>().session() { + return Err(Error::InvalidState); + } let pose = reference.get_viewer_pose(&self.data); - Some(XRViewerPose::new( + Ok(Some(XRViewerPose::new( &self.global(), &self.session, pose, &self.data, - )) + ))) + } + + /// https://immersive-web.github.io/webxr/#dom-xrframe-getpose + fn GetPose( + &self, + space: &XRSpace, + relative_to: &XRSpace, + ) -> Result<Option<DomRoot<XRPose>>, Error> { + if self.session != space.session() || self.session != relative_to.session() { + return Err(Error::InvalidState); + } + let space = space.get_pose(&self.data); + let relative_to = relative_to.get_pose(&self.data); + let pose = relative_to.inverse().pre_mul(&space); + Ok(Some(XRPose::new(&self.global(), pose))) } } diff --git a/components/script/dom/xrreferencespace.rs b/components/script/dom/xrreferencespace.rs index ed42d63b4be..804768eee69 100644 --- a/components/script/dom/xrreferencespace.rs +++ b/components/script/dom/xrreferencespace.rs @@ -54,9 +54,12 @@ impl XRReferenceSpaceMethods for XRReferenceSpace { } impl XRReferenceSpace { - /// Gets viewer pose represented by this space + /// Gets pose of the viewer with respect to this space + /// + /// This is equivalent to `get_pose(self).inverse() * get_pose(viewerSpace)`, however + /// we specialize it to be efficient pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { - let pose = self.get_pose(base_pose); + let pose = self.get_unoffset_viewer_pose(base_pose); // This may change, see https://github.com/immersive-web/webxr/issues/567 let offset = self.transform.get().transform(); @@ -64,16 +67,44 @@ impl XRReferenceSpace { inverse.pre_mul(&pose) } - /// Gets pose represented by this space + /// Gets pose of the viewer with respect to this space /// /// Does not apply originOffset, use get_viewer_pose instead if you need it - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { + pub fn get_unoffset_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { if let Some(stationary) = self.downcast::<XRStationaryReferenceSpace>() { - stationary.get_pose(base_pose) + stationary.get_unoffset_viewer_pose(base_pose) } else { // non-subclassed XRReferenceSpaces exist, obtained via the "identity" - // type. The pose does not depend on the base pose. + // type. These poses are equivalent to the viewer pose and follow the headset + // around, so the viewer is always at an identity transform with respect to them RigidTransform3D::identity() } } + + /// Gets pose represented by this space + /// + /// The reference origin used is common between all + /// get_pose calls for spaces from the same device, so this can be used to compare + /// with other spaces + pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { + let pose = self.get_unoffset_pose(base_pose); + + // This may change, see https://github.com/immersive-web/webxr/issues/567 + let offset = self.transform.get().transform(); + offset.post_mul(&pose) + } + + /// Gets pose represented by this space + /// + /// Does not apply originOffset, use get_viewer_pose instead if you need it + pub fn get_unoffset_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { + if let Some(stationary) = self.downcast::<XRStationaryReferenceSpace>() { + stationary.get_unoffset_pose(base_pose) + } else { + // non-subclassed XRReferenceSpaces exist, obtained via the "identity" + // type. These are equivalent to the viewer pose and follow the headset + // around + XRSpace::viewer_pose_from_frame_data(base_pose) + } + } } diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index bf7dcb92258..3b126ce445a 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -21,6 +21,7 @@ use crate::dom::vrdisplay::VRDisplay; use crate::dom::xrlayer::XRLayer; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrenderstate::XRRenderState; +use crate::dom::xrspace::XRSpace; use crate::dom::xrstationaryreferencespace::XRStationaryReferenceSpace; use dom_struct::dom_struct; use std::rc::Rc; @@ -82,9 +83,15 @@ impl XRSessionMethods for XRSession { ) } + // https://immersive-web.github.io/webxr/#dom-xrsession-viewerspace + fn ViewerSpace(&self) -> DomRoot<XRSpace> { + XRSpace::new_viewerspace(&self.global(), &self) + } + /// https://immersive-web.github.io/webxr/#dom-xrsession-requestanimationframe + #[allow(unsafe_code)] fn UpdateRenderState(&self, init: &XRRenderStateInit) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; self.display.queue_renderstate(init, p.clone()); p } @@ -105,8 +112,9 @@ impl XRSessionMethods for XRSession { } /// https://immersive-web.github.io/webxr/#dom-xrsession-requestreferencespace + #[allow(unsafe_code)] fn RequestReferenceSpace(&self, options: &XRReferenceSpaceOptions) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let p = unsafe { Promise::new_in_current_compartment(&self.global()) }; // https://immersive-web.github.io/webxr/#create-a-reference-space diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index 60589be4054..8948ac03c8e 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -11,13 +11,14 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; -use euclid::RigidTransform3D; +use euclid::{RigidTransform3D, Rotation3D, Vector3D}; use webvr_traits::WebVRFrameData; #[dom_struct] pub struct XRSpace { eventtarget: EventTarget, session: Dom<XRSession>, + is_viewerspace: bool, } impl XRSpace { @@ -25,13 +26,21 @@ impl XRSpace { XRSpace { eventtarget: EventTarget::new_inherited(), session: Dom::from_ref(session), + is_viewerspace: false, } } - #[allow(unused)] - pub fn new(global: &GlobalScope, session: &XRSession) -> DomRoot<XRSpace> { + fn new_viewerspace_inner(session: &XRSession) -> XRSpace { + XRSpace { + eventtarget: EventTarget::new_inherited(), + session: Dom::from_ref(session), + is_viewerspace: true, + } + } + + pub fn new_viewerspace(global: &GlobalScope, session: &XRSession) -> DomRoot<XRSpace> { reflect_dom_object( - Box::new(XRSpace::new_inherited(session)), + Box::new(XRSpace::new_viewerspace_inner(session)), global, XRSpaceBinding::Wrap, ) @@ -39,25 +48,35 @@ impl XRSpace { } impl XRSpace { - /// Gets viewer pose represented by this space - #[allow(unused)] - pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { - if let Some(reference) = self.downcast::<XRReferenceSpace>() { - reference.get_viewer_pose(base_pose) - } else { - unreachable!() - } - } - /// Gets pose represented by this space /// - /// Does not apply originOffset, use get_viewer_pose instead if you need it - #[allow(unused)] + /// The reference origin used is common between all + /// get_pose calls for spaces from the same device, so this can be used to compare + /// with other spaces pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { if let Some(reference) = self.downcast::<XRReferenceSpace>() { reference.get_pose(base_pose) + } else if self.is_viewerspace { + XRSpace::viewer_pose_from_frame_data(base_pose) } else { unreachable!() } } + + pub fn viewer_pose_from_frame_data(data: &WebVRFrameData) -> RigidTransform3D<f64> { + let pos = data.pose.position.unwrap_or([0., 0., 0.]); + let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); + let orient = data.pose.orientation.unwrap_or([0., 0., 0., 0.]); + let rotation = Rotation3D::quaternion( + orient[0] as f64, + orient[1] as f64, + orient[2] as f64, + orient[3] as f64, + ); + RigidTransform3D::new(rotation, translation) + } + + pub fn session(&self) -> &XRSession { + &self.session + } } diff --git a/components/script/dom/xrstationaryreferencespace.rs b/components/script/dom/xrstationaryreferencespace.rs index ddba9aaa20b..6c5d53f9457 100644 --- a/components/script/dom/xrstationaryreferencespace.rs +++ b/components/script/dom/xrstationaryreferencespace.rs @@ -10,8 +10,9 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrigidtransform::XRRigidTransform; use crate::dom::xrsession::XRSession; +use crate::dom::xrspace::XRSpace; use dom_struct::dom_struct; -use euclid::{RigidTransform3D, Rotation3D, Vector3D}; +use euclid::RigidTransform3D; use webvr_traits::WebVRFrameData; #[dom_struct] @@ -50,20 +51,22 @@ impl XRStationaryReferenceSpace { } impl XRStationaryReferenceSpace { + /// Gets pose of the viewer with respect to this space + /// + /// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead + pub fn get_unoffset_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { + // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled + XRSpace::viewer_pose_from_frame_data(base_pose) + } + /// Gets pose represented by this space /// - /// Does not apply originOffset, use get_viewer_pose instead - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { + /// Does not apply originOffset, use get_pose on XRReferenceSpace instead + pub fn get_unoffset_pose(&self, _: &WebVRFrameData) -> RigidTransform3D<f64> { // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled - let pos = base_pose.pose.position.unwrap_or([0., 0., 0.]); - let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); - let orient = base_pose.pose.orientation.unwrap_or([0., 0., 0., 0.]); - let rotation = Rotation3D::quaternion( - orient[0] as f64, - orient[1] as f64, - orient[2] as f64, - orient[3] as f64, - ); - RigidTransform3D::new(rotation, translation) + + // The eye-level pose is basically whatever the headset pose was at t=0, which + // for most devices is (0, 0, 0) + RigidTransform3D::identity() } } |