mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
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)
This commit is contained in:
parent
14bc8ab754
commit
75eb94afca
26 changed files with 362 additions and 252 deletions
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -523,6 +523,7 @@ impl HTMLFormElement {
|
|||
|
||||
// Step 3.
|
||||
target
|
||||
.task_manager()
|
||||
.dom_manipulation_task_source()
|
||||
.queue(task, target.upcast())
|
||||
.unwrap();
|
||||
|
|
|
@ -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);
|
||||
}),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 || {
|
||||
|
|
|
@ -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 || {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
use crate::dom::bindings::reflector::DomObject;
|
||||
use crate::dom::node::{document_from_node, Node};
|
||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
||||
use crate::task_source::TaskSourceName;
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::image_cache::{ImageCache, PendingImageId};
|
||||
|
@ -57,13 +56,16 @@ pub fn fetch_image_for_layout(
|
|||
}));
|
||||
|
||||
let document = document_from_node(node);
|
||||
let window = document.window();
|
||||
|
||||
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(),
|
||||
|
|
|
@ -69,6 +69,7 @@ pub mod script_thread;
|
|||
mod serviceworker_manager;
|
||||
mod serviceworkerjob;
|
||||
mod stylesheet_loader;
|
||||
mod task_manager;
|
||||
mod task_queue;
|
||||
mod task_source;
|
||||
pub mod test;
|
||||
|
|
|
@ -70,6 +70,7 @@ use crate::microtask::{Microtask, MicrotaskQueue};
|
|||
use crate::script_runtime::{get_reports, new_rt_and_cx, Runtime, ScriptPort};
|
||||
use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use crate::serviceworkerjob::{Job, JobQueue};
|
||||
use crate::task_manager::TaskManager;
|
||||
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
|
||||
use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
|
||||
use crate::task_source::file_reading::FileReadingTaskSource;
|
||||
|
@ -2583,20 +2584,23 @@ impl ScriptThread {
|
|||
pipeline_id: incomplete.pipeline_id,
|
||||
};
|
||||
|
||||
let task_manager = TaskManager::new(
|
||||
self.dom_manipulation_task_source(incomplete.pipeline_id),
|
||||
self.file_reading_task_source(incomplete.pipeline_id),
|
||||
self.history_traversal_task_source(incomplete.pipeline_id),
|
||||
self.media_element_task_source(incomplete.pipeline_id),
|
||||
self.networking_task_source(incomplete.pipeline_id),
|
||||
self.performance_timeline_task_source(incomplete.pipeline_id)
|
||||
.clone(),
|
||||
self.user_interaction_task_source(incomplete.pipeline_id),
|
||||
self.remote_event_task_source(incomplete.pipeline_id),
|
||||
self.websocket_task_source(incomplete.pipeline_id),
|
||||
);
|
||||
// Create the window and document objects.
|
||||
let window = Window::new(
|
||||
self.js_runtime.clone(),
|
||||
MainThreadScriptChan(sender.clone()),
|
||||
self.dom_manipulation_task_source(incomplete.pipeline_id),
|
||||
self.media_element_task_source(incomplete.pipeline_id),
|
||||
self.user_interaction_task_source(incomplete.pipeline_id),
|
||||
self.networking_task_source(incomplete.pipeline_id),
|
||||
self.history_traversal_task_source(incomplete.pipeline_id),
|
||||
self.file_reading_task_source(incomplete.pipeline_id),
|
||||
self.performance_timeline_task_source(incomplete.pipeline_id)
|
||||
.clone(),
|
||||
self.remote_event_task_source(incomplete.pipeline_id),
|
||||
self.websocket_task_source(incomplete.pipeline_id),
|
||||
task_manager,
|
||||
self.image_cache_channel.clone(),
|
||||
self.image_cache.clone(),
|
||||
self.resource_threads.clone(),
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::dom::htmlelement::HTMLElement;
|
|||
use crate::dom::htmllinkelement::{HTMLLinkElement, RequestGenerationId};
|
||||
use crate::dom::node::{document_from_node, window_from_node};
|
||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
||||
use crate::task_source::TaskSourceName;
|
||||
use cssparser::SourceLocation;
|
||||
use encoding_rs::UTF_8;
|
||||
use ipc_channel::ipc;
|
||||
|
@ -245,10 +244,14 @@ impl<'a> StylesheetLoader<'a> {
|
|||
}));
|
||||
|
||||
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: document.window().networking_task_source(),
|
||||
canceller: Some(document.window().task_canceller(TaskSourceName::Networking)),
|
||||
context,
|
||||
task_source,
|
||||
canceller: Some(canceller),
|
||||
};
|
||||
ROUTER.add_route(
|
||||
action_receiver.to_opaque(),
|
||||
|
|
162
components/script/task_manager.rs
Normal file
162
components/script/task_manager.rs
Normal file
|
@ -0,0 +1,162 @@
|
|||
/* 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 crate::dom::bindings::cell::DomRefCell;
|
||||
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_source::TaskSourceName;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
macro_rules! task_source_functions {
|
||||
($self:ident,$with_canceller:ident,$task_source:ident,$task_source_type:ident,$task_source_name:ident) => {
|
||||
pub fn $with_canceller(&$self) -> ($task_source_type, TaskCanceller) {
|
||||
($self.$task_source.clone(), $self.task_canceller(TaskSourceName::$task_source_name))
|
||||
}
|
||||
|
||||
pub fn $task_source(&$self) -> $task_source_type {
|
||||
$self.$task_source.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub struct TaskManager {
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
pub task_cancellers: DomRefCell<HashMap<TaskSourceName, Arc<AtomicBool>>>,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
dom_manipulation_task_source: DOMManipulationTaskSource,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
file_reading_task_source: FileReadingTaskSource,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
history_traversal_task_source: HistoryTraversalTaskSource,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
media_element_task_source: MediaElementTaskSource,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
networking_task_source: NetworkingTaskSource,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
||||
#[ignore_malloc_size_of = "task sources are hard"]
|
||||
user_interaction_task_source: UserInteractionTaskSource,
|
||||
#[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,
|
||||
}
|
||||
|
||||
impl TaskManager {
|
||||
pub fn new(
|
||||
dom_manipulation_task_source: DOMManipulationTaskSource,
|
||||
file_reading_task_source: FileReadingTaskSource,
|
||||
history_traversal_task_source: HistoryTraversalTaskSource,
|
||||
media_element_task_source: MediaElementTaskSource,
|
||||
networking_task_source: NetworkingTaskSource,
|
||||
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
||||
user_interaction_task_source: UserInteractionTaskSource,
|
||||
remote_event_task_source: RemoteEventTaskSource,
|
||||
websocket_task_source: WebsocketTaskSource,
|
||||
) -> Self {
|
||||
TaskManager {
|
||||
dom_manipulation_task_source,
|
||||
file_reading_task_source,
|
||||
history_traversal_task_source,
|
||||
media_element_task_source,
|
||||
networking_task_source,
|
||||
performance_timeline_task_source,
|
||||
user_interaction_task_source,
|
||||
remote_event_task_source,
|
||||
websocket_task_source,
|
||||
task_cancellers: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
dom_manipulation_task_source_with_canceller,
|
||||
dom_manipulation_task_source,
|
||||
DOMManipulationTaskSource,
|
||||
DOMManipulation
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
media_element_task_source_with_canceller,
|
||||
media_element_task_source,
|
||||
MediaElementTaskSource,
|
||||
MediaElement
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
user_interaction_task_source_with_canceller,
|
||||
user_interaction_task_source,
|
||||
UserInteractionTaskSource,
|
||||
UserInteraction
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
networking_task_source_with_canceller,
|
||||
networking_task_source,
|
||||
NetworkingTaskSource,
|
||||
Networking
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
file_reading_task_source_with_canceller,
|
||||
file_reading_task_source,
|
||||
FileReadingTaskSource,
|
||||
FileReading
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
history_traversal_task_source_with_canceller,
|
||||
history_traversal_task_source,
|
||||
HistoryTraversalTaskSource,
|
||||
HistoryTraversal
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
performance_timeline_task_source_with_canceller,
|
||||
performance_timeline_task_source,
|
||||
PerformanceTimelineTaskSource,
|
||||
PerformanceTimeline
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
remote_event_task_source_with_canceller,
|
||||
remote_event_task_source,
|
||||
RemoteEventTaskSource,
|
||||
RemoteEvent
|
||||
);
|
||||
|
||||
task_source_functions!(
|
||||
self,
|
||||
websocket_task_source_with_canceller,
|
||||
websocket_task_source,
|
||||
WebsocketTaskSource,
|
||||
Websocket
|
||||
);
|
||||
|
||||
pub fn task_canceller(&self, name: TaskSourceName) -> TaskCanceller {
|
||||
let mut flags = self.task_cancellers.borrow_mut();
|
||||
let cancel_flag = flags.entry(name).or_insert(Default::default());
|
||||
TaskCanceller {
|
||||
cancelled: Some(cancel_flag.clone()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,28 +2,16 @@
|
|||
* 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 crate::script_runtime::{CommonScriptMsg, ScriptThreadEventCategory};
|
||||
use crate::script_thread::MainThreadScriptMsg;
|
||||
use crate::task::{TaskCanceller, TaskOnce};
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
use script_thread::MainThreadScriptMsg;
|
||||
use servo_channel::Sender;
|
||||
use task::{TaskCanceller, TaskOnce};
|
||||
use task_source::{TaskSource, TaskSourceName};
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
#[derive(Clone, JSTraceable)]
|
||||
pub struct HistoryTraversalTaskSource(pub Sender<MainThreadScriptMsg>, pub PipelineId);
|
||||
|
||||
impl ScriptChan for HistoryTraversalTaskSource {
|
||||
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
|
||||
self.0
|
||||
.send(MainThreadScriptMsg::Common(msg))
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
||||
fn clone(&self) -> Box<ScriptChan + Send> {
|
||||
Box::new(HistoryTraversalTaskSource((&self.0).clone(), (&self.1).clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl TaskSource for HistoryTraversalTaskSource {
|
||||
const NAME: TaskSourceName = TaskSourceName::HistoryTraversal;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue