diff options
Diffstat (limited to 'components/script/dom/window.rs')
-rw-r--r-- | components/script/dom/window.rs | 147 |
1 files changed, 100 insertions, 47 deletions
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 7f3b6d1fb8d..37b5b5e3b2c 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -13,11 +13,10 @@ use crate::dom::bindings::codegen::Bindings::MediaQueryListBinding::MediaQueryLi use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::PermissionState; use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit; use crate::dom::bindings::codegen::Bindings::WindowBinding::{ - self, FrameRequestCallback, WindowMethods, + self, FrameRequestCallback, WindowMethods, WindowPostMessageOptions, }; use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use crate::dom::bindings::codegen::UnionTypes::RequestOrUSVString; -use crate::dom::bindings::conversions::ToJSValConvertible; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; @@ -25,7 +24,7 @@ use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::str::{DOMString, USVString}; -use crate::dom::bindings::structuredclone::StructuredCloneData; +use crate::dom::bindings::structuredclone; use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::utils::{GlobalStaticData, WindowProxyHandler}; use crate::dom::bindings::weakref::DOMTracker; @@ -44,7 +43,6 @@ use crate::dom::location::Location; use crate::dom::mediaquerylist::{MediaQueryList, MediaQueryListMatchState}; use crate::dom::mediaquerylistevent::MediaQueryListEvent; use crate::dom::messageevent::MessageEvent; -use crate::dom::messageport::TRANSFERRED_MESSAGE_PORTS; use crate::dom::navigator::Navigator; use crate::dom::node::{document_from_node, from_untrusted_node_address, Node, NodeDamage}; use crate::dom::performance::Performance; @@ -81,6 +79,7 @@ use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect}; use euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; use ipc_channel::ipc::{channel, IpcSender}; use ipc_channel::router::ROUTER; +use js::jsapi::Heap; use js::jsapi::JSAutoRealm; use js::jsapi::JSObject; use js::jsapi::JSPROP_ENUMERATE; @@ -88,7 +87,7 @@ use js::jsapi::{GCReason, JS_GC}; use js::jsval::UndefinedValue; use js::jsval::{JSVal, NullValue}; use js::rust::wrappers::JS_DefineProperty; -use js::rust::{CustomAutoRooterGuard, HandleValue}; +use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue}; use media::WindowGLContext; use msg::constellation_msg::PipelineId; use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse}; @@ -107,7 +106,10 @@ use script_layout_interface::rpc::{ use script_layout_interface::{PendingImageState, TrustedNodeAddress}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use script_traits::{ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData}; -use script_traits::{ScriptMsg, ScriptToConstellationChan, ScrollState, TimerEvent, TimerEventId}; +use script_traits::{ + ScriptMsg, ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerEvent, + TimerEventId, +}; use script_traits::{TimerSchedulerMsg, WindowSizeData, WindowSizeType}; use selectors::attr::CaseSensitivity; use servo_geometry::{f32_rect_to_au_rect, MaxRect}; @@ -976,31 +978,53 @@ impl WindowMethods for Window { &self, cx: JSContext, message: HandleValue, - origin: USVString, - transfer: CustomAutoRooterGuard<Option<Vec<*mut JSObject>>>, + target_origin: USVString, + mut transfer: CustomAutoRooterGuard<Option<Vec<*mut JSObject>>>, ) -> ErrorResult { - let source_global = GlobalScope::incumbent().expect("no incumbent global??"); - let source = source_global.as_window(); + let incumbent = GlobalScope::incumbent().expect("no incumbent global?"); + let source = incumbent.as_window(); + let source_origin = source.Document().origin().immutable().clone(); + + if transfer.is_some() { + let mut rooted = CustomAutoRooter::new(transfer.take().unwrap()); + let transfer = Some(CustomAutoRooterGuard::new(*cx, &mut rooted)); + self.post_message_impl(&target_origin, source_origin, source, cx, message, transfer) + } else { + self.post_message_impl(&target_origin, source_origin, source, cx, message, None) + } + } - // Step 3-5. - let origin = match &origin.0[..] { - "*" => None, - "/" => Some(source.Document().origin().immutable().clone()), - url => match ServoUrl::parse(&url) { - Ok(url) => Some(url.origin().clone()), - Err(_) => return Err(Error::Syntax), - }, - }; + /// <https://html.spec.whatwg.org/multipage/#dom-messageport-postmessage> + fn PostMessage_( + &self, + cx: JSContext, + message: HandleValue, + options: RootedTraceableBox<WindowPostMessageOptions>, + ) -> ErrorResult { + let mut rooted = CustomAutoRooter::new( + options + .transfer + .as_ref() + .unwrap_or(&Vec::with_capacity(0)) + .iter() + .map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get()) + .collect(), + ); + let transfer = Some(CustomAutoRooterGuard::new(*cx, &mut rooted)); - // Step 1-2, 6-8. - rooted!(in(*cx) let mut val = UndefinedValue()); - (*transfer).as_ref().unwrap_or(&Vec::new()).to_jsval(*cx, val.handle_mut()); + let incumbent = GlobalScope::incumbent().expect("no incumbent global?"); + let source = incumbent.as_window(); - let data = StructuredCloneData::write(*cx, message, val.handle())?; + let source_origin = source.Document().origin().immutable().clone(); - // Step 9. - self.post_message(origin, &*source.window_proxy(), data); - Ok(()) + self.post_message_impl( + &options.targetOrigin, + source_origin, + source, + cx, + message, + transfer, + ) } // https://html.spec.whatwg.org/multipage/#dom-window-captureevents @@ -1298,6 +1322,34 @@ impl WindowMethods for Window { } impl Window { + /// https://html.spec.whatwg.org/multipage/#window-post-message-steps + fn post_message_impl( + &self, + target_origin: &USVString, + source_origin: ImmutableOrigin, + source: &Window, + cx: JSContext, + message: HandleValue, + transfer: Option<CustomAutoRooterGuard<Vec<*mut JSObject>>>, + ) -> ErrorResult { + // Step 1-2, 6-8. + let data = structuredclone::write(cx, message, transfer)?; + + // Step 3-5. + let target_origin = match target_origin.0[..].as_ref() { + "*" => None, + "/" => Some(source_origin.clone()), + url => match ServoUrl::parse(&url) { + Ok(url) => Some(url.origin().clone()), + Err(_) => return Err(Error::Syntax), + }, + }; + + // Step 9. + self.post_message(target_origin, source_origin, &*source.window_proxy(), data); + Ok(()) + } + // https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet pub fn paint_worklet(&self) -> DomRoot<Worklet> { self.paint_worklet.or_init(|| self.new_paint_worklet()) @@ -1344,6 +1396,9 @@ impl Window { // thread, informing it that it can safely free the memory. self.Document().upcast::<Node>().teardown(); + // Tell the constellation to drop the sender to our message-port router, if there is any. + self.upcast::<GlobalScope>().remove_message_ports_router(); + // Clean up any active promises // https://github.com/servo/servo/issues/15318 if let Some(custom_elements) = self.custom_element_registry.get() { @@ -2345,8 +2400,9 @@ impl Window { pub fn post_message( &self, target_origin: Option<ImmutableOrigin>, + source_origin: ImmutableOrigin, source: &WindowProxy, - serialize_with_transfer_result: StructuredCloneData, + data: StructuredSerializedData, ) { let this = Trusted::new(self); let source = Trusted::new(source); @@ -2367,26 +2423,23 @@ impl Window { let obj = this.reflector().get_jsobject(); let _ac = JSAutoRealm::new(*cx, obj.get()); rooted!(in(*cx) let mut message_clone = UndefinedValue()); - assert!(serialize_with_transfer_result.read( - this.upcast(), - message_clone.handle_mut(), - )); - - // Step 7.6. - let new_ports = TRANSFERRED_MESSAGE_PORTS.with(|list| { - mem::replace(&mut *list.borrow_mut(), vec![]) - }); - - // Step 7.7. - // TODO(#12719): Set the other attributes. - MessageEvent::dispatch_jsval( - this.upcast(), - this.upcast(), - message_clone.handle(), - Some(&document.origin().immutable().ascii_serialization()), - Some(&*source), - new_ports, - ); + if let Ok(ports) = structuredclone::read(this.upcast(), data, message_clone.handle_mut()) { + // Step 7.6, 7.7 + MessageEvent::dispatch_jsval( + this.upcast(), + this.upcast(), + message_clone.handle(), + Some(&source_origin.ascii_serialization()), + Some(&*source), + ports, + ); + } else { + // Step 4, fire messageerror. + MessageEvent::dispatch_error( + this.upcast(), + this.upcast(), + ); + } }); // FIXME(nox): Why are errors silenced here? // TODO(#12718): Use the "posted message task source". |