diff options
author | Agustin Chiappe Berrini <jnieve@gmail.com> | 2018-09-24 19:31:59 -0400 |
---|---|---|
committer | Agustin Chiappe Berrini <jnieve@gmail.com> | 2018-11-14 06:36:44 -0500 |
commit | 75eb94afcaae2f868ecccba5b5dcea4066998d7a (patch) | |
tree | c70e246d752eaee753ca4b59b27e27218a0cdf5e /components/script/dom | |
parent | 14bc8ab7542287a18ecdede1ca7ee2af077eb8a9 (diff) | |
download | servo-75eb94afcaae2f868ecccba5b5dcea4066998d7a.tar.gz servo-75eb94afcaae2f868ecccba5b5dcea4066998d7a.zip |
Unify the task source and task canceller API
I moved away from the `Window` struct all the logic to handle task
sources, into a new struct called `TaskManager`. In a happy world, I'd
be able to just have there two functions, of the types:
```rust
fn task_source<T: TaskSource>(&self, name: TaskSourceName) -> Box<T>
fn task_source_with_canceller<T: TaskSource>(&self, name: TaskSourceName)
-> (Box<T>, TaskSourceCanceller)
```
And not so much duplicated code. However, because TaskSource can't be a
trait object (because it has generic type parameters), that's not
possible. Instead, I decided to reduce duplicated logic through macros.
For reasons[1], I have to pass both the name of the function with
canceller and the name of the function without, as I'm not able to
concatenate them in the macro itself. I could probably use
`concat_idents` to create both types already defined and reduce the
amount of arguments by one, but that macro is nightly only. At the same
time, not being able to declare macros inside `impl` forces me to pass
`self` as an argument.
All this makes this solution more verbose than it would be ideally. It
does reduce duplication, but it doesn't reduce the size of the file.
[1](https://github.com/rust-lang/rust/issues/29599)
Diffstat (limited to 'components/script/dom')
20 files changed, 166 insertions, 216 deletions
diff --git a/components/script/dom/analysernode.rs b/components/script/dom/analysernode.rs index cf04bd44fca..06ff08d9af2 100644 --- a/components/script/dom/analysernode.rs +++ b/components/script/dom/analysernode.rs @@ -17,7 +17,7 @@ use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::DomRoot; use crate::dom::window::Window; -use crate::task_source::{TaskSource, TaskSourceName}; +use crate::task_source::TaskSource; use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcReceiver}; use ipc_channel::router::ROUTER; @@ -97,8 +97,9 @@ impl AnalyserNode { ) -> Fallible<DomRoot<AnalyserNode>> { let (node, recv) = AnalyserNode::new_inherited(window, context, options)?; let object = reflect_dom_object(Box::new(node), window, AnalyserNodeBinding::Wrap); - let source = window.dom_manipulation_task_source(); - let canceller = window.task_canceller(TaskSourceName::DOMManipulation); + let (source, canceller) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); let this = Trusted::new(&*object); ROUTER.add_route( diff --git a/components/script/dom/audiocontext.rs b/components/script/dom/audiocontext.rs index 03cdb516139..9bb4f16ce67 100644 --- a/components/script/dom/audiocontext.rs +++ b/components/script/dom/audiocontext.rs @@ -126,7 +126,7 @@ impl AudioContextMethods for AudioContext { // Steps 4 and 5. let window = DomRoot::downcast::<Window>(self.global()).unwrap(); - let task_source = window.dom_manipulation_task_source(); + let task_source = window.task_manager().dom_manipulation_task_source(); let trusted_promise = TrustedPromise::new(promise.clone()); match self.context.audio_context_impl().suspend() { Ok(_) => { @@ -141,7 +141,7 @@ impl AudioContextMethods for AudioContext { if base_context.State() != AudioContextState::Suspended { base_context.set_state_attribute(AudioContextState::Suspended); let window = DomRoot::downcast::<Window>(context.global()).unwrap(); - window.dom_manipulation_task_source().queue_simple_event( + window.task_manager().dom_manipulation_task_source().queue_simple_event( context.upcast(), atom!("statechange"), &window @@ -188,7 +188,7 @@ impl AudioContextMethods for AudioContext { // Steps 4 and 5. let window = DomRoot::downcast::<Window>(self.global()).unwrap(); - let task_source = window.dom_manipulation_task_source(); + let task_source = window.task_manager().dom_manipulation_task_source(); let trusted_promise = TrustedPromise::new(promise.clone()); match self.context.audio_context_impl().close() { Ok(_) => { @@ -203,7 +203,7 @@ impl AudioContextMethods for AudioContext { if base_context.State() != AudioContextState::Closed { base_context.set_state_attribute(AudioContextState::Closed); let window = DomRoot::downcast::<Window>(context.global()).unwrap(); - window.dom_manipulation_task_source().queue_simple_event( + window.task_manager().dom_manipulation_task_source().queue_simple_event( context.upcast(), atom!("statechange"), &window diff --git a/components/script/dom/audioscheduledsourcenode.rs b/components/script/dom/audioscheduledsourcenode.rs index 31527fda3de..24437b88db9 100644 --- a/components/script/dom/audioscheduledsourcenode.rs +++ b/components/script/dom/audioscheduledsourcenode.rs @@ -10,7 +10,7 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::DomObject; -use crate::task_source::{TaskSource, TaskSourceName}; +use crate::task_source::TaskSource; use dom_struct::dom_struct; use servo_media::audio::node::OnEndedCallback; use servo_media::audio::node::{AudioNodeInit, AudioNodeMessage, AudioScheduledSourceNodeMessage}; @@ -71,15 +71,16 @@ impl AudioScheduledSourceNodeMethods for AudioScheduledSourceNode { let this = Trusted::new(self); let global = self.global(); let window = global.as_window(); - let task_source = window.dom_manipulation_task_source(); - let canceller = window.task_canceller(TaskSourceName::DOMManipulation); + let (task_source, canceller) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); let callback = OnEndedCallback::new(move || { let _ = task_source.queue_with_canceller( task!(ended: move || { let this = this.root(); let global = this.global(); let window = global.as_window(); - window.dom_manipulation_task_source().queue_simple_event( + window.task_manager().dom_manipulation_task_source().queue_simple_event( this.upcast(), atom!("ended"), &window diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs index 68acce4d255..6706bac28be 100644 --- a/components/script/dom/baseaudiocontext.rs +++ b/components/script/dom/baseaudiocontext.rs @@ -40,7 +40,7 @@ use crate::dom::oscillatornode::OscillatorNode; use crate::dom::pannernode::PannerNode; use crate::dom::promise::Promise; use crate::dom::window::Window; -use crate::task_source::{TaskSource, TaskSourceName}; +use crate::task_source::TaskSource; use dom_struct::dom_struct; use js::rust::CustomAutoRooterGuard; use js::typedarray::ArrayBuffer; @@ -213,7 +213,7 @@ impl BaseAudioContext { pub fn resume(&self) { let global = self.global(); let window = global.as_window(); - let task_source = window.dom_manipulation_task_source(); + let task_source = window.task_manager().dom_manipulation_task_source(); let this = Trusted::new(self); // Set the rendering thread state to 'running' and start // rendering the audio graph. @@ -227,7 +227,7 @@ impl BaseAudioContext { if this.state.get() != AudioContextState::Running { this.state.set(AudioContextState::Running); let window = DomRoot::downcast::<Window>(this.global()).unwrap(); - window.dom_manipulation_task_source().queue_simple_event( + window.task_manager().dom_manipulation_task_source().queue_simple_event( this.upcast(), atom!("statechange"), &window @@ -428,10 +428,12 @@ impl BaseAudioContextMethods for BaseAudioContext { let decoded_audio__ = decoded_audio.clone(); let this = Trusted::new(self); let this_ = this.clone(); - let task_source = window.dom_manipulation_task_source(); - let task_source_ = window.dom_manipulation_task_source(); - let canceller = window.task_canceller(TaskSourceName::DOMManipulation); - let canceller_ = window.task_canceller(TaskSourceName::DOMManipulation); + let (task_source, canceller) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); + let (task_source_, canceller_) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); let callbacks = AudioDecoderCallbacks::new() .ready(move |channel_count| { decoded_audio diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 36156a1d89f..a18da3f112f 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -521,6 +521,7 @@ impl Document { if self.ready_state.get() == DocumentReadyState::Complete { let document = Trusted::new(self); self.window + .task_manager() .dom_manipulation_task_source() .queue( task!(fire_pageshow_event: move || { @@ -1869,6 +1870,7 @@ impl Document { debug!("Document loads are complete."); let document = Trusted::new(self); self.window + .task_manager() .dom_manipulation_task_source() .queue( task!(fire_load_event: move || { @@ -1922,6 +1924,7 @@ impl Document { let document = Trusted::new(self); if document.root().browsing_context().is_some() { self.window + .task_manager() .dom_manipulation_task_source() .queue( task!(fire_pageshow_event: move || { @@ -2104,13 +2107,16 @@ impl Document { // Step 4.1. let window = self.window(); - window.dom_manipulation_task_source().queue_event( - self.upcast(), - atom!("DOMContentLoaded"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable, - window, - ); + window + .task_manager() + .dom_manipulation_task_source() + .queue_event( + self.upcast(), + atom!("DOMContentLoaded"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable, + window, + ); window.reflow(ReflowGoal::Full, ReflowReason::DOMContentLoaded); update_with_current_time_ms(&self.dom_content_loaded_event_end); diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 5d2ed77ce4d..bca3f36f68e 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -476,7 +476,7 @@ impl GlobalScope { /// this global scope. pub fn networking_task_source(&self) -> NetworkingTaskSource { if let Some(window) = self.downcast::<Window>() { - return window.networking_task_source(); + return window.task_manager().networking_task_source(); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.networking_task_source(); @@ -488,7 +488,7 @@ impl GlobalScope { /// this global scope. pub fn remote_event_task_source(&self) -> RemoteEventTaskSource { if let Some(window) = self.downcast::<Window>() { - return window.remote_event_task_source(); + return window.task_manager().remote_event_task_source(); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.remote_event_task_source(); @@ -500,7 +500,7 @@ impl GlobalScope { /// this global scope. pub fn websocket_task_source(&self) -> WebsocketTaskSource { if let Some(window) = self.downcast::<Window>() { - return window.websocket_task_source(); + return window.task_manager().websocket_task_source(); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.websocket_task_source(); @@ -635,7 +635,7 @@ impl GlobalScope { /// properly cancelled when the global scope is destroyed. pub fn task_canceller(&self, name: TaskSourceName) -> TaskCanceller { if let Some(window) = self.downcast::<Window>() { - return window.task_canceller(name); + return window.task_manager().task_canceller(name); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { // Note: the "name" is not passed to the worker, @@ -691,7 +691,7 @@ impl GlobalScope { pub fn dom_manipulation_task_source(&self) -> DOMManipulationTaskSource { if let Some(window) = self.downcast::<Window>() { - return window.dom_manipulation_task_source(); + return window.task_manager().dom_manipulation_task_source(); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.dom_manipulation_task_source(); @@ -703,7 +703,7 @@ impl GlobalScope { /// this of this global scope. pub fn file_reading_task_source(&self) -> FileReadingTaskSource { if let Some(window) = self.downcast::<Window>() { - return window.file_reading_task_source(); + return window.task_manager().file_reading_task_source(); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.file_reading_task_source(); @@ -756,7 +756,7 @@ impl GlobalScope { /// of this global scope. pub fn performance_timeline_task_source(&self) -> PerformanceTimelineTaskSource { if let Some(window) = self.downcast::<Window>() { - return window.performance_timeline_task_source(); + return window.task_manager().performance_timeline_task_source(); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.performance_timeline_task_source(); diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 3f7021dc786..e30b8ef4c52 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -76,7 +76,7 @@ impl VirtualMethods for HTMLDetailsElement { let window = window_from_node(self); let this = Trusted::new(self); // FIXME(nox): Why are errors silenced here? - let _ = window.dom_manipulation_task_source().queue( + let _ = window.task_manager().dom_manipulation_task_source().queue( task!(details_notification_task_steps: move || { let this = this.root(); if counter == this.toggle_counter.get() { diff --git a/components/script/dom/htmldialogelement.rs b/components/script/dom/htmldialogelement.rs index 36edbefa9cb..b7fdb090ba5 100644 --- a/components/script/dom/htmldialogelement.rs +++ b/components/script/dom/htmldialogelement.rs @@ -90,7 +90,8 @@ impl HTMLDialogElementMethods for HTMLDialogElement { // TODO: Step 4 implement pending dialog stack removal // Step 5 - win.dom_manipulation_task_source() + win.task_manager() + .dom_manipulation_task_source() .queue_simple_event(target, atom!("close"), &win); } } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index fc9e4832fe5..c335a06d0cc 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -523,6 +523,7 @@ impl HTMLFormElement { // Step 3. target + .task_manager() .dom_manipulation_task_source() .queue(task, target.upcast()) .unwrap(); diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 9cae4e83e7a..252f8a6b5aa 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -237,7 +237,7 @@ impl HTMLIFrameElement { let this = Trusted::new(self); let pipeline_id = self.pipeline_id().unwrap(); // FIXME(nox): Why are errors silenced here? - let _ = window.dom_manipulation_task_source().queue( + let _ = window.task_manager().dom_manipulation_task_source().queue( task!(iframe_load_event_steps: move || { this.root().iframe_load_event_steps(pipeline_id); }), diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 851f9971455..7fd95a57f30 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -40,7 +40,7 @@ use crate::dom::window::Window; use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::network_listener::{NetworkListener, PreInvoke}; use crate::script_thread::ScriptThread; -use crate::task_source::{TaskSource, TaskSourceName}; +use crate::task_source::TaskSource; use cssparser::{Parser, ParserInput}; use dom_struct::dom_struct; use euclid::Point2D; @@ -237,8 +237,9 @@ impl HTMLImageElement { let (responder_sender, responder_receiver) = ipc::channel().unwrap(); let window = window_from_node(elem); - let task_source = window.networking_task_source(); - let task_canceller = window.task_canceller(TaskSourceName::Networking); + let (task_source, canceller) = window + .task_manager() + .networking_task_source_with_canceller(); let generation = elem.generation.get(); ROUTER.add_route( responder_receiver.to_opaque(), @@ -257,7 +258,7 @@ impl HTMLImageElement { element.process_image_response(image); } }), - &task_canceller, + &canceller, ); }), ); @@ -308,10 +309,14 @@ impl HTMLImageElement { })); let (action_sender, action_receiver) = ipc::channel().unwrap(); + let (task_source, canceller) = document + .window() + .task_manager() + .networking_task_source_with_canceller(); let listener = NetworkListener { - context: context, - task_source: window.networking_task_source(), - canceller: Some(window.task_canceller(TaskSourceName::Networking)), + context, + task_source, + canceller: Some(canceller), }; ROUTER.add_route( action_receiver.to_opaque(), @@ -780,7 +785,7 @@ impl HTMLImageElement { fn update_the_image_data_sync_steps(&self) { let document = document_from_node(self); let window = document.window(); - let task_source = window.dom_manipulation_task_source(); + let task_source = window.task_manager().dom_manipulation_task_source(); let this = Trusted::new(self); let (src, pixel_density) = match self.select_image_source() { // Step 8 @@ -938,7 +943,7 @@ impl HTMLImageElement { current_request.current_pixel_density = pixel_density; let this = Trusted::new(self); let src = String::from(src); - let _ = window.dom_manipulation_task_source().queue( + let _ = window.task_manager().dom_manipulation_task_source().queue( task!(image_load_event: move || { let this = this.root(); { @@ -989,8 +994,9 @@ impl HTMLImageElement { let (responder_sender, responder_receiver) = ipc::channel().unwrap(); let window = window_from_node(elem); - let task_source = window.networking_task_source(); - let task_canceller = window.task_canceller(TaskSourceName::Networking); + let (task_source, canceller) = window + .task_manager() + .networking_task_source_with_canceller(); let generation = elem.generation.get(); ROUTER.add_route(responder_receiver.to_opaque(), Box::new(move |message| { debug!("Got image {:?}", message); @@ -1008,7 +1014,7 @@ impl HTMLImageElement { DOMString::from_string(selected_source_clone), generation, selected_pixel_density); } }), - &task_canceller, + &canceller, ); })); @@ -1133,7 +1139,7 @@ impl HTMLImageElement { let this = Trusted::new(self); let window = window_from_node(self); let src = src.to_string(); - let _ = window.dom_manipulation_task_source().queue( + let _ = window.task_manager().dom_manipulation_task_source().queue( task!(image_load_event: move || { let this = this.root(); let relevant_mutation = this.generation.get() != generation; diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 3b2a3e01552..d7110183c4a 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -1515,13 +1515,16 @@ impl VirtualMethods for HTMLInputElement { { if event.IsTrusted() { let window = window_from_node(self); - let _ = window.user_interaction_task_source().queue_event( - &self.upcast(), - atom!("input"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable, - &window, - ); + let _ = window + .task_manager() + .user_interaction_task_source() + .queue_event( + &self.upcast(), + atom!("input"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable, + &window, + ); } } } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index b178b4b5801..a91487d5555 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -36,7 +36,7 @@ use crate::fetch::FetchCanceller; use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::network_listener::{NetworkListener, PreInvoke}; use crate::script_thread::ScriptThread; -use crate::task_source::{TaskSource, TaskSourceName}; +use crate::task_source::TaskSource; use dom_struct::dom_struct; use headers_core::HeaderMapExt; use headers_ext::ContentLength; @@ -295,7 +295,7 @@ impl HTMLMediaElement { let window = window_from_node(self); // FIXME(nox): Why are errors silenced here? - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); if self.Paused() { // Step 6.1. self.paused.set(false); @@ -373,7 +373,7 @@ impl HTMLMediaElement { let window = window_from_node(self); let this = Trusted::new(self); let generation_id = self.generation_id.get(); - let _ = window.media_element_task_source().queue( + let _ = window.task_manager().media_element_task_source().queue( task!(internal_pause_steps: move || { let this = this.root(); if generation_id != this.generation_id.get() { @@ -415,7 +415,7 @@ impl HTMLMediaElement { let this = Trusted::new(self); let generation_id = self.generation_id.get(); // FIXME(nox): Why are errors silenced here? - let _ = window.media_element_task_source().queue( + let _ = window.task_manager().media_element_task_source().queue( task!(notify_about_playing: move || { let this = this.root(); if generation_id != this.generation_id.get() { @@ -449,7 +449,7 @@ impl HTMLMediaElement { } let window = window_from_node(self); - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); // Step 1. match (old_ready_state, ready_state) { @@ -604,11 +604,10 @@ impl HTMLMediaElement { // Step 8. let window = window_from_node(self); - window.media_element_task_source().queue_simple_event( - self.upcast(), - atom!("loadstart"), - &window, - ); + window + .task_manager() + .media_element_task_source() + .queue_simple_event(self.upcast(), atom!("loadstart"), &window); // Step 9. match mode { @@ -710,10 +709,13 @@ impl HTMLMediaElement { let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self))); let (action_sender, action_receiver) = ipc::channel().unwrap(); let window = window_from_node(self); + let (task_source, canceller) = window + .task_manager() + .networking_task_source_with_canceller(); let listener = NetworkListener { context, - task_source: window.networking_task_source(), - canceller: Some(window.task_canceller(TaskSourceName::Networking)), + task_source, + canceller: Some(canceller), }; ROUTER.add_route( action_receiver.to_opaque(), @@ -768,15 +770,15 @@ impl HTMLMediaElement { // Step 4.remote.1.2. let window = window_from_node(self); - window.media_element_task_source().queue_simple_event( - self.upcast(), - atom!("suspend"), - &window, - ); + window + .task_manager() + .media_element_task_source() + .queue_simple_event(self.upcast(), atom!("suspend"), &window); // Step 4.remote.1.3. let this = Trusted::new(self); window + .task_manager() .media_element_task_source() .queue( task!(set_media_delay_load_event_flag_to_false: move || { @@ -817,7 +819,7 @@ impl HTMLMediaElement { let generation_id = self.generation_id.get(); self.take_pending_play_promises(Err(Error::NotSupported)); // FIXME(nox): Why are errors silenced here? - let _ = window.media_element_task_source().queue( + let _ = window.task_manager().media_element_task_source().queue( task!(dedicated_media_source_failure_steps: move || { let this = this.root(); if generation_id != this.generation_id.get() { @@ -874,7 +876,7 @@ impl HTMLMediaElement { } let window = window_from_node(self); - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); // Step 5. let network_state = self.network_state.get(); @@ -1051,7 +1053,7 @@ impl HTMLMediaElement { // Step 10. let window = window_from_node(self); - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); task_source.queue_simple_event(self.upcast(), atom!("seeking"), &window); // Step 11. @@ -1074,7 +1076,7 @@ impl HTMLMediaElement { // Step 16. let window = window_from_node(self); - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window); // Step 17. @@ -1090,8 +1092,9 @@ impl HTMLMediaElement { let trusted_node = Trusted::new(self); let window = window_from_node(self); - let task_source = window.media_element_task_source(); - let task_canceller = window.task_canceller(TaskSourceName::DOMManipulation); + let (task_source, canceller) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); ROUTER.add_route( action_receiver.to_opaque(), Box::new(move |message| { @@ -1102,7 +1105,7 @@ impl HTMLMediaElement { task!(handle_player_event: move || { this.root().handle_player_event(&event); }), - &task_canceller, + &canceller, ) .unwrap(); }), @@ -1134,7 +1137,7 @@ impl HTMLMediaElement { } if previous_duration != self.duration.get() { let window = window_from_node(self); - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); task_source.queue_simple_event(self.upcast(), atom!("durationchange"), &window); } @@ -1147,7 +1150,7 @@ impl HTMLMediaElement { video_elem.set_video_width(metadata.width); video_elem.set_video_height(metadata.height); let window = window_from_node(self); - let task_source = window.media_element_task_source(); + let task_source = window.task_manager().media_element_task_source(); task_source.queue_simple_event(self.upcast(), atom!("resize"), &window); } } @@ -1515,11 +1518,10 @@ impl FetchResponseListener for HTMLMediaElementContext { // => "If mode is remote" step 2 if time::get_time() > self.next_progress_event { let window = window_from_node(&*elem); - window.media_element_task_source().queue_simple_event( - elem.upcast(), - atom!("progress"), - &window, - ); + window + .task_manager() + .media_element_task_source() + .queue_simple_event(elem.upcast(), atom!("progress"), &window); self.next_progress_event = time::get_time() + Duration::milliseconds(350); } } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 47a4950b3d6..d93b5357e24 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -25,7 +25,6 @@ use crate::dom::node::{document_from_node, window_from_node}; use crate::dom::node::{ChildrenMutation, CloneChildrenFlag, Node}; use crate::dom::virtualmethods::VirtualMethods; use crate::network_listener::{NetworkListener, PreInvoke}; -use crate::task_source::TaskSourceName; use dom_struct::dom_struct; use encoding_rs::Encoding; use html5ever::{LocalName, Prefix}; @@ -294,10 +293,14 @@ fn fetch_a_classic_script( })); let (action_sender, action_receiver) = ipc::channel().unwrap(); + let (task_source, canceller) = doc + .window() + .task_manager() + .networking_task_source_with_canceller(); let listener = NetworkListener { - context: context, - task_source: doc.window().networking_task_source(), - canceller: Some(doc.window().task_canceller(TaskSourceName::Networking)), + context, + task_source, + canceller: Some(canceller), }; ROUTER.add_route( @@ -623,11 +626,10 @@ impl HTMLScriptElement { pub fn queue_error_event(&self) { let window = window_from_node(self); - window.dom_manipulation_task_source().queue_simple_event( - self.upcast(), - atom!("error"), - &window, - ); + window + .task_manager() + .dom_manipulation_task_source() + .queue_simple_event(self.upcast(), atom!("error"), &window); } pub fn dispatch_load_event(&self) { diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 364640fa169..4c9d12d560a 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -127,11 +127,10 @@ impl HTMLStyleElement { // No subresource loads were triggered, queue load event if self.pending_loads.get() == 0 { let window = window_from_node(self); - window.dom_manipulation_task_source().queue_simple_event( - self.upcast(), - atom!("load"), - &window, - ); + window + .task_manager() + .dom_manipulation_task_source() + .queue_simple_event(self.upcast(), atom!("load"), &window); } self.set_stylesheet(sheet); diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 89ffff3e030..cb4929f4cab 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -565,13 +565,16 @@ impl VirtualMethods for HTMLTextAreaElement { } else if event.type_() == atom!("keypress") && !event.DefaultPrevented() { if event.IsTrusted() { let window = window_from_node(self); - let _ = window.user_interaction_task_source().queue_event( - &self.upcast(), - atom!("input"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable, - &window, - ); + let _ = window + .task_manager() + .user_interaction_task_source() + .queue_event( + &self.upcast(), + atom!("input"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable, + &window, + ); } } } diff --git a/components/script/dom/offlineaudiocontext.rs b/components/script/dom/offlineaudiocontext.rs index f98f3b44750..dccc72427f8 100644 --- a/components/script/dom/offlineaudiocontext.rs +++ b/components/script/dom/offlineaudiocontext.rs @@ -20,7 +20,7 @@ use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::offlineaudiocompletionevent::OfflineAudioCompletionEvent; use crate::dom::promise::Promise; use crate::dom::window::Window; -use crate::task_source::{TaskSource, TaskSourceName}; +use crate::task_source::TaskSource; use dom_struct::dom_struct; use servo_media::audio::context::OfflineAudioContextOptions as ServoMediaOfflineAudioContextOptions; use std::cell::Cell; @@ -141,8 +141,9 @@ impl OfflineAudioContextMethods for OfflineAudioContext { let this = Trusted::new(self); let global = self.global(); let window = global.as_window(); - let task_source = window.dom_manipulation_task_source(); - let canceller = window.task_canceller(TaskSourceName::DOMManipulation); + let (task_source, canceller) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); Builder::new() .name("OfflineAudioContextResolver".to_owned()) .spawn(move || { diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index ed6ed999fa2..4e8f0871571 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -209,6 +209,7 @@ impl Storage { let this = Trusted::new(self); global .as_window() + .task_manager() .dom_manipulation_task_source() .queue( task!(send_storage_notification: move || { diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs index 3ed20a2901a..1f276b94ba8 100644 --- a/components/script/dom/textcontrol.rs +++ b/components/script/dom/textcontrol.rs @@ -297,13 +297,16 @@ impl<'a, E: TextControlElement> TextControlSelection<'a, E> { // Step 6 if textinput.selection_state() != original_selection_state { let window = window_from_node(self.element); - window.user_interaction_task_source().queue_event( - &self.element.upcast::<EventTarget>(), - atom!("select"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable, - &window, - ); + window + .task_manager() + .user_interaction_task_source() + .queue_event( + &self.element.upcast::<EventTarget>(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable, + &window, + ); } self.element diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 110356374f6..51c379145c2 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -64,16 +64,7 @@ use crate::script_runtime::{ }; use crate::script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg}; use crate::script_thread::{ScriptThread, SendableMainThreadScriptChan}; -use crate::task::TaskCanceller; -use crate::task_source::dom_manipulation::DOMManipulationTaskSource; -use crate::task_source::file_reading::FileReadingTaskSource; -use crate::task_source::history_traversal::HistoryTraversalTaskSource; -use crate::task_source::media_element::MediaElementTaskSource; -use crate::task_source::networking::NetworkingTaskSource; -use crate::task_source::performance_timeline::PerformanceTimelineTaskSource; -use crate::task_source::remote_event::RemoteEventTaskSource; -use crate::task_source::user_interaction::UserInteractionTaskSource; -use crate::task_source::websocket::WebsocketTaskSource; +use crate::task_manager::TaskManager; use crate::task_source::TaskSourceName; use crate::timers::{IsInterval, TimerCallback}; use crate::webdriver_handlers::jsval_to_webdriver; @@ -127,7 +118,7 @@ use std::fs; use std::io::{stderr, stdout, Write}; use std::mem; use std::rc::Rc; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex}; use style::error_reporting::ParseErrorReporter; use style::media_queries; @@ -180,24 +171,7 @@ pub struct Window { globalscope: GlobalScope, #[ignore_malloc_size_of = "trait objects are hard"] script_chan: MainThreadScriptChan, - #[ignore_malloc_size_of = "task sources are hard"] - dom_manipulation_task_source: DOMManipulationTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - media_element_task_source: MediaElementTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - user_interaction_task_source: UserInteractionTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - networking_task_source: NetworkingTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - history_traversal_task_source: HistoryTraversalTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - file_reading_task_source: FileReadingTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - performance_timeline_task_source: PerformanceTimelineTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - remote_event_task_source: RemoteEventTaskSource, - #[ignore_malloc_size_of = "task sources are hard"] - websocket_task_source: WebsocketTaskSource, + task_manager: TaskManager, navigator: MutNullableDom<Navigator>, #[ignore_malloc_size_of = "Arc"] image_cache: Arc<ImageCache>, @@ -273,10 +247,6 @@ pub struct Window { current_viewport: Cell<Rect<Au>>, - /// 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<HashMap<TaskSourceName, Arc<AtomicBool>>>, - error_reporter: CSSErrorReporter, /// A list of scroll offsets for each scrollable element. @@ -324,6 +294,10 @@ pub struct Window { } impl Window { + pub fn task_manager(&self) -> &TaskManager { + &self.task_manager + } + pub fn get_exists_mut_observer(&self) -> bool { self.exists_mut_observer.get() } @@ -343,7 +317,7 @@ impl Window { } fn ignore_all_events(&self) { - let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); + let mut ignore_flags = self.task_manager.task_cancellers.borrow_mut(); for task_source_name in TaskSourceName::all() { let flag = ignore_flags .entry(task_source_name) @@ -365,39 +339,6 @@ impl Window { self.js_runtime.borrow().as_ref().unwrap().cx() } - pub fn dom_manipulation_task_source(&self) -> DOMManipulationTaskSource { - self.dom_manipulation_task_source.clone() - } - - pub fn media_element_task_source(&self) -> MediaElementTaskSource { - self.media_element_task_source.clone() - } - - pub fn user_interaction_task_source(&self) -> UserInteractionTaskSource { - self.user_interaction_task_source.clone() - } - - pub fn networking_task_source(&self) -> NetworkingTaskSource { - self.networking_task_source.clone() - } - - pub fn file_reading_task_source(&self) -> TaskManagement<FileReadingTaskSource> { - let canceller = self.task_canceller(TaskSourceName::FileReading); - TaskManagement(self.file_reading_task_source.clone(), canceller) - } - - pub fn performance_timeline_task_source(&self) -> PerformanceTimelineTaskSource { - self.performance_timeline_task_source.clone() - } - - pub fn remote_event_task_source(&self) -> RemoteEventTaskSource { - self.remote_event_task_source.clone() - } - - pub fn websocket_task_source(&self) -> WebsocketTaskSource { - self.websocket_task_source.clone() - } - pub fn main_thread_script_chan(&self) -> &Sender<MainThreadScriptMsg> { &self.script_chan.0 } @@ -1231,14 +1172,6 @@ impl Window { self.paint_worklet.or_init(|| self.new_paint_worklet()) } - 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(cancel_flag.clone()), - } - } - pub fn get_navigation_start(&self) -> u64 { self.navigation_start_precise.get() } @@ -1249,10 +1182,10 @@ impl Window { /// Cancels all the tasks associated with that window. /// - /// This sets the current `ignore_further_async_events` sentinel value to + /// This sets the current `task_manager.task_cancellers` sentinel value to /// `true` and replaces it with a brand new one for future tasks. pub fn cancel_all_tasks(&self) { - let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); + let mut ignore_flags = self.task_manager.task_cancellers.borrow_mut(); for task_source_name in TaskSourceName::all() { let flag = ignore_flags .entry(task_source_name) @@ -1266,7 +1199,7 @@ impl Window { /// This sets the current sentinel value to /// `true` and replaces it with a brand new one for future tasks. pub fn cancel_all_tasks_from_source(&self, task_source_name: TaskSourceName) { - let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); + let mut ignore_flags = self.task_manager.task_cancellers.borrow_mut(); let flag = ignore_flags .entry(task_source_name) .or_insert(Default::default()); @@ -1827,7 +1760,8 @@ impl Window { let _ = self.script_chan.send(CommonScriptMsg::Task( ScriptThreadEventCategory::DomEvent, Box::new( - self.task_canceller(TaskSourceName::DOMManipulation) + self.task_manager + .task_canceller(TaskSourceName::DOMManipulation) .wrap_task(task), ), self.pipeline_id(), @@ -2073,15 +2007,7 @@ impl Window { pub fn new( runtime: Rc<Runtime>, script_chan: MainThreadScriptChan, - dom_manipulation_task_source: DOMManipulationTaskSource, - media_element_task_source: MediaElementTaskSource, - user_interaction_task_source: UserInteractionTaskSource, - networking_task_source: NetworkingTaskSource, - history_traversal_task_source: HistoryTraversalTaskSource, - file_reading_task_source: FileReadingTaskSource, - performance_timeline_task_source: PerformanceTimelineTaskSource, - remote_event_task_source: RemoteEventTaskSource, - websocket_task_source: WebsocketTaskSource, + task_manager: TaskManager, image_cache_chan: Sender<ImageCacheMsg>, image_cache: Arc<dyn ImageCache>, resource_threads: ResourceThreads, @@ -2129,15 +2055,7 @@ impl Window { microtask_queue, ), script_chan, - dom_manipulation_task_source, - media_element_task_source, - user_interaction_task_source, - networking_task_source, - history_traversal_task_source, - file_reading_task_source, - performance_timeline_task_source, - remote_event_task_source, - websocket_task_source, + task_manager, image_cache_chan, image_cache, navigator: Default::default(), @@ -2170,7 +2088,6 @@ impl Window { devtools_marker_sender: Default::default(), devtools_markers: Default::default(), webdriver_script_chan: Default::default(), - ignore_further_async_events: Default::default(), error_reporter, scroll_offsets: Default::default(), media_query_lists: DOMTracker::new(), @@ -2311,7 +2228,8 @@ impl Window { let _ = self.script_chan.send(CommonScriptMsg::Task( ScriptThreadEventCategory::DomEvent, Box::new( - self.task_canceller(TaskSourceName::DOMManipulation) + self.task_manager + .task_canceller(TaskSourceName::DOMManipulation) .wrap_task(task), ), self.pipeline_id(), |