diff options
Diffstat (limited to 'components/script/dom/worker.rs')
-rw-r--r-- | components/script/dom/worker.rs | 78 |
1 files changed, 69 insertions, 9 deletions
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index f1f15c3c8f9..f6cf53b801e 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -21,12 +21,15 @@ use dom::eventtarget::EventTarget; use dom::messageevent::MessageEvent; use dom::workerglobalscope::WorkerGlobalScopeInit; use ipc_channel::ipc; -use js::jsapi::{HandleValue, JSContext, RootedValue}; -use js::jsapi::{JSAutoCompartment, JSAutoRequest}; +use js::jsapi::{HandleValue, JSContext, JSRuntime, RootedValue}; +use js::jsapi::{JSAutoCompartment, JSAutoRequest, JS_RequestInterruptCallback}; use js::jsval::UndefinedValue; +use js::rust::Runtime; use script_runtime::ScriptChan; use script_thread::Runnable; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{Sender, channel}; +use std::sync::{Arc, Mutex}; use util::str::DOMString; pub type TrustedWorkerAddress = Trusted<Worker>; @@ -39,21 +42,26 @@ pub struct Worker { /// Sender to the Receiver associated with the DedicatedWorkerGlobalScope /// this Worker created. sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, + closing: Arc<AtomicBool>, + #[ignore_heap_size_of = "Defined in rust-mozjs"] + runtime: Arc<Mutex<Option<SharedRt>>> } impl Worker { - fn new_inherited(sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>) - -> Worker { + fn new_inherited(sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, + closing: Arc<AtomicBool>) -> Worker { Worker { eventtarget: EventTarget::new_inherited(), sender: sender, + closing: closing, + runtime: Arc::new(Mutex::new(None)) } } pub fn new(global: GlobalRef, - sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>) - -> Root<Worker> { - reflect_dom_object(box Worker::new_inherited(sender), + sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, + closing: Arc<AtomicBool>) -> Root<Worker> { + reflect_dom_object(box Worker::new_inherited(sender, closing), global, WorkerBinding::Wrap) } @@ -71,7 +79,8 @@ impl Worker { let scheduler_chan = global.scheduler_chan(); let (sender, receiver) = channel(); - let worker = Worker::new(global, sender.clone()); + let closing = Arc::new(AtomicBool::new(false)); + let worker = Worker::new(global, sender.clone(), closing.clone()); let worker_ref = Trusted::new(worker.r(), global.script_chan()); let worker_id = global.get_next_worker_id(); @@ -100,18 +109,28 @@ impl Worker { constellation_chan: constellation_chan, scheduler_chan: scheduler_chan, worker_id: worker_id, + closing: closing, }; + DedicatedWorkerGlobalScope::run_worker_scope( - init, worker_url, global.pipeline(), devtools_receiver, worker_ref, + init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref, global.script_chan(), sender, receiver); Ok(worker) } + pub fn is_closing(&self) -> bool { + self.closing.load(Ordering::SeqCst) + } + pub fn handle_message(address: TrustedWorkerAddress, data: StructuredCloneData) { let worker = address.root(); + if worker.is_closing() { + return; + } + let global = worker.r().global(); let target = worker.upcast(); let _ar = JSAutoRequest::new(global.r().get_cx()); @@ -129,6 +148,11 @@ impl Worker { pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString, filename: DOMString, lineno: u32, colno: u32) { let worker = address.root(); + + if worker.is_closing() { + return; + } + let global = worker.r().global(); let error = RootedValue::new(global.r().get_cx(), UndefinedValue()); let errorevent = ErrorEvent::new(global.r(), atom!("error"), @@ -147,6 +171,19 @@ impl WorkerMethods for Worker { Ok(()) } + // https://html.spec.whatwg.org/multipage/#terminate-a-worker + fn Terminate(&self) { + // Step 1 + if self.closing.swap(true, Ordering::SeqCst) { + return; + } + + // Step 4 + if let Some(runtime) = *self.runtime.lock().unwrap() { + runtime.request_interrupt(); + } + } + // https://html.spec.whatwg.org/multipage/#handler-worker-onmessage event_handler!(message, GetOnmessage, SetOnmessage); @@ -221,3 +258,26 @@ impl Runnable for WorkerErrorHandler { Worker::handle_error_message(this.addr, this.msg, this.file_name, this.line_num, this.col_num); } } + +#[derive(Copy, Clone)] +pub struct SharedRt { + rt: *mut JSRuntime +} + +impl SharedRt { + pub fn new(rt: &Runtime) -> SharedRt { + SharedRt { + rt: rt.rt() + } + } + + #[allow(unsafe_code)] + pub fn request_interrupt(&self) { + unsafe { + JS_RequestInterruptCallback(self.rt); + } + } +} + +#[allow(unsafe_code)] +unsafe impl Send for SharedRt {} |