diff options
author | Gregory Terzian <gterzian@users.noreply.github.com> | 2018-07-05 12:33:09 +0800 |
---|---|---|
committer | Gregory Terzian <gterzian@users.noreply.github.com> | 2018-07-10 13:42:28 +0800 |
commit | 671627e97e20ae4baf728ae6dda61ef6f857c193 (patch) | |
tree | c86d1e568b551613bde1b61bf3db3dee42735a79 /components | |
parent | ce430566cdbccaa86ec498aa48392eab3ec69256 (diff) | |
download | servo-671627e97e20ae4baf728ae6dda61ef6f857c193.tar.gz servo-671627e97e20ae4baf728ae6dda61ef6f857c193.zip |
introduce "per task source" ignoring of tasks
Diffstat (limited to 'components')
20 files changed, 106 insertions, 34 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 7f30c842d34..7b2077c5fac 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -44,6 +44,7 @@ dom_struct = {path = "../dom_struct"} domobject_derive = {path = "../domobject_derive"} embedder_traits = {path = "../embedder_traits"} encoding_rs = "0.7" +enum-iterator = "0.2.0" euclid = "0.17" fnv = "1.0" gleam = "0.5" diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 3f2b829a457..f0b5726e6a3 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -34,7 +34,7 @@ use std::cell::Cell; use std::mem; use std::str::{Chars, FromStr}; use std::sync::{Arc, Mutex}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; use timers::OneshotTimerCallback; use utf8; @@ -482,10 +482,12 @@ impl EventSource { data: String::new(), last_event_id: String::new(), }; + // TODO: use the "remote event task source", and canceller. + // https://html.spec.whatwg.org/multipage/#remote-event-task-source let listener = NetworkListener { context: Arc::new(Mutex::new(context)), task_source: global.networking_task_source(), - canceller: Some(global.task_canceller()) + canceller: Some(global.task_canceller(TaskSourceName::Networking)) }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index 037e54907c0..6b88c645bbd 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -35,7 +35,7 @@ use std::ptr; use std::sync::Arc; use std::thread; use task::TaskCanceller; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; use task_source::file_reading::{FileReadingTask, FileReadingTaskSource}; #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] @@ -452,7 +452,7 @@ impl FileReader { let gen_id = self.generation_id.get(); let global = self.global(); - let canceller = global.task_canceller(); + let canceller = global.task_canceller(TaskSourceName::FileReading); let task_source = global.file_reading_task_source(); thread::Builder::new() diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index cec59c92510..759216df27a 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -52,6 +52,7 @@ use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use task::TaskCanceller; +use task_source::TaskSourceName; use task_source::file_reading::FileReadingTaskSource; use task_source::networking::NetworkingTaskSource; use task_source::performance_timeline::PerformanceTimelineTaskSource; @@ -508,11 +509,14 @@ impl GlobalScope { /// Returns the task canceller of this global to ensure that everything is /// properly cancelled when the global scope is destroyed. - pub fn task_canceller(&self) -> TaskCanceller { + pub fn task_canceller(&self, name: TaskSourceName) -> TaskCanceller { if let Some(window) = self.downcast::<Window>() { - return window.task_canceller(); + return window.task_canceller(name); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { + // Note: the "name" is not passed to the worker, + // because 'closing' it only requires one task canceller for all task sources. + // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-closing return worker.task_canceller(); } unreachable!(); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index b37199ca0db..668c66d7734 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -58,7 +58,7 @@ use std::i32; use std::sync::{Arc, Mutex}; use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_double, parse_unsigned_integer}; use style::str::is_ascii_digit; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; enum ParseState { InDescriptor, @@ -185,7 +185,7 @@ impl HTMLImageElement { let window = window_from_node(elem); let task_source = window.networking_task_source(); - let task_canceller = window.task_canceller(); + let task_canceller = window.task_canceller(TaskSourceName::Networking); let generation = elem.generation.get(); ROUTER.add_route(responder_receiver.to_opaque(), Box::new(move |message| { debug!("Got image {:?}", message); @@ -253,7 +253,7 @@ impl HTMLImageElement { let listener = NetworkListener { context: context, task_source: window.networking_task_source(), - canceller: Some(window.task_canceller()), + canceller: Some(window.task_canceller(TaskSourceName::Networking)), }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 1122e267e7e..466bcae3280 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -46,7 +46,7 @@ use std::collections::VecDeque; use std::mem; use std::rc::Rc; use std::sync::{Arc, Mutex}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; use time::{self, Timespec, Duration}; #[dom_struct] @@ -608,7 +608,7 @@ impl HTMLMediaElement { let listener = NetworkListener { context: context, task_source: window.networking_task_source(), - canceller: Some(window.task_canceller()) + canceller: Some(window.task_canceller(TaskSourceName::Networking)) }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index ee42746c71f..8f07f1e80c8 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -41,6 +41,7 @@ use std::path::PathBuf; use std::process::{Command, Stdio}; use std::sync::{Arc, Mutex}; use style::str::{HTML_SPACE_CHARACTERS, StaticStringVec}; +use task_source::TaskSourceName; use uuid::Uuid; #[dom_struct] @@ -273,7 +274,7 @@ fn fetch_a_classic_script(script: &HTMLScriptElement, let listener = NetworkListener { context: context, task_source: doc.window().networking_task_source(), - canceller: Some(doc.window().task_canceller()) + canceller: Some(doc.window().task_canceller(TaskSourceName::Networking)) }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index 031741db0df..14ff325f56d 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -39,7 +39,7 @@ use std::cell::Cell; use std::ptr; use std::thread; use task::{TaskOnce, TaskCanceller}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; use task_source::networking::NetworkingTaskSource; #[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)] @@ -199,8 +199,11 @@ impl WebSocket { }; let _ = global.core_resource_thread().send(CoreResourceMsg::Fetch(request, channels)); + // TODO: use a dedicated task source, + // https://html.spec.whatwg.org/multipage/#websocket-task-source + // When making the switch, also update the task_canceller call. let task_source = global.networking_task_source(); - let canceller = global.task_canceller(); + let canceller = global.task_canceller(TaskSourceName::Networking); thread::spawn(move || { while let Ok(event) = dom_event_receiver.recv() { match event { @@ -391,8 +394,13 @@ impl WebSocketMethods for WebSocket { self.ready_state.set(WebSocketRequestState::Closing); let address = Trusted::new(self); + // TODO: use a dedicated task source, + // https://html.spec.whatwg.org/multipage/#websocket-task-source + // When making the switch, also update the task_canceller call. let task_source = self.global().networking_task_source(); - fail_the_websocket_connection(address, &task_source, &self.global().task_canceller()); + fail_the_websocket_connection(address, + &task_source, + &self.global().task_canceller(TaskSourceName::Networking)); } WebSocketRequestState::Open => { self.ready_state.set(WebSocketRequestState::Closing); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index b536f28345f..d0d6e499639 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -109,6 +109,7 @@ use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::CssRuleType; use style_traits::{CSSPixel, DevicePixel, ParsingMode}; use task::TaskCanceller; +use task_source::TaskSourceName; use task_source::dom_manipulation::DOMManipulationTaskSource; use task_source::file_reading::FileReadingTaskSource; use task_source::history_traversal::HistoryTraversalTaskSource; @@ -246,9 +247,9 @@ pub struct Window { current_viewport: Cell<Rect<Au>>, - /// A flag to prevent async events from attempting to interact with this window. + /// A map of flags to prevent events from a given task source from attempting to interact with this window. #[ignore_malloc_size_of = "defined in std"] - ignore_further_async_events: DomRefCell<Arc<AtomicBool>>, + ignore_further_async_events: DomRefCell<HashMap<TaskSourceName, Arc<AtomicBool>>>, error_reporter: CSSErrorReporter, @@ -308,7 +309,15 @@ impl Window { *self.js_runtime.borrow_for_script_deallocation() = None; self.window_proxy.set(None); self.current_state.set(WindowState::Zombie); - self.ignore_further_async_events.borrow().store(true, Ordering::Relaxed); + self.ignore_all_events(); + } + } + + fn ignore_all_events(&self) { + let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); + for task_source_name in TaskSourceName::all() { + let flag = ignore_flags.entry(task_source_name).or_insert(Default::default()); + flag.store(true, Ordering::Relaxed); } } @@ -1065,9 +1074,11 @@ impl Window { self.paint_worklet.or_init(|| self.new_paint_worklet()) } - pub fn task_canceller(&self) -> TaskCanceller { + pub fn task_canceller(&self, name: TaskSourceName) -> TaskCanceller { + let mut flags = self.ignore_further_async_events.borrow_mut(); + let cancel_flag = flags.entry(name).or_insert(Default::default()); TaskCanceller { - cancelled: Some(self.ignore_further_async_events.borrow().clone()), + cancelled: Some(cancel_flag.clone()), } } @@ -1084,8 +1095,12 @@ impl Window { /// This sets the current `ignore_further_async_events` sentinel value to /// `true` and replaces it with a brand new one for future tasks. pub fn cancel_all_tasks(&self) { - let cancelled = mem::replace(&mut *self.ignore_further_async_events.borrow_mut(), Default::default()); - cancelled.store(true, Ordering::Relaxed); + let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); + for task_source_name in TaskSourceName::all() { + let mut flag = ignore_flags.entry(task_source_name).or_insert(Default::default()); + let cancelled = mem::replace(&mut *flag, Default::default()); + cancelled.store(true, Ordering::Relaxed); + } } pub fn clear_js_runtime(&self) { @@ -1117,7 +1132,7 @@ impl Window { self.current_state.set(WindowState::Zombie); *self.js_runtime.borrow_mut() = None; self.window_proxy.set(None); - self.ignore_further_async_events.borrow().store(true, Ordering::SeqCst); + self.ignore_all_events(); } /// <https://drafts.csswg.org/cssom-view/#dom-window-scroll> @@ -1998,9 +2013,10 @@ impl Window { }); // FIXME(nox): Why are errors silenced here? // TODO(#12718): Use the "posted message task source". + // TODO: When switching to the right task source, update the task_canceller call too. let _ = self.script_chan.send(CommonScriptMsg::Task( ScriptThreadEventCategory::DomEvent, - Box::new(self.task_canceller().wrap_task(task)), + Box::new(self.task_canceller(TaskSourceName::DOMManipulation).wrap_task(task)), self.pipeline_id() )); } diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 49a72bbf46d..3dee1e18fe6 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -70,6 +70,7 @@ use std::ptr::NonNull; use std::slice; use std::str; use std::sync::{Arc, Mutex}; +use task_source::TaskSourceName; use task_source::networking::NetworkingTaskSource; use time; use timers::{OneshotTimerCallback, OneshotTimerHandle}; @@ -268,7 +269,7 @@ impl XMLHttpRequest { let listener = NetworkListener { context: context, task_source: task_source, - canceller: Some(global.task_canceller()) + canceller: Some(global.task_canceller(TaskSourceName::Networking)) }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/fetch.rs b/components/script/fetch.rs index d7a688ced94..7f866ca8633 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -31,6 +31,7 @@ use servo_url::ServoUrl; use std::mem; use std::rc::Rc; use std::sync::{Arc, Mutex}; +use task_source::TaskSourceName; struct FetchContext { fetch_promise: Option<TrustedPromise>, @@ -154,7 +155,7 @@ pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: RootedTraceableBox< let listener = NetworkListener { context: fetch_context, task_source: global.networking_task_source(), - canceller: Some(global.task_canceller()) + canceller: Some(global.task_canceller(TaskSourceName::Networking)) }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { diff --git a/components/script/layout_image.rs b/components/script/layout_image.rs index 6cbdd292fe1..553972d24b1 100644 --- a/components/script/layout_image.rs +++ b/components/script/layout_image.rs @@ -17,6 +17,7 @@ use net_traits::request::{Destination, RequestInit as FetchRequestInit}; use network_listener::{NetworkListener, PreInvoke}; use servo_url::ServoUrl; use std::sync::{Arc, Mutex}; +use task_source::TaskSourceName; struct LayoutImageContext { id: PendingImageId, @@ -62,7 +63,7 @@ pub fn fetch_image_for_layout(url: ServoUrl, let listener = NetworkListener { context: context, task_source: window.networking_task_source(), - canceller: Some(window.task_canceller()), + canceller: Some(window.task_canceller(TaskSourceName::Networking)), }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/lib.rs b/components/script/lib.rs index cf020ab9ac6..837b744424c 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -37,6 +37,7 @@ extern crate dom_struct; extern crate domobject_derive; extern crate embedder_traits; extern crate encoding_rs; +#[macro_use] extern crate enum_iterator; extern crate euclid; extern crate fnv; extern crate gleam; diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 0c5e792ad6a..156d2577656 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -35,6 +35,7 @@ use style::stylesheets::{CssRules, ImportRule, Namespaces, Stylesheet, Styleshee use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::stylesheets::import_rule::ImportSheet; use style::values::CssUrl; +use task_source::TaskSourceName; pub trait StylesheetOwner { /// Returns whether this element was inserted by the parser (i.e., it should @@ -228,7 +229,7 @@ impl<'a> StylesheetLoader<'a> { let listener = NetworkListener { context: context, task_source: document.window().networking_task_source(), - canceller: Some(document.window().task_canceller()) + canceller: Some(document.window().task_canceller(TaskSourceName::Networking)) }; ROUTER.add_route(action_receiver.to_opaque(), Box::new(move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index 5b5e55570b4..03b2d85a945 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -15,7 +15,7 @@ use std::fmt; use std::result::Result; use std::sync::mpsc::Sender; use task::{TaskCanceller, TaskOnce}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; #[derive(Clone, JSTraceable)] pub struct DOMManipulationTaskSource(pub Sender<MainThreadScriptMsg>, pub PipelineId); @@ -27,6 +27,8 @@ impl fmt::Debug for DOMManipulationTaskSource { } impl TaskSource for DOMManipulationTaskSource { + const NAME: TaskSourceName = TaskSourceName::DOMManipulation; + fn queue_with_canceller<T>( &self, task: T, diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs index e94f957234c..8fd3a143eff 100644 --- a/components/script/task_source/file_reading.rs +++ b/components/script/task_source/file_reading.rs @@ -8,7 +8,7 @@ use msg::constellation_msg::PipelineId; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory, ScriptChan}; use std::sync::Arc; use task::{TaskCanceller, TaskOnce}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; #[derive(JSTraceable)] pub struct FileReadingTaskSource(pub Box<ScriptChan + Send + 'static>, pub PipelineId); @@ -20,6 +20,8 @@ impl Clone for FileReadingTaskSource { } impl TaskSource for FileReadingTaskSource { + const NAME: TaskSourceName = TaskSourceName::FileReading; + fn queue_with_canceller<T>( &self, task: T, diff --git a/components/script/task_source/mod.rs b/components/script/task_source/mod.rs index 4818ba2c80c..cf605976b46 100644 --- a/components/script/task_source/mod.rs +++ b/components/script/task_source/mod.rs @@ -2,6 +2,7 @@ * 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; @@ -10,10 +11,33 @@ pub mod performance_timeline; pub mod user_interaction; use dom::globalscope::GlobalScope; +use enum_iterator::IntoEnumIterator; use std::result::Result; use task::{TaskCanceller, TaskOnce}; +// The names of all task sources, used to differentiate TaskCancellers. +// Note: When adding a task source, update this enum. +// Note: The HistoryTraversalTaskSource is not part of this, +// because it doesn't implement TaskSource. +#[derive(Eq, Hash, IntoEnumIterator, JSTraceable, PartialEq)] +pub enum TaskSourceName { + DOMManipulation, + FileReading, + HistoryTraversal, + Networking, + PerformanceTimeline, + UserInteraction +} + +impl TaskSourceName { + pub fn all() -> Vec<TaskSourceName> { + TaskSourceName::into_enum_iter().collect() + } +} + pub trait TaskSource { + const NAME: TaskSourceName; + fn queue_with_canceller<T>( &self, task: T, @@ -26,6 +50,7 @@ pub trait TaskSource { where T: TaskOnce + 'static, { - self.queue_with_canceller(task, &global.task_canceller()) + let canceller = global.task_canceller(Self::NAME); + self.queue_with_canceller(task, &canceller) } } diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs index ed192d08003..9058f9653e4 100644 --- a/components/script/task_source/networking.rs +++ b/components/script/task_source/networking.rs @@ -5,7 +5,7 @@ use msg::constellation_msg::PipelineId; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use task::{TaskCanceller, TaskOnce}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; #[derive(JSTraceable)] pub struct NetworkingTaskSource(pub Box<ScriptChan + Send + 'static>, pub PipelineId); @@ -17,6 +17,8 @@ impl Clone for NetworkingTaskSource { } impl TaskSource for NetworkingTaskSource { + const NAME: TaskSourceName = TaskSourceName::Networking; + fn queue_with_canceller<T>( &self, task: T, diff --git a/components/script/task_source/performance_timeline.rs b/components/script/task_source/performance_timeline.rs index 9f72305b00e..05591bbe71b 100644 --- a/components/script/task_source/performance_timeline.rs +++ b/components/script/task_source/performance_timeline.rs @@ -13,7 +13,7 @@ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use std::fmt; use std::result::Result; use task::{TaskCanceller, TaskOnce}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; #[derive(JSTraceable)] pub struct PerformanceTimelineTaskSource(pub Box<ScriptChan + Send + 'static>, pub PipelineId); @@ -31,6 +31,8 @@ impl fmt::Debug for PerformanceTimelineTaskSource { } impl TaskSource for PerformanceTimelineTaskSource { + const NAME: TaskSourceName = TaskSourceName::PerformanceTimeline; + fn queue_with_canceller<T>( &self, task: T, diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 12f822afedd..2ace44f1093 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -15,7 +15,7 @@ use std::fmt; use std::result::Result; use std::sync::mpsc::Sender; use task::{TaskCanceller, TaskOnce}; -use task_source::TaskSource; +use task_source::{TaskSource, TaskSourceName}; #[derive(Clone, JSTraceable)] pub struct UserInteractionTaskSource(pub Sender<MainThreadScriptMsg>, pub PipelineId); @@ -27,6 +27,8 @@ impl fmt::Debug for UserInteractionTaskSource { } impl TaskSource for UserInteractionTaskSource { + const NAME: TaskSourceName = TaskSourceName::UserInteraction; + fn queue_with_canceller<T>( &self, task: T, |