From 96aad42a5d219e8219b2f94047eba967bb7affe0 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 11 Aug 2014 16:41:16 +0200 Subject: [PATCH] Give workers their own ScriptChan and use it for postMessage. This ensures that XHR callbacks for XHR objects in workers are called on the worker thread rather than the main thread. --- .../script/dom/dedicatedworkerglobalscope.rs | 25 +++++++++++-------- src/components/script/dom/worker.rs | 18 ++++++------- src/components/script/script_task.rs | 25 +++++++++++-------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/components/script/dom/dedicatedworkerglobalscope.rs b/src/components/script/dom/dedicatedworkerglobalscope.rs index 2aff963a8e0..f9e3210715e 100644 --- a/src/components/script/dom/dedicatedworkerglobalscope.rs +++ b/src/components/script/dom/dedicatedworkerglobalscope.rs @@ -14,11 +14,11 @@ use dom::eventtarget::WorkerGlobalScopeTypeId; use dom::messageevent::MessageEvent; use dom::workerglobalscope::DedicatedGlobalScope; use dom::workerglobalscope::WorkerGlobalScope; -use script_task::{ScriptTask, ScriptChan}; +use dom::xmlhttprequest::XMLHttpRequest; +use script_task::{ScriptTask, ScriptChan, ScriptMsg, DOMMessage, XHRProgressMsg}; use script_task::StackRootTLS; use servo_net::resource_task::{ResourceTask, load_whole_resource}; -use servo_util::str::DOMString; use js::rust::Cx; @@ -30,13 +30,13 @@ use url::Url; #[deriving(Encodable)] pub struct DedicatedWorkerGlobalScope { workerglobalscope: WorkerGlobalScope, - receiver: Untraceable>, + receiver: Untraceable>, } impl DedicatedWorkerGlobalScope { pub fn new_inherited(worker_url: Url, cx: Rc, - receiver: Receiver, + receiver: Receiver, resource_task: ResourceTask, script_chan: ScriptChan) -> DedicatedWorkerGlobalScope { @@ -50,7 +50,7 @@ impl DedicatedWorkerGlobalScope { pub fn new(worker_url: Url, cx: Rc, - receiver: Receiver, + receiver: Receiver, resource_task: ResourceTask, script_chan: ScriptChan) -> Temporary { @@ -62,9 +62,9 @@ impl DedicatedWorkerGlobalScope { impl DedicatedWorkerGlobalScope { pub fn run_worker_scope(worker_url: Url, - receiver: Receiver, - resource_task: ResourceTask, - script_chan: ScriptChan) { + resource_task: ResourceTask) -> ScriptChan { + let (receiver, sender) = ScriptChan::new(); + let sender_clone = sender.clone(); TaskBuilder::new() .native() .named(format!("Web Worker at {}", worker_url.serialize())) @@ -85,7 +85,7 @@ impl DedicatedWorkerGlobalScope { let (_js_runtime, js_context) = ScriptTask::new_rt_and_cx(); let global = DedicatedWorkerGlobalScope::new( worker_url, js_context.clone(), receiver, resource_task, - script_chan).root(); + sender).root(); match js_context.evaluate_script( global.reflector().get_jsobject(), source, url.serialize(), 1) { Ok(_) => (), @@ -98,13 +98,18 @@ impl DedicatedWorkerGlobalScope { EventTargetCast::from_ref(&*global); loop { match global.receiver.recv_opt() { - Ok(message) => { + Ok(DOMMessage(message)) => { MessageEvent::dispatch(target, &Worker(*scope), message) }, + Ok(XHRProgressMsg(addr, progress)) => { + XMLHttpRequest::handle_xhr_progress(addr, progress) + }, + Ok(_) => fail!("Unexpected message"), Err(_) => break, } } }); + return sender_clone; } } diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 88a9b10307a..670ae7a5beb 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -7,10 +7,10 @@ use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods; use dom::bindings::error::{Fallible, Syntax}; use dom::bindings::global::GlobalRef; 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}; +use script_task::{ScriptChan, DOMMessage}; use servo_util::str::DOMString; use url::UrlParser; @@ -18,18 +18,18 @@ use url::UrlParser; #[deriving(Encodable)] pub struct Worker { eventtarget: EventTarget, - sender: Untraceable>, + sender: ScriptChan, } impl Worker { - pub fn new_inherited(sender: Sender) -> Worker { + pub fn new_inherited(sender: ScriptChan) -> Worker { Worker { eventtarget: EventTarget::new_inherited(WorkerTypeId), - sender: Untraceable::new(sender), + sender: sender, } } - pub fn new(global: &GlobalRef, sender: Sender) -> Temporary { + pub fn new(global: &GlobalRef, sender: ScriptChan) -> Temporary { reflect_dom_object(box Worker::new_inherited(sender), global, WorkerBinding::Wrap) @@ -44,17 +44,17 @@ impl Worker { Err(_) => return Err(Syntax), }; - let (sender, receiver) = channel(); let resource_task = global.resource_task(); - DedicatedWorkerGlobalScope::run_worker_scope( - worker_url, receiver, resource_task, global.script_chan().clone()); + let sender = DedicatedWorkerGlobalScope::run_worker_scope( + worker_url, resource_task); Ok(Worker::new(global, sender)) } } impl<'a> WorkerMethods for JSRef<'a, Worker> { fn PostMessage(&self, message: DOMString) { - self.sender.send(message); + let ScriptChan(ref sender) = self.sender; + sender.send(DOMMessage(message)); } } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 2f7df8d6ddd..0d24eaccbba 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -31,12 +31,6 @@ use layout_interface::ContentChangedDocumentDamage; use layout_interface; use page::{Page, IterablePage, Frame}; -use geom::point::Point2D; -use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC}; -use js::jsapi::{JSContext, JSRuntime}; -use js::rust::{Cx, RtUtils}; -use js::rust::with_compartment; -use js; use script_traits::{CompositorEvent, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent}; use script_traits::{MouseMoveEvent, MouseUpEvent, ConstellationControlMsg, ScriptTaskFactory}; use script_traits::{ResizeMsg, AttachLayoutMsg, LoadMsg, SendEventMsg, ResizeInactiveMsg}; @@ -50,15 +44,23 @@ use servo_msg::constellation_msg; use servo_net::image_cache_task::ImageCacheTask; use servo_net::resource_task::ResourceTask; use servo_util::geometry::to_frac_px; +use servo_util::str::DOMString; use servo_util::task::spawn_named_with_send_on_failure; + +use geom::point::Point2D; +use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC}; +use js::jsapi::{JSContext, JSRuntime}; +use js::rust::{Cx, RtUtils}; +use js::rust::with_compartment; +use js; +use url::Url; + +use serialize::{Encoder, Encodable}; use std::any::{Any, AnyRefExt}; use std::cell::RefCell; use std::comm::{channel, Sender, Receiver, Select}; use std::mem::replace; use std::rc::Rc; -use url::Url; - -use serialize::{Encoder, Encodable}; local_data_key!(pub StackRoots: *const RootCollection) @@ -75,7 +77,9 @@ pub enum ScriptMsg { /// Notifies the script that a window associated with a particular pipeline should be closed. ExitWindowMsg(PipelineId), /// Notifies the script of progress on a fetch - XHRProgressMsg(TrustedXHRAddress, XHRProgress) + XHRProgressMsg(TrustedXHRAddress, XHRProgress), + /// Message sent through postMessage + DOMMessage(DOMString), } /// Encapsulates internal communication within the script task. @@ -430,6 +434,7 @@ impl ScriptTask { FromScript(ExitWindowMsg(id)) => self.handle_exit_window_msg(id), FromConstellation(ResizeMsg(..)) => fail!("should have handled ResizeMsg already"), FromScript(XHRProgressMsg(addr, progress)) => XMLHttpRequest::handle_xhr_progress(addr, progress), + FromScript(DOMMessage(..)) => fail!("unexpected message"), } }