From 69275162b03d663394cd7bfe564890187e00de52 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Sep 2017 01:15:44 +0200 Subject: [PATCH 01/37] Clean up Storage::queue_storage_event This moves the Runnable type directly in the method and makes it not use main_thread_handler, which is unneeded here anyway. --- components/script/dom/storage.rs | 89 ++++++++++++++++---------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index f14f1aad67f..1f7cba224f6 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -17,7 +17,7 @@ use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcSender}; use net_traits::IpcSend; use net_traits::storage_thread::{StorageThreadMsg, StorageType}; -use script_thread::{Runnable, ScriptThread}; +use script_thread::Runnable; use script_traits::ScriptMsg; use servo_url::ServoUrl; use task_source::TaskSource; @@ -158,50 +158,49 @@ impl Storage { } /// https://html.spec.whatwg.org/multipage/#send-a-storage-notification - pub fn queue_storage_event(&self, url: ServoUrl, - key: Option, old_value: Option, new_value: Option) { + pub fn queue_storage_event( + &self, + url: ServoUrl, + key: Option, + old_value: Option, + new_value: Option, + ) { let global = self.global(); - let window = global.as_window(); - let task_source = window.dom_manipulation_task_source(); - let trusted_storage = Trusted::new(self); - task_source - .queue( - box StorageEventRunnable::new(trusted_storage, url, key, old_value, new_value), &global) - .unwrap(); - } -} - -pub struct StorageEventRunnable { - element: Trusted, - url: ServoUrl, - key: Option, - old_value: Option, - new_value: Option -} - -impl StorageEventRunnable { - fn new(storage: Trusted, url: ServoUrl, - key: Option, old_value: Option, new_value: Option) -> StorageEventRunnable { - StorageEventRunnable { element: storage, url: url, key: key, old_value: old_value, new_value: new_value } - } -} - -impl Runnable for StorageEventRunnable { - fn main_thread_handler(self: Box, _: &ScriptThread) { - let this = *self; - let storage = this.element.root(); - let global = storage.global(); - let window = global.as_window(); - - let storage_event = StorageEvent::new( - &window, - atom!("storage"), - EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, - this.key.map(DOMString::from), this.old_value.map(DOMString::from), this.new_value.map(DOMString::from), - DOMString::from(this.url.into_string()), - Some(&storage) - ); - - storage_event.upcast::().fire(window.upcast()); + global.as_window().dom_manipulation_task_source().queue( + box StorageEventRunnable { + element: Trusted::new(self), + url, + key, + old_value, + new_value, + }, + global.upcast(), + ).unwrap(); + struct StorageEventRunnable { + element: Trusted, + url: ServoUrl, + key: Option, + old_value: Option, + new_value: Option + } + impl Runnable for StorageEventRunnable { + fn handler(self: Box) { + let this = *self; + let storage = this.element.root(); + let global = storage.global(); + let storage_event = StorageEvent::new( + global.as_window(), + atom!("storage"), + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + this.key.map(DOMString::from), + this.old_value.map(DOMString::from), + this.new_value.map(DOMString::from), + DOMString::from(this.url.into_string()), + Some(&storage) + ); + storage_event.upcast::().fire(global.upcast()); + } + } } } From 7ca52152a63615b38cecd9e149032bba712d3bc5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Sep 2017 01:25:51 +0200 Subject: [PATCH 02/37] Put the name of runnables in Debug for CommonScriptMsg --- components/script/script_runtime.rs | 4 +++- components/script/script_thread.rs | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 7236bc96ecc..d0473d2469c 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -50,7 +50,9 @@ impl fmt::Debug for CommonScriptMsg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CommonScriptMsg::CollectReports(_) => write!(f, "CollectReports(...)"), - CommonScriptMsg::RunnableMsg(category, _) => write!(f, "RunnableMsg({:?}, ...)", category), + CommonScriptMsg::RunnableMsg(ref category, ref runnable) => { + f.debug_tuple("RunnableMsg").field(category).field(runnable).finish() + }, } } } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index b2359c3ea94..c15531ff595 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -102,6 +102,7 @@ use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use std::cell::Cell; use std::collections::{hash_map, HashMap, HashSet}; use std::default::Default; +use std::fmt; use std::intrinsics; use std::ops::Deref; use std::option::Option; @@ -258,6 +259,12 @@ pub trait Runnable { fn main_thread_handler(self: Box, _script_thread: &ScriptThread) { self.handler(); } } +impl fmt::Debug for Runnable + Send { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple(self.name()).field(&format_args!("...")).finish() + } +} + #[derive(Debug)] enum MixedMessage { FromConstellation(ConstellationControlMsg), From 52a6f63608a25e0574fd43b69f404f79a9a6c28f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Sep 2017 01:55:26 +0200 Subject: [PATCH 03/37] Introduce MainThreadScriptMsg::MainThreadRunnable This will allow us to separate the types for tasks that must run on the main script thread and regular tasks. --- components/script/dom/workletglobalscope.rs | 10 ++++++---- components/script/script_thread.rs | 15 ++++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index 64a2b3199fb..25540139135 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -23,7 +23,6 @@ use net_traits::image_cache::ImageCache; use profile_traits::mem; use profile_traits::time; use script_layout_interface::message::Msg; -use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory; use script_thread::MainThreadScriptMsg; use script_thread::Runnable; @@ -100,9 +99,12 @@ impl WorkletGlobalScope { pub fn run_in_script_thread(&self, runnable: R) where R: 'static + Send + Runnable, { - let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable); - let msg = MainThreadScriptMsg::Common(msg); - self.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread."); + self.to_script_thread_sender + .send(MainThreadScriptMsg::MainThreadRunnable( + ScriptThreadEventCategory::WorkletEvent, + box runnable, + )) + .expect("Worklet thread outlived script thread."); } /// Send a message to layout. diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index c15531ff595..e1183368137 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -274,7 +274,7 @@ enum MixedMessage { FromScheduler(TimerEvent), } -/// Messages used to control the script event loop +/// Messages used to control the script event loop. #[derive(Debug)] pub enum MainThreadScriptMsg { /// Common variants associated with the script messages @@ -289,6 +289,8 @@ pub enum MainThreadScriptMsg { /// Notifies the script thread that a new worklet has been loaded, and thus the page should be /// reflowed. WorkletLoaded(PipelineId), + /// Runs a Runnable in the main thread. + MainThreadRunnable(ScriptThreadEventCategory, Box), } impl OpaqueSender for Box { @@ -1167,9 +1169,9 @@ impl ScriptThread { MixedMessage::FromImageCache(_) => ScriptThreadEventCategory::ImageCacheMsg, MixedMessage::FromScript(ref inner_msg) => { match *inner_msg { - MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(ref category, _)) => - *category, - _ => ScriptThreadEventCategory::ScriptEvent + MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(category, _)) | + MainThreadScriptMsg::MainThreadRunnable(category, _) => category, + _ => ScriptThreadEventCategory::ScriptEvent, } }, MixedMessage::FromScheduler(_) => ScriptThreadEventCategory::TimerEvent @@ -1299,7 +1301,7 @@ impl ScriptThread { self.handle_exit_window_msg(id) }, MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => { - runnable.main_thread_handler(self) + runnable.handler() } MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(chan)) => { self.collect_reports(chan) @@ -1307,6 +1309,9 @@ impl ScriptThread { MainThreadScriptMsg::WorkletLoaded(pipeline_id) => { self.handle_worklet_loaded(pipeline_id) }, + MainThreadScriptMsg::MainThreadRunnable(_, runnable) => { + runnable.main_thread_handler(self) + }, } } From 56117d31856be46d7df417e659a4406305b4e258 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Sep 2017 02:09:26 +0200 Subject: [PATCH 04/37] Rename Runnable to Task The changes are: * `*Runnable` -> `*Task`; * `RunnableMsg` -> `Task`; * `RunnableWrapper` -> `TaskCanceller`; * `MainThreadRunnable` -> `MainThreadTask`; * `wrap_runnable` -> `wrap_task`; * `get_runnable_wrapper` -> `task_canceller`; * `handler` -> `run`; * `main_thread_handler` -> `run_with_script_thread`. --- components/script/dom/bindings/refcounted.rs | 22 +++---- components/script/dom/bluetooth.rs | 15 +++-- .../script/dom/dedicatedworkerglobalscope.rs | 6 +- components/script/dom/document.rs | 10 +-- components/script/dom/element.rs | 10 +-- components/script/dom/event.rs | 14 ++--- components/script/dom/eventsource.rs | 44 ++++++------- components/script/dom/filereader.rs | 33 ++++++---- components/script/dom/globalscope.rs | 12 ++-- components/script/dom/htmldetailselement.rs | 12 ++-- components/script/dom/htmlformelement.rs | 10 +-- components/script/dom/htmliframeelement.rs | 6 +- components/script/dom/htmlimageelement.rs | 59 +++++++++--------- components/script/dom/htmlmediaelement.rs | 16 ++--- components/script/dom/htmlscriptelement.rs | 2 +- components/script/dom/serviceworker.rs | 6 +- components/script/dom/storage.rs | 10 +-- components/script/dom/vrdisplay.rs | 8 +-- components/script/dom/websocket.rs | 56 +++++++++-------- components/script/dom/window.rs | 18 +++--- components/script/dom/worker.rs | 14 ++--- components/script/dom/workerglobalscope.rs | 10 +-- components/script/dom/worklet.rs | 16 +++-- components/script/dom/workletglobalscope.rs | 23 ++++--- components/script/dom/xmlhttprequest.rs | 2 +- components/script/fetch.rs | 2 +- components/script/layout_image.rs | 2 +- components/script/network_listener.rs | 30 +++++---- components/script/script_runtime.rs | 8 +-- components/script/script_thread.rs | 61 ++++++++++--------- components/script/serviceworkerjob.rs | 10 +-- components/script/stylesheet_loader.rs | 2 +- .../script/task_source/dom_manipulation.rs | 24 +++----- components/script/task_source/file_reading.rs | 25 +++++--- components/script/task_source/mod.rs | 19 +++--- components/script/task_source/networking.rs | 30 ++++++--- .../task_source/performance_timeline.rs | 32 +++++----- .../script/task_source/user_interaction.rs | 23 +++---- 38 files changed, 370 insertions(+), 332 deletions(-) diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index 8acbe823e7c..b315416c48c 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -32,8 +32,7 @@ use dom::promise::Promise; use js::jsapi::JSAutoCompartment; use js::jsapi::JSTracer; use libc; -use script_thread::Runnable; -use script_thread::ScriptThread; +use script_thread::{ScriptThread, Task}; use std::cell::RefCell; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::HashMap; @@ -121,12 +120,12 @@ impl TrustedPromise { }) } - /// A runnable which will reject the promise. + /// A task which will reject the promise. #[allow(unrooted_must_root)] - pub fn reject_runnable(self, error: Error) -> impl Runnable + Send { + pub fn reject_task(self, error: Error) -> impl Send + Task { struct RejectPromise(TrustedPromise, Error); - impl Runnable for RejectPromise { - fn main_thread_handler(self: Box, script_thread: &ScriptThread) { + impl Task for RejectPromise { + fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { debug!("Rejecting promise."); let this = *self; let cx = script_thread.get_cx(); @@ -138,14 +137,15 @@ impl TrustedPromise { RejectPromise(self, error) } - /// A runnable which will resolve the promise. + /// A task which will resolve the promise. #[allow(unrooted_must_root)] - pub fn resolve_runnable(self, value: T) -> impl Runnable + Send where - T: ToJSValConvertible + Send + pub fn resolve_task(self, value: T) -> impl Send + Task + where + T: ToJSValConvertible + Send, { struct ResolvePromise(TrustedPromise, T); - impl Runnable for ResolvePromise { - fn main_thread_handler(self: Box, script_thread: &ScriptThread) { + impl Task for ResolvePromise { + fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { debug!("Resolving promise."); let this = *self; let cx = script_thread.get_cx(); diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index adac22b6063..35e6fdde3b1 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -35,7 +35,7 @@ use ipc_channel::router::ROUTER; use js::conversions::ConversionResult; use js::jsapi::{JSAutoCompartment, JSContext, JSObject}; use js::jsval::{ObjectValue, UndefinedValue}; -use script_thread::Runnable; +use script_thread::Task; use std::cell::Ref; use std::collections::HashMap; use std::rc::Rc; @@ -224,25 +224,28 @@ pub fn response_async( receiver: Trusted::new(receiver), })); ROUTER.add_route(action_receiver.to_opaque(), box move |message| { - struct ListenerRunnable { + struct ListenerTask { context: Arc>>, action: BluetoothResponseResult, } - impl Runnable for ListenerRunnable { - fn handler(self: Box) { + impl Task for ListenerTask + where + T: AsyncBluetoothListener + DomObject, + { + fn run(self: Box) { let this = *self; let mut context = this.context.lock().unwrap(); context.response(this.action); } } - let runnable = box ListenerRunnable { + let task = box ListenerTask { context: context.clone(), action: message.to().unwrap(), }; - let result = task_source.queue_wrapperless(runnable); + let result = task_source.queue_unconditionally(task); if let Err(err) = result { warn!("failed to deliver network data: {:?}", err); } diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index ce12696d94c..76c822e5679 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -190,7 +190,7 @@ impl DedicatedWorkerGlobalScope { &init.resource_threads.sender()) { Err(_) => { println!("error loading script {}", serialized_worker_url); - parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent, + parent_sender.send(CommonScriptMsg::Task(WorkerEvent, box SimpleWorkerErrorHandler::new(worker))).unwrap(); return; } @@ -352,7 +352,7 @@ impl DedicatedWorkerGlobalScope { let worker = self.worker.borrow().as_ref().unwrap().clone(); // TODO: Should use the DOM manipulation task source. self.parent_sender - .send(CommonScriptMsg::RunnableMsg(WorkerEvent, + .send(CommonScriptMsg::Task(WorkerEvent, box WorkerErrorHandler::new(worker, error_info))) .unwrap(); } @@ -376,7 +376,7 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope { let data = StructuredCloneData::write(cx, message)?; let worker = self.worker.borrow().as_ref().unwrap().clone(); self.parent_sender - .send(CommonScriptMsg::RunnableMsg(WorkerEvent, + .send(CommonScriptMsg::Task(WorkerEvent, box WorkerMessageHandler::new(worker, data))) .unwrap(); Ok(()) diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 5b44324780a..e0c5380cc59 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -113,7 +113,7 @@ use net_traits::response::HttpsState; use num_traits::ToPrimitive; use script_layout_interface::message::{Msg, ReflowQueryType}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptMsg, Runnable, ScriptThread}; +use script_thread::{MainThreadScriptMsg, ScriptThread, Task}; use script_traits::{AnimationState, CompositorEvent, DocumentActivity}; use script_traits::{MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{MsDuration, ScriptMsg, TouchpadPressurePhase}; @@ -2609,7 +2609,7 @@ impl Document { let trusted_pending = Trusted::new(pending); let trusted_promise = TrustedPromise::new(promise.clone()); let handler = ElementPerformFullscreenEnter::new(trusted_pending, trusted_promise, error); - let script_msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::EnterFullscreen, handler); + let script_msg = CommonScriptMsg::Task(ScriptThreadEventCategory::EnterFullscreen, handler); let msg = MainThreadScriptMsg::Common(script_msg); window.main_thread_script_chan().send(msg).unwrap(); @@ -2641,7 +2641,7 @@ impl Document { let trusted_element = Trusted::new(element.r()); let trusted_promise = TrustedPromise::new(promise.clone()); let handler = ElementPerformFullscreenExit::new(trusted_element, trusted_promise); - let script_msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::ExitFullscreen, handler); + let script_msg = CommonScriptMsg::Task(ScriptThreadEventCategory::ExitFullscreen, handler); let msg = MainThreadScriptMsg::Common(script_msg); window.main_thread_script_chan().send(msg).unwrap(); @@ -4016,8 +4016,8 @@ impl DocumentProgressHandler { } } -impl Runnable for DocumentProgressHandler { - fn handler(self: Box) { +impl Task for DocumentProgressHandler { + fn run(self: Box) { let document = self.addr.root(); let window = document.window(); if window.is_alive() { diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 60a237df618..f6322c65960 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -87,7 +87,7 @@ use js::jsval::JSVal; use net_traits::request::CorsSettings; use ref_filter_map::ref_filter_map; use script_layout_interface::message::ReflowQueryType; -use script_thread::{Runnable, ScriptThread}; +use script_thread::{ScriptThread, Task}; use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity}; use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode}; use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; @@ -3044,9 +3044,9 @@ impl ElementPerformFullscreenEnter { } } -impl Runnable for ElementPerformFullscreenEnter { +impl Task for ElementPerformFullscreenEnter { #[allow(unrooted_must_root)] - fn handler(self: Box) { + fn run(self: Box) { let element = self.element.root(); let document = document_from_node(element.r()); @@ -3097,9 +3097,9 @@ impl ElementPerformFullscreenExit { } } -impl Runnable for ElementPerformFullscreenExit { +impl Task for ElementPerformFullscreenExit { #[allow(unrooted_must_root)] - fn handler(self: Box) { + fn run(self: Box) { let element = self.element.root(); let document = document_from_node(element.r()); // TODO Step 9.1-5 diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 19cd8c48a24..fb6bf9c3b61 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -20,7 +20,7 @@ use dom::node::Node; use dom::virtualmethods::vtable_for; use dom::window::Window; use dom_struct::dom_struct; -use script_thread::Runnable; +use script_thread::Task; use servo_atoms::Atom; use std::cell::Cell; use std::default::Default; @@ -381,15 +381,15 @@ pub enum EventStatus { } // https://dom.spec.whatwg.org/#concept-event-fire -pub struct EventRunnable { +pub struct EventTask { pub target: Trusted, pub name: Atom, pub bubbles: EventBubbles, pub cancelable: EventCancelable, } -impl Runnable for EventRunnable { - fn handler(self: Box) { +impl Task for EventTask { + fn run(self: Box) { let target = self.target.root(); let bubbles = self.bubbles; let cancelable = self.cancelable; @@ -398,13 +398,13 @@ impl Runnable for EventRunnable { } // https://html.spec.whatwg.org/multipage/#fire-a-simple-event -pub struct SimpleEventRunnable { +pub struct SimpleEventTask { pub target: Trusted, pub name: Atom, } -impl Runnable for SimpleEventRunnable { - fn handler(self: Box) { +impl Task for SimpleEventTask { + fn run(self: Box) { let target = self.target.root(); target.fire_event(self.name); } diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 20f01b39c85..2bd5f32261e 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -27,7 +27,7 @@ use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseMsg, FetchResponse use net_traits::request::{CacheMode, CorsSettings, CredentialsMode}; use net_traits::request::{RequestInit, RequestMode}; use network_listener::{NetworkListener, PreInvoke}; -use script_thread::Runnable; +use script_thread::Task; use servo_atoms::Atom; use servo_url::ServoUrl; use std::cell::Cell; @@ -96,10 +96,10 @@ impl EventSourceContext { if self.gen_id != event_source.generation_id.get() { return; } - let runnable = box AnnounceConnectionRunnable { + let task = box AnnounceConnectionTask { event_source: self.event_source.clone() }; - let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global()); + let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); } fn fail_the_connection(&self) { @@ -107,10 +107,10 @@ impl EventSourceContext { if self.gen_id != event_source.generation_id.get() { return; } - let runnable = box FailConnectionRunnable { + let task = box FailConnectionTask { event_source: self.event_source.clone() }; - let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global()); + let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); } // https://html.spec.whatwg.org/multipage/#reestablish-the-connection @@ -122,11 +122,11 @@ impl EventSourceContext { } // Step 1 - let runnable = box ReestablishConnectionRunnable { + let task = box ReestablishConnectionTask { event_source: self.event_source.clone(), action_sender: self.action_sender.clone() }; - let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global()); + let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); } // https://html.spec.whatwg.org/multipage/#processField @@ -186,11 +186,11 @@ impl EventSourceContext { self.event_type.clear(); self.data.clear(); // Step 8 - let runnable = box DispatchEventRunnable { + let task = box DispatchEventTask { event_source: self.event_source.clone(), event: Trusted::new(&event) }; - let _ = event_source.global().networking_task_source().queue(runnable, &*event_source.global()); + let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); } // https://html.spec.whatwg.org/multipage/#event-stream-interpretation @@ -425,7 +425,7 @@ impl EventSource { let listener = NetworkListener { context: Arc::new(Mutex::new(context)), task_source: global.networking_task_source(), - wrapper: Some(global.get_runnable_wrapper()) + canceller: Some(global.task_canceller()) }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { listener.notify_fetch(message.to().unwrap()); @@ -469,13 +469,13 @@ impl EventSourceMethods for EventSource { } } -pub struct AnnounceConnectionRunnable { +pub struct AnnounceConnectionTask { event_source: Trusted, } -impl Runnable for AnnounceConnectionRunnable { +impl Task for AnnounceConnectionTask { // https://html.spec.whatwg.org/multipage/#announce-the-connection - fn handler(self: Box) { + fn run(self: Box) { let event_source = self.event_source.root(); if event_source.ready_state.get() != ReadyState::Closed { event_source.ready_state.set(ReadyState::Open); @@ -484,13 +484,13 @@ impl Runnable for AnnounceConnectionRunnable { } } -pub struct FailConnectionRunnable { +pub struct FailConnectionTask { event_source: Trusted, } -impl Runnable for FailConnectionRunnable { +impl Task for FailConnectionTask { // https://html.spec.whatwg.org/multipage/#fail-the-connection - fn handler(self: Box) { + fn run(self: Box) { let event_source = self.event_source.root(); if event_source.ready_state.get() != ReadyState::Closed { event_source.ready_state.set(ReadyState::Closed); @@ -499,14 +499,14 @@ impl Runnable for FailConnectionRunnable { } } -pub struct ReestablishConnectionRunnable { +pub struct ReestablishConnectionTask { event_source: Trusted, action_sender: ipc::IpcSender, } -impl Runnable for ReestablishConnectionRunnable { +impl Task for ReestablishConnectionTask { // https://html.spec.whatwg.org/multipage/#reestablish-the-connection - fn handler(self: Box) { + fn run(self: Box) { let event_source = self.event_source.root(); // Step 1.1 if event_source.ready_state.get() == ReadyState::Closed { @@ -556,14 +556,14 @@ impl EventSourceTimeoutCallback { } } -pub struct DispatchEventRunnable { +pub struct DispatchEventTask { event_source: Trusted, event: Trusted, } -impl Runnable for DispatchEventRunnable { +impl Task for DispatchEventTask { // https://html.spec.whatwg.org/multipage/#dispatchMessage - fn handler(self: Box) { + fn run(self: Box) { let event_source = self.event_source.root(); // Step 8 if event_source.ready_state.get() != ReadyState::Closed { diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index 4b903e654e5..91f16559bd5 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -29,7 +29,7 @@ use js::jsapi::JSAutoCompartment; use js::jsapi::JSContext; use js::jsval::{self, JSVal}; use js::typedarray::{ArrayBuffer, CreateWith}; -use script_thread::RunnableWrapper; +use script_thread::TaskCanceller; use servo_atoms::Atom; use std::cell::Cell; use std::ptr; @@ -383,11 +383,18 @@ impl FileReader { let gen_id = self.generation_id.get(); let global = self.global(); - let wrapper = global.get_runnable_wrapper(); + let canceller = global.task_canceller(); let task_source = global.file_reading_task_source(); thread::Builder::new().name("file reader async operation".to_owned()).spawn(move || { - perform_annotated_read_operation(gen_id, load_data, blob_contents, fr, task_source, wrapper) + perform_annotated_read_operation( + gen_id, + load_data, + blob_contents, + fr, + task_source, + canceller, + ) }).expect("Thread spawning failed"); Ok(()) @@ -399,19 +406,21 @@ impl FileReader { } // https://w3c.github.io/FileAPI/#thread-read-operation -fn perform_annotated_read_operation(gen_id: GenerationId, - data: ReadMetaData, - blob_contents: Arc>, - filereader: TrustedFileReader, - task_source: FileReadingTaskSource, - wrapper: RunnableWrapper) { +fn perform_annotated_read_operation( + gen_id: GenerationId, + data: ReadMetaData, + blob_contents: Arc>, + filereader: TrustedFileReader, + task_source: FileReadingTaskSource, + canceller: TaskCanceller, +) { // Step 4 let task = FileReadingRunnable::new(FileReadingTask::ProcessRead(filereader.clone(), gen_id)); - task_source.queue_with_wrapper(task, &wrapper).unwrap(); + task_source.queue_with_canceller(task, &canceller).unwrap(); let task = FileReadingRunnable::new(FileReadingTask::ProcessReadData(filereader.clone(), gen_id)); - task_source.queue_with_wrapper(task, &wrapper).unwrap(); + task_source.queue_with_canceller(task, &canceller).unwrap(); let task = FileReadingRunnable::new(FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents)); - task_source.queue_with_wrapper(task, &wrapper).unwrap(); + task_source.queue_with_canceller(task, &canceller).unwrap(); } diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 681953defdd..e661e315ea4 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -38,7 +38,7 @@ use msg::constellation_msg::PipelineId; use net_traits::{CoreResourceThread, ResourceThreads, IpcSend}; use profile_traits::{mem, time}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; -use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread}; +use script_thread::{MainThreadScriptChan, ScriptThread, TaskCanceller}; use script_traits::{MsDuration, ScriptToConstellationChan, TimerEvent}; use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource}; use servo_url::{MutableOrigin, ServoUrl}; @@ -477,14 +477,14 @@ impl GlobalScope { unreachable!(); } - /// Returns a wrapper for runnables to ensure they are cancelled if - /// the global scope is being destroyed. - pub fn get_runnable_wrapper(&self) -> RunnableWrapper { + /// Returns the task canceller of this global to ensure that everything is + /// properly cancelled when the global scope is destroyed. + pub fn task_canceller(&self) -> TaskCanceller { if let Some(window) = self.downcast::() { - return window.get_runnable_wrapper(); + return window.task_canceller(); } if let Some(worker) = self.downcast::() { - return worker.get_runnable_wrapper(); + return worker.task_canceller(); } unreachable!(); } diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 4e99b6ff7af..4f4087b4c38 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -16,7 +16,7 @@ use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; -use script_thread::Runnable; +use script_thread::Task; use std::cell::Cell; use task_source::TaskSource; @@ -74,22 +74,22 @@ impl VirtualMethods for HTMLDetailsElement { let window = window_from_node(self); let task_source = window.dom_manipulation_task_source(); let details = Trusted::new(self); - let runnable = box DetailsNotificationRunnable { + let task = box DetailsNotificationTask { element: details, toggle_number: counter }; - let _ = task_source.queue(runnable, window.upcast()); + let _ = task_source.queue(task, window.upcast()); } } } -pub struct DetailsNotificationRunnable { +pub struct DetailsNotificationTask { element: Trusted, toggle_number: u32 } -impl Runnable for DetailsNotificationRunnable { - fn handler(self: Box) { +impl Task for DetailsNotificationTask { + fn run(self: Box) { let target = self.element.root(); if target.check_toggle_count(self.toggle_number) { target.upcast::().fire_event(atom!("toggle")); diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 34ce7c25ec1..43771b17890 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -49,7 +49,7 @@ use html5ever::{LocalName, Prefix}; use hyper::header::{Charset, ContentDisposition, ContentType, DispositionParam, DispositionType}; use hyper::method::Method; use msg::constellation_msg::PipelineId; -use script_thread::{MainThreadScriptMsg, Runnable}; +use script_thread::{MainThreadScriptMsg, Task}; use script_traits::LoadData; use servo_rand::random; use std::borrow::ToOwned; @@ -432,8 +432,8 @@ impl HTMLFormElement { let window = window_from_node(self); // Step 1 - // Each planned navigation runnable is tagged with a generation ID, and - // before the runnable is handled, it first checks whether the HTMLFormElement's + // Each planned navigation task is tagged with a generation ID, and + // before the task is handled, it first checks whether the HTMLFormElement's // generation ID is the same as its own generation ID. let GenerationId(prev_id) = self.generation_id.get(); self.generation_id.set(GenerationId(prev_id + 1)); @@ -1115,8 +1115,8 @@ struct PlannedNavigation { form: Trusted } -impl Runnable for PlannedNavigation { - fn handler(self: Box) { +impl Task for PlannedNavigation { + fn run(self: Box) { if self.generation_id == self.form.root().generation_id.get() { let script_chan = self.script_chan.clone(); script_chan.send(MainThreadScriptMsg::Navigate(self.pipeline_id, self.load_data, false)).unwrap(); diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index c0b57f1dd02..fa6639ad422 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -43,7 +43,7 @@ use js::jsval::{NullValue, UndefinedValue}; use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TopLevelBrowsingContextId, TraversalDirection}; use net_traits::response::HttpsState; use script_layout_interface::message::ReflowQueryType; -use script_thread::{ScriptThread, Runnable}; +use script_thread::{ScriptThread, Task}; use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason}; use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg}; use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed}; @@ -849,8 +849,8 @@ impl IFrameLoadEventSteps { } } -impl Runnable for IFrameLoadEventSteps { - fn handler(self: Box) { +impl Task for IFrameLoadEventSteps { + fn run(self: Box) { let this = self.frame_element.root(); this.iframe_load_event_steps(self.pipeline_id); } diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 0410863dc7d..23348c9d263 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -48,7 +48,7 @@ use net_traits::image_cache::UsePlaceholder; use net_traits::request::{RequestInit, Type as RequestType}; use network_listener::{NetworkListener, PreInvoke}; use num_traits::ToPrimitive; -use script_thread::{Runnable, ScriptThread}; +use script_thread::{ScriptThread, Task}; use servo_url::ServoUrl; use servo_url::origin::ImmutableOrigin; use std::cell::{Cell, RefMut}; @@ -99,16 +99,16 @@ impl HTMLImageElement { } } -struct ImageResponseHandlerRunnable { +struct ImageResponseHandlerTask { element: Trusted, image: ImageResponse, generation: u32, } -impl ImageResponseHandlerRunnable { +impl ImageResponseHandlerTask { fn new(element: Trusted, image: ImageResponse, generation: u32) - -> ImageResponseHandlerRunnable { - ImageResponseHandlerRunnable { + -> ImageResponseHandlerTask { + ImageResponseHandlerTask { element: element, image: image, generation: generation, @@ -116,8 +116,8 @@ impl ImageResponseHandlerRunnable { } } -impl Runnable for ImageResponseHandlerRunnable { - fn handler(self: Box) { +impl Task for ImageResponseHandlerTask { + fn run(self: Box) { let element = self.element.root(); // Ignore any image response for a previous request that has been discarded. if element.generation.get() == self.generation { @@ -191,15 +191,18 @@ impl HTMLImageElement { let window = window_from_node(elem); let task_source = window.networking_task_source(); - let wrapper = window.get_runnable_wrapper(); + let wrapper = window.task_canceller(); let generation = elem.generation.get(); ROUTER.add_route(responder_receiver.to_opaque(), box move |message| { debug!("Got image {:?}", message); // Return the image via a message to the script thread, which marks // the element as dirty and triggers a reflow. - let runnable = ImageResponseHandlerRunnable::new( - trusted_node.clone(), message.to().unwrap(), generation); - let _ = task_source.queue_with_wrapper(box runnable, &wrapper); + let task = ImageResponseHandlerTask::new( + trusted_node.clone(), + message.to().unwrap(), + generation, + ); + let _ = task_source.queue_with_canceller(box task, &wrapper); }); image_cache.add_listener(id, ImageResponder::new(responder_sender, id)); @@ -249,7 +252,7 @@ impl HTMLImageElement { let listener = NetworkListener { context: context, task_source: window.networking_task_source(), - wrapper: Some(window.get_runnable_wrapper()), + canceller: Some(window.task_canceller()), }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { listener.notify_fetch(message.to().unwrap()); @@ -354,12 +357,12 @@ impl HTMLImageElement { /// Step 11.4 of https://html.spec.whatwg.org/multipage/#update-the-image-data fn set_current_request_url_to_selected_fire_error_and_loadend(&self, src: DOMString) { - struct Task { + struct SetCurrentRequestUrlTask { img: Trusted, src: String, } - impl Runnable for Task { - fn handler(self: Box) { + impl Task for SetCurrentRequestUrlTask { + fn run(self: Box) { let img = self.img.root(); { let mut current_request = img.current_request.borrow_mut(); @@ -372,7 +375,7 @@ impl HTMLImageElement { } } - let task = box Task { + let task = box SetCurrentRequestUrlTask { img: Trusted::new(self), src: src.into() }; @@ -387,21 +390,21 @@ impl HTMLImageElement { struct FireprogressEventTask { img: Trusted, } - impl Runnable for FireprogressEventTask { - fn handler(self: Box) { + impl Task for FireprogressEventTask { + fn run(self: Box) { let progressevent = ProgressEvent::new(&self.img.root().global(), atom!("loadstart"), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, false, 0, 0); progressevent.upcast::().fire(self.img.root().upcast()); } } - let runnable = box FireprogressEventTask { + let task = box FireprogressEventTask { img: Trusted::new(self), }; let document = document_from_node(self); let window = document.window(); - let task = window.dom_manipulation_task_source(); - let _ = task.queue(runnable, window.upcast()); + let task_source = window.dom_manipulation_task_source(); + let _ = task_source.queue(task, window.upcast()); } /// https://html.spec.whatwg.org/multipage/#update-the-source-set @@ -426,8 +429,8 @@ impl HTMLImageElement { struct SetUrlToNoneTask { img: Trusted, } - impl Runnable for SetUrlToNoneTask { - fn handler(self: Box) { + impl Task for SetUrlToNoneTask { + fn run(self: Box) { let img = self.img.root(); { let mut current_request = img.current_request.borrow_mut(); @@ -459,8 +462,8 @@ impl HTMLImageElement { src: String, url: ServoUrl } - impl Runnable for SetUrlToStringTask { - fn handler(self: Box) { + impl Task for SetUrlToStringTask { + fn run(self: Box) { let img = self.img.root(); { let mut current_request = img.current_request.borrow_mut(); @@ -471,15 +474,15 @@ impl HTMLImageElement { img.upcast::().fire_event(atom!("load")); } } - let runnable = box SetUrlToStringTask { + let task = box SetUrlToStringTask { img: Trusted::new(self), src: src.into(), url: url }; let document = document_from_node(self); let window = document.window(); - let task = window.dom_manipulation_task_source(); - let _ = task.queue(runnable, window.upcast()); + let task_source = window.dom_manipulation_task_source(); + let _ = task_source.queue(task, window.upcast()); } fn init_image_request(&self, diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index bb70b39ddc7..0f4549b0809 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -35,7 +35,7 @@ use microtask::{Microtask, MicrotaskRunnable}; use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError}; use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType}; use network_listener::{NetworkListener, PreInvoke}; -use script_thread::{Runnable, ScriptThread}; +use script_thread::{ScriptThread, Task}; use servo_url::ServoUrl; use std::cell::Cell; use std::sync::{Arc, Mutex}; @@ -145,8 +145,8 @@ impl HTMLMediaElement { window.upcast(), ); struct InternalPauseStepsTask(Trusted); - impl Runnable for InternalPauseStepsTask { - fn handler(self: Box) { + impl Task for InternalPauseStepsTask { + fn run(self: Box) { let target = self.0.root(); // Step 2.3.1. @@ -180,8 +180,8 @@ impl HTMLMediaElement { window.upcast(), ); struct NotifyAboutPlayingTask(Trusted); - impl Runnable for NotifyAboutPlayingTask { - fn handler(self: Box) { + impl Task for NotifyAboutPlayingTask { + fn run(self: Box) { let target = self.0.root(); // Step 2.1. @@ -428,7 +428,7 @@ impl HTMLMediaElement { let listener = NetworkListener { context: context, task_source: window.networking_task_source(), - wrapper: Some(window.get_runnable_wrapper()) + canceller: Some(window.task_canceller()) }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { @@ -750,8 +750,8 @@ impl DedicatedMediaSourceFailureTask { } } -impl Runnable for DedicatedMediaSourceFailureTask { - fn handler(self: Box) { +impl Task for DedicatedMediaSourceFailureTask { + fn run(self: Box) { self.elem.root().dedicated_media_source_failure(); } } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index ea0cc4c25e8..a9a7869e33e 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -277,7 +277,7 @@ fn fetch_a_classic_script(script: &HTMLScriptElement, let listener = NetworkListener { context: context, task_source: doc.window().networking_task_source(), - wrapper: Some(doc.window().get_runnable_wrapper()) + canceller: Some(doc.window().task_canceller()) }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs index 668a5b98bab..add6279e0a0 100644 --- a/components/script/dom/serviceworker.rs +++ b/components/script/dom/serviceworker.rs @@ -16,7 +16,7 @@ use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom_struct::dom_struct; use js::jsapi::{HandleValue, JSContext}; -use script_thread::Runnable; +use script_thread::Task; use script_traits::{ScriptMsg, DOMMessage}; use servo_url::ServoUrl; use std::cell::Cell; @@ -104,9 +104,9 @@ impl ServiceWorkerMethods for ServiceWorker { event_handler!(statechange, GetOnstatechange, SetOnstatechange); } -impl Runnable for SimpleWorkerErrorHandler { +impl Task for SimpleWorkerErrorHandler { #[allow(unrooted_must_root)] - fn handler(self: Box>) { + fn run(self: Box) { let this = *self; ServiceWorker::dispatch_simple_error(this.addr); } diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index 1f7cba224f6..65c21bc6706 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -17,7 +17,7 @@ use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcSender}; use net_traits::IpcSend; use net_traits::storage_thread::{StorageThreadMsg, StorageType}; -use script_thread::Runnable; +use script_thread::Task; use script_traits::ScriptMsg; use servo_url::ServoUrl; use task_source::TaskSource; @@ -167,7 +167,7 @@ impl Storage { ) { let global = self.global(); global.as_window().dom_manipulation_task_source().queue( - box StorageEventRunnable { + box StorageEventTask { element: Trusted::new(self), url, key, @@ -176,15 +176,15 @@ impl Storage { }, global.upcast(), ).unwrap(); - struct StorageEventRunnable { + struct StorageEventTask { element: Trusted, url: ServoUrl, key: Option, old_value: Option, new_value: Option } - impl Runnable for StorageEventRunnable { - fn handler(self: Box) { + impl Task for StorageEventTask { + fn run(self: Box) { let this = *self; let storage = this.element.root(); let global = storage.global(); diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 83f43253fb6..9bc40bd5a82 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -36,7 +36,7 @@ use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::JSContext; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebVREvent; -use script_thread::Runnable; +use script_thread::Task; use std::cell::Cell; use std::mem; use std::rc::Rc; @@ -515,7 +515,7 @@ impl VRDisplay { address: address.clone(), sender: raf_sender.clone() }; - js_sender.send(CommonScriptMsg::RunnableMsg(WebVREvent, msg)).unwrap(); + js_sender.send(CommonScriptMsg::Task(WebVREvent, msg)).unwrap(); // Run Sync Poses in parallell on Render thread let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone()); @@ -613,8 +613,8 @@ struct NotifyDisplayRAF { sender: mpsc::Sender> } -impl Runnable for NotifyDisplayRAF { - fn handler(self: Box) { +impl Task for NotifyDisplayRAF { + fn run(self: Box) { let display = self.address.root(); display.handle_raf(&self.sender); } diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index f9ca15fe3c1..a390381b924 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -31,7 +31,7 @@ use net_traits::CoreResourceMsg::WebsocketConnect; use net_traits::MessageData; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebSocketEvent; -use script_thread::{Runnable, RunnableWrapper}; +use script_thread::{Task, TaskCanceller}; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -67,30 +67,34 @@ mod close_code { pub const TLS_FAILED: u16 = 1015; } -pub fn close_the_websocket_connection(address: Trusted, - task_source: &NetworkingTaskSource, - wrapper: &RunnableWrapper, - code: Option, - reason: String) { +pub fn close_the_websocket_connection( + address: Trusted, + task_source: &NetworkingTaskSource, + canceller: &TaskCanceller, + code: Option, + reason: String, +) { let close_task = box CloseTask { address: address, failed: false, code: code, reason: Some(reason), }; - task_source.queue_with_wrapper(close_task, &wrapper).unwrap(); + task_source.queue_with_canceller(close_task, &canceller).unwrap(); } -pub fn fail_the_websocket_connection(address: Trusted, - task_source: &NetworkingTaskSource, - wrapper: &RunnableWrapper) { +pub fn fail_the_websocket_connection( + address: Trusted, + task_source: &NetworkingTaskSource, + canceller: &TaskCanceller, +) { let close_task = box CloseTask { address: address, failed: true, code: Some(close_code::ABNORMAL), reason: None, }; - task_source.queue_with_wrapper(close_task, &wrapper).unwrap(); + task_source.queue_with_canceller(close_task, &canceller).unwrap(); } #[dom_struct] @@ -197,7 +201,7 @@ impl WebSocket { *ws.sender.borrow_mut() = Some(dom_action_sender); let task_source = global.networking_task_source(); - let wrapper = global.get_runnable_wrapper(); + let canceller = global.task_canceller(); thread::spawn(move || { while let Ok(event) = dom_event_receiver.recv() { match event { @@ -206,22 +210,22 @@ impl WebSocket { address: address.clone(), protocol_in_use, }; - task_source.queue_with_wrapper(open_thread, &wrapper).unwrap(); + task_source.queue_with_canceller(open_thread, &canceller).unwrap(); }, WebSocketNetworkEvent::MessageReceived(message) => { let message_thread = box MessageReceivedTask { address: address.clone(), message: message, }; - task_source.queue_with_wrapper(message_thread, &wrapper).unwrap(); + task_source.queue_with_canceller(message_thread, &canceller).unwrap(); }, WebSocketNetworkEvent::Fail => { fail_the_websocket_connection(address.clone(), - &task_source, &wrapper); + &task_source, &canceller); }, WebSocketNetworkEvent::Close(code, reason) => { close_the_websocket_connection(address.clone(), - &task_source, &wrapper, code, reason); + &task_source, &canceller, code, reason); }, } } @@ -261,7 +265,7 @@ impl WebSocket { self.global() .script_chan() - .send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)) + .send(CommonScriptMsg::Task(WebSocketEvent, task)) .unwrap(); } @@ -368,7 +372,7 @@ impl WebSocketMethods for WebSocket { let address = Trusted::new(self); let task_source = self.global().networking_task_source(); - fail_the_websocket_connection(address, &task_source, &self.global().get_runnable_wrapper()); + fail_the_websocket_connection(address, &task_source, &self.global().task_canceller()); } WebSocketRequestState::Open => { self.ready_state.set(WebSocketRequestState::Closing); @@ -393,9 +397,9 @@ struct ConnectionEstablishedTask { protocol_in_use: Option, } -impl Runnable for ConnectionEstablishedTask { +impl Task for ConnectionEstablishedTask { /// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established - fn handler(self: Box) { + fn run(self: Box) { let ws = self.address.root(); // Step 1. @@ -418,13 +422,13 @@ struct BufferedAmountTask { address: Trusted, } -impl Runnable for BufferedAmountTask { +impl Task for BufferedAmountTask { // See https://html.spec.whatwg.org/multipage/#dom-websocket-bufferedamount // // To be compliant with standards, we need to reset bufferedAmount only when the event loop // reaches step 1. In our implementation, the bytes will already have been sent on a background // thread. - fn handler(self: Box) { + fn run(self: Box) { let ws = self.address.root(); ws.buffered_amount.set(0); @@ -439,8 +443,8 @@ struct CloseTask { reason: Option, } -impl Runnable for CloseTask { - fn handler(self: Box) { +impl Task for CloseTask { + fn run(self: Box) { let ws = self.address.root(); if ws.ready_state.get() == WebSocketRequestState::Closed { @@ -479,9 +483,9 @@ struct MessageReceivedTask { message: MessageData, } -impl Runnable for MessageReceivedTask { +impl Task for MessageReceivedTask { #[allow(unsafe_code)] - fn handler(self: Box) { + fn run(self: Box) { let ws = self.address.root(); debug!("MessageReceivedTask::handler({:p}): readyState={:?}", &*ws, ws.ready_state.get()); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 51d58eb77dc..3b555ca7c4c 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -76,8 +76,8 @@ use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, Lay use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse}; use script_layout_interface::rpc::{ResolvedStyleResponse, TextIndexResponse}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory}; -use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Runnable}; -use script_thread::{RunnableWrapper, ScriptThread, SendableMainThreadScriptChan}; +use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Task}; +use script_thread::{ScriptThread, SendableMainThreadScriptChan, TaskCanceller}; use script_traits::{ConstellationControlMsg, DocumentState, LoadData, MozBrowserEvent}; use script_traits::{ScriptToConstellationChan, ScriptMsg, ScrollState, TimerEvent, TimerEventId}; use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType}; @@ -1038,8 +1038,8 @@ impl WindowMethods for Window { } impl Window { - pub fn get_runnable_wrapper(&self) -> RunnableWrapper { - RunnableWrapper { + pub fn task_canceller(&self) -> TaskCanceller { + TaskCanceller { cancelled: Some(self.ignore_further_async_events.borrow().clone()), } } @@ -1986,9 +1986,9 @@ impl PostMessageHandler { } } -impl Runnable for PostMessageHandler { +impl Task for PostMessageHandler { // https://html.spec.whatwg.org/multipage/#dom-window-postmessage steps 10-12. - fn handler(self: Box) { + fn run(self: Box) { let this = *self; let window = this.destination.root(); @@ -2017,9 +2017,9 @@ impl Runnable for PostMessageHandler { impl Window { pub fn post_message(&self, origin: Option, data: StructuredCloneData) { - let runnable = PostMessageHandler::new(self, origin, data); - let runnable = self.get_runnable_wrapper().wrap_runnable(box runnable); - let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::DomEvent, runnable); + let task = PostMessageHandler::new(self, origin, data); + let task = self.task_canceller().wrap_task(box task); + let msg = CommonScriptMsg::Task(ScriptThreadEventCategory::DomEvent, task); // TODO(#12718): Use the "posted message task source". let _ = self.script_chan.send(msg); } diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 6bbf0736e73..498cae4b0f4 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -25,7 +25,7 @@ use dom_struct::dom_struct; use ipc_channel::ipc; use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, NullHandleValue}; use js::jsval::UndefinedValue; -use script_thread::Runnable; +use script_thread::Task; use script_traits::WorkerScriptLoadOrigin; use std::cell::Cell; use std::sync::{Arc, Mutex}; @@ -212,16 +212,16 @@ impl WorkerMessageHandler { } } -impl Runnable for WorkerMessageHandler { - fn handler(self: Box) { +impl Task for WorkerMessageHandler { + fn run(self: Box) { let this = *self; Worker::handle_message(this.addr, this.data); } } -impl Runnable for SimpleWorkerErrorHandler { +impl Task for SimpleWorkerErrorHandler { #[allow(unrooted_must_root)] - fn handler(self: Box>) { + fn run(self: Box) { let this = *self; Worker::dispatch_simple_error(this.addr); } @@ -241,8 +241,8 @@ impl WorkerErrorHandler { } } -impl Runnable for WorkerErrorHandler { - fn handler(self: Box) { +impl Task for WorkerErrorHandler { + fn run(self: Box) { let this = *self; this.address.root().dispatch_error(this.error_info); } diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index f3e98f0de47..c26fcc63fdb 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -33,7 +33,7 @@ use js::rust::Runtime; use net_traits::{IpcSend, load_whole_resource}; use net_traits::request::{CredentialsMode, Destination, RequestInit as NetRequestInit, Type as RequestType}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, get_reports}; -use script_thread::RunnableWrapper; +use script_thread::TaskCanceller; use script_traits::{TimerEvent, TimerEventId}; use script_traits::WorkerGlobalScopeInit; use servo_url::{MutableOrigin, ServoUrl}; @@ -161,8 +161,8 @@ impl WorkerGlobalScope { self.worker_id.clone() } - pub fn get_runnable_wrapper(&self) -> RunnableWrapper { - RunnableWrapper { + pub fn task_canceller(&self) -> TaskCanceller { + TaskCanceller { cancelled: self.closing.clone(), } } @@ -387,8 +387,8 @@ impl WorkerGlobalScope { pub fn process_event(&self, msg: CommonScriptMsg) { match msg { - CommonScriptMsg::RunnableMsg(_, runnable) => { - runnable.handler() + CommonScriptMsg::Task(_, task) => { + task.run() }, CommonScriptMsg::CollectReports(reports_chan) => { let cx = self.get_cx(); diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index 9783dfc14a5..9bfec3c78cb 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -51,9 +51,7 @@ use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory; use script_runtime::StackRootTLS; use script_runtime::new_rt_and_cx; -use script_thread::MainThreadScriptMsg; -use script_thread::Runnable; -use script_thread::ScriptThread; +use script_thread::{MainThreadScriptMsg, ScriptThread, Task}; use servo_rand; use servo_url::ImmutableOrigin; use servo_url::ServoUrl; @@ -600,7 +598,7 @@ impl WorkletThread { debug!("Failed to load script."); let old_counter = pending_tasks_struct.set_counter_to(-1); if old_counter > 0 { - self.run_in_script_thread(promise.reject_runnable(Error::Abort)); + self.run_in_script_thread(promise.reject_task(Error::Abort)); } } else { // Step 5. @@ -610,7 +608,7 @@ impl WorkletThread { debug!("Resolving promise."); let msg = MainThreadScriptMsg::WorkletLoaded(pipeline_id); self.global_init.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread."); - self.run_in_script_thread(promise.resolve_runnable(())); + self.run_in_script_thread(promise.resolve_task(())); } } } @@ -645,11 +643,11 @@ impl WorkletThread { } } - /// Run a runnable in the main script thread. - fn run_in_script_thread(&self, runnable: R) where - R: 'static + Send + Runnable, + /// Run a task in the main script thread. + fn run_in_script_thread(&self, task: T) where + T: 'static + Send + Task, { - let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable); + let msg = CommonScriptMsg::Task(ScriptThreadEventCategory::WorkletEvent, box task); let msg = MainThreadScriptMsg::Common(msg); self.global_init.to_script_thread_sender.send(msg).expect("Worklet thread outlived script thread."); } diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index 25540139135..f603547bb19 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -24,9 +24,7 @@ use profile_traits::mem; use profile_traits::time; use script_layout_interface::message::Msg; use script_runtime::ScriptThreadEventCategory; -use script_thread::MainThreadScriptMsg; -use script_thread::Runnable; -use script_thread::ScriptThread; +use script_thread::{MainThreadScriptMsg, ScriptThread, Task}; use script_traits::ScriptMsg; use script_traits::ScriptToConstellationChan; use script_traits::TimerSchedulerMsg; @@ -95,28 +93,29 @@ impl WorkletGlobalScope { self.globalscope.evaluate_js_on_global_with_result(&*script, rval.handle_mut()) } - /// Run a runnable in the main script thread. - pub fn run_in_script_thread(&self, runnable: R) where - R: 'static + Send + Runnable, + /// Run a task in the main script thread. + pub fn run_in_script_thread(&self, task: T) + where + T: 'static + Send + Task, { self.to_script_thread_sender - .send(MainThreadScriptMsg::MainThreadRunnable( + .send(MainThreadScriptMsg::MainThreadTask( ScriptThreadEventCategory::WorkletEvent, - box runnable, + box task, )) .expect("Worklet thread outlived script thread."); } /// Send a message to layout. pub fn send_to_layout(&self, msg: Msg) { - struct RunnableMsg(PipelineId, Msg); - impl Runnable for RunnableMsg { - fn main_thread_handler(self: Box, script_thread: &ScriptThread) { + struct SendToLayoutTask(PipelineId, Msg); + impl Task for SendToLayoutTask { + fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { script_thread.send_to_layout(self.0, self.1); } } let pipeline_id = self.globalscope.pipeline_id(); - self.run_in_script_thread(RunnableMsg(pipeline_id, msg)); + self.run_in_script_thread(SendToLayoutTask(pipeline_id, msg)); } /// The base URL of this global. diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 7065d5ccd13..559c7ef31a6 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -261,7 +261,7 @@ impl XMLHttpRequest { let listener = NetworkListener { context: context, task_source: task_source, - wrapper: Some(global.get_runnable_wrapper()) + canceller: Some(global.task_canceller()) }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/fetch.rs b/components/script/fetch.rs index d7bd48f4873..3692288f341 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -102,7 +102,7 @@ pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: RootedTraceableBox< let listener = NetworkListener { context: fetch_context, task_source: global.networking_task_source(), - wrapper: Some(global.get_runnable_wrapper()) + canceller: Some(global.task_canceller()) }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { diff --git a/components/script/layout_image.rs b/components/script/layout_image.rs index 4af9bab013b..85f8c99a49a 100644 --- a/components/script/layout_image.rs +++ b/components/script/layout_image.rs @@ -62,7 +62,7 @@ pub fn fetch_image_for_layout(url: ServoUrl, let listener = NetworkListener { context: context, task_source: window.networking_task_source(), - wrapper: Some(window.get_runnable_wrapper()), + canceller: Some(window.task_canceller()), }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index fc7b4635756..aa167ecdfca 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -3,29 +3,29 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use net_traits::{Action, FetchResponseListener, FetchResponseMsg}; -use script_thread::{Runnable, RunnableWrapper}; +use script_thread::{Task, TaskCanceller}; use std::sync::{Arc, Mutex}; use task_source::TaskSource; use task_source::networking::NetworkingTaskSource; -/// An off-thread sink for async network event runnables. All such events are forwarded to +/// An off-thread sink for async network event tasks. All such events are forwarded to /// a target thread, where they are invoked on the provided context object. pub struct NetworkListener { pub context: Arc>, pub task_source: NetworkingTaskSource, - pub wrapper: Option, + pub canceller: Option, } impl NetworkListener { pub fn notify + Send + 'static>(&self, action: A) { - let runnable = box ListenerRunnable { + let task = box ListenerTask { context: self.context.clone(), action: action, }; - let result = if let Some(ref wrapper) = self.wrapper { - self.task_source.queue_with_wrapper(runnable, wrapper) + let result = if let Some(ref canceller) = self.canceller { + self.task_source.queue_with_canceller(task, canceller) } else { - self.task_source.queue_wrapperless(runnable) + self.task_source.queue_unconditionally(task) }; if let Err(err) = result { warn!("failed to deliver network data: {:?}", err); @@ -40,8 +40,8 @@ impl NetworkListen } } -/// A gating mechanism that runs before invoking the runnable on the target thread. -/// If the `should_invoke` method returns false, the runnable is discarded without +/// A gating mechanism that runs before invoking the task on the target thread. +/// If the `should_invoke` method returns false, the task is discarded without /// being invoked. pub trait PreInvoke { fn should_invoke(&self) -> bool { @@ -49,14 +49,18 @@ pub trait PreInvoke { } } -/// A runnable for moving the async network events between threads. -struct ListenerRunnable + Send + 'static, Listener: PreInvoke + Send> { +/// A task for moving the async network events between threads. +struct ListenerTask + Send + 'static, Listener: PreInvoke + Send> { context: Arc>, action: A, } -impl + Send + 'static, Listener: PreInvoke + Send> Runnable for ListenerRunnable { - fn handler(self: Box>) { +impl Task for ListenerTask +where + A: Action + Send + 'static, + Listener: PreInvoke + Send, +{ + fn run(self: Box) { let this = *self; let mut context = this.context.lock().unwrap(); if context.should_invoke() { diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index d0473d2469c..b12649668e5 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -23,7 +23,7 @@ use js::panic::wrap_panic; use js::rust::Runtime; use microtask::{EnqueuedPromiseCallback, Microtask}; use profile_traits::mem::{Report, ReportKind, ReportsChan}; -use script_thread::{Runnable, STACK_ROOTS, trace_thread}; +use script_thread::{STACK_ROOTS, Task, trace_thread}; use servo_config::opts; use servo_config::prefs::PREFS; use std::cell::Cell; @@ -43,15 +43,15 @@ pub enum CommonScriptMsg { /// supplied channel. CollectReports(ReportsChan), /// Generic message that encapsulates event handling. - RunnableMsg(ScriptThreadEventCategory, Box), + Task(ScriptThreadEventCategory, Box), } impl fmt::Debug for CommonScriptMsg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CommonScriptMsg::CollectReports(_) => write!(f, "CollectReports(...)"), - CommonScriptMsg::RunnableMsg(ref category, ref runnable) => { - f.debug_tuple("RunnableMsg").field(category).field(runnable).finish() + CommonScriptMsg::Task(ref category, ref task) => { + f.debug_tuple("Task").field(category).field(task).finish() }, } } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e1183368137..e6ace85b51a 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -203,29 +203,32 @@ impl InProgressLoad { } } -/// Encapsulated state required to create cancellable runnables from non-script threads. -pub struct RunnableWrapper { +/// Encapsulated state required to create cancellable tasks from non-script threads. +pub struct TaskCanceller { pub cancelled: Option>, } -impl RunnableWrapper { - pub fn wrap_runnable(&self, runnable: Box) -> Box { - box CancellableRunnable { +impl TaskCanceller { + pub fn wrap_task(&self, task: Box) -> Box + where + T: Send + Task + 'static, + { + box CancellableTask { cancelled: self.cancelled.clone(), - inner: runnable, + inner: task, } } } -/// A runnable that can be discarded by toggling a shared flag. -pub struct CancellableRunnable { +/// A task that can be discarded by toggling a shared flag. +pub struct CancellableTask { cancelled: Option>, inner: Box, } -impl CancellableRunnable +impl CancellableTask where - T: Runnable + Send, + T: Send + Task, { fn is_cancelled(&self) -> bool { self.cancelled.as_ref().map_or(false, |cancelled| { @@ -234,32 +237,34 @@ where } } -impl Runnable for CancellableRunnable +impl Task for CancellableTask where - T: Runnable + Send, + T: Send + Task, { - fn main_thread_handler(self: Box>, script_thread: &ScriptThread) { + fn run_with_script_thread(self: Box>, script_thread: &ScriptThread) { if !self.is_cancelled() { - self.inner.main_thread_handler(script_thread); + self.inner.run_with_script_thread(script_thread); } } - fn handler(self: Box>) { + fn run(self: Box) { if !self.is_cancelled() { - self.inner.handler() + self.inner.run() } } } -pub trait Runnable { +pub trait Task { fn name(&self) -> &'static str { unsafe { intrinsics::type_name::() } } - fn handler(self: Box) { + fn run(self: Box) { panic!("This should probably be redefined.") } - fn main_thread_handler(self: Box, _script_thread: &ScriptThread) { self.handler(); } + fn run_with_script_thread(self: Box, _script_thread: &ScriptThread) { + self.run(); + } } -impl fmt::Debug for Runnable + Send { +impl fmt::Debug for Task + Send { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_tuple(self.name()).field(&format_args!("...")).finish() } @@ -289,8 +294,8 @@ pub enum MainThreadScriptMsg { /// Notifies the script thread that a new worklet has been loaded, and thus the page should be /// reflowed. WorkletLoaded(PipelineId), - /// Runs a Runnable in the main thread. - MainThreadRunnable(ScriptThreadEventCategory, Box), + /// Runs a Task in the main thread. + MainThreadTask(ScriptThreadEventCategory, Box), } impl OpaqueSender for Box { @@ -1169,8 +1174,8 @@ impl ScriptThread { MixedMessage::FromImageCache(_) => ScriptThreadEventCategory::ImageCacheMsg, MixedMessage::FromScript(ref inner_msg) => { match *inner_msg { - MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(category, _)) | - MainThreadScriptMsg::MainThreadRunnable(category, _) => category, + MainThreadScriptMsg::Common(CommonScriptMsg::Task(category, _)) | + MainThreadScriptMsg::MainThreadTask(category, _) => category, _ => ScriptThreadEventCategory::ScriptEvent, } }, @@ -1300,8 +1305,8 @@ impl ScriptThread { MainThreadScriptMsg::ExitWindow(id) => { self.handle_exit_window_msg(id) }, - MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => { - runnable.handler() + MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, task)) => { + task.run() } MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(chan)) => { self.collect_reports(chan) @@ -1309,8 +1314,8 @@ impl ScriptThread { MainThreadScriptMsg::WorkletLoaded(pipeline_id) => { self.handle_worklet_loaded(pipeline_id) }, - MainThreadScriptMsg::MainThreadRunnable(_, runnable) => { - runnable.main_thread_handler(self) + MainThreadScriptMsg::MainThreadTask(_, task) => { + task.run_with_script_thread(self) }, } } diff --git a/components/script/serviceworkerjob.rs b/components/script/serviceworkerjob.rs index e1f43a34763..483662132e4 100644 --- a/components/script/serviceworkerjob.rs +++ b/components/script/serviceworkerjob.rs @@ -18,7 +18,7 @@ use dom::promise::Promise; use dom::serviceworkerregistration::ServiceWorkerRegistration; use dom::urlhelper::UrlHelper; use js::jsapi::JSAutoCompartment; -use script_thread::{ScriptThread, Runnable}; +use script_thread::{ScriptThread, Task}; use servo_url::ServoUrl; use std::cmp::PartialEq; use std::collections::HashMap; @@ -105,9 +105,9 @@ impl AsyncJobHandler { } } -impl Runnable for AsyncJobHandler { +impl Task for AsyncJobHandler { #[allow(unrooted_must_root)] - fn main_thread_handler(self: Box, script_thread: &ScriptThread) { + fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { script_thread.dispatch_job_queue(self); } } @@ -292,9 +292,9 @@ struct AsyncPromiseSettle { settle_type: SettleType, } -impl Runnable for AsyncPromiseSettle { +impl Task for AsyncPromiseSettle { #[allow(unrooted_must_root)] - fn handler(self: Box) { + fn run(self: Box) { let global = self.global.root(); let settle_type = self.settle_type.clone(); let promise = self.promise.root(); diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 597fac81cf1..e789d32e7b0 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -229,7 +229,7 @@ impl<'a> StylesheetLoader<'a> { let listener = NetworkListener { context: context, task_source: document.window().networking_task_source(), - wrapper: Some(document.window().get_runnable_wrapper()) + canceller: Some(document.window().task_canceller()) }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { listener.notify_fetch(message.to().unwrap()); diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index 636b99f87bf..f7b7a6577f8 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -4,11 +4,11 @@ use dom::bindings::inheritance::Castable; use dom::bindings::refcounted::Trusted; -use dom::event::{EventBubbles, EventCancelable, EventRunnable, SimpleEventRunnable}; +use dom::event::{EventBubbles, EventCancelable, EventTask, SimpleEventTask}; use dom::eventtarget::EventTarget; use dom::window::Window; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptMsg, Runnable, RunnableWrapper}; +use script_thread::{MainThreadScriptMsg, Task, TaskCanceller}; use servo_atoms::Atom; use std::fmt; use std::result::Result; @@ -25,17 +25,17 @@ impl fmt::Debug for DOMManipulationTaskSource { } impl TaskSource for DOMManipulationTaskSource { - fn queue_with_wrapper( + fn queue_with_canceller( &self, msg: Box, - wrapper: &RunnableWrapper, + canceller: &TaskCanceller, ) -> Result<(), ()> where - T: Runnable + Send + 'static, + T: Task + Send + 'static, { - let msg = MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg( + let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task( ScriptThreadEventCategory::ScriptEvent, - wrapper.wrap_runnable(msg), + canceller.wrap_task(msg), )); self.0.send(msg).map_err(|_| ()) } @@ -49,21 +49,17 @@ impl DOMManipulationTaskSource { cancelable: EventCancelable, window: &Window) { let target = Trusted::new(target); - let runnable = box EventRunnable { + let task = box EventTask { target: target, name: name, bubbles: bubbles, cancelable: cancelable, }; - let _ = self.queue(runnable, window.upcast()); + let _ = self.queue(task, window.upcast()); } pub fn queue_simple_event(&self, target: &EventTarget, name: Atom, window: &Window) { let target = Trusted::new(target); - let runnable = box SimpleEventRunnable { - target: target, - name: name, - }; - let _ = self.queue(runnable, window.upcast()); + let _ = self.queue(box SimpleEventTask { target, name }, window.upcast()); } } diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs index a1732995fcb..433cc78c260 100644 --- a/components/script/task_source/file_reading.rs +++ b/components/script/task_source/file_reading.rs @@ -5,7 +5,7 @@ use dom::domexception::DOMErrorName; use dom::filereader::{FileReader, TrustedFileReader, GenerationId, ReadMetaData}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory, ScriptChan}; -use script_thread::{Runnable, RunnableWrapper}; +use script_thread::{Task, TaskCanceller}; use std::sync::Arc; use task_source::TaskSource; @@ -19,13 +19,18 @@ impl Clone for FileReadingTaskSource { } impl TaskSource for FileReadingTaskSource { - fn queue_with_wrapper(&self, - msg: Box, - wrapper: &RunnableWrapper) - -> Result<(), ()> - where T: Runnable + Send + 'static { - self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::FileRead, - wrapper.wrap_runnable(msg))) + fn queue_with_canceller( + &self, + msg: Box, + canceller: &TaskCanceller, + ) -> Result<(), ()> + where + T: Send + Task + 'static, + { + self.0.send(CommonScriptMsg::Task( + ScriptThreadEventCategory::FileRead, + canceller.wrap_task(msg), + )) } } @@ -41,8 +46,8 @@ impl FileReadingRunnable { } } -impl Runnable for FileReadingRunnable { - fn handler(self: Box) { +impl Task for FileReadingRunnable { + fn run(self: Box) { self.task.handle_task(); } } diff --git a/components/script/task_source/mod.rs b/components/script/task_source/mod.rs index ff41a63f118..3dbb753883e 100644 --- a/components/script/task_source/mod.rs +++ b/components/script/task_source/mod.rs @@ -10,16 +10,19 @@ pub mod performance_timeline; pub mod user_interaction; use dom::globalscope::GlobalScope; -use script_thread::{Runnable, RunnableWrapper}; +use script_thread::{Task, TaskCanceller}; use std::result::Result; pub trait TaskSource { - fn queue_with_wrapper(&self, - msg: Box, - wrapper: &RunnableWrapper) - -> Result<(), ()> - where T: Runnable + Send + 'static; - fn queue(&self, msg: Box, global: &GlobalScope) -> Result<(), ()> { - self.queue_with_wrapper(msg, &global.get_runnable_wrapper()) + fn queue_with_canceller( + &self, + msg: Box, + canceller: &TaskCanceller, + ) -> Result<(), ()> + where + T: Send + Task + 'static; + + fn queue(&self, msg: Box, global: &GlobalScope) -> Result<(), ()> { + self.queue_with_canceller(msg, &global.task_canceller()) } } diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs index 8306a4789bb..56c583d775f 100644 --- a/components/script/task_source/networking.rs +++ b/components/script/task_source/networking.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; -use script_thread::{Runnable, RunnableWrapper}; +use script_thread::{Task, TaskCanceller}; use task_source::TaskSource; #[derive(JSTraceable)] @@ -16,18 +16,28 @@ impl Clone for NetworkingTaskSource { } impl TaskSource for NetworkingTaskSource { - fn queue_with_wrapper(&self, - msg: Box, - wrapper: &RunnableWrapper) - -> Result<(), ()> - where T: Runnable + Send + 'static { - self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::NetworkEvent, - wrapper.wrap_runnable(msg))) + fn queue_with_canceller( + &self, + msg: Box, + canceller: &TaskCanceller, + ) -> Result<(), ()> + where + T: Send + Task + 'static, + { + self.0.send(CommonScriptMsg::Task( + ScriptThreadEventCategory::NetworkEvent, + canceller.wrap_task(msg), + )) } } impl NetworkingTaskSource { - pub fn queue_wrapperless(&self, msg: Box) -> Result<(), ()> { - self.0.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::NetworkEvent, msg)) + /// This queues a task that will not be cancelled when its associated + /// global scope gets destroyed. + pub fn queue_unconditionally(&self, msg: Box) -> Result<(), ()> + where + T: Task + Send + 'static, + { + self.0.send(CommonScriptMsg::Task(ScriptThreadEventCategory::NetworkEvent, msg)) } } diff --git a/components/script/task_source/performance_timeline.rs b/components/script/task_source/performance_timeline.rs index 7d77b6b7db7..db80789a206 100644 --- a/components/script/task_source/performance_timeline.rs +++ b/components/script/task_source/performance_timeline.rs @@ -10,25 +10,25 @@ use dom::bindings::refcounted::Trusted; use dom::globalscope::GlobalScope; use dom::performance::Performance; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; -use script_thread::{Runnable, RunnableWrapper}; +use script_thread::{Task, TaskCanceller}; use std::fmt; use std::result::Result; use task_source::TaskSource; -pub struct NotifyPerformanceObserverRunnable { +pub struct NotifyPerformanceObserverTask { owner: Trusted, } -impl NotifyPerformanceObserverRunnable { +impl NotifyPerformanceObserverTask { pub fn new(owner: Trusted) -> Self { - NotifyPerformanceObserverRunnable { + NotifyPerformanceObserverTask { owner, } } } -impl Runnable for NotifyPerformanceObserverRunnable { - fn handler(self: Box) { +impl Task for NotifyPerformanceObserverTask { + fn run(self: Box) { self.owner.root().notify_observers(); } } @@ -49,13 +49,17 @@ impl fmt::Debug for PerformanceTimelineTaskSource { } impl TaskSource for PerformanceTimelineTaskSource { - fn queue_with_wrapper(&self, - msg: Box, - wrapper: &RunnableWrapper) -> Result<(), ()> - where T: Runnable + Send + 'static { - let msg = CommonScriptMsg::RunnableMsg( + fn queue_with_canceller( + &self, + msg: Box, + canceller: &TaskCanceller, + ) -> Result<(), ()> + where + T: Send + Task + 'static, + { + let msg = CommonScriptMsg::Task( ScriptThreadEventCategory::PerformanceTimelineTask, - wrapper.wrap_runnable(msg) + canceller.wrap_task(msg) ); self.0.send(msg).map_err(|_| ()) } @@ -64,7 +68,7 @@ impl TaskSource for PerformanceTimelineTaskSource { impl PerformanceTimelineTaskSource { pub fn queue_notification(&self, global: &GlobalScope) { let owner = Trusted::new(&*global.performance()); - let runnable = box NotifyPerformanceObserverRunnable::new(owner); - let _ = self.queue(runnable, global); + let task = box NotifyPerformanceObserverTask::new(owner); + let _ = self.queue(task, global); } } diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 9456d940416..3e84e0fb19a 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -4,11 +4,11 @@ use dom::bindings::inheritance::Castable; use dom::bindings::refcounted::Trusted; -use dom::event::{EventBubbles, EventCancelable, EventRunnable}; +use dom::event::{EventBubbles, EventCancelable, EventTask}; use dom::eventtarget::EventTarget; use dom::window::Window; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptMsg, Runnable, RunnableWrapper}; +use script_thread::{MainThreadScriptMsg, Task, TaskCanceller}; use servo_atoms::Atom; use std::fmt; use std::result::Result; @@ -25,17 +25,17 @@ impl fmt::Debug for UserInteractionTaskSource { } impl TaskSource for UserInteractionTaskSource { - fn queue_with_wrapper( + fn queue_with_canceller( &self, msg: Box, - wrapper: &RunnableWrapper, + canceller: &TaskCanceller, ) -> Result<(), ()> where - T: Runnable + Send + 'static, + T: Task + Send + 'static, { - let msg = MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg( + let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task( ScriptThreadEventCategory::InputEvent, - wrapper.wrap_runnable(msg), + canceller.wrap_task(msg), )); self.0.send(msg).map_err(|_| ()) } @@ -49,12 +49,7 @@ impl UserInteractionTaskSource { cancelable: EventCancelable, window: &Window) { let target = Trusted::new(target); - let runnable = box EventRunnable { - target: target, - name: name, - bubbles: bubbles, - cancelable: cancelable, - }; - let _ = self.queue(runnable, window.upcast()); + let task = box EventTask { target, name, bubbles, cancelable }; + let _ = self.queue(task, window.upcast()); } } From 4a39631eafe8e7144a92e2c33e0688a8f3b83295 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Sep 2017 03:17:35 +0200 Subject: [PATCH 05/37] Remove FileReadingRunnable --- components/script/dom/filereader.rs | 14 +++++++------- components/script/task_source/file_reading.rs | 18 +++--------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index 91f16559bd5..d954e1431ef 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -36,7 +36,7 @@ use std::ptr; use std::sync::Arc; use std::thread; use task_source::TaskSource; -use task_source::file_reading::{FileReadingTaskSource, FileReadingRunnable, FileReadingTask}; +use task_source::file_reading::{FileReadingTask, FileReadingTaskSource}; #[derive(Clone, Copy, HeapSizeOf, JSTraceable, PartialEq)] pub enum FileReaderFunction { @@ -415,12 +415,12 @@ fn perform_annotated_read_operation( canceller: TaskCanceller, ) { // Step 4 - let task = FileReadingRunnable::new(FileReadingTask::ProcessRead(filereader.clone(), gen_id)); - task_source.queue_with_canceller(task, &canceller).unwrap(); + let task = FileReadingTask::ProcessRead(filereader.clone(), gen_id); + task_source.queue_with_canceller(box task, &canceller).unwrap(); - let task = FileReadingRunnable::new(FileReadingTask::ProcessReadData(filereader.clone(), gen_id)); - task_source.queue_with_canceller(task, &canceller).unwrap(); + let task = FileReadingTask::ProcessReadData(filereader.clone(), gen_id); + task_source.queue_with_canceller(box task, &canceller).unwrap(); - let task = FileReadingRunnable::new(FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents)); - task_source.queue_with_canceller(task, &canceller).unwrap(); + let task = FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents); + task_source.queue_with_canceller(box task, &canceller).unwrap(); } diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs index 433cc78c260..dc9a6a751dd 100644 --- a/components/script/task_source/file_reading.rs +++ b/components/script/task_source/file_reading.rs @@ -34,21 +34,9 @@ impl TaskSource for FileReadingTaskSource { } } -pub struct FileReadingRunnable { - task: FileReadingTask, -} - -impl FileReadingRunnable { - pub fn new(task: FileReadingTask) -> Box { - box FileReadingRunnable { - task: task - } - } -} - -impl Task for FileReadingRunnable { - fn run(self: Box) { - self.task.handle_task(); +impl Task for FileReadingTask { + fn run(self: Box) { + self.handle_task(); } } From 9a267e53feed09ae236a554b7b58b607cdcc55d9 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Sep 2017 15:36:10 +0200 Subject: [PATCH 06/37] Send AsyncJobHandler as a MainThreadTask --- components/script/serviceworkerjob.rs | 6 ++++-- .../script/task_source/dom_manipulation.rs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/components/script/serviceworkerjob.rs b/components/script/serviceworkerjob.rs index 483662132e4..7d92e9afde0 100644 --- a/components/script/serviceworkerjob.rs +++ b/components/script/serviceworkerjob.rs @@ -133,8 +133,10 @@ impl JobQueue { if job_queue.is_empty() { let scope_url = job.scope_url.clone(); job_queue.push(job); - let run_job_handler = box AsyncJobHandler::new(scope_url); - let _ = script_thread.dom_manipulation_task_source().queue(run_job_handler, global); + let _ = script_thread.dom_manipulation_task_source().queue_main_thread_task( + box AsyncJobHandler::new(scope_url), + global, + ); debug!("queued task to run newly-queued job"); } else { // Step 2 diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index f7b7a6577f8..0120564806c 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -6,6 +6,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::refcounted::Trusted; use dom::event::{EventBubbles, EventCancelable, EventTask, SimpleEventTask}; use dom::eventtarget::EventTarget; +use dom::globalscope::GlobalScope; use dom::window::Window; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; use script_thread::{MainThreadScriptMsg, Task, TaskCanceller}; @@ -42,6 +43,21 @@ impl TaskSource for DOMManipulationTaskSource { } impl DOMManipulationTaskSource { + pub fn queue_main_thread_task( + &self, + task: Box, + global: &GlobalScope, + ) -> Result<(), ()> + where + T: Task + Send + 'static, + { + let msg = MainThreadScriptMsg::MainThreadTask( + ScriptThreadEventCategory::ScriptEvent, + global.task_canceller().wrap_task(task), + ); + self.0.send(msg).map_err(|_| ()) + } + pub fn queue_event(&self, target: &EventTarget, name: Atom, From 95dc54d216d63b7314214afc1b50025b73a132b1 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 01:34:07 +0200 Subject: [PATCH 07/37] Use normal tasks to reject and resolve promises --- components/script/dom/bindings/refcounted.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index b315416c48c..1be8a369d8f 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -32,7 +32,7 @@ use dom::promise::Promise; use js::jsapi::JSAutoCompartment; use js::jsapi::JSTracer; use libc; -use script_thread::{ScriptThread, Task}; +use script_thread::Task; use std::cell::RefCell; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::HashMap; @@ -125,11 +125,11 @@ impl TrustedPromise { pub fn reject_task(self, error: Error) -> impl Send + Task { struct RejectPromise(TrustedPromise, Error); impl Task for RejectPromise { - fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { + fn run(self: Box) { debug!("Rejecting promise."); let this = *self; - let cx = script_thread.get_cx(); let promise = this.0.root(); + let cx = promise.global().get_cx(); let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get()); promise.reject_error(cx, this.1); } @@ -145,11 +145,11 @@ impl TrustedPromise { { struct ResolvePromise(TrustedPromise, T); impl Task for ResolvePromise { - fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { + fn run(self: Box) { debug!("Resolving promise."); let this = *self; - let cx = script_thread.get_cx(); let promise = this.0.root(); + let cx = promise.global().get_cx(); let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get()); promise.resolve_native(cx, &this.1); } From f58207b851494562f855b8fdb929a529d9850f44 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 09:57:12 +0200 Subject: [PATCH 08/37] Introduce MainThreadScriptMsg::RegisterPaintWorklet This avoids the need for a generic task to send messages to the layout thread through the main script thread. --- .../script/dom/paintworkletglobalscope.rs | 4 +- components/script/dom/workletglobalscope.rs | 44 ++++++---------- components/script/script_thread.rs | 52 +++++++++++++++---- components/script_traits/lib.rs | 6 +++ 4 files changed, 67 insertions(+), 39 deletions(-) diff --git a/components/script/dom/paintworkletglobalscope.rs b/components/script/dom/paintworkletglobalscope.rs index 0a01e62cd9b..8eba2c8bb14 100644 --- a/components/script/dom/paintworkletglobalscope.rs +++ b/components/script/dom/paintworkletglobalscope.rs @@ -46,7 +46,6 @@ use js::rust::Runtime; use msg::constellation_msg::PipelineId; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageCache; -use script_layout_interface::message::Msg; use script_traits::DrawAPaintImageResult; use script_traits::Painter; use servo_atoms::Atom; @@ -443,8 +442,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope { // Inform layout that there is a registered paint worklet. // TODO: layout will end up getting this message multiple times. let painter = self.painter(name.clone()); - let msg = Msg::RegisterPaint(name, properties, painter); - self.worklet_global.send_to_layout(msg); + self.worklet_global.register_paint_worklet(name, properties, painter); Ok(()) } diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index f603547bb19..210ede4172e 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -22,12 +22,10 @@ use net_traits::ResourceThreads; use net_traits::image_cache::ImageCache; use profile_traits::mem; use profile_traits::time; -use script_layout_interface::message::Msg; -use script_runtime::ScriptThreadEventCategory; -use script_thread::{MainThreadScriptMsg, ScriptThread, Task}; -use script_traits::ScriptMsg; -use script_traits::ScriptToConstellationChan; -use script_traits::TimerSchedulerMsg; +use script_thread::MainThreadScriptMsg; +use script_traits::{Painter, ScriptMsg}; +use script_traits::{ScriptToConstellationChan, TimerSchedulerMsg}; +use servo_atoms::Atom; use servo_url::ImmutableOrigin; use servo_url::MutableOrigin; use servo_url::ServoUrl; @@ -93,31 +91,23 @@ impl WorkletGlobalScope { self.globalscope.evaluate_js_on_global_with_result(&*script, rval.handle_mut()) } - /// Run a task in the main script thread. - pub fn run_in_script_thread(&self, task: T) - where - T: 'static + Send + Task, - { + /// Register a paint worklet to the script thread. + pub fn register_paint_worklet( + &self, + name: Atom, + properties: Vec, + painter: Box, + ) { self.to_script_thread_sender - .send(MainThreadScriptMsg::MainThreadTask( - ScriptThreadEventCategory::WorkletEvent, - box task, - )) + .send(MainThreadScriptMsg::RegisterPaintWorklet { + pipeline_id: self.globalscope.pipeline_id(), + name, + properties, + painter, + }) .expect("Worklet thread outlived script thread."); } - /// Send a message to layout. - pub fn send_to_layout(&self, msg: Msg) { - struct SendToLayoutTask(PipelineId, Msg); - impl Task for SendToLayoutTask { - fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { - script_thread.send_to_layout(self.0, self.1); - } - } - let pipeline_id = self.globalscope.pipeline_id(); - self.run_in_script_thread(SendToLayoutTask(pipeline_id, msg)); - } - /// The base URL of this global. pub fn base_url(&self) -> ServoUrl { self.base_url.clone() diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e6ace85b51a..02d6158c887 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -87,16 +87,19 @@ use profile_traits::time::{self, ProfilerCategory, profile}; use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowQueryType}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx}; -use script_traits::{CompositorEvent, ConstellationControlMsg, PaintMetricType}; -use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult}; -use script_traits::{InitialScriptState, JsEvalResult, LayoutMsg, LoadData, MouseButton, MouseEventType}; -use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptToConstellationChan, ScriptMsg, UpdatePipelineIdReason}; -use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource}; -use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType}; +use script_traits::{CompositorEvent, ConstellationControlMsg}; +use script_traits::{DiscardBrowsingContext, DocumentActivity, EventResult}; +use script_traits::{InitialScriptState, JsEvalResult, LayoutMsg, LoadData}; +use script_traits::{MouseButton, MouseEventType, MozBrowserEvent, NewLayoutInfo}; +use script_traits::{PaintMetricType, Painter, ScriptMsg, ScriptThreadFactory}; +use script_traits::{ScriptToConstellationChan, TimerEvent, TimerSchedulerMsg}; +use script_traits::{TimerSource, TouchEventType, TouchId, UntrustedNodeAddress}; +use script_traits::{UpdatePipelineIdReason, WindowSizeData, WindowSizeType}; use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent}; use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent}; use script_traits::webdriver_msg::WebDriverScriptCommand; use serviceworkerjob::{Job, JobQueue, AsyncJobHandler}; +use servo_atoms::Atom; use servo_config::opts; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use std::cell::Cell; @@ -294,6 +297,13 @@ pub enum MainThreadScriptMsg { /// Notifies the script thread that a new worklet has been loaded, and thus the page should be /// reflowed. WorkletLoaded(PipelineId), + /// Notifies the script thread that a new paint worklet has been registered. + RegisterPaintWorklet { + pipeline_id: PipelineId, + name: Atom, + properties: Vec, + painter: Box + }, /// Runs a Task in the main thread. MainThreadTask(ScriptThreadEventCategory, Box), } @@ -780,13 +790,21 @@ impl ScriptThread { }) } - pub fn send_to_layout(&self, pipeline_id: PipelineId, msg: Msg) { + fn handle_register_paint_worklet( + &self, + pipeline_id: PipelineId, + name: Atom, + properties: Vec, + painter: Box, + ) { let window = self.documents.borrow().find_window(pipeline_id); let window = match window { Some(window) => window, - None => return warn!("Message sent to layout after pipeline {} closed.", pipeline_id), + None => return warn!("Paint worklet registered after pipeline {} closed.", pipeline_id), }; - let _ = window.layout_chan().send(msg); + let _ = window.layout_chan().send( + Msg::RegisterPaint(name, properties, painter), + ); } pub fn push_new_element_queue() { @@ -1176,6 +1194,9 @@ impl ScriptThread { match *inner_msg { MainThreadScriptMsg::Common(CommonScriptMsg::Task(category, _)) | MainThreadScriptMsg::MainThreadTask(category, _) => category, + MainThreadScriptMsg::RegisterPaintWorklet { .. } => { + ScriptThreadEventCategory::WorkletEvent + }, _ => ScriptThreadEventCategory::ScriptEvent, } }, @@ -1314,6 +1335,19 @@ impl ScriptThread { MainThreadScriptMsg::WorkletLoaded(pipeline_id) => { self.handle_worklet_loaded(pipeline_id) }, + MainThreadScriptMsg::RegisterPaintWorklet { + pipeline_id, + name, + properties, + painter, + } => { + self.handle_register_paint_worklet( + pipeline_id, + name, + properties, + painter, + ) + }, MainThreadScriptMsg::MainThreadTask(_, task) => { task.run_with_script_thread(self) }, diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index dbc65343a76..8b2c98b1eb6 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -860,6 +860,12 @@ pub trait Painter: SpeculativePainter { -> DrawAPaintImageResult; } +impl fmt::Debug for Painter { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Painter").field(&format_args!("..")).finish() + } +} + /// The result of executing paint code: the image together with any image URLs that need to be loaded. /// TODO: this should return a WR display list. https://github.com/servo/servo/issues/17497 #[derive(Clone, Debug, Deserialize, HeapSizeOf, Serialize)] From 1d52df0562ebac00358f03c51cf85969db4d8273 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 10:27:02 +0200 Subject: [PATCH 09/37] Remove uses of AsyncJobHandler from script_thread --- components/script/script_thread.rs | 6 +++--- components/script/serviceworkerjob.rs | 18 ++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 02d6158c887..2f7698ff960 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -98,7 +98,7 @@ use script_traits::{UpdatePipelineIdReason, WindowSizeData, WindowSizeType}; use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent}; use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent}; use script_traits::webdriver_msg::WebDriverScriptCommand; -use serviceworkerjob::{Job, JobQueue, AsyncJobHandler}; +use serviceworkerjob::{Job, JobQueue}; use servo_atoms::Atom; use servo_config::opts; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; @@ -1787,8 +1787,8 @@ impl ScriptThread { let _ = self.script_sender.send((pipeline_id, ScriptMsg::RegisterServiceWorker(scope_things, scope.clone()))); } - pub fn dispatch_job_queue(&self, job_handler: Box) { - self.job_queue_map.run_job(job_handler, self); + pub fn dispatch_job_queue(&self, scope_url: ServoUrl) { + self.job_queue_map.run_job(scope_url, self); } pub fn dom_manipulation_task_source(&self) -> &DOMManipulationTaskSource { diff --git a/components/script/serviceworkerjob.rs b/components/script/serviceworkerjob.rs index 7d92e9afde0..41f875ab866 100644 --- a/components/script/serviceworkerjob.rs +++ b/components/script/serviceworkerjob.rs @@ -108,7 +108,7 @@ impl AsyncJobHandler { impl Task for AsyncJobHandler { #[allow(unrooted_must_root)] fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { - script_thread.dispatch_job_queue(self); + script_thread.dispatch_job_queue(self.scope_url); } } @@ -157,30 +157,29 @@ impl JobQueue { #[allow(unrooted_must_root)] // https://w3c.github.io/ServiceWorker/#run-job-algorithm - pub fn run_job(&self, run_job_handler: Box, script_thread: &ScriptThread) { + pub fn run_job(&self, scope_url: ServoUrl, script_thread: &ScriptThread) { debug!("running a job"); let url = { let queue_ref = self.0.borrow(); let front_job = { - let job_vec = queue_ref.get(&run_job_handler.scope_url); + let job_vec = queue_ref.get(&scope_url); job_vec.unwrap().first().unwrap() }; - let scope_url = front_job.scope_url.clone(); + let front_scope_url = front_job.scope_url.clone(); match front_job.job_type { - JobType::Register => self.run_register(front_job, run_job_handler, script_thread), + JobType::Register => self.run_register(front_job, scope_url, script_thread), JobType::Update => self.update(front_job, script_thread), JobType::Unregister => unreachable!(), }; - scope_url + front_scope_url }; self.finish_job(url, script_thread); } #[allow(unrooted_must_root)] // https://w3c.github.io/ServiceWorker/#register-algorithm - fn run_register(&self, job: &Job, register_job_handler: Box, script_thread: &ScriptThread) { + fn run_register(&self, job: &Job, scope_url: ServoUrl, script_thread: &ScriptThread) { debug!("running register job"); - let AsyncJobHandler { scope_url, .. } = *register_job_handler; // Step 1-3 if !UrlHelper::is_origin_trustworthy(&job.script_url) { // Step 1.1 @@ -239,8 +238,7 @@ impl JobQueue { if run_job { debug!("further jobs in queue after finishing"); - let handler = box AsyncJobHandler::new(scope_url); - self.run_job(handler, script_thread); + self.run_job(scope_url, script_thread); } } From 8e78f18d2d282e651c5a8a20b2fe28cb015b264a Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 10:46:00 +0200 Subject: [PATCH 10/37] Introduce MainThreadScriptMsg::DispatchJobQueue This removes the last remaining use of Task::run_with_script_thread --- .../script/dom/serviceworkercontainer.rs | 2 +- components/script/script_thread.rs | 36 +++++++------------ components/script/serviceworkerjob.rs | 29 ++------------- .../script/task_source/dom_manipulation.rs | 16 --------- 4 files changed, 16 insertions(+), 67 deletions(-) diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs index ba2e327409f..37e89714fe2 100644 --- a/components/script/dom/serviceworkercontainer.rs +++ b/components/script/dom/serviceworkercontainer.rs @@ -114,7 +114,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer { // B: Step 8 let job = Job::create_job(JobType::Register, scope, script_url, promise.clone(), &*self.client); - ScriptThread::schedule_job(job, &*self.global()); + ScriptThread::schedule_job(job); promise } } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 2f7698ff960..21989316864 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -244,12 +244,6 @@ impl Task for CancellableTask where T: Send + Task, { - fn run_with_script_thread(self: Box>, script_thread: &ScriptThread) { - if !self.is_cancelled() { - self.inner.run_with_script_thread(script_thread); - } - } - fn run(self: Box) { if !self.is_cancelled() { self.inner.run() @@ -259,12 +253,7 @@ where pub trait Task { fn name(&self) -> &'static str { unsafe { intrinsics::type_name::() } } - fn run(self: Box) { - panic!("This should probably be redefined.") - } - fn run_with_script_thread(self: Box, _script_thread: &ScriptThread) { - self.run(); - } + fn run(self: Box); } impl fmt::Debug for Task + Send { @@ -304,8 +293,8 @@ pub enum MainThreadScriptMsg { properties: Vec, painter: Box }, - /// Runs a Task in the main thread. - MainThreadTask(ScriptThreadEventCategory, Box), + /// Dispatches a job queue. + DispatchJobQueue { scope_url: ServoUrl }, } impl OpaqueSender for Box { @@ -718,11 +707,11 @@ impl ScriptThread { } #[allow(unrooted_must_root)] - pub fn schedule_job(job: Job, global: &GlobalScope) { + pub fn schedule_job(job: Job) { SCRIPT_THREAD_ROOT.with(|root| { let script_thread = unsafe { &*root.get().unwrap() }; let job_queue = &*script_thread.job_queue_map; - job_queue.schedule_job(job, global, &script_thread); + job_queue.schedule_job(job, &script_thread); }); } @@ -1192,8 +1181,9 @@ impl ScriptThread { MixedMessage::FromImageCache(_) => ScriptThreadEventCategory::ImageCacheMsg, MixedMessage::FromScript(ref inner_msg) => { match *inner_msg { - MainThreadScriptMsg::Common(CommonScriptMsg::Task(category, _)) | - MainThreadScriptMsg::MainThreadTask(category, _) => category, + MainThreadScriptMsg::Common(CommonScriptMsg::Task(category, _)) => { + category + }, MainThreadScriptMsg::RegisterPaintWorklet { .. } => { ScriptThreadEventCategory::WorkletEvent }, @@ -1348,9 +1338,9 @@ impl ScriptThread { painter, ) }, - MainThreadScriptMsg::MainThreadTask(_, task) => { - task.run_with_script_thread(self) - }, + MainThreadScriptMsg::DispatchJobQueue { scope_url } => { + self.job_queue_map.run_job(scope_url, self) + } } } @@ -1787,8 +1777,8 @@ impl ScriptThread { let _ = self.script_sender.send((pipeline_id, ScriptMsg::RegisterServiceWorker(scope_things, scope.clone()))); } - pub fn dispatch_job_queue(&self, scope_url: ServoUrl) { - self.job_queue_map.run_job(scope_url, self); + pub fn schedule_job_queue(&self, scope_url: ServoUrl) { + let _ = self.chan.0.send(MainThreadScriptMsg::DispatchJobQueue { scope_url }); } pub fn dom_manipulation_task_source(&self) -> &DOMManipulationTaskSource { diff --git a/components/script/serviceworkerjob.rs b/components/script/serviceworkerjob.rs index 41f875ab866..db457dc394a 100644 --- a/components/script/serviceworkerjob.rs +++ b/components/script/serviceworkerjob.rs @@ -93,25 +93,6 @@ impl PartialEq for Job { } } -pub struct AsyncJobHandler { - pub scope_url: ServoUrl, -} - -impl AsyncJobHandler { - fn new(scope_url: ServoUrl) -> AsyncJobHandler { - AsyncJobHandler { - scope_url: scope_url, - } - } -} - -impl Task for AsyncJobHandler { - #[allow(unrooted_must_root)] - fn run_with_script_thread(self: Box, script_thread: &ScriptThread) { - script_thread.dispatch_job_queue(self.scope_url); - } -} - #[must_root] #[derive(JSTraceable)] pub struct JobQueue(pub DOMRefCell>>); @@ -122,10 +103,7 @@ impl JobQueue { } #[allow(unrooted_must_root)] // https://w3c.github.io/ServiceWorker/#schedule-job-algorithm - pub fn schedule_job(&self, - job: Job, - global: &GlobalScope, - script_thread: &ScriptThread) { + pub fn schedule_job(&self, job: Job, script_thread: &ScriptThread) { debug!("scheduling {:?} job", job.job_type); let mut queue_ref = self.0.borrow_mut(); let job_queue = queue_ref.entry(job.scope_url.clone()).or_insert(vec![]); @@ -133,10 +111,7 @@ impl JobQueue { if job_queue.is_empty() { let scope_url = job.scope_url.clone(); job_queue.push(job); - let _ = script_thread.dom_manipulation_task_source().queue_main_thread_task( - box AsyncJobHandler::new(scope_url), - global, - ); + let _ = script_thread.schedule_job_queue(scope_url); debug!("queued task to run newly-queued job"); } else { // Step 2 diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index 0120564806c..f7b7a6577f8 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -6,7 +6,6 @@ use dom::bindings::inheritance::Castable; use dom::bindings::refcounted::Trusted; use dom::event::{EventBubbles, EventCancelable, EventTask, SimpleEventTask}; use dom::eventtarget::EventTarget; -use dom::globalscope::GlobalScope; use dom::window::Window; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; use script_thread::{MainThreadScriptMsg, Task, TaskCanceller}; @@ -43,21 +42,6 @@ impl TaskSource for DOMManipulationTaskSource { } impl DOMManipulationTaskSource { - pub fn queue_main_thread_task( - &self, - task: Box, - global: &GlobalScope, - ) -> Result<(), ()> - where - T: Task + Send + 'static, - { - let msg = MainThreadScriptMsg::MainThreadTask( - ScriptThreadEventCategory::ScriptEvent, - global.task_canceller().wrap_task(task), - ); - self.0.send(msg).map_err(|_| ()) - } - pub fn queue_event(&self, target: &EventTarget, name: Atom, From 46628fba05a548c1c2141d7c709b6e5d812f3114 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 16:41:54 +0200 Subject: [PATCH 11/37] Move Task to its own module --- components/script/dom/bindings/refcounted.rs | 2 +- components/script/dom/bluetooth.rs | 2 +- components/script/dom/document.rs | 3 +- components/script/dom/element.rs | 3 +- components/script/dom/event.rs | 2 +- components/script/dom/eventsource.rs | 2 +- components/script/dom/filereader.rs | 2 +- components/script/dom/globalscope.rs | 3 +- components/script/dom/htmldetailselement.rs | 2 +- components/script/dom/htmlformelement.rs | 3 +- components/script/dom/htmliframeelement.rs | 3 +- components/script/dom/htmlimageelement.rs | 3 +- components/script/dom/htmlmediaelement.rs | 3 +- components/script/dom/serviceworker.rs | 2 +- components/script/dom/storage.rs | 2 +- components/script/dom/vrdisplay.rs | 2 +- components/script/dom/websocket.rs | 2 +- components/script/dom/window.rs | 5 +- components/script/dom/worker.rs | 2 +- components/script/dom/workerglobalscope.rs | 2 +- components/script/dom/worklet.rs | 3 +- components/script/lib.rs | 1 + components/script/network_listener.rs | 2 +- components/script/script_runtime.rs | 3 +- components/script/script_thread.rs | 59 ---------------- components/script/serviceworkerjob.rs | 3 +- components/script/task.rs | 70 +++++++++++++++++++ .../script/task_source/dom_manipulation.rs | 3 +- components/script/task_source/file_reading.rs | 2 +- components/script/task_source/mod.rs | 2 +- components/script/task_source/networking.rs | 2 +- .../task_source/performance_timeline.rs | 2 +- .../script/task_source/user_interaction.rs | 3 +- 33 files changed, 115 insertions(+), 90 deletions(-) create mode 100644 components/script/task.rs diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index 1be8a369d8f..4da753cb833 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -32,7 +32,6 @@ use dom::promise::Promise; use js::jsapi::JSAutoCompartment; use js::jsapi::JSTracer; use libc; -use script_thread::Task; use std::cell::RefCell; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::HashMap; @@ -41,6 +40,7 @@ use std::marker::PhantomData; use std::os; use std::rc::Rc; use std::sync::{Arc, Weak}; +use task::Task; #[allow(missing_docs)] // FIXME diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 35e6fdde3b1..2cd557d52b8 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -35,12 +35,12 @@ use ipc_channel::router::ROUTER; use js::conversions::ConversionResult; use js::jsapi::{JSAutoCompartment, JSContext, JSObject}; use js::jsval::{ObjectValue, UndefinedValue}; -use script_thread::Task; use std::cell::Ref; use std::collections::HashMap; use std::rc::Rc; use std::str::FromStr; use std::sync::{Arc, Mutex}; +use task::Task; const KEY_CONVERSION_ERROR: &'static str = "This `manufacturerData` key can not be parsed as unsigned short:"; const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices."; diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index e0c5380cc59..90853a28e7f 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -113,7 +113,7 @@ use net_traits::response::HttpsState; use num_traits::ToPrimitive; use script_layout_interface::message::{Msg, ReflowQueryType}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptMsg, ScriptThread, Task}; +use script_thread::{MainThreadScriptMsg, ScriptThread}; use script_traits::{AnimationState, CompositorEvent, DocumentActivity}; use script_traits::{MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{MsDuration, ScriptMsg, TouchpadPressurePhase}; @@ -142,6 +142,7 @@ use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuar use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join}; use style::stylesheet_set::StylesheetSet; use style::stylesheets::{Stylesheet, StylesheetContents, Origin, OriginSet}; +use task::Task; use task_source::TaskSource; use time; use timers::OneshotTimerCallback; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index f6322c65960..56fbcc0fcaf 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -87,7 +87,7 @@ use js::jsval::JSVal; use net_traits::request::CorsSettings; use ref_filter_map::ref_filter_map; use script_layout_interface::message::ReflowQueryType; -use script_thread::{ScriptThread, Task}; +use script_thread::ScriptThread; use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity}; use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode}; use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; @@ -119,6 +119,7 @@ use style::thread_state; use style::values::{CSSFloat, Either}; use style::values::{specified, computed}; use stylesheet_loader::StylesheetOwner; +use task::Task; // TODO: Update focus state when the top-level browsing context gains or loses system focus, // and when the element enters or leaves a browsing context container. diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index fb6bf9c3b61..f5143ec72c4 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -20,10 +20,10 @@ use dom::node::Node; use dom::virtualmethods::vtable_for; use dom::window::Window; use dom_struct::dom_struct; -use script_thread::Task; use servo_atoms::Atom; use std::cell::Cell; use std::default::Default; +use task::Task; use time; #[dom_struct] diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 2bd5f32261e..438200e3bab 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -27,13 +27,13 @@ use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseMsg, FetchResponse use net_traits::request::{CacheMode, CorsSettings, CredentialsMode}; use net_traits::request::{RequestInit, RequestMode}; use network_listener::{NetworkListener, PreInvoke}; -use script_thread::Task; use servo_atoms::Atom; use servo_url::ServoUrl; use std::cell::Cell; use std::mem; use std::str::{Chars, FromStr}; use std::sync::{Arc, Mutex}; +use task::Task; use task_source::TaskSource; use timers::OneshotTimerCallback; use utf8; diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index d954e1431ef..b2f5b1ca36f 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -29,12 +29,12 @@ use js::jsapi::JSAutoCompartment; use js::jsapi::JSContext; use js::jsval::{self, JSVal}; use js::typedarray::{ArrayBuffer, CreateWith}; -use script_thread::TaskCanceller; use servo_atoms::Atom; use std::cell::Cell; use std::ptr; use std::sync::Arc; use std::thread; +use task::TaskCanceller; use task_source::TaskSource; use task_source::file_reading::{FileReadingTask, FileReadingTaskSource}; diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index e661e315ea4..529b1791d59 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -38,7 +38,7 @@ use msg::constellation_msg::PipelineId; use net_traits::{CoreResourceThread, ResourceThreads, IpcSend}; use profile_traits::{mem, time}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; -use script_thread::{MainThreadScriptChan, ScriptThread, TaskCanceller}; +use script_thread::{MainThreadScriptChan, ScriptThread}; use script_traits::{MsDuration, ScriptToConstellationChan, TimerEvent}; use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource}; use servo_url::{MutableOrigin, ServoUrl}; @@ -47,6 +47,7 @@ use std::collections::HashMap; use std::collections::hash_map::Entry; use std::ffi::CString; use std::rc::Rc; +use task::TaskCanceller; use task_source::file_reading::FileReadingTaskSource; use task_source::networking::NetworkingTaskSource; use task_source::performance_timeline::PerformanceTimelineTaskSource; diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 4f4087b4c38..8cd5133dca7 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -16,8 +16,8 @@ use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; -use script_thread::Task; use std::cell::Cell; +use task::Task; use task_source::TaskSource; #[dom_struct] diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 43771b17890..ca14df723b8 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -49,7 +49,7 @@ use html5ever::{LocalName, Prefix}; use hyper::header::{Charset, ContentDisposition, ContentType, DispositionParam, DispositionType}; use hyper::method::Method; use msg::constellation_msg::PipelineId; -use script_thread::{MainThreadScriptMsg, Task}; +use script_thread::MainThreadScriptMsg; use script_traits::LoadData; use servo_rand::random; use std::borrow::ToOwned; @@ -57,6 +57,7 @@ use std::cell::Cell; use std::sync::mpsc::Sender; use style::attr::AttrValue; use style::str::split_html_space_chars; +use task::Task; use task_source::TaskSource; #[derive(Clone, Copy, HeapSizeOf, JSTraceable, PartialEq)] diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index fa6639ad422..0452c40d2f9 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -43,7 +43,7 @@ use js::jsval::{NullValue, UndefinedValue}; use msg::constellation_msg::{FrameType, BrowsingContextId, PipelineId, TopLevelBrowsingContextId, TraversalDirection}; use net_traits::response::HttpsState; use script_layout_interface::message::ReflowQueryType; -use script_thread::{ScriptThread, Task}; +use script_thread::ScriptThread; use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason}; use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg}; use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed}; @@ -54,6 +54,7 @@ use servo_url::ServoUrl; use std::cell::Cell; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::context::ReflowGoal; +use task::Task; use task_source::TaskSource; bitflags! { diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 23348c9d263..9967728e745 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -48,7 +48,7 @@ use net_traits::image_cache::UsePlaceholder; use net_traits::request::{RequestInit, Type as RequestType}; use network_listener::{NetworkListener, PreInvoke}; use num_traits::ToPrimitive; -use script_thread::{ScriptThread, Task}; +use script_thread::ScriptThread; use servo_url::ServoUrl; use servo_url::origin::ImmutableOrigin; use std::cell::{Cell, RefMut}; @@ -56,6 +56,7 @@ use std::default::Default; use std::i32; use std::sync::{Arc, Mutex}; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; +use task::Task; use task_source::TaskSource; #[derive(Clone, Copy, HeapSizeOf, JSTraceable)] diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 0f4549b0809..f307dc2e733 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -35,10 +35,11 @@ use microtask::{Microtask, MicrotaskRunnable}; use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError}; use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType}; use network_listener::{NetworkListener, PreInvoke}; -use script_thread::{ScriptThread, Task}; +use script_thread::ScriptThread; use servo_url::ServoUrl; use std::cell::Cell; use std::sync::{Arc, Mutex}; +use task::Task; use task_source::TaskSource; use time::{self, Timespec, Duration}; diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs index add6279e0a0..74169428453 100644 --- a/components/script/dom/serviceworker.rs +++ b/components/script/dom/serviceworker.rs @@ -16,10 +16,10 @@ use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom_struct::dom_struct; use js::jsapi::{HandleValue, JSContext}; -use script_thread::Task; use script_traits::{ScriptMsg, DOMMessage}; use servo_url::ServoUrl; use std::cell::Cell; +use task::Task; pub type TrustedServiceWorkerAddress = Trusted; diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index 65c21bc6706..fdd2ae4c504 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -17,9 +17,9 @@ use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcSender}; use net_traits::IpcSend; use net_traits::storage_thread::{StorageThreadMsg, StorageType}; -use script_thread::Task; use script_traits::ScriptMsg; use servo_url::ServoUrl; +use task::Task; use task_source::TaskSource; #[dom_struct] diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 9bc40bd5a82..2b2ab80f2e5 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -36,12 +36,12 @@ use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::JSContext; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebVREvent; -use script_thread::Task; use std::cell::Cell; use std::mem; use std::rc::Rc; use std::sync::mpsc; use std::thread; +use task::Task; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVRFrameData, WebVRLayer, WebVRMsg}; #[dom_struct] diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index a390381b924..52b2dcc85d6 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -31,13 +31,13 @@ use net_traits::CoreResourceMsg::WebsocketConnect; use net_traits::MessageData; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebSocketEvent; -use script_thread::{Task, TaskCanceller}; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; use std::ptr; use std::thread; +use task::{Task, TaskCanceller}; use task_source::TaskSource; use task_source::networking::NetworkingTaskSource; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 3b555ca7c4c..7492962e682 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -76,8 +76,8 @@ use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, Lay use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse}; use script_layout_interface::rpc::{ResolvedStyleResponse, TextIndexResponse}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory}; -use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, Task}; -use script_thread::{ScriptThread, SendableMainThreadScriptChan, TaskCanceller}; +use script_thread::{ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg}; +use script_thread::{ScriptThread, SendableMainThreadScriptChan}; use script_traits::{ConstellationControlMsg, DocumentState, LoadData, MozBrowserEvent}; use script_traits::{ScriptToConstellationChan, ScriptMsg, ScrollState, TimerEvent, TimerEventId}; use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType}; @@ -111,6 +111,7 @@ use style::selector_parser::PseudoElement; use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::CssRuleType; use style_traits::PARSING_MODE_DEFAULT; +use task::{Task, TaskCanceller}; use task_source::dom_manipulation::DOMManipulationTaskSource; use task_source::file_reading::FileReadingTaskSource; use task_source::history_traversal::HistoryTraversalTaskSource; diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 498cae4b0f4..70efc86606a 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -25,12 +25,12 @@ use dom_struct::dom_struct; use ipc_channel::ipc; use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, NullHandleValue}; use js::jsval::UndefinedValue; -use script_thread::Task; use script_traits::WorkerScriptLoadOrigin; use std::cell::Cell; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{Sender, channel}; +use task::Task; pub type TrustedWorkerAddress = Trusted; diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index c26fcc63fdb..57017f5cd55 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -33,7 +33,6 @@ use js::rust::Runtime; use net_traits::{IpcSend, load_whole_resource}; use net_traits::request::{CredentialsMode, Destination, RequestInit as NetRequestInit, Type as RequestType}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, get_reports}; -use script_thread::TaskCanceller; use script_traits::{TimerEvent, TimerEventId}; use script_traits::WorkerGlobalScopeInit; use servo_url::{MutableOrigin, ServoUrl}; @@ -42,6 +41,7 @@ use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::Receiver; +use task::TaskCanceller; use task_source::file_reading::FileReadingTaskSource; use task_source::networking::NetworkingTaskSource; use task_source::performance_timeline::PerformanceTimelineTaskSource; diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index 9bfec3c78cb..b55f9d328a0 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -51,7 +51,7 @@ use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory; use script_runtime::StackRootTLS; use script_runtime::new_rt_and_cx; -use script_thread::{MainThreadScriptMsg, ScriptThread, Task}; +use script_thread::{MainThreadScriptMsg, ScriptThread}; use servo_rand; use servo_url::ImmutableOrigin; use servo_url::ServoUrl; @@ -69,6 +69,7 @@ use std::thread; use style::thread_state; use swapper::Swapper; use swapper::swapper; +use task::Task; use uuid::Uuid; // Magic numbers diff --git a/components/script/lib.rs b/components/script/lib.rs index 5ba671440bd..b015a5407b0 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -123,6 +123,7 @@ pub mod script_thread; mod serviceworker_manager; mod serviceworkerjob; mod stylesheet_loader; +mod task; mod task_source; pub mod test; pub mod textinput; diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index aa167ecdfca..8b291128065 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -3,8 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use net_traits::{Action, FetchResponseListener, FetchResponseMsg}; -use script_thread::{Task, TaskCanceller}; use std::sync::{Arc, Mutex}; +use task::{Task, TaskCanceller}; use task_source::TaskSource; use task_source::networking::NetworkingTaskSource; diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index b12649668e5..270dd0cdafe 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -23,7 +23,7 @@ use js::panic::wrap_panic; use js::rust::Runtime; use microtask::{EnqueuedPromiseCallback, Microtask}; use profile_traits::mem::{Report, ReportKind, ReportsChan}; -use script_thread::{STACK_ROOTS, Task, trace_thread}; +use script_thread::{STACK_ROOTS, trace_thread}; use servo_config::opts; use servo_config::prefs::PREFS; use std::cell::Cell; @@ -35,6 +35,7 @@ use std::os::raw::c_void; use std::panic::AssertUnwindSafe; use std::ptr; use style::thread_state; +use task::Task; use time::{Tm, now}; /// Common messages used to control the event loops in both the script and the worker diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 21989316864..56f47cfdbef 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -105,15 +105,12 @@ use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use std::cell::Cell; use std::collections::{hash_map, HashMap, HashSet}; use std::default::Default; -use std::fmt; -use std::intrinsics; use std::ops::Deref; use std::option::Option; use std::ptr; use std::rc::Rc; use std::result::Result; use std::sync::Arc; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{Receiver, Select, Sender, channel}; use std::thread; use style::context::ReflowGoal; @@ -206,62 +203,6 @@ impl InProgressLoad { } } -/// Encapsulated state required to create cancellable tasks from non-script threads. -pub struct TaskCanceller { - pub cancelled: Option>, -} - -impl TaskCanceller { - pub fn wrap_task(&self, task: Box) -> Box - where - T: Send + Task + 'static, - { - box CancellableTask { - cancelled: self.cancelled.clone(), - inner: task, - } - } -} - -/// A task that can be discarded by toggling a shared flag. -pub struct CancellableTask { - cancelled: Option>, - inner: Box, -} - -impl CancellableTask -where - T: Send + Task, -{ - fn is_cancelled(&self) -> bool { - self.cancelled.as_ref().map_or(false, |cancelled| { - cancelled.load(Ordering::SeqCst) - }) - } -} - -impl Task for CancellableTask -where - T: Send + Task, -{ - fn run(self: Box) { - if !self.is_cancelled() { - self.inner.run() - } - } -} - -pub trait Task { - fn name(&self) -> &'static str { unsafe { intrinsics::type_name::() } } - fn run(self: Box); -} - -impl fmt::Debug for Task + Send { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_tuple(self.name()).field(&format_args!("...")).finish() - } -} - #[derive(Debug)] enum MixedMessage { FromConstellation(ConstellationControlMsg), diff --git a/components/script/serviceworkerjob.rs b/components/script/serviceworkerjob.rs index db457dc394a..fef1d02e4da 100644 --- a/components/script/serviceworkerjob.rs +++ b/components/script/serviceworkerjob.rs @@ -18,11 +18,12 @@ use dom::promise::Promise; use dom::serviceworkerregistration::ServiceWorkerRegistration; use dom::urlhelper::UrlHelper; use js::jsapi::JSAutoCompartment; -use script_thread::{ScriptThread, Task}; +use script_thread::ScriptThread; use servo_url::ServoUrl; use std::cmp::PartialEq; use std::collections::HashMap; use std::rc::Rc; +use task::Task; use task_source::TaskSource; use task_source::dom_manipulation::DOMManipulationTaskSource; diff --git a/components/script/task.rs b/components/script/task.rs new file mode 100644 index 00000000000..55c8f37aca4 --- /dev/null +++ b/components/script/task.rs @@ -0,0 +1,70 @@ +/* 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/. */ + +//! Machinery for [tasks](https://html.spec.whatwg.org/multipage/#concept-task). + +use std::fmt; +use std::intrinsics; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; + +/// A task that can be run. The name method is for profiling purposes. +pub trait Task { + #[allow(unsafe_code)] + fn name(&self) -> &'static str { unsafe { intrinsics::type_name::() } } + fn run(self: Box); +} + +impl fmt::Debug for Task + Send { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple(self.name()).field(&format_args!("...")).finish() + } +} + +/// Encapsulated state required to create cancellable tasks from non-script threads. +pub struct TaskCanceller { + pub cancelled: Option>, +} + +impl TaskCanceller { + /// Returns a wrapped `task` that will be cancelled if the `TaskCanceller` + /// says so. + pub fn wrap_task(&self, task: Box) -> Box + where + T: Send + Task + 'static, + { + box CancellableTask { + cancelled: self.cancelled.clone(), + inner: task, + } + } +} + +/// A task that can be cancelled by toggling a shared flag. +pub struct CancellableTask { + cancelled: Option>, + inner: Box, +} + +impl CancellableTask +where + T: Send + Task, +{ + fn is_cancelled(&self) -> bool { + self.cancelled.as_ref().map_or(false, |cancelled| { + cancelled.load(Ordering::SeqCst) + }) + } +} + +impl Task for CancellableTask +where + T: Send + Task, +{ + fn run(self: Box) { + if !self.is_cancelled() { + self.inner.run() + } + } +} diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index f7b7a6577f8..93cdfde95f4 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -8,11 +8,12 @@ use dom::event::{EventBubbles, EventCancelable, EventTask, SimpleEventTask}; use dom::eventtarget::EventTarget; use dom::window::Window; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptMsg, Task, TaskCanceller}; +use script_thread::MainThreadScriptMsg; use servo_atoms::Atom; use std::fmt; use std::result::Result; use std::sync::mpsc::Sender; +use task::{Task, TaskCanceller}; use task_source::TaskSource; #[derive(Clone, JSTraceable)] diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs index dc9a6a751dd..1d44a4087d6 100644 --- a/components/script/task_source/file_reading.rs +++ b/components/script/task_source/file_reading.rs @@ -5,8 +5,8 @@ use dom::domexception::DOMErrorName; use dom::filereader::{FileReader, TrustedFileReader, GenerationId, ReadMetaData}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory, ScriptChan}; -use script_thread::{Task, TaskCanceller}; use std::sync::Arc; +use task::{Task, TaskCanceller}; use task_source::TaskSource; #[derive(JSTraceable)] diff --git a/components/script/task_source/mod.rs b/components/script/task_source/mod.rs index 3dbb753883e..40b3c2f3261 100644 --- a/components/script/task_source/mod.rs +++ b/components/script/task_source/mod.rs @@ -10,8 +10,8 @@ pub mod performance_timeline; pub mod user_interaction; use dom::globalscope::GlobalScope; -use script_thread::{Task, TaskCanceller}; use std::result::Result; +use task::{Task, TaskCanceller}; pub trait TaskSource { fn queue_with_canceller( diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs index 56c583d775f..5d339037729 100644 --- a/components/script/task_source/networking.rs +++ b/components/script/task_source/networking.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; -use script_thread::{Task, TaskCanceller}; +use task::{Task, TaskCanceller}; use task_source::TaskSource; #[derive(JSTraceable)] diff --git a/components/script/task_source/performance_timeline.rs b/components/script/task_source/performance_timeline.rs index db80789a206..938566b7a8f 100644 --- a/components/script/task_source/performance_timeline.rs +++ b/components/script/task_source/performance_timeline.rs @@ -10,9 +10,9 @@ use dom::bindings::refcounted::Trusted; use dom::globalscope::GlobalScope; use dom::performance::Performance; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; -use script_thread::{Task, TaskCanceller}; use std::fmt; use std::result::Result; +use task::{Task, TaskCanceller}; use task_source::TaskSource; pub struct NotifyPerformanceObserverTask { diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 3e84e0fb19a..8b36a61e9d0 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -8,11 +8,12 @@ use dom::event::{EventBubbles, EventCancelable, EventTask}; use dom::eventtarget::EventTarget; use dom::window::Window; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use script_thread::{MainThreadScriptMsg, Task, TaskCanceller}; +use script_thread::MainThreadScriptMsg; use servo_atoms::Atom; use std::fmt; use std::result::Result; use std::sync::mpsc::Sender; +use task::{Task, TaskCanceller}; use task_source::TaskSource; #[derive(Clone, JSTraceable)] From 5412767f466861a9b0ad08b3a65744c3f3b17e09 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 17:30:21 +0200 Subject: [PATCH 12/37] Introduce a task! macro and use it for internal pause steps --- components/script/dom/htmlmediaelement.rs | 15 ++++++--------- components/script/lib.rs | 4 +++- components/script/task.rs | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index f307dc2e733..d14afa7ac28 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -140,15 +140,11 @@ impl HTMLMediaElement { // Step 2.3. let window = window_from_node(self); + let target = Trusted::new(self.upcast::()); // FIXME(nox): Why are errors silenced here? let _ = window.dom_manipulation_task_source().queue( - box InternalPauseStepsTask(Trusted::new(self.upcast())), - window.upcast(), - ); - struct InternalPauseStepsTask(Trusted); - impl Task for InternalPauseStepsTask { - fn run(self: Box) { - let target = self.0.root(); + box task!(internal_pause_steps: move || { + let target = target.root(); // Step 2.3.1. target.fire_event(atom!("timeupdate")); @@ -159,8 +155,9 @@ impl HTMLMediaElement { // Step 2.3.3. // FIXME(nox): Reject pending play promises with promises // and an "AbortError" DOMException. - } - } + }), + window.upcast(), + ); // Step 2.4. // FIXME(nox): Set the official playback position to the current diff --git a/components/script/lib.rs b/components/script/lib.rs index b015a5407b0..1f8401961fe 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -106,6 +106,9 @@ extern crate webrender_api; extern crate webvr_traits; extern crate xml5ever; +#[macro_use] +mod task; + mod body; pub mod clipboard_provider; mod devtools; @@ -123,7 +126,6 @@ pub mod script_thread; mod serviceworker_manager; mod serviceworkerjob; mod stylesheet_loader; -mod task; mod task_source; pub mod test; pub mod textinput; diff --git a/components/script/task.rs b/components/script/task.rs index 55c8f37aca4..35f202480ca 100644 --- a/components/script/task.rs +++ b/components/script/task.rs @@ -9,6 +9,26 @@ use std::intrinsics; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; +macro_rules! task { + ($name:ident: move || $body:tt) => {{ + #[allow(non_camel_case_types)] + struct $name(F); + impl ::task::Task for $name + where + F: ::std::ops::FnOnce(), + { + fn name(&self) -> &'static str { + stringify!($name) + } + + fn run(self: Box) { + (self.0)(); + } + } + $name(move || $body) + }}; +} + /// A task that can be run. The name method is for profiling purposes. pub trait Task { #[allow(unsafe_code)] From e9f6ea40c25758976e030872879c44726b7b97f2 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 17:30:48 +0200 Subject: [PATCH 13/37] Use task! instead of DocumentProgressHandler --- components/script/dom/document.rs | 114 +++++++++++++----------------- 1 file changed, 51 insertions(+), 63 deletions(-) diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 90853a28e7f..0d180ca9934 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -142,7 +142,6 @@ use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuar use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join}; use style::stylesheet_set::StylesheetSet; use style::stylesheets::{Stylesheet, StylesheetContents, Origin, OriginSet}; -use task::Task; use task_source::TaskSource; use time; use timers::OneshotTimerCallback; @@ -1715,8 +1714,57 @@ impl Document { // The rest will ever run only once per document. // Step 7. debug!("Document loads are complete."); - let handler = box DocumentProgressHandler::new(Trusted::new(self)); - self.window.dom_manipulation_task_source().queue(handler, self.window.upcast()).unwrap(); + let document = Trusted::new(self); + self.window.dom_manipulation_task_source().queue( + box task!(fire_load_event: move || { + let document = document.root(); + let window = document.window(); + if !window.is_alive() { + return; + } + + // Step 7.1. + document.set_ready_state(DocumentReadyState::Complete); + + // Step 7.2. + if document.browsing_context().is_none() { + return; + } + let event = Event::new( + window.upcast(), + atom!("load"), + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + ); + event.set_trusted(true); + + // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart + update_with_current_time_ms(&document.load_event_start); + + debug!("About to dispatch load for {:?}", document.url()); + // FIXME(nox): Why are errors silenced here? + let _ = window.upcast::().dispatch_event_with_target( + document.upcast(), + &event, + ); + + // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd + update_with_current_time_ms(&document.load_event_end); + + window.reflow( + ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::DocumentLoaded, + ); + + document.notify_constellation_load(); + + if let Some(fragment) = document.url().fragment() { + document.check_and_scroll_fragment(fragment); + } + }), + self.window.upcast(), + ).unwrap(); // Step 8. // TODO: pageshow event. @@ -3971,66 +4019,6 @@ pub fn determine_policy_for_token(token: &str) -> Option { } } -pub struct DocumentProgressHandler { - addr: Trusted -} - -impl DocumentProgressHandler { - pub fn new(addr: Trusted) -> DocumentProgressHandler { - DocumentProgressHandler { - addr: addr - } - } - - fn set_ready_state_complete(&self) { - let document = self.addr.root(); - document.set_ready_state(DocumentReadyState::Complete); - } - - fn dispatch_load(&self) { - let document = self.addr.root(); - if document.browsing_context().is_none() { - return; - } - let window = document.window(); - let event = Event::new(window.upcast(), - atom!("load"), - EventBubbles::DoesNotBubble, - EventCancelable::NotCancelable); - let wintarget = window.upcast::(); - event.set_trusted(true); - - // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart - update_with_current_time_ms(&document.load_event_start); - - debug!("About to dispatch load for {:?}", document.url()); - let _ = wintarget.dispatch_event_with_target(document.upcast(), &event); - - // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd - update_with_current_time_ms(&document.load_event_end); - - window.reflow(ReflowGoal::ForDisplay, - ReflowQueryType::NoQuery, - ReflowReason::DocumentLoaded); - - document.notify_constellation_load(); - } -} - -impl Task for DocumentProgressHandler { - fn run(self: Box) { - let document = self.addr.root(); - let window = document.window(); - if window.is_alive() { - self.set_ready_state_complete(); - self.dispatch_load(); - if let Some(fragment) = document.url().fragment() { - document.check_and_scroll_fragment(fragment); - } - } - } -} - /// Specifies the type of focus event that is sent to a pipeline #[derive(Clone, Copy, PartialEq)] pub enum FocusType { From 91c2865e36cde4af7e4449493dd0c921c7e4453d Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 17:41:42 +0200 Subject: [PATCH 14/37] Use task! for notifying about playing --- components/script/dom/htmlmediaelement.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index d14afa7ac28..057f0ef0512 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -171,24 +171,21 @@ impl HTMLMediaElement { // TODO(nox): Take pending play promises and let promises be the result. // Step 2. + let target = Trusted::new(self.upcast::()); let window = window_from_node(self); // FIXME(nox): Why are errors silenced here? let _ = window.dom_manipulation_task_source().queue( - box NotifyAboutPlayingTask(Trusted::new(self.upcast())), - window.upcast(), - ); - struct NotifyAboutPlayingTask(Trusted); - impl Task for NotifyAboutPlayingTask { - fn run(self: Box) { - let target = self.0.root(); + box task!(notify_about_playing: move || { + let target = target.root(); // Step 2.1. target.fire_event(atom!("playing")); // Step 2.2. // FIXME(nox): Resolve pending play promises with promises. - } - } + }), + window.upcast(), + ); } // https://html.spec.whatwg.org/multipage/#ready-states From 30a1d3f617b8a53cb4af64c1c62a401a41ccdcbf Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 19:44:13 +0200 Subject: [PATCH 15/37] Use task! for the dedicated media source failure steps --- components/script/dom/htmlmediaelement.rs | 62 ++++++++++------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 057f0ef0512..59ebbd10aea 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -39,7 +39,6 @@ use script_thread::ScriptThread; use servo_url::ServoUrl; use std::cell::Cell; use std::sync::{Arc, Mutex}; -use task::Task; use task_source::TaskSource; use time::{self, Timespec, Duration}; @@ -461,30 +460,43 @@ impl HTMLMediaElement { } } + /// Queues the [dedicated media source failure steps][steps]. + /// + /// [steps]: https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps fn queue_dedicated_media_source_failure_steps(&self) { + let this = Trusted::new(self); let window = window_from_node(self); + // FIXME(nox): Why are errors silenced here? let _ = window.dom_manipulation_task_source().queue( - box DedicatedMediaSourceFailureTask::new(self), window.upcast()); - } + box task!(dedicated_media_source_failure_steps: move || { + let this = this.root(); - // https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps - fn dedicated_media_source_failure(&self) { - // Step 1 - self.error.set(Some(&*MediaError::new(&*window_from_node(self), - MEDIA_ERR_SRC_NOT_SUPPORTED))); + // Step 1. + this.error.set(Some(&*MediaError::new( + &window_from_node(&*this), + MEDIA_ERR_SRC_NOT_SUPPORTED, + ))); - // TODO step 2 (forget resource tracks) + // Step 2. + // FIXME(nox): Forget the media-resource-specific tracks. - // Step 3 - self.network_state.set(NetworkState::NoSource); + // Step 3. + this.network_state.set(NetworkState::NoSource); - // TODO step 4 (show poster) + // Step 4. + // FIXME(nox): Set show poster flag to true. - // Step 5 - self.upcast::().fire_event(atom!("error")); + // Step 5. + this.upcast::().fire_event(atom!("error")); - // TODO step 6 (resolve pending play promises) - // TODO step 7 (delay load event) + // Step 6. + // FIXME(nox): Reject pending play promises. + + // Step 7. + // FIXME(nox): Set the delaying-the-load-event flag to false. + }), + window.upcast(), + ); } // https://html.spec.whatwg.org/multipage/#media-element-load-algorithm @@ -733,24 +745,6 @@ impl MicrotaskRunnable for MediaElementMicrotask { } } -struct DedicatedMediaSourceFailureTask { - elem: Trusted, -} - -impl DedicatedMediaSourceFailureTask { - fn new(elem: &HTMLMediaElement) -> DedicatedMediaSourceFailureTask { - DedicatedMediaSourceFailureTask { - elem: Trusted::new(elem), - } - } -} - -impl Task for DedicatedMediaSourceFailureTask { - fn run(self: Box) { - self.elem.root().dedicated_media_source_failure(); - } -} - enum ResourceSelectionMode { Object, Attribute(String), From fba54c77355990a59bdd54733359eda1352ac0e4 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 20:39:14 +0200 Subject: [PATCH 16/37] Use task! to fire a progress event when updating the image data --- components/script/dom/htmlimageelement.rs | 45 +++++++++++------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 9967728e745..d565d859e76 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -386,28 +386,6 @@ impl HTMLImageElement { let _ = task_source.queue(task, window.upcast()); } - /// Step 10 of html.spec.whatwg.org/multipage/#update-the-image-data - fn dispatch_loadstart_progress_event(&self) { - struct FireprogressEventTask { - img: Trusted, - } - impl Task for FireprogressEventTask { - fn run(self: Box) { - let progressevent = ProgressEvent::new(&self.img.root().global(), - atom!("loadstart"), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, - false, 0, 0); - progressevent.upcast::().fire(self.img.root().upcast()); - } - } - let task = box FireprogressEventTask { - img: Trusted::new(self), - }; - let document = document_from_node(self); - let window = document.window(); - let task_source = window.dom_manipulation_task_source(); - let _ = task_source.queue(task, window.upcast()); - } - /// https://html.spec.whatwg.org/multipage/#update-the-source-set fn update_source_set(&self) -> Vec { let elem = self.upcast::(); @@ -550,8 +528,27 @@ impl HTMLImageElement { // TODO: take pixel density into account match self.select_image_source() { Some(src) => { - // Step 10 - self.dispatch_loadstart_progress_event(); + // Step 10. + let window = document.window(); + let this = Trusted::new(self); + // FIXME(nox): Why are errors silenced here? + let _ = window.dom_manipulation_task_source().queue( + box task!(fire_progress_event: move || { + let this = this.root(); + + let event = ProgressEvent::new( + &this.global(), + atom!("loadstart"), + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + false, + 0, + 0, + ); + event.upcast::().fire(this.upcast()); + }), + window.upcast(), + ); // Step 11 let base_url = document.base_url(); let parsed_url = base_url.join(&src); From 407af95db50e86bf77be2eebb8c8160223f737f9 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 20:56:16 +0200 Subject: [PATCH 17/37] Use task! for step 9 of updating the image data --- components/script/dom/htmlimageelement.rs | 124 ++++++++++------------ 1 file changed, 58 insertions(+), 66 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index d565d859e76..c9af5f5eee0 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -403,37 +403,6 @@ impl HTMLImageElement { self.update_source_set().first().cloned() } - /// Step 9.2 of https://html.spec.whatwg.org/multipage/#update-the-image-data - fn set_current_request_url_to_none_fire_error(&self) { - struct SetUrlToNoneTask { - img: Trusted, - } - impl Task for SetUrlToNoneTask { - fn run(self: Box) { - let img = self.img.root(); - { - let mut current_request = img.current_request.borrow_mut(); - current_request.source_url = None; - current_request.parsed_url = None; - } - let elem = img.upcast::(); - if elem.has_attribute(&local_name!("src")) { - img.upcast::().fire_event(atom!("error")); - } - img.abort_request(State::Broken, ImageRequestPhase::Current); - img.abort_request(State::Broken, ImageRequestPhase::Pending); - } - } - - let task = box SetUrlToNoneTask { - img: Trusted::new(self), - }; - let document = document_from_node(self); - let window = document.window(); - let task_source = window.dom_manipulation_task_source(); - let _ = task_source.queue(task, window.upcast()); - } - /// Step 5.3.7 of https://html.spec.whatwg.org/multipage/#update-the-image-data fn set_current_request_url_to_string_and_fire_load(&self, src: DOMString, url: ServoUrl) { struct SetUrlToStringTask { @@ -524,49 +493,72 @@ impl HTMLImageElement { /// Step 8-12 of html.spec.whatwg.org/multipage/#update-the-image-data fn update_the_image_data_sync_steps(&self) { let document = document_from_node(self); - // Step 8 - // TODO: take pixel density into account - match self.select_image_source() { + let window = document.window(); + let task_source = window.dom_manipulation_task_source(); + let this = Trusted::new(self); + let src = match self.select_image_source() { Some(src) => { - // Step 10. - let window = document.window(); - let this = Trusted::new(self); + // Step 8. + // TODO: Handle pixel density. + src + }, + None => { + // Step 9. // FIXME(nox): Why are errors silenced here? - let _ = window.dom_manipulation_task_source().queue( - box task!(fire_progress_event: move || { + let _ = task_source.queue( + box task!(image_null_source_error: move || { let this = this.root(); - - let event = ProgressEvent::new( - &this.global(), - atom!("loadstart"), - EventBubbles::DoesNotBubble, - EventCancelable::NotCancelable, - false, - 0, - 0, - ); - event.upcast::().fire(this.upcast()); + { + let mut current_request = + this.current_request.borrow_mut(); + current_request.source_url = None; + current_request.parsed_url = None; + } + if this.upcast::().has_attribute(&local_name!("src")) { + this.upcast::().fire_event(atom!("error")); + } + // FIXME(nox): According to the spec, setting the current + // request to the broken state is done prior to queuing a + // task, why is this here? + this.abort_request(State::Broken, ImageRequestPhase::Current); + this.abort_request(State::Broken, ImageRequestPhase::Pending); }), window.upcast(), ); - // Step 11 - let base_url = document.base_url(); - let parsed_url = base_url.join(&src); - match parsed_url { - Ok(url) => { - // Step 12 - self.prepare_image_request(&url, &src); - }, - Err(_) => { - // Step 11.1-11.5 - self.set_current_request_url_to_selected_fire_error_and_loadend(src); - } - } + return; }, - None => { - // Step 9 - self.set_current_request_url_to_none_fire_error(); + }; + // Step 10. + // FIXME(nox): Why are errors silenced here? + let _ = task_source.queue( + box task!(fire_progress_event: move || { + let this = this.root(); + + let event = ProgressEvent::new( + &this.global(), + atom!("loadstart"), + EventBubbles::DoesNotBubble, + EventCancelable::NotCancelable, + false, + 0, + 0, + ); + event.upcast::().fire(this.upcast()); + }), + window.upcast(), + ); + // Step 11 + let base_url = document.base_url(); + let parsed_url = base_url.join(&src); + match parsed_url { + Ok(url) => { + // Step 12 + self.prepare_image_request(&url, &src); }, + Err(_) => { + // Step 11.1-11.5 + self.set_current_request_url_to_selected_fire_error_and_loadend(src); + } } } From aa67ff30db2c4e28cae82ee8f11629909f27c715 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 21:08:21 +0200 Subject: [PATCH 18/37] Use task! for step 5.3.7 of updating the image data --- components/script/dom/htmlimageelement.rs | 49 ++++++++--------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index c9af5f5eee0..f32be52442b 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -403,36 +403,6 @@ impl HTMLImageElement { self.update_source_set().first().cloned() } - /// Step 5.3.7 of https://html.spec.whatwg.org/multipage/#update-the-image-data - fn set_current_request_url_to_string_and_fire_load(&self, src: DOMString, url: ServoUrl) { - struct SetUrlToStringTask { - img: Trusted, - src: String, - url: ServoUrl - } - impl Task for SetUrlToStringTask { - fn run(self: Box) { - let img = self.img.root(); - { - let mut current_request = img.current_request.borrow_mut(); - current_request.parsed_url = Some(self.url.clone()); - current_request.source_url = Some(self.src.into()); - } - // TODO: restart animation, if set - img.upcast::().fire_event(atom!("load")); - } - } - let task = box SetUrlToStringTask { - img: Trusted::new(self), - src: src.into(), - url: url - }; - let document = document_from_node(self); - let window = document.window(); - let task_source = window.dom_manipulation_task_source(); - let _ = task_source.queue(task, window.upcast()); - } - fn init_image_request(&self, request: &mut RefMut, url: &ServoUrl, @@ -606,8 +576,23 @@ impl HTMLImageElement { current_request.final_url = Some(url); current_request.image = Some(image.clone()); current_request.metadata = Some(metadata); - self.set_current_request_url_to_string_and_fire_load(src, img_url); - return + let this = Trusted::new(self); + let src = String::from(src); + let _ = window.dom_manipulation_task_source().queue( + box task!(image_load_event: move || { + let this = this.root(); + { + let mut current_request = + this.current_request.borrow_mut(); + current_request.parsed_url = Some(img_url); + current_request.source_url = Some(src.into()); + } + // TODO: restart animation, if set. + this.upcast::().fire_event(atom!("load")); + }), + window.upcast(), + ); + return; } } } From 3592108759c6175a3aa37e1330ca8cdafdf43c9b Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 21:35:21 +0200 Subject: [PATCH 19/37] Use task! for form planned navigations. --- components/script/dom/htmlformelement.rs | 51 +++++++++--------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index ca14df723b8..81b9cdb44a1 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -48,16 +48,13 @@ use encoding::label::encoding_from_whatwg_label; use html5ever::{LocalName, Prefix}; use hyper::header::{Charset, ContentDisposition, ContentType, DispositionParam, DispositionType}; use hyper::method::Method; -use msg::constellation_msg::PipelineId; use script_thread::MainThreadScriptMsg; use script_traits::LoadData; use servo_rand::random; use std::borrow::ToOwned; use std::cell::Cell; -use std::sync::mpsc::Sender; use style::attr::AttrValue; use style::str::split_html_space_chars; -use task::Task; use task_source::TaskSource; #[derive(Clone, Copy, HeapSizeOf, JSTraceable, PartialEq)] @@ -436,20 +433,26 @@ impl HTMLFormElement { // Each planned navigation task is tagged with a generation ID, and // before the task is handled, it first checks whether the HTMLFormElement's // generation ID is the same as its own generation ID. - let GenerationId(prev_id) = self.generation_id.get(); - self.generation_id.set(GenerationId(prev_id + 1)); + let generation_id = GenerationId(self.generation_id.get().0 + 1); + self.generation_id.set(generation_id); - // Step 2 - let nav = box PlannedNavigation { - load_data: load_data, - pipeline_id: window.upcast::().pipeline_id(), - script_chan: window.main_thread_script_chan().clone(), - generation_id: self.generation_id.get(), - form: Trusted::new(self) - }; + // Step 2. + let pipeline_id = window.upcast::().pipeline_id(); + let script_chan = window.main_thread_script_chan().clone(); + let this = Trusted::new(self); + let task = box task!(navigate_to_form_planned_navigation: move || { + if generation_id != this.root().generation_id.get() { + return; + } + script_chan.send(MainThreadScriptMsg::Navigate( + pipeline_id, + load_data, + false, + )).unwrap(); + }); - // Step 3 - window.dom_manipulation_task_source().queue(nav, window.upcast()).unwrap(); + // Step 3. + window.dom_manipulation_task_source().queue(task, window.upcast()).unwrap(); } /// Interactively validate the constraints of form elements @@ -1108,24 +1111,6 @@ impl FormControlElementHelpers for Element { } } -struct PlannedNavigation { - load_data: LoadData, - pipeline_id: PipelineId, - script_chan: Sender, - generation_id: GenerationId, - form: Trusted -} - -impl Task for PlannedNavigation { - fn run(self: Box) { - if self.generation_id == self.form.root().generation_id.get() { - let script_chan = self.script_chan.clone(); - script_chan.send(MainThreadScriptMsg::Navigate(self.pipeline_id, self.load_data, false)).unwrap(); - } - } -} - - // https://html.spec.whatwg.org/multipage/#multipart/form-data-encoding-algorithm pub fn encode_multipart_form_data(form_data: &mut Vec, boundary: String, encoding: EncodingRef) -> Vec { From 5b41e66f27419228e71b8f009ca6ed11a8da4f69 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 23:09:27 +0200 Subject: [PATCH 20/37] Use task! to process image responses --- components/script/dom/htmlimageelement.rs | 46 +++++++---------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index f32be52442b..75ae78f6902 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -100,33 +100,6 @@ impl HTMLImageElement { } } -struct ImageResponseHandlerTask { - element: Trusted, - image: ImageResponse, - generation: u32, -} - -impl ImageResponseHandlerTask { - fn new(element: Trusted, image: ImageResponse, generation: u32) - -> ImageResponseHandlerTask { - ImageResponseHandlerTask { - element: element, - image: image, - generation: generation, - } - } -} - -impl Task for ImageResponseHandlerTask { - fn run(self: Box) { - let element = self.element.root(); - // Ignore any image response for a previous request that has been discarded. - if element.generation.get() == self.generation { - element.process_image_response(self.image); - } - } -} - /// The context required for asynchronously loading an external image. struct ImageContext { /// Reference to the script thread image cache. @@ -192,18 +165,25 @@ impl HTMLImageElement { let window = window_from_node(elem); let task_source = window.networking_task_source(); - let wrapper = window.task_canceller(); + let task_canceller = window.task_canceller(); let generation = elem.generation.get(); ROUTER.add_route(responder_receiver.to_opaque(), box move |message| { debug!("Got image {:?}", message); // Return the image via a message to the script thread, which marks // the element as dirty and triggers a reflow. - let task = ImageResponseHandlerTask::new( - trusted_node.clone(), - message.to().unwrap(), - generation, + let element = trusted_node.clone(); + let image = message.to().unwrap(); + // FIXME(nox): Why are errors silenced here? + let _ = task_source.queue_with_canceller( + box task!(process_image_response: move || { + let element = element.root(); + // Ignore any image response for a previous request that has been discarded. + if generation == element.generation.get() { + element.process_image_response(image); + } + }), + &task_canceller, ); - let _ = task_source.queue_with_canceller(box task, &wrapper); }); image_cache.add_listener(id, ImageResponder::new(responder_sender, id)); From b3e27509b7424c652d6a7de92709f427a8309d67 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 23:17:19 +0200 Subject: [PATCH 21/37] Use task! for step 11.4 of updating the image data --- components/script/dom/htmlimageelement.rs | 62 ++++++++++------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 75ae78f6902..30ef64da97e 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -56,7 +56,6 @@ use std::default::Default; use std::i32; use std::sync::{Arc, Mutex}; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; -use task::Task; use task_source::TaskSource; #[derive(Clone, Copy, HeapSizeOf, JSTraceable)] @@ -336,36 +335,6 @@ impl HTMLImageElement { request.metadata = None; } - /// Step 11.4 of https://html.spec.whatwg.org/multipage/#update-the-image-data - fn set_current_request_url_to_selected_fire_error_and_loadend(&self, src: DOMString) { - struct SetCurrentRequestUrlTask { - img: Trusted, - src: String, - } - impl Task for SetCurrentRequestUrlTask { - fn run(self: Box) { - let img = self.img.root(); - { - let mut current_request = img.current_request.borrow_mut(); - current_request.source_url = Some(DOMString::from_string(self.src)); - } - img.upcast::().fire_event(atom!("error")); - img.upcast::().fire_event(atom!("loadend")); - img.abort_request(State::Broken, ImageRequestPhase::Current); - img.abort_request(State::Broken, ImageRequestPhase::Pending); - } - } - - let task = box SetCurrentRequestUrlTask { - img: Trusted::new(self), - src: src.into() - }; - let document = document_from_node(self); - let window = document.window(); - let task_source = window.dom_manipulation_task_source(); - let _ = task_source.queue(task, window.upcast()); - } - /// https://html.spec.whatwg.org/multipage/#update-the-source-set fn update_source_set(&self) -> Vec { let elem = self.upcast::(); @@ -479,13 +448,14 @@ impl HTMLImageElement { }, }; // Step 10. + let target = Trusted::new(self.upcast::()); // FIXME(nox): Why are errors silenced here? let _ = task_source.queue( box task!(fire_progress_event: move || { - let this = this.root(); + let target = target.root(); let event = ProgressEvent::new( - &this.global(), + &target.global(), atom!("loadstart"), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, @@ -493,7 +463,7 @@ impl HTMLImageElement { 0, 0, ); - event.upcast::().fire(this.upcast()); + event.upcast::().fire(&target); }), window.upcast(), ); @@ -506,8 +476,28 @@ impl HTMLImageElement { self.prepare_image_request(&url, &src); }, Err(_) => { - // Step 11.1-11.5 - self.set_current_request_url_to_selected_fire_error_and_loadend(src); + // Step 11.1-11.5. + let src = String::from(src); + // FIXME(nox): Why are errors silenced here? + let _ = task_source.queue( + box task!(image_selected_source_error: move || { + let this = this.root(); + { + let mut current_request = + this.current_request.borrow_mut(); + current_request.source_url = Some(src.into()); + } + this.upcast::().fire_event(atom!("error")); + this.upcast::().fire_event(atom!("loadend")); + + // FIXME(nox): According to the spec, setting the current + // request to the broken state is done prior to queuing a + // task, why is this here? + this.abort_request(State::Broken, ImageRequestPhase::Current); + this.abort_request(State::Broken, ImageRequestPhase::Pending); + }), + window.upcast(), + ); } } } From 915a4f83858fb28153e1e7662d8c46ba9c86e1f9 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 23:25:56 +0200 Subject: [PATCH 22/37] Use task! for the details notification steps --- components/script/dom/htmldetailselement.rs | 37 ++++++--------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 8cd5133dca7..59090f80f48 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -17,7 +17,6 @@ use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; use std::cell::Cell; -use task::Task; use task_source::TaskSource; #[dom_struct] @@ -45,10 +44,6 @@ impl HTMLDetailsElement { document, HTMLDetailsElementBinding::Wrap) } - - pub fn check_toggle_count(&self, number: u32) -> bool { - number == self.toggle_counter.get() - } } impl HTMLDetailsElementMethods for HTMLDetailsElement { @@ -72,27 +67,17 @@ impl VirtualMethods for HTMLDetailsElement { self.toggle_counter.set(counter); let window = window_from_node(self); - let task_source = window.dom_manipulation_task_source(); - let details = Trusted::new(self); - let task = box DetailsNotificationTask { - element: details, - toggle_number: counter - }; - let _ = task_source.queue(task, window.upcast()); - } - } -} - -pub struct DetailsNotificationTask { - element: Trusted, - toggle_number: u32 -} - -impl Task for DetailsNotificationTask { - fn run(self: Box) { - let target = self.element.root(); - if target.check_toggle_count(self.toggle_number) { - target.upcast::().fire_event(atom!("toggle")); + let this = Trusted::new(self); + // FIXME(nox): Why are errors silenced here? + let _ = window.dom_manipulation_task_source().queue( + box task!(details_notification_task_steps: move || { + let this = this.root(); + if counter == this.toggle_counter.get() { + this.upcast::().fire_event(atom!("toggle")); + } + }), + window.upcast(), + ); } } } From 56a546afcde4f33838b37792bbc7b91576ab79a7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 23:32:16 +0200 Subject: [PATCH 23/37] Use task! to send a storage notification --- components/script/dom/storage.rs | 45 ++++++++++---------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index fdd2ae4c504..3dbada1b334 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -19,7 +19,6 @@ use net_traits::IpcSend; use net_traits::storage_thread::{StorageThreadMsg, StorageType}; use script_traits::ScriptMsg; use servo_url::ServoUrl; -use task::Task; use task_source::TaskSource; #[dom_struct] @@ -166,41 +165,25 @@ impl Storage { new_value: Option, ) { let global = self.global(); + let this = Trusted::new(self); global.as_window().dom_manipulation_task_source().queue( - box StorageEventTask { - element: Trusted::new(self), - url, - key, - old_value, - new_value, - }, - global.upcast(), - ).unwrap(); - struct StorageEventTask { - element: Trusted, - url: ServoUrl, - key: Option, - old_value: Option, - new_value: Option - } - impl Task for StorageEventTask { - fn run(self: Box) { - let this = *self; - let storage = this.element.root(); - let global = storage.global(); - let storage_event = StorageEvent::new( + box task!(send_storage_notification: move || { + let this = this.root(); + let global = this.global(); + let event = StorageEvent::new( global.as_window(), atom!("storage"), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, - this.key.map(DOMString::from), - this.old_value.map(DOMString::from), - this.new_value.map(DOMString::from), - DOMString::from(this.url.into_string()), - Some(&storage) + key.map(DOMString::from), + old_value.map(DOMString::from), + new_value.map(DOMString::from), + DOMString::from(url.into_string()), + Some(&this), ); - storage_event.upcast::().fire(global.upcast()); - } - } + event.upcast::().fire(global.upcast()); + }), + global.upcast(), + ).unwrap(); } } From 76745699d2805cdd283324ad254b357ea11e01cf Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 23:39:12 +0200 Subject: [PATCH 24/37] Use task! to post worker messages --- .../script/dom/dedicatedworkerglobalscope.rs | 10 ++++----- components/script/dom/worker.rs | 21 ------------------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 76c822e5679..abc7a9261a8 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -17,7 +17,7 @@ use dom::bindings::str::DOMString; use dom::bindings::structuredclone::StructuredCloneData; use dom::globalscope::GlobalScope; use dom::messageevent::MessageEvent; -use dom::worker::{TrustedWorkerAddress, WorkerErrorHandler, WorkerMessageHandler}; +use dom::worker::{TrustedWorkerAddress, Worker, WorkerErrorHandler}; use dom::workerglobalscope::WorkerGlobalScope; use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -375,10 +375,10 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope { unsafe fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult { let data = StructuredCloneData::write(cx, message)?; let worker = self.worker.borrow().as_ref().unwrap().clone(); - self.parent_sender - .send(CommonScriptMsg::Task(WorkerEvent, - box WorkerMessageHandler::new(worker, data))) - .unwrap(); + let task = box task!(post_worker_message: move || { + Worker::handle_message(worker, data); + }); + self.parent_sender.send(CommonScriptMsg::Task(WorkerEvent, task)).unwrap(); Ok(()) } diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 70efc86606a..9d9d635ffa5 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -198,27 +198,6 @@ impl WorkerMethods for Worker { event_handler!(error, GetOnerror, SetOnerror); } -pub struct WorkerMessageHandler { - addr: TrustedWorkerAddress, - data: StructuredCloneData, -} - -impl WorkerMessageHandler { - pub fn new(addr: TrustedWorkerAddress, data: StructuredCloneData) -> WorkerMessageHandler { - WorkerMessageHandler { - addr: addr, - data: data, - } - } -} - -impl Task for WorkerMessageHandler { - fn run(self: Box) { - let this = *self; - Worker::handle_message(this.addr, this.data); - } -} - impl Task for SimpleWorkerErrorHandler { #[allow(unrooted_must_root)] fn run(self: Box) { From c051fc1995ea290a780c2ad73a19ae9555bc2141 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 17 Sep 2017 23:49:18 +0200 Subject: [PATCH 25/37] Use task! for raf events from VR --- components/script/dom/vrdisplay.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 2b2ab80f2e5..9c86e5a6bf3 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -41,7 +41,6 @@ use std::mem; use std::rc::Rc; use std::sync::mpsc; use std::thread; -use task::Task; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVRFrameData, WebVRLayer, WebVRMsg}; #[dom_struct] @@ -511,11 +510,12 @@ impl VRDisplay { api_sender.send_vr(WebVRCommand::Create(display_id)).unwrap(); loop { // Run RAF callbacks on JavaScript thread - let msg = box NotifyDisplayRAF { - address: address.clone(), - sender: raf_sender.clone() - }; - js_sender.send(CommonScriptMsg::Task(WebVREvent, msg)).unwrap(); + let this = address.clone(); + let sender = raf_sender.clone(); + let task = box task!(handle_vrdisplay_raf: move || { + this.root().handle_raf(&sender); + }); + js_sender.send(CommonScriptMsg::Task(WebVREvent, task)).unwrap(); // Run Sync Poses in parallell on Render thread let msg = WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone()); @@ -608,19 +608,6 @@ impl VRDisplay { } } -struct NotifyDisplayRAF { - address: Trusted, - sender: mpsc::Sender> -} - -impl Task for NotifyDisplayRAF { - fn run(self: Box) { - let display = self.address.root(); - display.handle_raf(&self.sender); - } -} - - // WebVR Spec: If the number of values in the leftBounds/rightBounds arrays // is not 0 or 4 for any of the passed layers the promise is rejected fn parse_bounds(src: &Option>>, dst: &mut [f32; 4]) -> Result<(), &'static str> { From a6af86824b6e8a11441655dabb58767a908e1cd8 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 09:32:24 +0200 Subject: [PATCH 26/37] Use task! for posting messages --- components/script/dom/window.rs | 95 +++++++++++++++------------------ 1 file changed, 43 insertions(+), 52 deletions(-) diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 7492962e682..8694b77487b 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1969,59 +1969,50 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue println!("{}", debug_msg); } -struct PostMessageHandler { - destination: Trusted, - origin: Option, - message: StructuredCloneData, -} - -impl PostMessageHandler { - fn new(window: &Window, - origin: Option, - message: StructuredCloneData) -> PostMessageHandler { - PostMessageHandler { - destination: Trusted::new(window), - origin: origin, - message: message, - } - } -} - -impl Task for PostMessageHandler { - // https://html.spec.whatwg.org/multipage/#dom-window-postmessage steps 10-12. - fn run(self: Box) { - let this = *self; - let window = this.destination.root(); - - // Step 10. - let doc = window.Document(); - if let Some(source) = this.origin { - if !source.same_origin(doc.origin()) { - return; - } - } - - let cx = window.get_cx(); - let globalhandle = window.reflector().get_jsobject(); - let _ac = JSAutoCompartment::new(cx, globalhandle.get()); - - rooted!(in(cx) let mut message = UndefinedValue()); - this.message.read(window.upcast(), message.handle_mut()); - - // Step 11-12. - // TODO(#12719): set the other attributes. - MessageEvent::dispatch_jsval(window.upcast(), - window.upcast(), - message.handle()); - } -} - impl Window { - pub fn post_message(&self, origin: Option, data: StructuredCloneData) { - let task = PostMessageHandler::new(self, origin, data); - let task = self.task_canceller().wrap_task(box task); - let msg = CommonScriptMsg::Task(ScriptThreadEventCategory::DomEvent, task); + // https://html.spec.whatwg.org/multipage/#dom-window-postmessage step 7. + pub fn post_message( + &self, + target_origin: Option, + serialize_with_transfer_result: StructuredCloneData, + ) { + let this = Trusted::new(self); + let task = box task!(post_serialised_message: move || { + let this = this.root(); + + // Step 7.1. + if let Some(target_origin) = target_origin { + if !target_origin.same_origin(this.Document().origin()) { + return; + } + } + + // Steps 7.2.-7.5. + let cx = this.get_cx(); + let obj = this.reflector().get_jsobject(); + let _ac = JSAutoCompartment::new(cx, obj.get()); + rooted!(in(cx) let mut message_clone = UndefinedValue()); + serialize_with_transfer_result.read( + this.upcast(), + message_clone.handle_mut(), + ); + + // Step 7.6. + // TODO: MessagePort array. + + // Step 7.7. + // TODO(#12719): Set the other attributes. + MessageEvent::dispatch_jsval( + this.upcast(), + this.upcast(), + message.handle(), + ); + }); + // FIXME(nox): Why are errors silenced here? // TODO(#12718): Use the "posted message task source". - let _ = self.script_chan.send(msg); + let _ = self.script_chan.send(CommonScriptMsg::Task( + ScriptThreadEventCategory::DomEvent, + self.task_canceller().wrap_task(task), + )); } } From c53d1e46b4756e2e1b15800139b617222e910415 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 09:40:45 +0200 Subject: [PATCH 27/37] Clean up GlobalScope::report_an_error --- components/script/dom/globalscope.rs | 32 ++++++++++++++++------------ components/script/dom/window.rs | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 529b1791d59..e298cb184c8 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -313,30 +313,34 @@ impl GlobalScope { // Step 2. self.in_error_reporting_mode.set(true); - // Steps 3-12. + // Steps 3-6. // FIXME(#13195): muted errors. - let event = ErrorEvent::new(self, - atom!("error"), - EventBubbles::DoesNotBubble, - EventCancelable::Cancelable, - error_info.message.as_str().into(), - error_info.filename.as_str().into(), - error_info.lineno, - error_info.column, - value); + let event = ErrorEvent::new( + self, + atom!("error"), + EventBubbles::DoesNotBubble, + EventCancelable::Cancelable, + error_info.message.as_str().into(), + error_info.filename.as_str().into(), + error_info.lineno, + error_info.column, + value, + ); - // Step 13. + // Step 7. let event_status = event.upcast::().fire(self.upcast::()); - // Step 15 + // Step 8. + self.in_error_reporting_mode.set(false); + + // Step 9. if event_status == EventStatus::NotCanceled { + // https://html.spec.whatwg.org/multipage/#runtime-script-errors-2 if let Some(dedicated) = self.downcast::() { dedicated.forward_error_to_worker_object(error_info); } } - // Step 14 - self.in_error_reporting_mode.set(false); } /// Get the `&ResourceThreads` for this global scope. diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 8694b77487b..1a44169fd1c 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -2005,7 +2005,7 @@ impl Window { MessageEvent::dispatch_jsval( this.upcast(), this.upcast(), - message.handle(), + message_clone.handle(), ); }); // FIXME(nox): Why are errors silenced here? From 1fa0e21e4b67bbd6407283f9df0d997c38c6c7b5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 09:45:20 +0200 Subject: [PATCH 28/37] Use task! to forward unhandled errors to worker objects --- .../script/dom/dedicatedworkerglobalscope.rs | 38 ++++++++++++--- components/script/dom/htmliframeelement.rs | 34 ++++--------- components/script/dom/window.rs | 2 +- components/script/dom/worker.rs | 48 +------------------ 4 files changed, 44 insertions(+), 78 deletions(-) diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index abc7a9261a8..46093a7bb7f 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -15,15 +15,18 @@ use dom::bindings::js::{Root, RootCollection}; use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; use dom::bindings::structuredclone::StructuredCloneData; +use dom::errorevent::ErrorEvent; +use dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; +use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::messageevent::MessageEvent; -use dom::worker::{TrustedWorkerAddress, Worker, WorkerErrorHandler}; +use dom::worker::{TrustedWorkerAddress, Worker}; use dom::workerglobalscope::WorkerGlobalScope; use dom_struct::dom_struct; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use js::jsapi::{HandleValue, JS_SetInterruptCallback}; -use js::jsapi::{JSAutoCompartment, JSContext}; +use js::jsapi::{JSAutoCompartment, JSContext, NullHandleValue}; use js::jsval::UndefinedValue; use js::rust::Runtime; use msg::constellation_msg::TopLevelBrowsingContextId; @@ -348,13 +351,36 @@ impl DedicatedWorkerGlobalScope { } } + // https://html.spec.whatwg.org/multipage/#runtime-script-errors-2 + #[allow(unsafe_code)] pub fn forward_error_to_worker_object(&self, error_info: ErrorInfo) { let worker = self.worker.borrow().as_ref().unwrap().clone(); + let task = box task!(forward_error_to_worker_object: move || { + let worker = worker.root(); + let global = worker.global(); + + // Step 1. + let event = ErrorEvent::new( + &global, + atom!("error"), + EventBubbles::DoesNotBubble, + EventCancelable::Cancelable, + error_info.message.as_str().into(), + error_info.filename.as_str().into(), + error_info.lineno, + error_info.column, + unsafe { NullHandleValue }, + ); + let event_status = + event.upcast::().fire(worker.upcast::()); + + // Step 2. + if event_status == EventStatus::NotCanceled { + global.report_an_error(error_info, unsafe { NullHandleValue }); + } + }); // TODO: Should use the DOM manipulation task source. - self.parent_sender - .send(CommonScriptMsg::Task(WorkerEvent, - box WorkerErrorHandler::new(worker, error_info))) - .unwrap(); + self.parent_sender.send(CommonScriptMsg::Task(WorkerEvent, task)).unwrap(); } } diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 0452c40d2f9..81a0f8417a7 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -54,7 +54,6 @@ use servo_url::ServoUrl; use std::cell::Cell; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::context::ReflowGoal; -use task::Task; use task_source::TaskSource; bitflags! { @@ -233,9 +232,15 @@ impl HTMLIFrameElement { // https://github.com/whatwg/html/issues/490 if mode == ProcessingMode::FirstTime && !self.upcast::().has_attribute(&local_name!("src")) { - let event_loop = window.dom_manipulation_task_source(); - let _ = event_loop.queue(box IFrameLoadEventSteps::new(self), - window.upcast()); + 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( + box task!(iframe_load_event_steps: move || { + this.root().iframe_load_event_steps(pipeline_id); + }), + window.upcast(), + ); return; } @@ -835,24 +840,3 @@ impl VirtualMethods for HTMLIFrameElement { self.destroy_nested_browsing_context(); } } - -struct IFrameLoadEventSteps { - frame_element: Trusted, - pipeline_id: PipelineId, -} - -impl IFrameLoadEventSteps { - fn new(frame_element: &HTMLIFrameElement) -> IFrameLoadEventSteps { - IFrameLoadEventSteps { - frame_element: Trusted::new(frame_element), - pipeline_id: frame_element.pipeline_id().unwrap(), - } - } -} - -impl Task for IFrameLoadEventSteps { - fn run(self: Box) { - let this = self.frame_element.root(); - this.iframe_load_event_steps(self.pipeline_id); - } -} diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 1a44169fd1c..c4a22c70757 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -111,7 +111,7 @@ use style::selector_parser::PseudoElement; use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::CssRuleType; use style_traits::PARSING_MODE_DEFAULT; -use task::{Task, TaskCanceller}; +use task::TaskCanceller; use task_source::dom_manipulation::DOMManipulationTaskSource; use task_source::file_reading::FileReadingTaskSource; use task_source::history_traversal::HistoryTraversalTaskSource; diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 9d9d635ffa5..d250633a49e 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -7,7 +7,7 @@ use dom::abstractworker::{SharedRt, SimpleWorkerErrorHandler}; use dom::abstractworker::WorkerScriptMsg; use dom::bindings::codegen::Bindings::WorkerBinding; use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods; -use dom::bindings::error::{Error, ErrorResult, Fallible, ErrorInfo}; +use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::bindings::refcounted::Trusted; @@ -15,15 +15,13 @@ use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bindings::structuredclone::StructuredCloneData; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; -use dom::errorevent::ErrorEvent; -use dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::messageevent::MessageEvent; use dom::workerglobalscope::prepare_workerscope_init; use dom_struct::dom_struct; use ipc_channel::ipc; -use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, NullHandleValue}; +use js::jsapi::{HandleValue, JSAutoCompartment, JSContext}; use js::jsval::UndefinedValue; use script_traits::WorkerScriptLoadOrigin; use std::cell::Cell; @@ -139,27 +137,6 @@ impl Worker { let worker = address.root(); worker.upcast().fire_event(atom!("error")); } - - #[allow(unsafe_code)] - fn dispatch_error(&self, error_info: ErrorInfo) { - let global = self.global(); - let event = ErrorEvent::new(&global, - atom!("error"), - EventBubbles::DoesNotBubble, - EventCancelable::Cancelable, - error_info.message.as_str().into(), - error_info.filename.as_str().into(), - error_info.lineno, - error_info.column, - unsafe { NullHandleValue }); - - let event_status = event.upcast::().fire(self.upcast::()); - if event_status == EventStatus::Canceled { - return; - } - - global.report_an_error(error_info, unsafe { NullHandleValue }); - } } impl WorkerMethods for Worker { @@ -205,24 +182,3 @@ impl Task for SimpleWorkerErrorHandler { Worker::dispatch_simple_error(this.addr); } } - -pub struct WorkerErrorHandler { - address: Trusted, - error_info: ErrorInfo, -} - -impl WorkerErrorHandler { - pub fn new(address: Trusted, error_info: ErrorInfo) -> WorkerErrorHandler { - WorkerErrorHandler { - address: address, - error_info: error_info, - } - } -} - -impl Task for WorkerErrorHandler { - fn run(self: Box) { - let this = *self; - this.address.root().dispatch_error(this.error_info); - } -} From 445a93eb8b52f8187b172a81d009b933e1de3ed8 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:09:45 +0200 Subject: [PATCH 29/37] Use task! to reestablish the event source connection --- components/script/dom/eventsource.rs | 72 ++++++++++++++-------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 438200e3bab..273ee2c0475 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -121,12 +121,43 @@ impl EventSourceContext { return; } - // Step 1 - let task = box ReestablishConnectionTask { - event_source: self.event_source.clone(), - action_sender: self.action_sender.clone() - }; - let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); + let trusted_event_source = self.event_source.clone(); + let action_sender = self.action_sender.clone(); + let global = event_source.global(); + // FIXME(nox): Why are errors silenced here? + let _ = global.networking_task_source().queue( + box task!(reestablish_the_event_source_onnection: move || { + let event_source = trusted_event_source.root(); + + // Step 1.1. + if event_source.ready_state.get() == ReadyState::Closed { + return; + } + + // Step 1.2. + event_source.ready_state.set(ReadyState::Connecting); + + // Step 1.3. + event_source.upcast::().fire_event(atom!("error")); + + // Step 2. + let duration = Length::new(event_source.reconnection_time.get()); + + // Step 3. + // TODO: Optionally wait some more. + + // Steps 4-5. + let callback = OneshotTimerCallback::EventSourceTimeout( + EventSourceTimeoutCallback { + event_source: trusted_event_source, + action_sender, + } + ); + // FIXME(nox): Why are errors silenced here? + let _ = event_source.global().schedule_callback(callback, duration); + }), + &global, + ); } // https://html.spec.whatwg.org/multipage/#processField @@ -499,35 +530,6 @@ impl Task for FailConnectionTask { } } -pub struct ReestablishConnectionTask { - event_source: Trusted, - action_sender: ipc::IpcSender, -} - -impl Task for ReestablishConnectionTask { - // https://html.spec.whatwg.org/multipage/#reestablish-the-connection - fn run(self: Box) { - let event_source = self.event_source.root(); - // Step 1.1 - if event_source.ready_state.get() == ReadyState::Closed { - return; - } - // Step 1.2 - event_source.ready_state.set(ReadyState::Connecting); - // Step 1.3 - event_source.upcast::().fire_event(atom!("error")); - // Step 2 - let duration = Length::new(event_source.reconnection_time.get()); - // TODO Step 3: Optionally wait some more - // Steps 4-5 - let callback = OneshotTimerCallback::EventSourceTimeout(EventSourceTimeoutCallback { - event_source: self.event_source.clone(), - action_sender: self.action_sender.clone() - }); - let _ = event_source.global().schedule_callback(callback, duration); - } -} - #[derive(HeapSizeOf, JSTraceable)] pub struct EventSourceTimeoutCallback { #[ignore_heap_size_of = "Because it is non-owning"] From 9339eb7d685710c5f096ec8c3f7ec038b1de2542 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:17:05 +0200 Subject: [PATCH 30/37] Use task! to dispatch events from event sources --- components/script/dom/eventsource.rs | 37 +++++++++++----------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 273ee2c0475..839dfad5589 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -216,12 +216,21 @@ impl EventSourceContext { // Step 7 self.event_type.clear(); self.data.clear(); - // Step 8 - let task = box DispatchEventTask { - event_source: self.event_source.clone(), - event: Trusted::new(&event) - }; - let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); + + // Step 8. + let global = event_source.global(); + let event_source = self.event_source.clone(); + let event = Trusted::new(&*event); + // FIXME(nox): Why are errors silenced here? + let _ = global.networking_task_source().queue( + box task!(dispatch_the_event_source_event: move || { + let event_source = event_source.root(); + if event_source.ready_state.get() != ReadyState::Closed { + event.root().upcast::().fire(&event_source.upcast()); + } + }), + &global, + ); } // https://html.spec.whatwg.org/multipage/#event-stream-interpretation @@ -557,19 +566,3 @@ impl EventSourceTimeoutCallback { global.core_resource_thread().send(CoreResourceMsg::Fetch(request, self.action_sender)).unwrap(); } } - -pub struct DispatchEventTask { - event_source: Trusted, - event: Trusted, -} - -impl Task for DispatchEventTask { - // https://html.spec.whatwg.org/multipage/#dispatchMessage - fn run(self: Box) { - let event_source = self.event_source.root(); - // Step 8 - if event_source.ready_state.get() != ReadyState::Closed { - self.event.root().upcast::().fire(&event_source.upcast()); - } - } -} From 7a5d7e2e90f581e8ac52742ff75732f234f9bf4c Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:22:18 +0200 Subject: [PATCH 31/37] Use task! to fail event source connections --- components/script/dom/eventsource.rs | 33 ++++++++++++---------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 839dfad5589..3e010c00663 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -102,15 +102,25 @@ impl EventSourceContext { let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); } + /// https://html.spec.whatwg.org/multipage/#fail-the-connection fn fail_the_connection(&self) { let event_source = self.event_source.root(); if self.gen_id != event_source.generation_id.get() { return; } - let task = box FailConnectionTask { - event_source: self.event_source.clone() - }; - let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); + let global = event_source.global(); + let event_source = self.event_source.clone(); + // FIXME(nox): Why are errors silenced here? + let _ = global.networking_task_source().queue( + box task!(fail_the_event_source_connection: move || { + let event_source = event_source.root(); + if event_source.ready_state.get() != ReadyState::Closed { + event_source.ready_state.set(ReadyState::Closed); + event_source.upcast::().fire_event(atom!("error")); + } + }), + &global, + ); } // https://html.spec.whatwg.org/multipage/#reestablish-the-connection @@ -524,21 +534,6 @@ impl Task for AnnounceConnectionTask { } } -pub struct FailConnectionTask { - event_source: Trusted, -} - -impl Task for FailConnectionTask { - // https://html.spec.whatwg.org/multipage/#fail-the-connection - fn run(self: Box) { - let event_source = self.event_source.root(); - if event_source.ready_state.get() != ReadyState::Closed { - event_source.ready_state.set(ReadyState::Closed); - event_source.upcast::().fire_event(atom!("error")); - } - } -} - #[derive(HeapSizeOf, JSTraceable)] pub struct EventSourceTimeoutCallback { #[ignore_heap_size_of = "Because it is non-owning"] From ad41ce7a6f679f4fda1382f010a0b7b145421708 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:25:19 +0200 Subject: [PATCH 32/37] Use task! to announce event source connections --- components/script/dom/eventsource.rs | 34 ++++++++++++---------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 3e010c00663..bf4c1c78c95 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -33,7 +33,6 @@ use std::cell::Cell; use std::mem; use std::str::{Chars, FromStr}; use std::sync::{Arc, Mutex}; -use task::Task; use task_source::TaskSource; use timers::OneshotTimerCallback; use utf8; @@ -91,15 +90,25 @@ struct EventSourceContext { } impl EventSourceContext { + /// https://html.spec.whatwg.org/multipage/#announce-the-connection fn announce_the_connection(&self) { let event_source = self.event_source.root(); if self.gen_id != event_source.generation_id.get() { return; } - let task = box AnnounceConnectionTask { - event_source: self.event_source.clone() - }; - let _ = event_source.global().networking_task_source().queue(task, &*event_source.global()); + let global = event_source.global(); + let event_source = self.event_source.clone(); + // FIXME(nox): Why are errors silenced here? + let _ = global.networking_task_source().queue( + box task!(announce_the_event_source_connection: move || { + let event_source = event_source.root(); + if event_source.ready_state.get() != ReadyState::Closed { + event_source.ready_state.set(ReadyState::Open); + event_source.upcast::().fire_event(atom!("open")); + } + }), + &global, + ); } /// https://html.spec.whatwg.org/multipage/#fail-the-connection @@ -519,21 +528,6 @@ impl EventSourceMethods for EventSource { } } -pub struct AnnounceConnectionTask { - event_source: Trusted, -} - -impl Task for AnnounceConnectionTask { - // https://html.spec.whatwg.org/multipage/#announce-the-connection - fn run(self: Box) { - let event_source = self.event_source.root(); - if event_source.ready_state.get() != ReadyState::Closed { - event_source.ready_state.set(ReadyState::Open); - event_source.upcast::().fire_event(atom!("open")); - } - } -} - #[derive(HeapSizeOf, JSTraceable)] pub struct EventSourceTimeoutCallback { #[ignore_heap_size_of = "Because it is non-owning"] From 851d40b204da546d5200e421439118b4e12c8d74 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:41:16 +0200 Subject: [PATCH 33/37] Use task! to reject promises --- components/script/dom/bindings/refcounted.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index 4da753cb833..c11232ee70a 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -123,18 +123,14 @@ impl TrustedPromise { /// A task which will reject the promise. #[allow(unrooted_must_root)] pub fn reject_task(self, error: Error) -> impl Send + Task { - struct RejectPromise(TrustedPromise, Error); - impl Task for RejectPromise { - fn run(self: Box) { - debug!("Rejecting promise."); - let this = *self; - let promise = this.0.root(); - let cx = promise.global().get_cx(); - let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get()); - promise.reject_error(cx, this.1); - } - } - RejectPromise(self, error) + let this = self; + task!(reject_promise: move || { + debug!("Rejecting promise."); + let this = this.root(); + let cx = this.global().get_cx(); + let _ac = JSAutoCompartment::new(cx, this.reflector().get_jsobject().get()); + this.reject_error(cx, error); + }) } /// A task which will resolve the promise. From a7655a3f84c4c379328ab28b9000cd923516b412 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:49:36 +0200 Subject: [PATCH 34/37] Use task! to resolve promises --- components/script/dom/bindings/refcounted.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index c11232ee70a..cdf80264edb 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -139,18 +139,14 @@ impl TrustedPromise { where T: ToJSValConvertible + Send, { - struct ResolvePromise(TrustedPromise, T); - impl Task for ResolvePromise { - fn run(self: Box) { - debug!("Resolving promise."); - let this = *self; - let promise = this.0.root(); - let cx = promise.global().get_cx(); - let _ac = JSAutoCompartment::new(cx, promise.reflector().get_jsobject().get()); - promise.resolve_native(cx, &this.1); - } - } - ResolvePromise(self, value) + let this = self; + task!(resolve_promise: move || { + debug!("Resolving promise."); + let this = this.root(); + let cx = this.global().get_cx(); + let _ac = JSAutoCompartment::new(cx, this.reflector().get_jsobject().get()); + this.resolve_native(cx, &value); + }) } } From 5ed6abe22c69fb71685c297b7a59e48550c5dbb5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:51:07 +0200 Subject: [PATCH 35/37] Preserve the name of inner tasks in cancellable ones --- components/script/task.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/script/task.rs b/components/script/task.rs index 35f202480ca..08f5c499aa6 100644 --- a/components/script/task.rs +++ b/components/script/task.rs @@ -82,6 +82,10 @@ impl Task for CancellableTask where T: Send + Task, { + fn name(&self) -> &'static str { + self.inner.name() + } + fn run(self: Box) { if !self.is_cancelled() { self.inner.run() From 99ff976e8507e647beec9892ca67b46753cf697e Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 10:54:11 +0200 Subject: [PATCH 36/37] Use task! to notify performance observers --- .../task_source/performance_timeline.rs | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/components/script/task_source/performance_timeline.rs b/components/script/task_source/performance_timeline.rs index 938566b7a8f..0b379d496f4 100644 --- a/components/script/task_source/performance_timeline.rs +++ b/components/script/task_source/performance_timeline.rs @@ -8,31 +8,12 @@ use dom::bindings::refcounted::Trusted; use dom::globalscope::GlobalScope; -use dom::performance::Performance; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use std::fmt; use std::result::Result; use task::{Task, TaskCanceller}; use task_source::TaskSource; -pub struct NotifyPerformanceObserverTask { - owner: Trusted, -} - -impl NotifyPerformanceObserverTask { - pub fn new(owner: Trusted) -> Self { - NotifyPerformanceObserverTask { - owner, - } - } -} - -impl Task for NotifyPerformanceObserverTask { - fn run(self: Box) { - self.owner.root().notify_observers(); - } -} - #[derive(JSTraceable)] pub struct PerformanceTimelineTaskSource(pub Box); @@ -68,7 +49,12 @@ impl TaskSource for PerformanceTimelineTaskSource { impl PerformanceTimelineTaskSource { pub fn queue_notification(&self, global: &GlobalScope) { let owner = Trusted::new(&*global.performance()); - let task = box NotifyPerformanceObserverTask::new(owner); - let _ = self.queue(task, global); + // FIXME(nox): Why are errors silenced here? + let _ = self.queue( + box task!(notify_performance_observers: move || { + owner.root().notify_observers(); + }), + global, + ); } } From 37fe4fbc851e0b8c45e71923efd14cf42c9eda0e Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 18 Sep 2017 11:00:54 +0200 Subject: [PATCH 37/37] Use task! to settle promises for jobs --- components/script/serviceworkerjob.rs | 41 +++++++-------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/components/script/serviceworkerjob.rs b/components/script/serviceworkerjob.rs index fef1d02e4da..cae17fc65b1 100644 --- a/components/script/serviceworkerjob.rs +++ b/components/script/serviceworkerjob.rs @@ -23,7 +23,6 @@ use servo_url::ServoUrl; use std::cmp::PartialEq; use std::collections::HashMap; use std::rc::Rc; -use task::Task; use task_source::TaskSource; use task_source::dom_manipulation::DOMManipulationTaskSource; @@ -262,33 +261,6 @@ impl JobQueue { } } -struct AsyncPromiseSettle { - global: Trusted, - promise: TrustedPromise, - settle_type: SettleType, -} - -impl Task for AsyncPromiseSettle { - #[allow(unrooted_must_root)] - fn run(self: Box) { - let global = self.global.root(); - let settle_type = self.settle_type.clone(); - let promise = self.promise.root(); - settle_job_promise(&*global, &*promise, settle_type) - } -} - -impl AsyncPromiseSettle { - #[allow(unrooted_must_root)] - fn new(promise: Rc, settle_type: SettleType) -> AsyncPromiseSettle { - AsyncPromiseSettle { - global: Trusted::new(&*promise.global()), - promise: TrustedPromise::new(promise), - settle_type: settle_type, - } - } -} - fn settle_job_promise(global: &GlobalScope, promise: &Promise, settle: SettleType) { let _ac = JSAutoCompartment::new(global.get_cx(), promise.reflector().get_jsobject().get()); match settle { @@ -297,11 +269,18 @@ fn settle_job_promise(global: &GlobalScope, promise: &Promise, settle: SettleTyp }; } +#[allow(unrooted_must_root)] fn queue_settle_promise_for_job(job: &Job, settle: SettleType, task_source: &DOMManipulationTaskSource) { - let task = box AsyncPromiseSettle::new(job.promise.clone(), settle); let global = job.client.global(); - let _ = task_source.queue(task, &*global); - + let promise = TrustedPromise::new(job.promise.clone()); + // FIXME(nox): Why are errors silenced here? + let _ = task_source.queue( + box task!(settle_promise_for_job: move || { + let promise = promise.root(); + settle_job_promise(&promise.global(), &promise, settle) + }), + &*global, + ); } // https://w3c.github.io/ServiceWorker/#reject-job-promise-algorithm