aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/worker.rs
diff options
context:
space:
mode:
authorMs2ger <ms2ger@gmail.com>2014-08-12 20:26:28 +0200
committerMs2ger <ms2ger@gmail.com>2014-08-12 20:26:28 +0200
commit6d2dcc2852c081b6b04c0de6e8b837abed91ebb8 (patch)
tree75fda2cc08414d8e19a6812a60b5de508ed99052 /src/components/script/dom/worker.rs
parentd9105ca9b461b01590ca792229c8380a75ee3fb4 (diff)
parentbac9a3cf6da2932f6c24e50885a657e094c77686 (diff)
downloadservo-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.rs77
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));
}