diff options
author | Ms2ger <ms2ger@gmail.com> | 2014-08-12 20:26:28 +0200 |
---|---|---|
committer | Ms2ger <ms2ger@gmail.com> | 2014-08-12 20:26:28 +0200 |
commit | 6d2dcc2852c081b6b04c0de6e8b837abed91ebb8 (patch) | |
tree | 75fda2cc08414d8e19a6812a60b5de508ed99052 /src/components/script/dom/worker.rs | |
parent | d9105ca9b461b01590ca792229c8380a75ee3fb4 (diff) | |
parent | bac9a3cf6da2932f6c24e50885a657e094c77686 (diff) | |
download | servo-6d2dcc2852c081b6b04c0de6e8b837abed91ebb8.tar.gz servo-6d2dcc2852c081b6b04c0de6e8b837abed91ebb8.zip |
Merge pull request #3076 from Ms2ger/DWGS-postMessage
Implement DedicatedWorkerGlobalScope.postMessage; r=Manishearth
Diffstat (limited to 'src/components/script/dom/worker.rs')
-rw-r--r-- | src/components/script/dom/worker.rs | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 670ae7a5beb..f5e25db68e2 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -4,33 +4,48 @@ use dom::bindings::codegen::Bindings::WorkerBinding; use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods; +use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::error::{Fallible, Syntax}; -use dom::bindings::global::GlobalRef; -use dom::bindings::js::{JSRef, Temporary}; +use dom::bindings::global::{GlobalRef, GlobalField}; +use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::eventtarget::{EventTarget, WorkerTypeId}; +use dom::messageevent::MessageEvent; use script_task::{ScriptChan, DOMMessage}; use servo_util::str::DOMString; + +use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot}; use url::UrlParser; +use libc::c_void; +use std::cell::Cell; + +pub struct TrustedWorkerAddress(pub *const c_void); + #[deriving(Encodable)] pub struct Worker { eventtarget: EventTarget, + refcount: Cell<uint>, + global: GlobalField, + /// Sender to the Receiver associated with the DedicatedWorkerGlobalScope + /// this Worker created. sender: ScriptChan, } impl Worker { - pub fn new_inherited(sender: ScriptChan) -> Worker { + pub fn new_inherited(global: &GlobalRef, sender: ScriptChan) -> Worker { Worker { eventtarget: EventTarget::new_inherited(WorkerTypeId), + refcount: Cell::new(0), + global: GlobalField::from_rooted(global), sender: sender, } } pub fn new(global: &GlobalRef, sender: ScriptChan) -> Temporary<Worker> { - reflect_dom_object(box Worker::new_inherited(sender), + reflect_dom_object(box Worker::new_inherited(global, sender), global, WorkerBinding::Wrap) } @@ -45,14 +60,62 @@ impl Worker { }; let resource_task = global.resource_task(); - let sender = DedicatedWorkerGlobalScope::run_worker_scope( - worker_url, resource_task); - Ok(Worker::new(global, sender)) + let (receiver, sender) = ScriptChan::new(); + + let worker = Worker::new(global, sender.clone()).root(); + let worker_ref = worker.addref(); + + DedicatedWorkerGlobalScope::run_worker_scope( + worker_url, worker_ref, resource_task, global.script_chan().clone(), + sender, receiver); + + Ok(Temporary::from_rooted(&*worker)) + } + + pub fn handle_message(address: TrustedWorkerAddress, message: DOMString) { + let worker = unsafe { JS::from_trusted_worker_address(address).root() }; + + let target: &JSRef<EventTarget> = EventTargetCast::from_ref(&*worker); + let global = worker.global.root(); + MessageEvent::dispatch(target, &global.root_ref(), message); + } +} + +impl Worker { + // Creates a trusted address to the object, and roots it. Always pair this with a release() + pub fn addref(&self) -> TrustedWorkerAddress { + let refcount = self.refcount.get(); + if refcount == 0 { + let cx = self.global.root().root_ref().get_cx(); + unsafe { + JS_AddObjectRoot(cx, self.reflector().rootable()); + } + } + self.refcount.set(refcount + 1); + TrustedWorkerAddress(self as *const Worker as *const c_void) + } + + pub fn release(&self) { + let refcount = self.refcount.get(); + assert!(refcount > 0) + self.refcount.set(refcount - 1); + if refcount == 1 { + let cx = self.global.root().root_ref().get_cx(); + unsafe { + JS_RemoveObjectRoot(cx, self.reflector().rootable()); + } + } + } + + pub fn handle_release(address: TrustedWorkerAddress) { + let worker = unsafe { JS::from_trusted_worker_address(address).root() }; + worker.release(); } } impl<'a> WorkerMethods for JSRef<'a, Worker> { fn PostMessage(&self, message: DOMString) { + self.addref(); let ScriptChan(ref sender) = self.sender; sender.send(DOMMessage(message)); } |