From 96aad42a5d219e8219b2f94047eba967bb7affe0 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 11 Aug 2014 16:41:16 +0200 Subject: [PATCH 1/2] 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"), } } From 034e815657fced9c3b31d48989be6316ee4f33a8 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 11 Aug 2014 21:27:30 +0200 Subject: [PATCH 2/2] Improve the documentation for ScriptMsg. --- src/components/script/script_task.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 0d24eaccbba..ba6cd12c372 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -64,21 +64,27 @@ use std::rc::Rc; local_data_key!(pub StackRoots: *const RootCollection) -/// Messages used to control the script task. +/// Messages used to control script event loops, such as ScriptTask and +/// DedicatedWorkerGlobalScope. pub enum ScriptMsg { - /// Acts on a fragment URL load on the specified pipeline. + /// Acts on a fragment URL load on the specified pipeline (only dispatched + /// to ScriptTask). TriggerFragmentMsg(PipelineId, Url), - /// Begins a content-initiated load on the specified pipeline. + /// Begins a content-initiated load on the specified pipeline (only + /// dispatched to ScriptTask). TriggerLoadMsg(PipelineId, Url), - /// Instructs the script task to send a navigate message to the constellation. + /// Instructs the script task to send a navigate message to + /// the constellation (only dispatched to ScriptTask). NavigateMsg(NavigationDirection), - /// Fires a JavaScript timeout. + /// Fires a JavaScript timeout (only dispatched to ScriptTask). FireTimerMsg(PipelineId, TimerId), - /// Notifies the script that a window associated with a particular pipeline should be closed. + /// Notifies the script that a window associated with a particular pipeline + /// should be closed (only dispatched to ScriptTask). ExitWindowMsg(PipelineId), - /// Notifies the script of progress on a fetch + /// Notifies the script of progress on a fetch (dispatched to all tasks). XHRProgressMsg(TrustedXHRAddress, XHRProgress), - /// Message sent through postMessage + /// Message sent through Worker.postMessage (only dispatched to + /// DedicatedWorkerGlobalScope). DOMMessage(DOMString), }