diff options
Diffstat (limited to 'components/script/dom/messageevent.rs')
-rw-r--r-- | components/script/dom/messageevent.rs | 302 |
1 files changed, 241 insertions, 61 deletions
diff --git a/components/script/dom/messageevent.rs b/components/script/dom/messageevent.rs index 0bbeeb05cd7..c00e2bc5dec 100644 --- a/components/script/dom/messageevent.rs +++ b/components/script/dom/messageevent.rs @@ -1,58 +1,138 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use dom::bindings::codegen::Bindings::EventBinding::EventMethods; -use dom::bindings::codegen::Bindings::MessageEventBinding; -use dom::bindings::codegen::Bindings::MessageEventBinding::MessageEventMethods; -use dom::bindings::error::Fallible; -use dom::bindings::inheritance::Castable; -use dom::bindings::js::Root; -use dom::bindings::reflector::reflect_dom_object; -use dom::bindings::str::DOMString; -use dom::bindings::trace::RootedTraceableBox; -use dom::event::Event; -use dom::eventtarget::EventTarget; -use dom::globalscope::GlobalScope; + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods; +use crate::dom::bindings::codegen::Bindings::MessageEventBinding; +use crate::dom::bindings::codegen::Bindings::MessageEventBinding::MessageEventMethods; +use crate::dom::bindings::codegen::UnionTypes::WindowProxyOrMessagePortOrServiceWorker; +use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::bindings::str::DOMString; +use crate::dom::bindings::trace::RootedTraceableBox; +use crate::dom::bindings::utils::to_frozen_array; +use crate::dom::event::Event; +use crate::dom::eventtarget::EventTarget; +use crate::dom::globalscope::GlobalScope; +use crate::dom::messageport::MessagePort; +use crate::dom::serviceworker::ServiceWorker; +use crate::dom::windowproxy::WindowProxy; +use crate::script_runtime::JSContext; use dom_struct::dom_struct; -use js::jsapi::{HandleValue, Heap, JSContext}; +use js::jsapi::Heap; use js::jsval::JSVal; +use js::rust::HandleValue; use servo_atoms::Atom; +#[unrooted_must_root_lint::must_root] +#[derive(JSTraceable, MallocSizeOf)] +enum SrcObject { + WindowProxy(Dom<WindowProxy>), + MessagePort(Dom<MessagePort>), + ServiceWorker(Dom<ServiceWorker>), +} + +impl From<&WindowProxyOrMessagePortOrServiceWorker> for SrcObject { + #[allow(unrooted_must_root)] + fn from(src_object: &WindowProxyOrMessagePortOrServiceWorker) -> SrcObject { + match src_object { + WindowProxyOrMessagePortOrServiceWorker::WindowProxy(blob) => { + SrcObject::WindowProxy(Dom::from_ref(&*blob)) + }, + WindowProxyOrMessagePortOrServiceWorker::MessagePort(stream) => { + SrcObject::MessagePort(Dom::from_ref(&*stream)) + }, + WindowProxyOrMessagePortOrServiceWorker::ServiceWorker(stream) => { + SrcObject::ServiceWorker(Dom::from_ref(&*stream)) + }, + } + } +} + #[dom_struct] +#[allow(non_snake_case)] pub struct MessageEvent { event: Event, + #[ignore_malloc_size_of = "mozjs"] data: Heap<JSVal>, - origin: DOMString, - lastEventId: DOMString, + origin: DomRefCell<DOMString>, + source: DomRefCell<Option<SrcObject>>, + lastEventId: DomRefCell<DOMString>, + ports: DomRefCell<Vec<Dom<MessagePort>>>, + #[ignore_malloc_size_of = "mozjs"] + frozen_ports: DomRefCell<Option<Heap<JSVal>>>, } +#[allow(non_snake_case)] impl MessageEvent { - pub fn new_uninitialized(global: &GlobalScope) -> Root<MessageEvent> { - MessageEvent::new_initialized(global, - HandleValue::undefined(), - DOMString::new(), - DOMString::new()) + pub fn new_inherited( + origin: DOMString, + source: Option<&WindowProxyOrMessagePortOrServiceWorker>, + lastEventId: DOMString, + ports: Vec<DomRoot<MessagePort>>, + ) -> MessageEvent { + MessageEvent { + event: Event::new_inherited(), + data: Heap::default(), + source: DomRefCell::new(source.map(|source| source.into())), + origin: DomRefCell::new(origin), + lastEventId: DomRefCell::new(lastEventId), + ports: DomRefCell::new( + ports + .into_iter() + .map(|port| Dom::from_ref(&*port)) + .collect(), + ), + frozen_ports: DomRefCell::new(None), + } } - pub fn new_initialized(global: &GlobalScope, - data: HandleValue, - origin: DOMString, - lastEventId: DOMString) -> Root<MessageEvent> { - let ev = box MessageEvent { - event: Event::new_inherited(), - data: Heap::new(data.get()), - origin: origin, - lastEventId: lastEventId, - }; - reflect_dom_object(ev, global, MessageEventBinding::Wrap) + pub fn new_uninitialized(global: &GlobalScope) -> DomRoot<MessageEvent> { + MessageEvent::new_initialized( + global, + HandleValue::undefined(), + DOMString::new(), + None, + DOMString::new(), + vec![], + ) + } + + pub fn new_initialized( + global: &GlobalScope, + data: HandleValue, + origin: DOMString, + source: Option<&WindowProxyOrMessagePortOrServiceWorker>, + lastEventId: DOMString, + ports: Vec<DomRoot<MessagePort>>, + ) -> DomRoot<MessageEvent> { + let ev = Box::new(MessageEvent::new_inherited( + origin, + source, + lastEventId, + ports, + )); + let ev = reflect_dom_object(ev, global); + ev.data.set(data.get()); + + ev } - pub fn new(global: &GlobalScope, type_: Atom, - bubbles: bool, cancelable: bool, - data: HandleValue, origin: DOMString, lastEventId: DOMString) - -> Root<MessageEvent> { - let ev = MessageEvent::new_initialized(global, data, origin, lastEventId); + pub fn new( + global: &GlobalScope, + type_: Atom, + bubbles: bool, + cancelable: bool, + data: HandleValue, + origin: DOMString, + source: Option<&WindowProxyOrMessagePortOrServiceWorker>, + lastEventId: DOMString, + ports: Vec<DomRoot<MessagePort>>, + ) -> DomRoot<MessageEvent> { + let ev = MessageEvent::new_initialized(global, data, origin, source, lastEventId, ports); { let event = ev.upcast::<Event>(); event.init_event(type_, bubbles, cancelable); @@ -60,56 +140,156 @@ impl MessageEvent { ev } - pub fn Constructor(global: &GlobalScope, - type_: DOMString, - init: RootedTraceableBox<MessageEventBinding::MessageEventInit>) - -> Fallible<Root<MessageEvent>> { - let ev = MessageEvent::new(global, - Atom::from(type_), - init.parent.bubbles, - init.parent.cancelable, - init.data.handle(), - init.origin.clone(), - init.lastEventId.clone()); + pub fn Constructor( + global: &GlobalScope, + type_: DOMString, + init: RootedTraceableBox<MessageEventBinding::MessageEventInit>, + ) -> Fallible<DomRoot<MessageEvent>> { + let ev = MessageEvent::new( + global, + Atom::from(type_), + init.parent.bubbles, + init.parent.cancelable, + init.data.handle(), + init.origin.clone(), + init.source.as_ref(), + init.lastEventId.clone(), + init.ports.clone(), + ); Ok(ev) } } impl MessageEvent { - pub fn dispatch_jsval(target: &EventTarget, - scope: &GlobalScope, - message: HandleValue) { + pub fn dispatch_jsval( + target: &EventTarget, + scope: &GlobalScope, + message: HandleValue, + origin: Option<&str>, + source: Option<&WindowProxy>, + ports: Vec<DomRoot<MessagePort>>, + ) { let messageevent = MessageEvent::new( scope, atom!("message"), false, false, message, + DOMString::from(origin.unwrap_or("")), + source + .map(|source| { + WindowProxyOrMessagePortOrServiceWorker::WindowProxy(DomRoot::from_ref(source)) + }) + .as_ref(), DOMString::new(), - DOMString::new()); + ports, + ); + messageevent.upcast::<Event>().fire(target); + } + + pub fn dispatch_error(target: &EventTarget, scope: &GlobalScope) { + let init = MessageEventBinding::MessageEventInit::empty(); + let messageevent = MessageEvent::new( + scope, + atom!("messageerror"), + init.parent.bubbles, + init.parent.cancelable, + init.data.handle(), + init.origin.clone(), + init.source.as_ref(), + init.lastEventId.clone(), + init.ports.clone(), + ); messageevent.upcast::<Event>().fire(target); } } impl MessageEventMethods for MessageEvent { - #[allow(unsafe_code)] - // https://html.spec.whatwg.org/multipage/#dom-messageevent-data - unsafe fn Data(&self, _cx: *mut JSContext) -> JSVal { + /// <https://html.spec.whatwg.org/multipage/#dom-messageevent-data> + fn Data(&self, _cx: JSContext) -> JSVal { self.data.get() } - // https://html.spec.whatwg.org/multipage/#dom-messageevent-origin + /// <https://html.spec.whatwg.org/multipage/#dom-messageevent-origin> fn Origin(&self) -> DOMString { - self.origin.clone() + self.origin.borrow().clone() + } + + // https://html.spec.whatwg.org/multipage/#dom-messageevent-source + fn GetSource(&self) -> Option<WindowProxyOrMessagePortOrServiceWorker> { + match &*self.source.borrow() { + Some(SrcObject::WindowProxy(i)) => Some( + WindowProxyOrMessagePortOrServiceWorker::WindowProxy(DomRoot::from_ref(&*i)), + ), + Some(SrcObject::MessagePort(i)) => Some( + WindowProxyOrMessagePortOrServiceWorker::MessagePort(DomRoot::from_ref(&*i)), + ), + Some(SrcObject::ServiceWorker(i)) => Some( + WindowProxyOrMessagePortOrServiceWorker::ServiceWorker(DomRoot::from_ref(&*i)), + ), + None => None, + } } - // https://html.spec.whatwg.org/multipage/#dom-messageevent-lasteventid + /// <https://html.spec.whatwg.org/multipage/#dom-messageevent-lasteventid> fn LastEventId(&self) -> DOMString { - self.lastEventId.clone() + self.lastEventId.borrow().clone() } - // https://dom.spec.whatwg.org/#dom-event-istrusted + /// <https://dom.spec.whatwg.org/#dom-event-istrusted> fn IsTrusted(&self) -> bool { self.event.IsTrusted() } + + /// <https://html.spec.whatwg.org/multipage/#dom-messageevent-ports> + fn Ports(&self, cx: JSContext) -> JSVal { + if let Some(ports) = &*self.frozen_ports.borrow() { + return ports.get(); + } + + let ports: Vec<DomRoot<MessagePort>> = self + .ports + .borrow() + .iter() + .map(|port| DomRoot::from_ref(&**port)) + .collect(); + let frozen_ports = to_frozen_array(ports.as_slice(), cx); + + // Safety: need to create the Heap value in its final memory location before setting it. + *self.frozen_ports.borrow_mut() = Some(Heap::default()); + self.frozen_ports + .borrow() + .as_ref() + .unwrap() + .set(frozen_ports); + + frozen_ports + } + + /// <https://html.spec.whatwg.org/multipage/#dom-messageevent-initmessageevent> + #[allow(non_snake_case)] + fn InitMessageEvent( + &self, + _cx: JSContext, + type_: DOMString, + bubbles: bool, + cancelable: bool, + data: HandleValue, + origin: DOMString, + lastEventId: DOMString, + source: Option<WindowProxyOrMessagePortOrServiceWorker>, + ports: Vec<DomRoot<MessagePort>>, + ) { + self.data.set(data.get()); + *self.origin.borrow_mut() = origin.clone(); + *self.source.borrow_mut() = source.as_ref().map(|source| source.into()); + *self.lastEventId.borrow_mut() = lastEventId.clone(); + *self.ports.borrow_mut() = ports + .into_iter() + .map(|port| Dom::from_ref(&*port)) + .collect(); + *self.frozen_ports.borrow_mut() = None; + self.event + .init_event(Atom::from(type_), bubbles, cancelable); + } } |