continue messageport, transferable, postmessage options

This commit is contained in:
Gregory Terzian 2019-06-26 00:25:48 +08:00
parent c3b17c1201
commit 2f8932a6a1
100 changed files with 2456 additions and 1171 deletions

View file

@ -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();
// 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),
},
};
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 1-2, 6-8.
rooted!(in(*cx) let mut val = UndefinedValue());
(*transfer).as_ref().unwrap_or(&Vec::new()).to_jsval(*cx, val.handle_mut());
/// <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));
let data = StructuredCloneData::write(*cx, message, val.handle())?;
let incumbent = GlobalScope::incumbent().expect("no incumbent global?");
let source = incumbent.as_window();
// Step 9.
self.post_message(origin, &*source.window_proxy(), data);
Ok(())
let source_origin = source.Document().origin().immutable().clone();
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".