From 07a89a06c96b4c27850ffb4df386fae4ce0a4494 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Thu, 17 Jul 2014 20:14:42 +0200 Subject: [PATCH 1/2] Implement MessageEvent::dispatch. This avoids duplicating the dispatching code for multiple postMessage implementations. --- src/components/script/dom/messageevent.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/components/script/dom/messageevent.rs b/src/components/script/dom/messageevent.rs index a9d536fad06..05eca45fd71 100644 --- a/src/components/script/dom/messageevent.rs +++ b/src/components/script/dom/messageevent.rs @@ -4,12 +4,14 @@ use dom::bindings::codegen::Bindings::MessageEventBinding; use dom::bindings::codegen::InheritTypes::{EventCast, MessageEventDerived}; +use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::trace::Traceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::event::{Event, EventMethods, MessageEventTypeId}; +use dom::eventtarget::{EventTarget, EventTargetHelpers}; use servo_util::str::DOMString; @@ -63,6 +65,19 @@ impl MessageEvent { } } +impl MessageEvent { + pub fn dispatch(target: &JSRef, + scope: &GlobalRef, + message: DOMString) { + let messageevent = MessageEvent::new( + scope, "message".to_string(), false, false, + message.to_jsval(scope.get_cx()), + "".to_string(), "".to_string()).root(); + let event: &JSRef = EventCast::from_ref(&*messageevent); + target.dispatch_event_with_target(None, &*event).unwrap(); + } +} + pub trait MessageEventMethods { fn Data(&self, cx: *mut JSContext) -> JSVal; fn Origin(&self) -> DOMString; From 5b6aef3d9c016107963ba072b1ddb36ae8092bc2 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 16 Jul 2014 13:21:53 +0200 Subject: [PATCH 2/2] Implement Worker.postMessage. --- .../script/dom/dedicatedworkerglobalscope.rs | 33 ++++++++++++++++--- .../script/dom/webidls/Worker.webidl | 1 + src/components/script/dom/worker.rs | 24 ++++++++++---- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/components/script/dom/dedicatedworkerglobalscope.rs b/src/components/script/dom/dedicatedworkerglobalscope.rs index 578b13042a5..918a054b91c 100644 --- a/src/components/script/dom/dedicatedworkerglobalscope.rs +++ b/src/components/script/dom/dedicatedworkerglobalscope.rs @@ -4,10 +4,14 @@ use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; -use dom::bindings::js::{Temporary, RootCollection}; +use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; +use dom::bindings::global::Worker; +use dom::bindings::js::{JSRef, Temporary, RootCollection}; +use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector}; use dom::eventtarget::EventTarget; use dom::eventtarget::WorkerGlobalScopeTypeId; +use dom::messageevent::MessageEvent; use dom::workerglobalscope::DedicatedGlobalScope; use dom::workerglobalscope::WorkerGlobalScope; use script_task::{ScriptTask, ScriptChan}; @@ -15,6 +19,8 @@ use script_task::StackRootTLS; use servo_net::resource_task::{ResourceTask, load_whole_resource}; +use servo_util::str::DOMString; + use js::rust::Cx; use std::rc::Rc; @@ -25,11 +31,13 @@ use url::Url; #[deriving(Encodable)] pub struct DedicatedWorkerGlobalScope { workerglobalscope: WorkerGlobalScope, + receiver: Untraceable>, } impl DedicatedWorkerGlobalScope { pub fn new_inherited(worker_url: Url, cx: Rc, + receiver: Receiver, resource_task: ResourceTask, script_chan: ScriptChan) -> DedicatedWorkerGlobalScope { @@ -37,22 +45,26 @@ impl DedicatedWorkerGlobalScope { workerglobalscope: WorkerGlobalScope::new_inherited( DedicatedGlobalScope, worker_url, cx, resource_task, script_chan), + receiver: Untraceable::new(receiver), } } pub fn new(worker_url: Url, cx: Rc, + receiver: Receiver, resource_task: ResourceTask, script_chan: ScriptChan) -> Temporary { let scope = box DedicatedWorkerGlobalScope::new_inherited( - worker_url, cx.clone(), resource_task, script_chan); + worker_url, cx.clone(), receiver, resource_task, script_chan); DedicatedWorkerGlobalScopeBinding::Wrap(cx.ptr, scope) } } impl DedicatedWorkerGlobalScope { - pub fn run_worker_scope(worker_url: Url, resource_task: ResourceTask, + pub fn run_worker_scope(worker_url: Url, + receiver: Receiver, + resource_task: ResourceTask, script_chan: ScriptChan) { let mut task_opts = TaskOpts::new(); task_opts.name = Some(format!("Web Worker at {}", worker_url).into_maybe_owned()); @@ -72,13 +84,26 @@ impl DedicatedWorkerGlobalScope { let (_js_runtime, js_context) = ScriptTask::new_rt_and_cx(); let global = DedicatedWorkerGlobalScope::new( - worker_url, js_context.clone(), resource_task, + worker_url, js_context.clone(), receiver, resource_task, script_chan).root(); match js_context.evaluate_script( global.reflector().get_jsobject(), source, filename.to_str(), 1) { Ok(_) => (), Err(_) => println!("evaluate_script failed") } + + let scope: &JSRef = + WorkerGlobalScopeCast::from_ref(&*global); + let target: &JSRef = + EventTargetCast::from_ref(&*global); + loop { + match global.receiver.recv_opt() { + Ok(message) => { + MessageEvent::dispatch(target, &Worker(*scope), message) + }, + Err(_) => break, + } + } }); } } diff --git a/src/components/script/dom/webidls/Worker.webidl b/src/components/script/dom/webidls/Worker.webidl index 273ab8e5bfd..7eacefab9f4 100644 --- a/src/components/script/dom/webidls/Worker.webidl +++ b/src/components/script/dom/webidls/Worker.webidl @@ -15,6 +15,7 @@ interface Worker : EventTarget { //void terminate(); //void postMessage(any message/*, optional sequence transfer*/); + void postMessage(DOMString message); // attribute EventHandler onmessage; }; Worker implements AbstractWorker; diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index f0850d72e93..bd6ce75486d 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -5,7 +5,8 @@ use dom::bindings::codegen::Bindings::WorkerBinding; use dom::bindings::error::{Fallible, Syntax}; use dom::bindings::global::GlobalRef; -use dom::bindings::js::Temporary; +use dom::bindings::js::{JSRef, Temporary}; +use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::eventtarget::{EventTarget, WorkerTypeId}; @@ -16,17 +17,19 @@ use servo_util::url::try_parse_url; #[deriving(Encodable)] pub struct Worker { eventtarget: EventTarget, + sender: Untraceable>, } impl Worker { - pub fn new_inherited() -> Worker { + pub fn new_inherited(sender: Sender) -> Worker { Worker { eventtarget: EventTarget::new_inherited(WorkerTypeId), + sender: Untraceable::new(sender), } } - pub fn new(global: &GlobalRef) -> Temporary { - reflect_dom_object(box Worker::new_inherited(), + pub fn new(global: &GlobalRef, sender: Sender) -> Temporary { + reflect_dom_object(box Worker::new_inherited(sender), global, WorkerBinding::Wrap) } @@ -39,13 +42,22 @@ impl Worker { Err(_) => return Err(Syntax), }; + let (sender, receiver) = channel(); let resource_task = global.resource_task(); - DedicatedWorkerGlobalScope::run_worker_scope(worker_url, resource_task, global.script_chan().clone()); - Ok(Worker::new(global)) + DedicatedWorkerGlobalScope::run_worker_scope( + worker_url, receiver, resource_task, global.script_chan().clone()); + Ok(Worker::new(global, sender)) } } pub trait WorkerMethods { + fn PostMessage(&self, message: DOMString); +} + +impl<'a> WorkerMethods for JSRef<'a, Worker> { + fn PostMessage(&self, message: DOMString) { + self.sender.send(message); + } } impl Reflectable for Worker {