Auto merge of #7006 - Wafflespeanut:script_cleanup, r=jdm

Splitting ScriptMsg into various enums...

... for #3734, which is also one of the oldest issues. (/cc @jdm)

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7006)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-08-15 03:48:47 -06:00
commit 6a52ec9484
18 changed files with 261 additions and 164 deletions

View file

@ -5,11 +5,12 @@
//! Tracking of pending loads in a document. //! Tracking of pending loads in a document.
//! https://html.spec.whatwg.org/multipage/#the-end //! https://html.spec.whatwg.org/multipage/#the-end
use script_task::{ScriptMsg, ScriptChan}; use script_task::MainThreadScriptMsg;
use msg::constellation_msg::{PipelineId}; use msg::constellation_msg::{PipelineId};
use net_traits::{Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad}; use net_traits::{Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad};
use net_traits::AsyncResponseTarget; use net_traits::AsyncResponseTarget;
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Sender;
use url::Url; use url::Url;
#[derive(JSTraceable, PartialEq, Clone, Debug, HeapSizeOf)] #[derive(JSTraceable, PartialEq, Clone, Debug, HeapSizeOf)]
@ -46,7 +47,7 @@ pub struct DocumentLoader {
#[derive(JSTraceable, HeapSizeOf)] #[derive(JSTraceable, HeapSizeOf)]
pub struct NotifierData { pub struct NotifierData {
#[ignore_heap_size_of = "trait objects are hard"] #[ignore_heap_size_of = "trait objects are hard"]
pub script_chan: Box<ScriptChan + Send>, pub script_chan: Sender<MainThreadScriptMsg>,
pub pipeline: PipelineId, pub pipeline: PipelineId,
} }
@ -100,7 +101,7 @@ impl DocumentLoader {
if let Some(NotifierData { ref script_chan, pipeline }) = self.notifier_data { if let Some(NotifierData { ref script_chan, pipeline }) = self.notifier_data {
if !self.is_blocked() { if !self.is_blocked() {
script_chan.send(ScriptMsg::DocumentLoadsComplete(pipeline)).unwrap(); script_chan.send(MainThreadScriptMsg::DocumentLoadsComplete(pipeline)).unwrap();
} }
} }
} }

View file

@ -15,7 +15,7 @@ use dom::document::DocumentHelpers;
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use dom::window::{self, WindowHelpers, ScriptHelpers}; use dom::window::{self, WindowHelpers, ScriptHelpers};
use devtools_traits::ScriptToDevtoolsControlMsg; use devtools_traits::ScriptToDevtoolsControlMsg;
use script_task::{ScriptChan, ScriptPort, ScriptMsg, ScriptTask}; use script_task::{ScriptChan, ScriptPort, CommonScriptMsg, ScriptTask};
use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId}; use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
use net_traits::ResourceTask; use net_traits::ResourceTask;
@ -168,7 +168,7 @@ impl<'a> GlobalRef<'a> {
/// Process a single event as if it were the next event in the task queue for /// Process a single event as if it were the next event in the task queue for
/// this global. /// this global.
pub fn process_event(&self, msg: ScriptMsg) { pub fn process_event(&self, msg: CommonScriptMsg) {
match *self { match *self {
GlobalRef::Window(_) => ScriptTask::process_event(msg), GlobalRef::Window(_) => ScriptTask::process_event(msg),
GlobalRef::Worker(ref worker) => worker.process_event(msg), GlobalRef::Worker(ref worker) => worker.process_event(msg),

View file

@ -25,7 +25,7 @@
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, Reflectable}; use dom::bindings::utils::{Reflector, Reflectable};
use dom::bindings::trace::trace_reflector; use dom::bindings::trace::trace_reflector;
use script_task::{ScriptMsg, ScriptChan}; use script_task::{ScriptChan, CommonScriptMsg};
use js::jsapi::{JSContext, JSTracer}; use js::jsapi::{JSContext, JSTracer};
@ -130,7 +130,7 @@ impl<T: Reflectable> Drop for Trusted<T> {
// It's possible this send will fail if the script task // It's possible this send will fail if the script task
// has already exited. There's not much we can do at this // has already exited. There's not much we can do at this
// point though. // point though.
let msg = ScriptMsg::RefcountCleanup(TrustedReference(self.ptr)); let msg = CommonScriptMsg::RefcountCleanup(TrustedReference(self.ptr));
let _ = self.script_chan.send(msg); let _ = self.script_chan.send(msg);
} }
} }

View file

@ -22,8 +22,7 @@ use dom::messageevent::MessageEvent;
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler, WorkerErrorHandler}; use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler, WorkerErrorHandler};
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit}; use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit};
use script_task::{ScriptTask, ScriptChan, ScriptMsg, TimerSource, ScriptPort}; use script_task::{ScriptTask, ScriptChan, TimerSource, ScriptPort, StackRootTLS, CommonScriptMsg};
use script_task::StackRootTLS;
use devtools_traits::DevtoolScriptControlMsg; use devtools_traits::DevtoolScriptControlMsg;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
@ -45,17 +44,25 @@ use std::mem::replace;
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::{Sender, Receiver, channel, Select, RecvError}; use std::sync::mpsc::{Sender, Receiver, channel, Select, RecvError};
/// Messages used to control the worker event loops
pub enum WorkerScriptMsg {
/// Common variants associated with the script messages
Common(CommonScriptMsg),
/// Message sent through Worker.postMessage
DOMMessage(StructuredCloneData),
}
/// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with /// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with
/// every message. While this SendableWorkerScriptChan is alive, the associated Worker object /// common event loop messages. While this SendableWorkerScriptChan is alive, the associated
/// will remain alive. /// Worker object will remain alive.
#[derive(JSTraceable, Clone)] #[derive(JSTraceable, Clone)]
pub struct SendableWorkerScriptChan { pub struct SendableWorkerScriptChan {
sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, sender: Sender<(TrustedWorkerAddress, CommonScriptMsg)>,
worker: TrustedWorkerAddress, worker: TrustedWorkerAddress,
} }
impl ScriptChan for SendableWorkerScriptChan { impl ScriptChan for SendableWorkerScriptChan {
fn send(&self, msg: ScriptMsg) -> Result<(), ()> { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
return self.sender.send((self.worker.clone(), msg)).map_err(|_| ()); return self.sender.send((self.worker.clone(), msg)).map_err(|_| ());
} }
@ -67,6 +74,39 @@ impl ScriptChan for SendableWorkerScriptChan {
} }
} }
/// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with
/// worker event loop messages. While this SendableWorkerScriptChan is alive, the associated
/// Worker object will remain alive.
#[derive(JSTraceable, Clone)]
pub struct WorkerThreadWorkerChan {
sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
worker: TrustedWorkerAddress,
}
impl ScriptChan for WorkerThreadWorkerChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
return self.sender
.send((self.worker.clone(), WorkerScriptMsg::Common(msg)))
.map_err(|_| ());
}
fn clone(&self) -> Box<ScriptChan + Send> {
box WorkerThreadWorkerChan {
sender: self.sender.clone(),
worker: self.worker.clone(),
}
}
}
impl ScriptPort for Receiver<(TrustedWorkerAddress, WorkerScriptMsg)> {
fn recv(&self) -> CommonScriptMsg {
match self.recv().unwrap().1 {
WorkerScriptMsg::Common(script_msg) => script_msg,
WorkerScriptMsg::DOMMessage(_) => panic!("unexpected worker event message!"),
}
}
}
/// Set the `worker` field of a related DedicatedWorkerGlobalScope object to a particular /// Set the `worker` field of a related DedicatedWorkerGlobalScope object to a particular
/// value for the duration of this object's lifetime. This ensures that the related Worker /// value for the duration of this object's lifetime. This ensures that the related Worker
/// object only lives as long as necessary (ie. while events are being executed), while /// object only lives as long as necessary (ie. while events are being executed), while
@ -92,7 +132,7 @@ impl<'a> Drop for AutoWorkerReset<'a> {
} }
enum MixedMessage { enum MixedMessage {
FromWorker((TrustedWorkerAddress, ScriptMsg)), FromWorker((TrustedWorkerAddress, WorkerScriptMsg)),
FromDevtools(DevtoolScriptControlMsg), FromDevtools(DevtoolScriptControlMsg),
} }
@ -103,9 +143,9 @@ pub struct DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope, workerglobalscope: WorkerGlobalScope,
id: PipelineId, id: PipelineId,
#[ignore_heap_size_of = "Defined in std"] #[ignore_heap_size_of = "Defined in std"]
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>, receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
#[ignore_heap_size_of = "Defined in std"] #[ignore_heap_size_of = "Defined in std"]
own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
#[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"] #[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"]
worker: DOMRefCell<Option<TrustedWorkerAddress>>, worker: DOMRefCell<Option<TrustedWorkerAddress>>,
#[ignore_heap_size_of = "Can't measure trait objects"] #[ignore_heap_size_of = "Can't measure trait objects"]
@ -120,8 +160,8 @@ impl DedicatedWorkerGlobalScope {
devtools_port: Receiver<DevtoolScriptControlMsg>, devtools_port: Receiver<DevtoolScriptControlMsg>,
runtime: Rc<Runtime>, runtime: Rc<Runtime>,
parent_sender: Box<ScriptChan+Send>, parent_sender: Box<ScriptChan+Send>,
own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>) receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>)
-> DedicatedWorkerGlobalScope { -> DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScope { DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited( workerglobalscope: WorkerGlobalScope::new_inherited(
@ -141,8 +181,8 @@ impl DedicatedWorkerGlobalScope {
devtools_port: Receiver<DevtoolScriptControlMsg>, devtools_port: Receiver<DevtoolScriptControlMsg>,
runtime: Rc<Runtime>, runtime: Rc<Runtime>,
parent_sender: Box<ScriptChan+Send>, parent_sender: Box<ScriptChan+Send>,
own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>) receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>)
-> Root<DedicatedWorkerGlobalScope> { -> Root<DedicatedWorkerGlobalScope> {
let scope = box DedicatedWorkerGlobalScope::new_inherited( let scope = box DedicatedWorkerGlobalScope::new_inherited(
init, worker_url, id, devtools_port, runtime.clone(), parent_sender, init, worker_url, id, devtools_port, runtime.clone(), parent_sender,
@ -158,8 +198,8 @@ impl DedicatedWorkerGlobalScope {
devtools_ipc_port: IpcReceiver<DevtoolScriptControlMsg>, devtools_ipc_port: IpcReceiver<DevtoolScriptControlMsg>,
worker: TrustedWorkerAddress, worker: TrustedWorkerAddress,
parent_sender: Box<ScriptChan+Send>, parent_sender: Box<ScriptChan+Send>,
own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>) { receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>) {
let serialized_worker_url = worker_url.serialize(); let serialized_worker_url = worker_url.serialize();
spawn_named(format!("WebWorker for {}", serialized_worker_url), move || { spawn_named(format!("WebWorker for {}", serialized_worker_url), move || {
task_state::initialize(SCRIPT | IN_WORKER); task_state::initialize(SCRIPT | IN_WORKER);
@ -170,7 +210,7 @@ impl DedicatedWorkerGlobalScope {
let (url, source) = match load_whole_resource(&init.resource_task, worker_url) { let (url, source) = match load_whole_resource(&init.resource_task, worker_url) {
Err(_) => { Err(_) => {
println!("error loading script {}", serialized_worker_url); println!("error loading script {}", serialized_worker_url);
parent_sender.send(ScriptMsg::RunnableMsg( parent_sender.send(CommonScriptMsg::RunnableMsg(
box WorkerEventHandler::new(worker))).unwrap(); box WorkerEventHandler::new(worker))).unwrap();
return; return;
} }
@ -201,7 +241,7 @@ impl DedicatedWorkerGlobalScope {
while let Ok(event) = global.receive_event() { while let Ok(event) = global.receive_event() {
global.handle_event(event); global.handle_event(event);
} }
}, reporter_name, parent_sender, ScriptMsg::CollectReports); }, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
}); });
} }
} }
@ -210,12 +250,12 @@ pub trait DedicatedWorkerGlobalScopeHelpers {
fn script_chan(self) -> Box<ScriptChan+Send>; fn script_chan(self) -> Box<ScriptChan+Send>;
fn pipeline(self) -> PipelineId; fn pipeline(self) -> PipelineId;
fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>); fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
fn process_event(self, msg: ScriptMsg); fn process_event(self, msg: CommonScriptMsg);
} }
impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope { impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
fn script_chan(self) -> Box<ScriptChan+Send> { fn script_chan(self) -> Box<ScriptChan+Send> {
box SendableWorkerScriptChan { box WorkerThreadWorkerChan {
sender: self.own_sender.clone(), sender: self.own_sender.clone(),
worker: self.worker.borrow().as_ref().unwrap().clone(), worker: self.worker.borrow().as_ref().unwrap().clone(),
} }
@ -234,13 +274,13 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
(chan, box rx) (chan, box rx)
} }
fn process_event(self, msg: ScriptMsg) { fn process_event(self, msg: CommonScriptMsg) {
self.handle_script_event(msg); self.handle_script_event(WorkerScriptMsg::Common(msg));
} }
} }
trait PrivateDedicatedWorkerGlobalScopeHelpers { trait PrivateDedicatedWorkerGlobalScopeHelpers {
fn handle_script_event(self, msg: ScriptMsg); fn handle_script_event(self, msg: WorkerScriptMsg);
fn dispatch_error_to_worker(self, &ErrorEvent); fn dispatch_error_to_worker(self, &ErrorEvent);
fn receive_event(self) -> Result<MixedMessage, RecvError>; fn receive_event(self) -> Result<MixedMessage, RecvError>;
fn handle_event(self, event: MixedMessage); fn handle_event(self, event: MixedMessage);
@ -272,9 +312,9 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
} }
} }
fn handle_script_event(self, msg: ScriptMsg) { fn handle_script_event(self, msg: WorkerScriptMsg) {
match msg { match msg {
ScriptMsg::DOMMessage(data) => { WorkerScriptMsg::DOMMessage(data) => {
let scope = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
let target = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
let _ar = JSAutoRequest::new(scope.get_cx()); let _ar = JSAutoRequest::new(scope.get_cx());
@ -283,24 +323,27 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
data.read(GlobalRef::Worker(scope), message.handle_mut()); data.read(GlobalRef::Worker(scope), message.handle_mut());
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle()); MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
}, },
ScriptMsg::RunnableMsg(runnable) => { WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(runnable)) => {
runnable.handler() runnable.handler()
}, },
ScriptMsg::RefcountCleanup(addr) => { WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => {
LiveDOMReferences::cleanup(addr); LiveDOMReferences::cleanup(addr);
} },
ScriptMsg::FireTimer(TimerSource::FromWorker, timer_id) => { WorkerScriptMsg::Common(
CommonScriptMsg::FireTimer(TimerSource::FromWorker, timer_id)) => {
let scope = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
scope.handle_fire_timer(timer_id); scope.handle_fire_timer(timer_id);
} },
ScriptMsg::CollectReports(reports_chan) => { WorkerScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => {
let scope = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
let cx = scope.get_cx(); let cx = scope.get_cx();
let path_seg = format!("url({})", scope.get_url()); let path_seg = format!("url({})", scope.get_url());
let reports = ScriptTask::get_reports(cx, path_seg); let reports = ScriptTask::get_reports(cx, path_seg);
reports_chan.send(reports); reports_chan.send(reports);
} },
_ => panic!("Unexpected message"), WorkerScriptMsg::Common(CommonScriptMsg::FireTimer(_, _)) => {
panic!("obtained a fire timeout from window for the worker!")
},
} }
} }
@ -331,7 +374,7 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
let line_num = errorevent.Lineno(); let line_num = errorevent.Lineno();
let col_num = errorevent.Colno(); let col_num = errorevent.Colno();
let worker = self.worker.borrow().as_ref().unwrap().clone(); let worker = self.worker.borrow().as_ref().unwrap().clone();
self.parent_sender.send(ScriptMsg::RunnableMsg( self.parent_sender.send(CommonScriptMsg::RunnableMsg(
box WorkerErrorHandler::new(worker, msg, file_name, line_num, col_num))).unwrap(); box WorkerErrorHandler::new(worker, msg, file_name, line_num, col_num))).unwrap();
} }
} }
@ -341,7 +384,7 @@ impl<'a> DedicatedWorkerGlobalScopeMethods for &'a DedicatedWorkerGlobalScope {
fn PostMessage(self, cx: *mut JSContext, message: HandleValue) -> ErrorResult { fn PostMessage(self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
let data = try!(StructuredCloneData::write(cx, message)); let data = try!(StructuredCloneData::write(cx, message));
let worker = self.worker.borrow().as_ref().unwrap().clone(); let worker = self.worker.borrow().as_ref().unwrap().clone();
self.parent_sender.send(ScriptMsg::RunnableMsg( self.parent_sender.send(CommonScriptMsg::RunnableMsg(
box WorkerMessageHandler::new(worker, data))).unwrap(); box WorkerMessageHandler::new(worker, data))).unwrap();
Ok(()) Ok(())
} }

View file

@ -22,7 +22,7 @@ use encoding::types::{EncodingRef, DecoderTrap};
use encoding::label::encoding_from_whatwg_label; use encoding::label::encoding_from_whatwg_label;
use hyper::mime::{Mime, Attr}; use hyper::mime::{Mime, Attr};
use std::sync::mpsc; use std::sync::mpsc;
use script_task::{ScriptChan, ScriptMsg, Runnable, ScriptPort}; use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use util::str::DOMString; use util::str::DOMString;
@ -408,22 +408,22 @@ fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, bl
let chan = &script_chan; let chan = &script_chan;
// Step 4 // Step 4
let task = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id); let task = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id);
chan.send(ScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
let task = box FileReaderEvent::ProcessReadData(filereader.clone(), let task = box FileReaderEvent::ProcessReadData(filereader.clone(),
gen_id, DOMString::new()); gen_id, DOMString::new());
chan.send(ScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
let bytes = match blob_contents.recv() { let bytes = match blob_contents.recv() {
Ok(bytes) => bytes, Ok(bytes) => bytes,
Err(_) => { Err(_) => {
let task = box FileReaderEvent::ProcessReadError(filereader, let task = box FileReaderEvent::ProcessReadError(filereader,
gen_id, DOMErrorName::NotFoundError); gen_id, DOMErrorName::NotFoundError);
chan.send(ScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
return; return;
} }
}; };
let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes); let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes);
chan.send(ScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
} }

View file

@ -34,7 +34,7 @@ use hyper::header::ContentType;
use hyper::mime; use hyper::mime;
use msg::constellation_msg::LoadData; use msg::constellation_msg::LoadData;
use util::str::DOMString; use util::str::DOMString;
use script_task::{ScriptChan, ScriptMsg}; use script_task::{ScriptChan, MainThreadScriptMsg};
use url::UrlParser; use url::UrlParser;
use url::form_urlencoded::serialize; use url::form_urlencoded::serialize;
use string_cache::Atom; use string_cache::Atom;
@ -232,7 +232,8 @@ impl<'a> HTMLFormElementHelpers for &'a HTMLFormElement {
} }
// This is wrong. https://html.spec.whatwg.org/multipage/#planned-navigation // This is wrong. https://html.spec.whatwg.org/multipage/#planned-navigation
win.r().script_chan().send(ScriptMsg::Navigate(win.r().pipeline(), load_data)).unwrap(); win.r().main_thread_script_chan().send(MainThreadScriptMsg::Navigate(
win.r().pipeline(), load_data)).unwrap();
} }
fn get_form_dataset<'b>(self, submitter: Option<FormSubmitter<'b>>) -> Vec<FormDatum> { fn get_form_dataset<'b>(self, submitter: Option<FormSubmitter<'b>>) -> Vec<FormDatum> {

View file

@ -23,7 +23,7 @@ use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{document_from_node, Node, NodeTypeId, NodeHelpers, NodeDamage, window_from_node}; use dom::node::{document_from_node, Node, NodeTypeId, NodeHelpers, NodeDamage, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers; use dom::window::WindowHelpers;
use script_task::{Runnable, ScriptChan, ScriptMsg}; use script_task::{Runnable, ScriptChan, CommonScriptMsg};
use util::str::DOMString; use util::str::DOMString;
use string_cache::Atom; use string_cache::Atom;
@ -140,9 +140,9 @@ impl<'a> PrivateHTMLImageElementHelpers for &'a HTMLImageElement {
// Return the image via a message to the script task, which marks the element // Return the image via a message to the script task, which marks the element
// as dirty and triggers a reflow. // as dirty and triggers a reflow.
let image_response = message.to().unwrap(); let image_response = message.to().unwrap();
script_chan.send(ScriptMsg::RunnableMsg(box ImageResponseHandlerRunnable::new( script_chan.send(CommonScriptMsg::RunnableMsg(
trusted_node.clone(), box ImageResponseHandlerRunnable::new(
image_response))).unwrap(); trusted_node.clone(), image_response))).unwrap();
}); });
image_cache.request_image(img_url, image_cache.request_image(img_url,
@ -345,4 +345,3 @@ impl<'a> VirtualMethods for &'a HTMLImageElement {
} }
} }
} }

View file

@ -33,7 +33,7 @@ use dom::servohtmlparser::ServoHTMLParserHelpers;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::{WindowHelpers, ScriptHelpers}; use dom::window::{WindowHelpers, ScriptHelpers};
use network_listener::{NetworkListener, PreInvoke}; use network_listener::{NetworkListener, PreInvoke};
use script_task::{ScriptChan, ScriptMsg, Runnable}; use script_task::{ScriptChan, Runnable, CommonScriptMsg};
use js::jsapi::RootedValue; use js::jsapi::RootedValue;
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
@ -459,7 +459,7 @@ impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement {
element: handler, element: handler,
is_error: false, is_error: false,
}; };
chan.send(ScriptMsg::RunnableMsg(dispatcher)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(dispatcher)).unwrap();
} }
} }
@ -472,7 +472,7 @@ impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement {
element: handler, element: handler,
is_error: true, is_error: true,
}; };
chan.send(ScriptMsg::RunnableMsg(dispatcher)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(dispatcher)).unwrap();
} }
fn dispatch_before_script_execute_event(self) -> bool { fn dispatch_before_script_execute_event(self) -> bool {

View file

@ -28,7 +28,7 @@ use dom::node::{NodeHelpers, NodeTypeId, document_from_node, window_from_node};
use textinput::{TextInput, Lines, KeyReaction}; use textinput::{TextInput, Lines, KeyReaction};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers; use dom::window::WindowHelpers;
use script_task::{ScriptMsg, Runnable}; use script_task::{Runnable, CommonScriptMsg};
use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::ConstellationChan;
use util::str::DOMString; use util::str::DOMString;
@ -368,7 +368,7 @@ impl<'a> VirtualMethods for &'a HTMLTextAreaElement {
let dispatcher = ChangeEventRunnable { let dispatcher = ChangeEventRunnable {
element: handler, element: handler,
}; };
let _ = chan.send(ScriptMsg::RunnableMsg(box dispatcher)); let _ = chan.send(CommonScriptMsg::RunnableMsg(box dispatcher));
} }
self.force_relayout(); self.force_relayout();

View file

@ -17,12 +17,11 @@ use ipc_channel::ipc;
use util::str::DOMString; use util::str::DOMString;
use page::IterablePage; use page::IterablePage;
use net_traits::storage_task::{StorageTask, StorageTaskMsg, StorageType}; use net_traits::storage_task::{StorageTask, StorageTaskMsg, StorageType};
use script_task::{ScriptTask, MainThreadRunnable, MainThreadScriptMsg};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use url::Url; use url::Url;
use script_task::{ScriptTask, ScriptMsg, MainThreadRunnable};
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)] #[derive(HeapSizeOf)]
pub struct Storage { pub struct Storage {
@ -148,12 +147,12 @@ impl<'a> PrivateStorageHelpers for &'a Storage {
new_value: Option<DOMString>){ new_value: Option<DOMString>){
let global_root = self.global.root(); let global_root = self.global.root();
let global_ref = global_root.r(); let global_ref = global_root.r();
let main_script_chan = global_ref.as_window().main_thread_script_chan();
let script_chan = global_ref.script_chan(); let script_chan = global_ref.script_chan();
let trusted_storage = Trusted::new(global_ref.get_cx(), self, let trusted_storage = Trusted::new(global_ref.get_cx(), self,
script_chan.clone()); script_chan.clone());
script_chan.send(ScriptMsg::MainThreadRunnableMsg( main_script_chan.send(MainThreadScriptMsg::MainThreadRunnableMsg(
box StorageEventRunnable::new(trusted_storage, key, box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap();
old_value, new_value))).unwrap();
} }
} }

View file

@ -22,8 +22,7 @@ use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers}; use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
use script_task::Runnable; use script_task::{Runnable, CommonScriptMsg};
use script_task::ScriptMsg;
use net_traits::hosts::replace_hosts; use net_traits::hosts::replace_hosts;
use util::str::DOMString; use util::str::DOMString;
@ -179,7 +178,7 @@ impl WebSocket {
let task = box CloseTask { let task = box CloseTask {
addr: address, addr: address,
}; };
sender.send(ScriptMsg::RunnableMsg(task)).unwrap(); sender.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
return; return;
} }
}; };
@ -189,7 +188,7 @@ impl WebSocket {
addr: address.clone(), addr: address.clone(),
sender: ws_sender.clone(), sender: ws_sender.clone(),
}; };
sender.send(ScriptMsg::RunnableMsg(open_task)).unwrap(); sender.send(CommonScriptMsg::RunnableMsg(open_task)).unwrap();
for message in receiver.incoming_messages() { for message in receiver.incoming_messages() {
let message = match message { let message = match message {
@ -205,7 +204,7 @@ impl WebSocket {
let task = box CloseTask { let task = box CloseTask {
addr: address, addr: address,
}; };
sender.send(ScriptMsg::RunnableMsg(task)).unwrap(); sender.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
break; break;
}, },
Err(_) => break, Err(_) => break,
@ -214,7 +213,7 @@ impl WebSocket {
address: address.clone(), address: address.clone(),
message: message, message: message,
}; };
sender.send(ScriptMsg::RunnableMsg(message_task)).unwrap(); sender.send(CommonScriptMsg::RunnableMsg(message_task)).unwrap();
} }
}); });

View file

@ -34,8 +34,8 @@ use dom::storage::Storage;
use layout_interface::{ReflowGoal, ReflowQueryType, LayoutRPC, LayoutChan, Reflow, Msg}; use layout_interface::{ReflowGoal, ReflowQueryType, LayoutRPC, LayoutChan, Reflow, Msg};
use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ResolvedStyleResponse, ScriptReflow}; use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ResolvedStyleResponse, ScriptReflow};
use page::Page; use page::Page;
use script_task::{TimerSource, ScriptChan, ScriptPort, NonWorkerScriptChan}; use script_task::{TimerSource, ScriptChan, ScriptPort, MainThreadScriptMsg};
use script_task::ScriptMsg; use script_task::{SendableMainThreadScriptChan, MainThreadScriptChan};
use script_traits::ConstellationControlMsg; use script_traits::ConstellationControlMsg;
use timers::{IsInterval, TimerId, TimerManager, TimerCallback}; use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
use webdriver_handlers::jsval_to_webdriver; use webdriver_handlers::jsval_to_webdriver;
@ -110,7 +110,7 @@ pub enum ReflowReason {
pub struct Window { pub struct Window {
eventtarget: EventTarget, eventtarget: EventTarget,
#[ignore_heap_size_of = "trait objects are hard"] #[ignore_heap_size_of = "trait objects are hard"]
script_chan: Box<ScriptChan+Send>, script_chan: MainThreadScriptChan,
#[ignore_heap_size_of = "channels are hard"] #[ignore_heap_size_of = "channels are hard"]
control_chan: Sender<ConstellationControlMsg>, control_chan: Sender<ConstellationControlMsg>,
console: MutNullableHeap<JS<Console>>, console: MutNullableHeap<JS<Console>>,
@ -236,6 +236,11 @@ impl Window {
self.script_chan.clone() self.script_chan.clone()
} }
pub fn main_thread_script_chan(&self) -> &Sender<MainThreadScriptMsg> {
let MainThreadScriptChan(ref sender) = self.script_chan;
sender
}
pub fn image_cache_chan(&self) -> ImageCacheChan { pub fn image_cache_chan(&self) -> ImageCacheChan {
self.image_cache_chan.clone() self.image_cache_chan.clone()
} }
@ -261,7 +266,7 @@ impl Window {
pub fn new_script_pair(&self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) { pub fn new_script_pair(&self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
let (tx, rx) = channel(); let (tx, rx) = channel();
(box NonWorkerScriptChan(tx), box rx) (box SendableMainThreadScriptChan(tx), box rx)
} }
pub fn image_cache_task<'a>(&'a self) -> &'a ImageCacheTask { pub fn image_cache_task<'a>(&'a self) -> &'a ImageCacheTask {
@ -370,7 +375,7 @@ impl<'a> WindowMethods for &'a Window {
// https://html.spec.whatwg.org/multipage/#dom-window-close // https://html.spec.whatwg.org/multipage/#dom-window-close
fn Close(self) { fn Close(self) {
self.script_chan.send(ScriptMsg::ExitWindow(self.id.clone())).unwrap(); self.main_thread_script_chan().send(MainThreadScriptMsg::ExitWindow(self.id.clone())).unwrap();
} }
// https://html.spec.whatwg.org/multipage/#dom-document-0 // https://html.spec.whatwg.org/multipage/#dom-document-0
@ -887,7 +892,8 @@ impl<'a> WindowHelpers for &'a Window {
/// Commence a new URL load which will either replace this window or scroll to a fragment. /// Commence a new URL load which will either replace this window or scroll to a fragment.
fn load_url(self, url: Url) { fn load_url(self, url: Url) {
self.script_chan.send(ScriptMsg::Navigate(self.id, LoadData::new(url))).unwrap(); self.main_thread_script_chan().send(
MainThreadScriptMsg::Navigate(self.id, LoadData::new(url))).unwrap();
} }
fn handle_fire_timer(self, timer_id: TimerId) { fn handle_fire_timer(self, timer_id: TimerId) {
@ -1064,7 +1070,7 @@ impl<'a> WindowHelpers for &'a Window {
impl Window { impl Window {
pub fn new(runtime: Rc<Runtime>, pub fn new(runtime: Rc<Runtime>,
page: Rc<Page>, page: Rc<Page>,
script_chan: Box<ScriptChan+Send>, script_chan: MainThreadScriptChan,
image_cache_chan: ImageCacheChan, image_cache_chan: ImageCacheChan,
control_chan: Sender<ConstellationControlMsg>, control_chan: Sender<ConstellationControlMsg>,
compositor: ScriptListener, compositor: ScriptListener,

View file

@ -15,23 +15,22 @@ use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, reflect_dom_object}; use dom::bindings::utils::{Reflectable, reflect_dom_object};
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::window::WindowHelpers; use dom::window::WindowHelpers;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::dedicatedworkerglobalscope::{DedicatedWorkerGlobalScope, WorkerScriptMsg};
use dom::errorevent::ErrorEvent; use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers}; use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
use dom::workerglobalscope::WorkerGlobalScopeInit; use dom::workerglobalscope::WorkerGlobalScopeInit;
use script_task::{ScriptChan, ScriptMsg, Runnable};
use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg}; use devtools_traits::{DevtoolsPageInfo, ScriptToDevtoolsControlMsg};
use script_task::{ScriptChan, Runnable};
use util::str::DOMString;
use ipc_channel::ipc; use ipc_channel::ipc;
use js::jsapi::{JSContext, HandleValue, RootedValue}; use js::jsapi::{JSContext, HandleValue, RootedValue};
use js::jsapi::{JSAutoRequest, JSAutoCompartment}; use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use url::UrlParser; use url::UrlParser;
use util::str::DOMString;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::sync::mpsc::{channel, Sender}; use std::sync::mpsc::{channel, Sender};
@ -47,11 +46,13 @@ pub struct Worker {
#[ignore_heap_size_of = "Defined in std"] #[ignore_heap_size_of = "Defined in std"]
/// Sender to the Receiver associated with the DedicatedWorkerGlobalScope /// Sender to the Receiver associated with the DedicatedWorkerGlobalScope
/// this Worker created. /// this Worker created.
sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
} }
impl Worker { impl Worker {
fn new_inherited(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Worker { fn new_inherited(global: GlobalRef,
sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>)
-> Worker {
Worker { Worker {
eventtarget: EventTarget::new_inherited(EventTargetTypeId::Worker), eventtarget: EventTarget::new_inherited(EventTargetTypeId::Worker),
global: GlobalField::from_rooted(&global), global: GlobalField::from_rooted(&global),
@ -59,7 +60,9 @@ impl Worker {
} }
} }
pub fn new(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Root<Worker> { pub fn new(global: GlobalRef,
sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>)
-> Root<Worker> {
reflect_dom_object(box Worker::new_inherited(global, sender), reflect_dom_object(box Worker::new_inherited(global, sender),
global, global,
WorkerBinding::Wrap) WorkerBinding::Wrap)
@ -157,7 +160,7 @@ impl<'a> WorkerMethods for &'a Worker {
fn PostMessage(self, cx: *mut JSContext, message: HandleValue) -> ErrorResult { fn PostMessage(self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
let data = try!(StructuredCloneData::write(cx, message)); let data = try!(StructuredCloneData::write(cx, message));
let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone()); let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone());
self.sender.send((address, ScriptMsg::DOMMessage(data))).unwrap(); self.sender.send((address, WorkerScriptMsg::DOMMessage(data))).unwrap();
Ok(()) Ok(())
} }

View file

@ -17,7 +17,7 @@ use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::workerlocation::WorkerLocation; use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator; use dom::workernavigator::WorkerNavigator;
use dom::window::{base64_atob, base64_btoa}; use dom::window::{base64_atob, base64_btoa};
use script_task::{ScriptChan, TimerSource, ScriptPort, ScriptMsg}; use script_task::{CommonScriptMsg, ScriptChan, TimerSource, ScriptPort};
use timers::{IsInterval, TimerId, TimerManager, TimerCallback}; use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolScriptControlMsg}; use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolScriptControlMsg};
@ -291,7 +291,7 @@ pub trait WorkerGlobalScopeHelpers {
fn script_chan(self) -> Box<ScriptChan+Send>; fn script_chan(self) -> Box<ScriptChan+Send>;
fn pipeline(self) -> PipelineId; fn pipeline(self) -> PipelineId;
fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>); fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
fn process_event(self, msg: ScriptMsg); fn process_event(self, msg: CommonScriptMsg);
fn get_cx(self) -> *mut JSContext; fn get_cx(self) -> *mut JSContext;
fn set_devtools_wants_updates(self, value: bool); fn set_devtools_wants_updates(self, value: bool);
} }
@ -338,7 +338,7 @@ impl<'a> WorkerGlobalScopeHelpers for &'a WorkerGlobalScope {
} }
} }
fn process_event(self, msg: ScriptMsg) { fn process_event(self, msg: CommonScriptMsg) {
let dedicated = let dedicated =
DedicatedWorkerGlobalScopeCast::to_ref(self); DedicatedWorkerGlobalScopeCast::to_ref(self);
match dedicated { match dedicated {

View file

@ -28,7 +28,7 @@ use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId;
use dom::xmlhttprequestupload::XMLHttpRequestUpload; use dom::xmlhttprequestupload::XMLHttpRequestUpload;
use network_listener::{NetworkListener, PreInvoke}; use network_listener::{NetworkListener, PreInvoke};
use script_task::{ScriptChan, ScriptMsg, Runnable, ScriptPort}; use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
use encoding::all::UTF_8; use encoding::all::UTF_8;
use encoding::label::encoding_from_whatwg_label; use encoding::label::encoding_from_whatwg_label;
@ -1013,7 +1013,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for &'a XMLHttpRequest {
sleep_ms(duration_ms); sleep_ms(duration_ms);
match cancel_rx.try_recv() { match cancel_rx.try_recv() {
Err(TryRecvError::Empty) => { Err(TryRecvError::Empty) => {
timeout_target.send(ScriptMsg::RunnableMsg(box XHRTimeout { timeout_target.send(CommonScriptMsg::RunnableMsg(box XHRTimeout {
xhr: xhr, xhr: xhr,
gen_id: gen_id, gen_id: gen_id,
})).unwrap(); })).unwrap();

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use script_task::{ScriptChan, ScriptMsg, Runnable}; use script_task::{ScriptChan, Runnable, CommonScriptMsg};
use net_traits::{AsyncResponseListener, ResponseAction}; use net_traits::{AsyncResponseListener, ResponseAction};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -15,7 +15,7 @@ pub struct NetworkListener<T: AsyncResponseListener + PreInvoke + Send + 'static
impl<T: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<T> { impl<T: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<T> {
pub fn notify(&self, action: ResponseAction) { pub fn notify(&self, action: ResponseAction) {
if let Err(err) = self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { if let Err(err) = self.script_chan.send(CommonScriptMsg::RunnableMsg(box ListenerRunnable {
context: self.context.clone(), context: self.context.clone(),
action: action, action: action,
})) { })) {

View file

@ -30,7 +30,6 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, RootCollection, trace_roots}; use dom::bindings::js::{JS, RootCollection, trace_roots};
use dom::bindings::js::{RootCollectionPtr, Root, RootedReference}; use dom::bindings::js::{RootCollectionPtr, Root, RootedReference};
use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference, trace_refcounted_objects}; use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference, trace_refcounted_objects};
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::{JSTraceable, trace_traceables, RootedVec}; use dom::bindings::trace::{JSTraceable, trace_traceables, RootedVec};
use dom::bindings::utils::{WRAP_CALLBACKS, DOM_CALLBACKS}; use dom::bindings::utils::{WRAP_CALLBACKS, DOM_CALLBACKS};
use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentProgressHandler, use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentProgressHandler,
@ -179,45 +178,47 @@ pub trait MainThreadRunnable {
fn handler(self: Box<Self>, script_task: &ScriptTask); fn handler(self: Box<Self>, script_task: &ScriptTask);
} }
/// Messages used to control script event loops, such as ScriptTask and /// Common messages used to control the event loops in both the script and the worker
/// DedicatedWorkerGlobalScope. pub enum CommonScriptMsg {
pub enum ScriptMsg { /// Requests that the script task measure its memory usage. The results are sent back via the
/// Begins a content-initiated load on the specified pipeline (only /// supplied channel.
/// dispatched to ScriptTask). CollectReports(ReportsChan),
Navigate(PipelineId, LoadData),
/// Fires a JavaScript timeout /// Fires a JavaScript timeout
/// TimerSource must be FromWindow when dispatched to ScriptTask and /// TimerSource must be FromWindow when dispatched to ScriptTask and
/// must be FromWorker when dispatched to a DedicatedGlobalWorkerScope /// must be FromWorker when dispatched to a DedicatedGlobalWorkerScope
FireTimer(TimerSource, TimerId), FireTimer(TimerSource, TimerId),
/// A DOM object's last pinned reference was removed (dispatched to all tasks).
RefcountCleanup(TrustedReference),
/// Generic message that encapsulates event handling.
RunnableMsg(Box<Runnable+Send>),
}
/// Messages used to control the script event loop
pub enum MainThreadScriptMsg {
/// Common variants associated with the script messages
Common(CommonScriptMsg),
/// Notify a document that all pending loads are complete.
DocumentLoadsComplete(PipelineId),
/// Notifies the script that a window associated with a particular pipeline /// Notifies the script that a window associated with a particular pipeline
/// should be closed (only dispatched to ScriptTask). /// should be closed (only dispatched to ScriptTask).
ExitWindow(PipelineId), ExitWindow(PipelineId),
/// Message sent through Worker.postMessage (only dispatched to
/// DedicatedWorkerGlobalScope).
DOMMessage(StructuredCloneData),
/// Generic message that encapsulates event handling.
RunnableMsg(Box<Runnable+Send>),
/// Generic message for running tasks in the ScriptTask /// Generic message for running tasks in the ScriptTask
MainThreadRunnableMsg(Box<MainThreadRunnable+Send>), MainThreadRunnableMsg(Box<MainThreadRunnable+Send>),
/// A DOM object's last pinned reference was removed (dispatched to all tasks). /// Begins a content-initiated load on the specified pipeline (only
RefcountCleanup(TrustedReference), /// dispatched to ScriptTask).
/// Notify a document that all pending loads are complete. Navigate(PipelineId, LoadData),
DocumentLoadsComplete(PipelineId),
/// Requests that the script task measure its memory usage. The results are sent back via the
/// supplied channel.
CollectReports(ReportsChan),
} }
/// A cloneable interface for communicating with an event loop. /// A cloneable interface for communicating with an event loop.
pub trait ScriptChan { pub trait ScriptChan {
/// Send a message to the associated event loop. /// Send a message to the associated event loop.
fn send(&self, msg: ScriptMsg) -> Result<(), ()>; fn send(&self, msg: CommonScriptMsg) -> Result<(), ()>;
/// Clone this handle. /// Clone this handle.
fn clone(&self) -> Box<ScriptChan+Send>; fn clone(&self) -> Box<ScriptChan+Send>;
} }
impl OpaqueSender<ScriptMsg> for Box<ScriptChan+Send> { impl OpaqueSender<CommonScriptMsg> for Box<ScriptChan+Send> {
fn send(&self, msg: ScriptMsg) { fn send(&self, msg: CommonScriptMsg) {
ScriptChan::send(&**self, msg).unwrap(); ScriptChan::send(&**self, msg).unwrap();
} }
} }
@ -226,42 +227,84 @@ impl OpaqueSender<ScriptMsg> for Box<ScriptChan+Send> {
/// APIs that need to abstract over multiple kinds of event loops (worker/main thread) with /// APIs that need to abstract over multiple kinds of event loops (worker/main thread) with
/// different Receiver interfaces. /// different Receiver interfaces.
pub trait ScriptPort { pub trait ScriptPort {
fn recv(&self) -> ScriptMsg; fn recv(&self) -> CommonScriptMsg;
} }
impl ScriptPort for Receiver<ScriptMsg> { impl ScriptPort for Receiver<CommonScriptMsg> {
fn recv(&self) -> ScriptMsg { fn recv(&self) -> CommonScriptMsg {
self.recv().unwrap() self.recv().unwrap()
} }
} }
impl ScriptPort for Receiver<(TrustedWorkerAddress, ScriptMsg)> { impl ScriptPort for Receiver<MainThreadScriptMsg> {
fn recv(&self) -> ScriptMsg { fn recv(&self) -> CommonScriptMsg {
match self.recv().unwrap() {
MainThreadScriptMsg::Common(script_msg) => script_msg,
_ => panic!("unexpected main thread event message!")
}
}
}
impl ScriptPort for Receiver<(TrustedWorkerAddress, CommonScriptMsg)> {
fn recv(&self) -> CommonScriptMsg {
self.recv().unwrap().1 self.recv().unwrap().1
} }
} }
/// Encapsulates internal communication within the script task. impl ScriptPort for Receiver<(TrustedWorkerAddress, MainThreadScriptMsg)> {
#[derive(JSTraceable)] fn recv(&self) -> CommonScriptMsg {
pub struct NonWorkerScriptChan(pub Sender<ScriptMsg>); match self.recv().unwrap().1 {
MainThreadScriptMsg::Common(script_msg) => script_msg,
_ => panic!("unexpected main thread event message!")
}
}
}
impl ScriptChan for NonWorkerScriptChan { /// Encapsulates internal communication of shared messages within the script task.
fn send(&self, msg: ScriptMsg) -> Result<(), ()> { #[derive(JSTraceable)]
let NonWorkerScriptChan(ref chan) = *self; pub struct SendableMainThreadScriptChan(pub Sender<CommonScriptMsg>);
impl ScriptChan for SendableMainThreadScriptChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let SendableMainThreadScriptChan(ref chan) = *self;
return chan.send(msg).map_err(|_| ()); return chan.send(msg).map_err(|_| ());
} }
fn clone(&self) -> Box<ScriptChan+Send> { fn clone(&self) -> Box<ScriptChan+Send> {
let NonWorkerScriptChan(ref chan) = *self; let SendableMainThreadScriptChan(ref chan) = *self;
box NonWorkerScriptChan((*chan).clone()) box SendableMainThreadScriptChan((*chan).clone())
} }
} }
impl NonWorkerScriptChan { impl SendableMainThreadScriptChan {
/// Creates a new script chan. /// Creates a new script chan.
pub fn new() -> (Receiver<ScriptMsg>, Box<NonWorkerScriptChan>) { pub fn new() -> (Receiver<CommonScriptMsg>, Box<SendableMainThreadScriptChan>) {
let (chan, port) = channel(); let (chan, port) = channel();
(port, box NonWorkerScriptChan(chan)) (port, box SendableMainThreadScriptChan(chan))
}
}
/// Encapsulates internal communication of main thread messages within the script task.
#[derive(JSTraceable)]
pub struct MainThreadScriptChan(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for MainThreadScriptChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let MainThreadScriptChan(ref chan) = *self;
return chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ());
}
fn clone(&self) -> Box<ScriptChan+Send> {
let MainThreadScriptChan(ref chan) = *self;
box MainThreadScriptChan((*chan).clone())
}
}
impl MainThreadScriptChan {
/// Creates a new script chan.
pub fn new() -> (Receiver<MainThreadScriptMsg>, Box<MainThreadScriptChan>) {
let (chan, port) = channel();
(port, box MainThreadScriptChan(chan))
} }
} }
@ -302,10 +345,10 @@ pub struct ScriptTask {
storage_task: StorageTask, storage_task: StorageTask,
/// The port on which the script task receives messages (load URL, exit, etc.) /// The port on which the script task receives messages (load URL, exit, etc.)
port: Receiver<ScriptMsg>, port: Receiver<MainThreadScriptMsg>,
/// A channel to hand out to script task-based entities that need to be able to enqueue /// A channel to hand out to script task-based entities that need to be able to enqueue
/// events in the event queue. /// events in the event queue.
chan: NonWorkerScriptChan, chan: MainThreadScriptChan,
/// A channel to hand out to tasks that need to respond to a message from the script task. /// A channel to hand out to tasks that need to respond to a message from the script task.
control_chan: Sender<ConstellationControlMsg>, control_chan: Sender<ConstellationControlMsg>,
@ -419,7 +462,7 @@ impl ScriptTaskFactory for ScriptTask {
spawn_named_with_send_on_failure(format!("ScriptTask {:?}", id), task_state::SCRIPT, move || { spawn_named_with_send_on_failure(format!("ScriptTask {:?}", id), task_state::SCRIPT, move || {
let roots = RootCollection::new(); let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots); let _stack_roots_tls = StackRootTLS::new(&roots);
let chan = NonWorkerScriptChan(script_chan); let chan = MainThreadScriptChan(script_chan);
let channel_for_reporter = chan.clone(); let channel_for_reporter = chan.clone();
let script_task = ScriptTask::new(compositor, let script_task = ScriptTask::new(compositor,
script_port, script_port,
@ -446,7 +489,7 @@ impl ScriptTaskFactory for ScriptTask {
let reporter_name = format!("script-reporter-{}", id.0); let reporter_name = format!("script-reporter-{}", id.0);
mem_profiler_chan.run_with_memory_reporting(|| { mem_profiler_chan.run_with_memory_reporting(|| {
script_task.start(); script_task.start();
}, reporter_name, channel_for_reporter, ScriptMsg::CollectReports); }, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports);
// This must always be the very last operation performed before the task completes // This must always be the very last operation performed before the task completes
failsafe.neuter(); failsafe.neuter();
@ -526,19 +569,19 @@ impl ScriptTask {
}); });
} }
pub fn process_event(msg: ScriptMsg) { pub fn process_event(msg: CommonScriptMsg) {
SCRIPT_TASK_ROOT.with(|root| { SCRIPT_TASK_ROOT.with(|root| {
if let Some(script_task) = *root.borrow() { if let Some(script_task) = *root.borrow() {
let script_task = unsafe { &*script_task }; let script_task = unsafe { &*script_task };
script_task.handle_msg_from_script(msg); script_task.handle_msg_from_script(MainThreadScriptMsg::Common(msg));
} }
}); });
} }
/// Creates a new script task. /// Creates a new script task.
pub fn new(compositor: ScriptListener, pub fn new(compositor: ScriptListener,
port: Receiver<ScriptMsg>, port: Receiver<MainThreadScriptMsg>,
chan: NonWorkerScriptChan, chan: MainThreadScriptChan,
control_chan: Sender<ConstellationControlMsg>, control_chan: Sender<ConstellationControlMsg>,
control_port: Receiver<ConstellationControlMsg>, control_port: Receiver<ConstellationControlMsg>,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
@ -672,7 +715,7 @@ impl ScriptTask {
enum MixedMessage { enum MixedMessage {
FromConstellation(ConstellationControlMsg), FromConstellation(ConstellationControlMsg),
FromScript(ScriptMsg), FromScript(MainThreadScriptMsg),
FromDevtools(DevtoolScriptControlMsg), FromDevtools(DevtoolScriptControlMsg),
FromImageCache(ImageCacheResult), FromImageCache(ImageCacheResult),
} }
@ -855,27 +898,27 @@ impl ScriptTask {
} }
} }
fn handle_msg_from_script(&self, msg: ScriptMsg) { fn handle_msg_from_script(&self, msg: MainThreadScriptMsg) {
match msg { match msg {
ScriptMsg::Navigate(id, load_data) => MainThreadScriptMsg::Navigate(id, load_data) =>
self.handle_navigate(id, None, load_data), self.handle_navigate(id, None, load_data),
ScriptMsg::FireTimer(TimerSource::FromWindow(id), timer_id) => MainThreadScriptMsg::ExitWindow(id) =>
self.handle_fire_timer_msg(id, timer_id),
ScriptMsg::FireTimer(TimerSource::FromWorker, _) =>
panic!("Worker timeouts must not be sent to script task"),
ScriptMsg::ExitWindow(id) =>
self.handle_exit_window_msg(id), self.handle_exit_window_msg(id),
ScriptMsg::DOMMessage(..) => MainThreadScriptMsg::MainThreadRunnableMsg(runnable) =>
panic!("unexpected message"),
ScriptMsg::RunnableMsg(runnable) =>
runnable.handler(),
ScriptMsg::MainThreadRunnableMsg(runnable) =>
runnable.handler(self), runnable.handler(self),
ScriptMsg::RefcountCleanup(addr) => MainThreadScriptMsg::DocumentLoadsComplete(id) =>
LiveDOMReferences::cleanup(addr),
ScriptMsg::DocumentLoadsComplete(id) =>
self.handle_loads_complete(id), self.handle_loads_complete(id),
ScriptMsg::CollectReports(reports_chan) => MainThreadScriptMsg::Common(
CommonScriptMsg::FireTimer(TimerSource::FromWindow(id), timer_id)) =>
self.handle_fire_timer_msg(id, timer_id),
MainThreadScriptMsg::Common(
CommonScriptMsg::FireTimer(TimerSource::FromWorker, _)) =>
panic!("Worker timeouts must not be sent to script task"),
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(runnable)) =>
runnable.handler(),
MainThreadScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) =>
LiveDOMReferences::cleanup(addr),
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) =>
self.collect_reports(reports_chan), self.collect_reports(reports_chan),
} }
} }
@ -1085,7 +1128,7 @@ impl ScriptTask {
// https://html.spec.whatwg.org/multipage/#the-end step 7 // https://html.spec.whatwg.org/multipage/#the-end step 7
let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone()); let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone());
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load); let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load);
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap(); self.chan.send(CommonScriptMsg::RunnableMsg(handler)).unwrap();
let ConstellationChan(ref chan) = self.constellation_chan; let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap(); chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap();
@ -1455,11 +1498,12 @@ impl ScriptTask {
PageToRemove::Child(incomplete.pipeline_id) PageToRemove::Child(incomplete.pipeline_id)
}; };
let mut page_remover = AutoPageRemover::new(self, page_to_remove); let mut page_remover = AutoPageRemover::new(self, page_to_remove);
let MainThreadScriptChan(ref sender) = self.chan;
// Create the window and document objects. // Create the window and document objects.
let window = Window::new(self.js_runtime.clone(), let window = Window::new(self.js_runtime.clone(),
page.clone(), page.clone(),
self.chan.clone(), MainThreadScriptChan(sender.clone()),
self.image_cache_channel.clone(), self.image_cache_channel.clone(),
self.control_chan.clone(), self.control_chan.clone(),
self.compositor.borrow_mut().dup(), self.compositor.borrow_mut().dup(),
@ -1485,9 +1529,12 @@ impl ScriptTask {
_ => None _ => None
}; };
let notifier_data = NotifierData { let notifier_data = {
script_chan: self.chan.clone(), let MainThreadScriptChan(ref sender) = self.chan;
pipeline: page.pipeline(), NotifierData {
script_chan: sender.clone(),
pipeline: page.pipeline(),
}
}; };
let loader = DocumentLoader::new_with_task(self.resource_task.clone(), let loader = DocumentLoader::new_with_task(self.resource_task.clone(),
Some(notifier_data), Some(notifier_data),
@ -1822,7 +1869,7 @@ impl ScriptTask {
// https://html.spec.whatwg.org/multipage/#the-end step 4 // https://html.spec.whatwg.org/multipage/#the-end step 4
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone()); let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded);
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap(); self.chan.send(CommonScriptMsg::RunnableMsg(handler)).unwrap();
window.r().set_fragment_name(final_url.fragment.clone()); window.r().set_fragment_name(final_url.fragment.clone());

View file

@ -7,10 +7,9 @@ use dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::global::global_object_for_js_object; use dom::bindings::global::global_object_for_js_object;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::window::ScriptHelpers; use dom::window::ScriptHelpers;
use script_task::{ScriptChan, ScriptMsg, TimerSource}; use script_task::{ScriptChan, TimerSource, CommonScriptMsg};
use horribly_inefficient_timers; use horribly_inefficient_timers;
use util::mem::HeapSizeOf; use util::mem::HeapSizeOf;
@ -149,7 +148,7 @@ impl TimerManager {
let handle = self.next_timer_handle.get(); let handle = self.next_timer_handle.get();
self.next_timer_handle.set(handle + 1); self.next_timer_handle.set(handle + 1);
// Spawn a new timer task; it will dispatch the `ScriptMsg::FireTimer` // Spawn a new timer task; it will dispatch the `CommonScriptMsg::FireTimer`
// to the relevant script handler that will deal with it. // to the relevant script handler that will deal with it.
let (control_chan, control_port) = channel(); let (control_chan, control_port) = channel();
let spawn_name = match source { let spawn_name = match source {
@ -177,7 +176,7 @@ impl TimerManager {
if id == timeout_handle.id() { if id == timeout_handle.id() {
timeout_port.recv().unwrap(); timeout_port.recv().unwrap();
if script_chan.send(ScriptMsg::FireTimer(source, TimerId(handle))).is_err() { if script_chan.send(CommonScriptMsg::FireTimer(source, TimerId(handle))).is_err() {
break; break;
} }