From 3f2cbf002520289f706e7a7c6448a39ca7fa4bef Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Wed, 6 Jan 2016 11:44:54 -0500 Subject: [PATCH] Add task_source directory Use DOMManipulationTaskSource whenever possible --- components/script/dom/bindings/global.rs | 19 ++- components/script/dom/document.rs | 19 +-- components/script/dom/htmldetailselement.rs | 30 ++--- components/script/dom/htmlformelement.rs | 17 ++- components/script/dom/htmlscriptelement.rs | 43 ++----- components/script/dom/storage.rs | 11 +- components/script/dom/webidls/Worker.webidl | 4 +- components/script/dom/window.rs | 16 ++- components/script/dom/worker.rs | 10 +- components/script/lib.rs | 1 + components/script/script_thread.rs | 113 ++---------------- .../script/task_source/dom_manipulation.rs | 63 ++++++++++ components/script/task_source/file_reading.rs | 21 ++++ .../script/task_source/history_traversal.rs | 21 ++++ components/script/task_source/mod.rs | 16 +++ components/script/task_source/networking.rs | 21 ++++ .../script/task_source/user_interaction.rs | 21 ++++ 17 files changed, 261 insertions(+), 185 deletions(-) create mode 100644 components/script/task_source/dom_manipulation.rs create mode 100644 components/script/task_source/file_reading.rs create mode 100644 components/script/task_source/history_traversal.rs create mode 100644 components/script/task_source/mod.rs create mode 100644 components/script/task_source/networking.rs create mode 100644 components/script/task_source/user_interaction.rs diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index c7ba5aaaf6cc..dab74fd5850b 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -21,8 +21,10 @@ use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use msg::constellation_msg::{ConstellationChan, PipelineId}; use net_traits::ResourceThread; use profile_traits::mem; -use script_thread::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThread}; +use script_thread::{CommonScriptMsg, MainThreadScriptChan, ScriptChan, ScriptPort, ScriptThread}; use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest}; +use task_source::TaskSource; +use task_source::dom_manipulation::DOMManipulationTask; use timers::{OneshotTimerCallback, OneshotTimerHandle}; use url::Url; @@ -142,13 +144,24 @@ impl<'a> GlobalRef<'a> { /// `ScriptChan` used to send messages to the event loop of this global's /// thread. - pub fn dom_manipulation_task_source(&self) -> Box { + pub fn script_chan(&self) -> Box { match *self { - GlobalRef::Window(ref window) => window.dom_manipulation_task_source(), + GlobalRef::Window(ref window) => { + MainThreadScriptChan(window.main_thread_script_chan().clone()).clone() + } GlobalRef::Worker(ref worker) => worker.script_chan(), } } + /// `TaskSource` used to queue DOM manipulation messages to the event loop of this global's + /// thread. + pub fn dom_manipulation_task_source(&self) -> Box + Send> { + match *self { + GlobalRef::Window(ref window) => window.dom_manipulation_task_source(), + GlobalRef::Worker(_) => unimplemented!(), + } + } + /// `ScriptChan` used to send messages to the event loop of this global's /// thread. pub fn user_interaction_task_source(&self) -> Box { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 7d0a3be8b140..e0f4c0c55923 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -89,7 +89,7 @@ use net_traits::CookieSource::NonHTTP; use net_traits::response::HttpsState; use net_traits::{AsyncResponseTarget, PendingAsyncLoad}; use num::ToPrimitive; -use script_thread::{MainThreadScriptMsg, Runnable}; +use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan}; use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg}; use script_traits::{TouchEventType, TouchId}; @@ -108,6 +108,7 @@ use string_cache::{Atom, QualName}; use style::context::ReflowGoal; use style::restyle_hints::ElementSnapshot; use style::servo::Stylesheet; +use task_source::dom_manipulation::DOMManipulationTask; use time; use url::percent_encoding::percent_decode; use url::{Host, Url}; @@ -1406,11 +1407,11 @@ impl Document { update_with_current_time(&self.dom_content_loaded_event_start); - let doctarget = self.upcast::(); - let _ = doctarget.fire_event("DOMContentLoaded", - EventBubbles::Bubbles, - EventCancelable::NotCancelable); - + let chan = MainThreadScriptChan(self.window().main_thread_script_chan().clone()).clone(); + let doctarget = Trusted::new(self.upcast::(), chan); + let task_source = self.window().dom_manipulation_task_source(); + let _ = task_source.queue(DOMManipulationTask::FireEvent( + atom!("DOMContentLoaded"), doctarget, EventBubbles::Bubbles, EventCancelable::NotCancelable)); self.window().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::DOMContentLoaded); @@ -2590,13 +2591,13 @@ fn update_with_current_time(marker: &Cell) { } pub struct DocumentProgressHandler { - addr: Trusted, + addr: Trusted } impl DocumentProgressHandler { - pub fn new(addr: Trusted) -> DocumentProgressHandler { + pub fn new(addr: Trusted) -> DocumentProgressHandler { DocumentProgressHandler { - addr: addr, + addr: addr } } diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 8b8735ca0d66..01286dd22654 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -14,10 +14,10 @@ use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; -use script_thread::ScriptThreadEventCategory::DomEvent; -use script_thread::{CommonScriptMsg, Runnable}; +use script_thread::{MainThreadScriptChan, Runnable, ScriptChan}; use std::cell::Cell; use string_cache::Atom; +use task_source::dom_manipulation::DOMManipulationTask; use util::str::DOMString; #[dom_struct] @@ -69,7 +69,17 @@ impl VirtualMethods for HTMLDetailsElement { if attr.local_name() == &atom!("open") { let counter = self.toggle_counter.get() + 1; self.toggle_counter.set(counter); - ToggleEventRunnable::send(&self, counter); + + let window = window_from_node(self); + let window = window.r(); + let task_source = window.dom_manipulation_task_source(); + let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(); + let details = Trusted::new(self, chan.clone()); + let runnable = box ToggleEventRunnable { + element: details, + toggle_number: counter + }; + let _ = task_source.queue(DOMManipulationTask::FireToggleEvent(runnable)); } } } @@ -79,20 +89,6 @@ pub struct ToggleEventRunnable { toggle_number: u32 } -impl ToggleEventRunnable { - pub fn send(node: &HTMLDetailsElement, toggle_number: u32) { - let window = window_from_node(node); - let window = window.r(); - let chan = window.dom_manipulation_task_source(); - let handler = Trusted::new(node, chan.clone()); - let dispatcher = ToggleEventRunnable { - element: handler, - toggle_number: toggle_number, - }; - let _ = chan.send(CommonScriptMsg::RunnableMsg(DomEvent, box dispatcher)); - } -} - impl Runnable for ToggleEventRunnable { fn handler(self: Box) { let target = self.element.root(); diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 167e16988450..1d84c78f78b7 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -37,12 +37,12 @@ use hyper::header::ContentType; use hyper::method::Method; use hyper::mime; use msg::constellation_msg::{LoadData, PipelineId}; -use script_thread::ScriptThreadEventCategory::FormPlannedNavigation; -use script_thread::{CommonScriptMsg, MainThreadScriptMsg, Runnable, ScriptChan}; +use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan}; use std::borrow::ToOwned; use std::cell::Cell; use std::sync::mpsc::Sender; use string_cache::Atom; +use task_source::dom_manipulation::DOMManipulationTask; use url::form_urlencoded::serialize; use util::str::DOMString; @@ -76,6 +76,10 @@ impl HTMLFormElement { let element = HTMLFormElement::new_inherited(localName, prefix, document); Node::reflect_node(box element, document, HTMLFormElementBinding::Wrap) } + + pub fn generation_id(&self) -> GenerationId { + self.generation_id.get() + } } impl HTMLFormElementMethods for HTMLFormElement { @@ -322,17 +326,20 @@ impl HTMLFormElement { // generation ID is the same as its own generation ID. let GenerationId(prev_id) = self.generation_id.get(); self.generation_id.set(GenerationId(prev_id + 1)); + // Step 2 + let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(); let nav = box PlannedNavigation { load_data: load_data, pipeline_id: window.pipeline(), script_chan: window.main_thread_script_chan().clone(), generation_id: self.generation_id.get(), - form: Trusted::new(self, window.dom_manipulation_task_source()) + form: Trusted::new(self, chan) }; + // Step 3 - window.dom_manipulation_task_source().send( - CommonScriptMsg::RunnableMsg(FormPlannedNavigation, nav)).unwrap(); + window.dom_manipulation_task_source().queue( + DOMManipulationTask::PlannedNavigation(nav)).unwrap(); } /// Interactively validate the constraints of form elements diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index b0e0c9c041e7..bbd1884dc4f7 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -19,6 +19,7 @@ use dom::bindings::trace::JSTraceable; use dom::document::Document; use dom::element::{AttributeMutation, Element, ElementCreator}; use dom::event::{Event, EventBubbles, EventCancelable}; +use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::node::{ChildrenMutation, CloneChildrenFlag, Node}; use dom::node::{document_from_node, window_from_node}; @@ -34,13 +35,13 @@ use js::jsapi::RootedValue; use js::jsval::UndefinedValue; use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata}; use network_listener::{NetworkListener, PreInvoke}; -use script_thread::ScriptThreadEventCategory::ScriptEvent; -use script_thread::{CommonScriptMsg, Runnable, ScriptChan}; +use script_thread::{MainThreadScriptChan, ScriptChan}; use std::ascii::AsciiExt; use std::cell::Cell; use std::mem; use std::sync::{Arc, Mutex}; use string_cache::Atom; +use task_source::dom_manipulation::DOMManipulationTask; use url::Url; use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; @@ -442,26 +443,20 @@ impl HTMLScriptElement { if external { self.dispatch_load_event(); } else { - let chan = window.dom_manipulation_task_source(); - let handler = Trusted::new(self, chan.clone()); - let dispatcher = box EventDispatcher { - element: handler, - is_error: false, - }; - chan.send(CommonScriptMsg::RunnableMsg(ScriptEvent, dispatcher)).unwrap(); + let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(); + let script_element = Trusted::new(self.upcast::(), chan); + let task_source = window.dom_manipulation_task_source(); + task_source.queue(DOMManipulationTask::FireSimpleEvent(atom!("load"), script_element)).unwrap(); } } pub fn queue_error_event(&self) { let window = window_from_node(self); let window = window.r(); - let chan = window.dom_manipulation_task_source(); - let handler = Trusted::new(self, chan.clone()); - let dispatcher = box EventDispatcher { - element: handler, - is_error: true, - }; - chan.send(CommonScriptMsg::RunnableMsg(ScriptEvent, dispatcher)).unwrap(); + let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(); + let task_source = window.dom_manipulation_task_source(); + let script_element = Trusted::new(self.upcast::(), chan); + task_source.queue(DOMManipulationTask::FireSimpleEvent(atom!("error"), script_element)).unwrap(); } pub fn dispatch_before_script_execute_event(&self) -> bool { @@ -610,19 +605,3 @@ impl HTMLScriptElementMethods for HTMLScriptElement { self.upcast::().SetTextContent(Some(value)) } } - -struct EventDispatcher { - element: Trusted, - is_error: bool, -} - -impl Runnable for EventDispatcher { - fn handler(self: Box) { - let target = self.element.root(); - if self.is_error { - target.dispatch_error_event(); - } else { - target.dispatch_load_event(); - } - } -} diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index c5d79fe7bafa..b264580495a5 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -16,7 +16,8 @@ use dom::urlhelper::UrlHelper; use ipc_channel::ipc; use net_traits::storage_thread::{StorageThread, StorageThreadMsg, StorageType}; use page::IterablePage; -use script_thread::{MainThreadRunnable, MainThreadScriptMsg, ScriptThread}; +use script_thread::{MainThreadRunnable, MainThreadScriptChan, ScriptChan, ScriptThread}; +use task_source::dom_manipulation::DOMManipulationTask; use url::Url; use util::str::DOMString; @@ -153,10 +154,10 @@ impl Storage { new_value: Option) { let global_root = self.global(); let global_ref = global_root.r(); - let main_script_chan = global_ref.as_window().main_thread_script_chan(); - let script_chan = global_ref.dom_manipulation_task_source(); - let trusted_storage = Trusted::new(self, script_chan); - main_script_chan.send(MainThreadScriptMsg::MainThreadRunnableMsg( + let task_source = global_ref.as_window().dom_manipulation_task_source(); + let chan = MainThreadScriptChan(global_ref.as_window().main_thread_script_chan().clone()).clone(); + let trusted_storage = Trusted::new(self, chan); + task_source.queue(DOMManipulationTask::SendStorageNotification( box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap(); } } diff --git a/components/script/dom/webidls/Worker.webidl b/components/script/dom/webidls/Worker.webidl index c80ff3898cce..62cd5c89f924 100644 --- a/components/script/dom/webidls/Worker.webidl +++ b/components/script/dom/webidls/Worker.webidl @@ -14,8 +14,8 @@ interface AbstractWorker { interface Worker : EventTarget { //void terminate(); - [Throws] - void postMessage(any message/*, optional sequence transfer*/); +[Throws] +void postMessage(any message/*, optional sequence transfer*/); attribute EventHandler onmessage; }; Worker implements AbstractWorker; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index e81efa4a77c0..eeb62d833c6d 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -53,9 +53,8 @@ use page::Page; use profile_traits::mem; use reporter::CSSErrorReporter; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; -use script_thread::{DOMManipulationTaskSource, UserInteractionTaskSource, NetworkingTaskSource}; -use script_thread::{HistoryTraversalTaskSource, FileReadingTaskSource, SendableMainThreadScriptChan}; -use script_thread::{ScriptChan, ScriptPort, MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper}; +use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper}; +use script_thread::{SendableMainThreadScriptChan, ScriptChan, ScriptPort}; use script_traits::{ConstellationControlMsg, UntrustedNodeAddress}; use script_traits::{DocumentState, MsDuration, ScriptToCompositorMsg, TimerEvent, TimerEventId}; use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource}; @@ -75,6 +74,12 @@ use string_cache::Atom; use style::context::ReflowGoal; use style::error_reporting::ParseErrorReporter; use style::selector_impl::PseudoElement; +use task_source::TaskSource; +use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask}; +use task_source::file_reading::FileReadingTaskSource; +use task_source::history_traversal::HistoryTraversalTaskSource; +use task_source::networking::NetworkingTaskSource; +use task_source::user_interaction::UserInteractionTaskSource; use time; use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback}; use url::Url; @@ -258,7 +263,7 @@ impl Window { self.js_runtime.borrow().as_ref().unwrap().cx() } - pub fn dom_manipulation_task_source(&self) -> Box { + pub fn dom_manipulation_task_source(&self) -> Box + Send> { self.dom_manipulation_task_source.clone() } @@ -279,8 +284,7 @@ impl Window { } pub fn main_thread_script_chan(&self) -> &Sender { - let MainThreadScriptChan(ref sender) = self.script_chan; - sender + &self.script_chan.0 } pub fn image_cache_chan(&self) -> ImageCacheChan { diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 815100ba32f4..dfa8d1363f3b 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -71,7 +71,7 @@ impl Worker { let (sender, receiver) = channel(); let worker = Worker::new(global, sender.clone()); - let worker_ref = Trusted::new(worker.r(), global.dom_manipulation_task_source()); + let worker_ref = Trusted::new(worker.r(), global.script_chan()); let worker_id = global.get_next_worker_id(); let (devtools_sender, devtools_receiver) = ipc::channel().unwrap(); @@ -102,7 +102,7 @@ impl Worker { }; DedicatedWorkerGlobalScope::run_worker_scope( init, worker_url, global.pipeline(), devtools_receiver, worker_ref, - global.dom_manipulation_task_source(), sender, receiver); + global.script_chan(), sender, receiver); Ok(worker) } @@ -138,15 +138,15 @@ impl Worker { } impl WorkerMethods for Worker { - // https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage + // https://html.spec.whatwg.org/multipage/#dom-worker-postmessage fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult { let data = try!(StructuredCloneData::write(cx, message)); - let address = Trusted::new(self, self.global().r().dom_manipulation_task_source()); + let address = Trusted::new(self, self.global().r().script_chan()); self.sender.send((address, WorkerScriptMsg::DOMMessage(data))).unwrap(); Ok(()) } - // https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage + // https://html.spec.whatwg.org/multipage/#handler-worker-onmessage event_handler!(message, GetOnmessage, SetOnmessage); // https://html.spec.whatwg.org/multipage/#handler-workerglobalscope-onerror diff --git a/components/script/lib.rs b/components/script/lib.rs index bee43944c69c..ed7b530d6f6b 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -91,6 +91,7 @@ pub mod parse; pub mod reporter; #[allow(unsafe_code)] pub mod script_thread; +mod task_source; pub mod textinput; mod timers; mod unpremultiplytable; diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index a735603431a5..9cfc26277867 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -99,6 +99,12 @@ use std::sync::atomic::{Ordering, AtomicBool}; use std::sync::mpsc::{Receiver, Select, Sender, channel}; use std::sync::{Arc, Mutex}; use style::context::ReflowGoal; +use task_source::TaskSource; +use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask}; +use task_source::file_reading::FileReadingTaskSource; +use task_source::history_traversal::HistoryTraversalTaskSource; +use task_source::networking::NetworkingTaskSource; +use task_source::user_interaction::UserInteractionTaskSource; use time::{Tm, now}; use url::Url; use util::opts; @@ -251,11 +257,11 @@ pub enum MainThreadScriptMsg { /// Notifies the script that a window associated with a particular pipeline /// should be closed (only dispatched to ScriptThread). ExitWindow(PipelineId), - /// Generic message for running threads in the ScriptThread - MainThreadRunnableMsg(Box), /// Begins a content-initiated load on the specified pipeline (only /// dispatched to ScriptThread). Navigate(PipelineId, LoadData), + /// Tasks that originate from the DOM manipulation task source + DOMManipulation(DOMManipulationTask), } /// A cloneable interface for communicating with an event loop. @@ -357,102 +363,6 @@ impl MainThreadScriptChan { } } -// FIXME: Use a task source specific message instead of MainThreadScriptMsg -#[derive(JSTraceable)] -pub struct DOMManipulationTaskSource(pub Sender); - -impl ScriptChan for DOMManipulationTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let DOMManipulationTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - let DOMManipulationTaskSource(ref chan) = *self; - box DOMManipulationTaskSource((*chan).clone()) - } -} - -// FIXME: Use a task source specific message instead of MainThreadScriptMsg -#[derive(JSTraceable)] -pub struct UserInteractionTaskSource(pub Sender); - -impl ScriptChan for UserInteractionTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let UserInteractionTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - let UserInteractionTaskSource(ref chan) = *self; - box UserInteractionTaskSource((*chan).clone()) - } -} - -// FIXME: Use a task source specific message instead of MainThreadScriptMsg -#[derive(JSTraceable)] -pub struct NetworkingTaskSource(pub Sender); - -impl ScriptChan for NetworkingTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let NetworkingTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - let NetworkingTaskSource(ref chan) = *self; - box NetworkingTaskSource((*chan).clone()) - } -} - -// FIXME: Use a task source specific message instead of MainThreadScriptMsg -#[derive(JSTraceable)] -pub struct HistoryTraversalTaskSource(pub Sender); - -impl ScriptChan for HistoryTraversalTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let HistoryTraversalTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - let HistoryTraversalTaskSource(ref chan) = *self; - box HistoryTraversalTaskSource((*chan).clone()) - } -} - -// FIXME: Use a task source specific message instead of MainThreadScriptMsg -#[derive(JSTraceable)] -pub struct FileReadingTaskSource(pub Sender); - -impl ScriptChan for FileReadingTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let FileReadingTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - let FileReadingTaskSource(ref chan) = *self; - box FileReadingTaskSource((*chan).clone()) - } -} - -// FIXME: Use a task source specific message instead of MainThreadScriptMsg -#[derive(JSTraceable)] -pub struct ProfilerThreadSource(pub Sender); - -impl ScriptChan for ProfilerThreadSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let ProfilerThreadSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - let ProfilerThreadSource(ref chan) = *self; - box ProfilerThreadSource((*chan).clone()) - } -} - pub struct StackRootTLS<'a>(PhantomData<&'a u32>); impl<'a> StackRootTLS<'a> { @@ -494,6 +404,7 @@ pub struct ScriptThread { /// A channel to hand out to script thread-based entities that need to be able to enqueue /// events in the event queue. chan: MainThreadScriptChan, + dom_manipulation_task_source: DOMManipulationTaskSource, user_interaction_task_source: UserInteractionTaskSource, @@ -1155,8 +1066,6 @@ impl ScriptThread { self.handle_navigate(id, None, load_data), MainThreadScriptMsg::ExitWindow(id) => self.handle_exit_window_msg(id), - MainThreadScriptMsg::MainThreadRunnableMsg(runnable) => - runnable.handler(self), MainThreadScriptMsg::DocumentLoadsComplete(id) => self.handle_loads_complete(id), MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => { @@ -1170,6 +1079,8 @@ impl ScriptThread { LiveDOMReferences::cleanup(addr), MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => self.collect_reports(reports_chan), + MainThreadScriptMsg::DOMManipulation(msg) => + msg.handle_msg(self), } } @@ -1366,7 +1277,7 @@ impl ScriptThread { // https://html.spec.whatwg.org/multipage/#the-end step 7 let addr: Trusted = Trusted::new(doc, self.chan.clone()); let handler = box DocumentProgressHandler::new(addr.clone()); - self.chan.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::DocumentEvent, handler)).unwrap(); + self.dom_manipulation_task_source.queue(DOMManipulationTask::DocumentProgress(handler)).unwrap(); let ConstellationChan(ref chan) = self.constellation_chan; chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap(); diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs new file mode 100644 index 000000000000..d60ce7de93d2 --- /dev/null +++ b/components/script/task_source/dom_manipulation.rs @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +use dom::bindings::refcounted::Trusted; +use dom::event::{EventBubbles, EventCancelable}; +use dom::eventtarget::EventTarget; +use script_thread::{MainThreadRunnable, MainThreadScriptMsg, Runnable, ScriptThread}; +use std::result::Result; +use std::sync::mpsc::Sender; +use string_cache::Atom; +use task_source::TaskSource; + +#[derive(JSTraceable)] +pub struct DOMManipulationTaskSource(pub Sender); + +impl TaskSource for DOMManipulationTaskSource { + fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> { + let DOMManipulationTaskSource(ref chan) = *self; + chan.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ()) + } + + fn clone(&self) -> Box + Send> { + let DOMManipulationTaskSource(ref chan) = *self; + box DOMManipulationTaskSource((*chan).clone()) + } +} + +pub enum DOMManipulationTask { + // https://html.spec.whatwg.org/multipage/#the-end step 7 + DocumentProgress(Box), + // https://dom.spec.whatwg.org/#concept-event-fire + FireEvent(Atom, Trusted, EventBubbles, EventCancelable), + // https://html.spec.whatwg.org/multipage/#fire-a-simple-event + FireSimpleEvent(Atom, Trusted), + // https://html.spec.whatwg.org/multipage/#details-notification-task-steps + FireToggleEvent(Box), + // https://html.spec.whatwg.org/multipage/#planned-navigation + PlannedNavigation(Box), + // https://html.spec.whatwg.org/multipage/#send-a-storage-notification + SendStorageNotification(Box) +} + +impl DOMManipulationTask { + pub fn handle_msg(self, script_thread: &ScriptThread) { + use self::DOMManipulationTask::*; + + match self { + DocumentProgress(runnable) => runnable.handler(), + FireEvent(name, element, bubbles, cancelable) => { + let target = element.root(); + target.fire_event(&*name, bubbles, cancelable); + } + FireSimpleEvent(name, element) => { + let target = element.root(); + target.fire_simple_event(&*name); + } + FireToggleEvent(runnable) => runnable.handler(), + PlannedNavigation(runnable) => runnable.handler(), + SendStorageNotification(runnable) => runnable.handler(script_thread) + } + } +} diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs new file mode 100644 index 000000000000..e4afad34b4ba --- /dev/null +++ b/components/script/task_source/file_reading.rs @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan}; +use std::sync::mpsc::Sender; + +#[derive(JSTraceable)] +pub struct FileReadingTaskSource(pub Sender); + +impl ScriptChan for FileReadingTaskSource { + fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { + let FileReadingTaskSource(ref chan) = *self; + chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + } + + fn clone(&self) -> Box { + let FileReadingTaskSource(ref chan) = *self; + box FileReadingTaskSource((*chan).clone()) + } +} diff --git a/components/script/task_source/history_traversal.rs b/components/script/task_source/history_traversal.rs new file mode 100644 index 000000000000..0916c1213456 --- /dev/null +++ b/components/script/task_source/history_traversal.rs @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan}; +use std::sync::mpsc::Sender; + +#[derive(JSTraceable)] +pub struct HistoryTraversalTaskSource(pub Sender); + +impl ScriptChan for HistoryTraversalTaskSource { + fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { + let HistoryTraversalTaskSource(ref chan) = *self; + chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + } + + fn clone(&self) -> Box { + let HistoryTraversalTaskSource(ref chan) = *self; + box HistoryTraversalTaskSource((*chan).clone()) + } +} diff --git a/components/script/task_source/mod.rs b/components/script/task_source/mod.rs new file mode 100644 index 000000000000..74dd7347e9e9 --- /dev/null +++ b/components/script/task_source/mod.rs @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +pub mod dom_manipulation; +pub mod file_reading; +pub mod history_traversal; +pub mod networking; +pub mod user_interaction; + +use std::result::Result; + +pub trait TaskSource { + fn queue(&self, msg: T) -> Result<(), ()>; + fn clone(&self) -> Box + Send>; +} diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs new file mode 100644 index 000000000000..8ebeecdb965e --- /dev/null +++ b/components/script/task_source/networking.rs @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan}; +use std::sync::mpsc::Sender; + +#[derive(JSTraceable)] +pub struct NetworkingTaskSource(pub Sender); + +impl ScriptChan for NetworkingTaskSource { + fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { + let NetworkingTaskSource(ref chan) = *self; + chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + } + + fn clone(&self) -> Box { + let NetworkingTaskSource(ref chan) = *self; + box NetworkingTaskSource((*chan).clone()) + } +} diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs new file mode 100644 index 000000000000..7912eac720d6 --- /dev/null +++ b/components/script/task_source/user_interaction.rs @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan}; +use std::sync::mpsc::Sender; + +#[derive(JSTraceable)] +pub struct UserInteractionTaskSource(pub Sender); + +impl ScriptChan for UserInteractionTaskSource { + fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { + let UserInteractionTaskSource(ref chan) = *self; + chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + } + + fn clone(&self) -> Box { + let UserInteractionTaskSource(ref chan) = *self; + box UserInteractionTaskSource((*chan).clone()) + } +}