diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 669c4d9a31a..8630d64eb7a 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -1488,11 +1488,12 @@ impl Document { update_with_current_time_ms(&self.dom_content_loaded_event_start); - self.window().dom_manipulation_task_source().queue_event(self.upcast(), atom!("DOMContentLoaded"), - EventBubbles::Bubbles, EventCancelable::NotCancelable); - self.window().reflow(ReflowGoal::ForDisplay, - ReflowQueryType::NoQuery, - ReflowReason::DOMContentLoaded); + let window = self.window(); + window.dom_manipulation_task_source().queue_event(self.upcast(), atom!("DOMContentLoaded"), + EventBubbles::Bubbles, EventCancelable::NotCancelable, window); + window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::DOMContentLoaded); update_with_current_time_ms(&self.dom_content_loaded_event_end); } diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 9174fa2cb3d..da7664e0e19 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -8,9 +8,11 @@ use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethod use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::eventtarget::EventTarget; +use script_thread::Runnable; use std::cell::Cell; use std::default::Default; use string_cache::Atom; @@ -26,7 +28,7 @@ pub enum EventPhase { Bubbling = EventConstants::BUBBLING_PHASE, } -#[derive(PartialEq, HeapSizeOf)] +#[derive(PartialEq, HeapSizeOf, Copy, Clone)] pub enum EventBubbles { Bubbles, DoesNotBubble @@ -50,7 +52,7 @@ impl From for EventBubbles { } } -#[derive(PartialEq, HeapSizeOf)] +#[derive(PartialEq, HeapSizeOf, Copy, Clone)] pub enum EventCancelable { Cancelable, NotCancelable @@ -297,3 +299,35 @@ impl Event { target.dispatch_event(self) } } + +// https://dom.spec.whatwg.org/#concept-event-fire +pub struct EventRunnable { + pub target: Trusted, + pub name: Atom, + pub bubbles: EventBubbles, + pub cancelable: EventCancelable, +} + +impl Runnable for EventRunnable { + fn name(&self) -> &'static str { "EventRunnable" } + + fn handler(self: Box) { + let target = self.target.root(); + target.fire_event(&*self.name, self.bubbles, self.cancelable); + } +} + +// https://html.spec.whatwg.org/multipage/#fire-a-simple-event +pub struct SimpleEventRunnable { + pub target: Trusted, + pub name: Atom, +} + +impl Runnable for SimpleEventRunnable { + fn name(&self) -> &'static str { "SimpleEventRunnable" } + + fn handler(self: Box) { + let target = self.target.root(); + target.fire_simple_event(&*self.name); + } +} diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index f8fc6545f8d..619c8263e3f 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -19,7 +19,6 @@ use script_thread::Runnable; use std::cell::Cell; use string_cache::Atom; use task_source::TaskSource; -use task_source::dom_manipulation::DOMManipulationTask; #[dom_struct] pub struct HTMLDetailsElement { @@ -72,14 +71,13 @@ impl VirtualMethods for HTMLDetailsElement { self.toggle_counter.set(counter); let window = window_from_node(self); - let window = window.r(); let task_source = window.dom_manipulation_task_source(); let details = Trusted::new(self); let runnable = box DetailsNotificationRunnable { element: details, toggle_number: counter }; - let _ = task_source.queue(DOMManipulationTask::Runnable(runnable)); + let _ = task_source.queue(runnable, window.r()); } } } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 18c30a9d86c..f2615ff0374 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -53,7 +53,6 @@ use string_cache::Atom; use style::attr::AttrValue; use style::str::split_html_space_chars; use task_source::TaskSource; -use task_source::dom_manipulation::DOMManipulationTask; use url::form_urlencoded; #[derive(JSTraceable, PartialEq, Clone, Copy, HeapSizeOf)] @@ -484,7 +483,7 @@ impl HTMLFormElement { }; // Step 3 - window.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(nav)).unwrap(); + window.dom_manipulation_task_source().queue(nav, window).unwrap(); } /// Interactively validate the constraints of form elements diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 8c28b1e8c8d..52d5c9d7222 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -32,7 +32,6 @@ use std::sync::Arc; use string_cache::Atom; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use task_source::TaskSource; -use task_source::dom_manipulation::DOMManipulationTask; use url::Url; #[derive(JSTraceable, HeapSizeOf)] @@ -141,7 +140,7 @@ impl HTMLImageElement { // Return the image via a message to the script thread, which marks the element // as dirty and triggers a reflow. let image_response = message.to().unwrap(); - let runnable = ImageResponseHandlerRunnable::new( + let runnable = box ImageResponseHandlerRunnable::new( trusted_node.clone(), image_response); let runnable = wrapper.wrap_runnable(runnable); let _ = script_chan.send(CommonScriptMsg::RunnableMsg( @@ -180,12 +179,12 @@ impl HTMLImageElement { } } - let runnable = Box::new(ImgParseErrorRunnable { + let runnable = box ImgParseErrorRunnable { img: Trusted::new(self), src: src.into(), - }); + }; let task = window.dom_manipulation_task_source(); - let _ = task.queue(DOMManipulationTask::Runnable(runnable)); + let _ = task.queue(runnable, window); } } } diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 35e2a6f5116..9ec4dd53ab8 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -577,7 +577,8 @@ impl HTMLInputElementMethods for HTMLInputElement { &self.upcast(), atom!("select"), EventBubbles::Bubbles, - EventCancelable::NotCancelable); + EventCancelable::NotCancelable, + window.r()); self.upcast::().dirty(NodeDamage::OtherNodeDamage); } @@ -1070,7 +1071,8 @@ impl VirtualMethods for HTMLInputElement { &self.upcast(), atom!("input"), EventBubbles::Bubbles, - EventCancelable::NotCancelable); + EventCancelable::NotCancelable, + window.r()); } self.upcast::().dirty(NodeDamage::OtherNodeDamage); diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index b38f796e57c..b95244f02bf 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -33,7 +33,6 @@ use std::cell::Cell; use std::sync::{Arc, Mutex}; use string_cache::Atom; use task_source::TaskSource; -use task_source::dom_manipulation::DOMManipulationTask; use time::{self, Timespec, Duration}; use url::Url; @@ -238,11 +237,11 @@ impl HTMLMediaElement { } } - let task = Task { + let task = box Task { elem: Trusted::new(self), }; let win = window_from_node(self); - let _ = win.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(box task)); + let _ = win.dom_manipulation_task_source().queue(task, win.r()); } // https://html.spec.whatwg.org/multipage/#internal-pause-steps step 2.2 @@ -262,17 +261,17 @@ impl HTMLMediaElement { } } - let task = Task { + let task = box Task { elem: Trusted::new(self), }; let win = window_from_node(self); - let _ = win.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(box task)); + let _ = win.dom_manipulation_task_source().queue(task, win.r()); } fn queue_fire_simple_event(&self, type_: &'static str) { let win = window_from_node(self); - let task = FireSimpleEventTask::new(self, type_); - let _ = win.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(box task)); + let task = box FireSimpleEventTask::new(self, type_); + let _ = win.dom_manipulation_task_source().queue(task, win.r()); } fn fire_simple_event(&self, type_: &str) { @@ -498,8 +497,8 @@ impl HTMLMediaElement { } fn queue_dedicated_media_source_failure_steps(&self) { - let _ = window_from_node(self).dom_manipulation_task_source().queue( - DOMManipulationTask::Runnable(box DedicatedMediaSourceFailureTask::new(self))); + let window = window_from_node(self); + let _ = window.dom_manipulation_task_source().queue(box DedicatedMediaSourceFailureTask::new(self), window.r()); } // https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 2d10e5f43d8..5195b0e53a6 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -460,12 +460,13 @@ impl HTMLScriptElement { if external { self.dispatch_load_event(); } else { - window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("load")); + window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("load"), window.r()); } } pub fn queue_error_event(&self) { - window_from_node(self).dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error")); + let window = window_from_node(self); + window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), window.r()); } pub fn dispatch_before_script_execute_event(&self) -> bool { diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 69fe9046dad..5fb3a6ea102 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -260,7 +260,8 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { &self.upcast(), atom!("select"), EventBubbles::Bubbles, - EventCancelable::NotCancelable); + EventCancelable::NotCancelable, + window.r()); self.upcast::().dirty(NodeDamage::OtherNodeDamage); } } @@ -383,7 +384,8 @@ impl VirtualMethods for HTMLTextAreaElement { &self.upcast(), atom!("input"), EventBubbles::Bubbles, - EventCancelable::NotCancelable); + EventCancelable::NotCancelable, + window.r()); } self.upcast::().dirty(NodeDamage::OtherNodeDamage); diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index d927c5ba213..11dfc3ab5d2 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_thread::{Runnable, ScriptThread}; use task_source::TaskSource; -use task_source::dom_manipulation::DOMManipulationTask; use url::Url; #[dom_struct] @@ -159,10 +158,10 @@ impl Storage { new_value: Option) { let global_root = self.global(); let global_ref = global_root.r(); - let task_source = global_ref.as_window().dom_manipulation_task_source(); + let window = global_ref.as_window(); + let task_source = window.dom_manipulation_task_source(); let trusted_storage = Trusted::new(self); - task_source.queue(DOMManipulationTask::Runnable( - box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap(); + task_source.queue(box StorageEventRunnable::new(trusted_storage, key, old_value, new_value), window).unwrap(); } } diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index 5d37b025cca..1dd0d8f0a34 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -19,20 +19,17 @@ pub struct NetworkListener { impl NetworkListener { pub fn notify + Send + 'static>(&self, action: A) { - let runnable = ListenerRunnable { + let runnable = box ListenerRunnable { context: self.context.clone(), action: action, }; - if let Some(ref wrapper) = self.wrapper { - if let Err(err) = self.script_chan.send( - CommonScriptMsg::RunnableMsg(NetworkEvent, wrapper.wrap_runnable(runnable))) { - warn!("failed to deliver network data: {:?}", err); - } + let result = if let Some(ref wrapper) = self.wrapper { + self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, wrapper.wrap_runnable(runnable))) } else { - if let Err(err) = self.script_chan.send( - CommonScriptMsg::RunnableMsg(NetworkEvent, box runnable)) { - warn!("failed to deliver network data: {:?}", err); - } + self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, runnable)) + }; + if let Err(err) = result { + warn!("failed to deliver network data: {:?}", err); } } } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index e116ace1be4..788ec212a72 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -174,10 +174,10 @@ pub struct RunnableWrapper { } impl RunnableWrapper { - pub fn wrap_runnable(&self, runnable: T) -> Box { + pub fn wrap_runnable(&self, runnable: Box) -> Box { box CancellableRunnable { cancelled: self.cancelled.clone(), - inner: box runnable, + inner: runnable, } } } @@ -189,10 +189,16 @@ pub struct CancellableRunnable { } impl Runnable for CancellableRunnable { + fn name(&self) -> &'static str { self.inner.name() } + fn is_cancelled(&self) -> bool { self.cancelled.load(Ordering::SeqCst) } + fn main_thread_handler(self: Box>, script_thread: &ScriptThread) { + self.inner.main_thread_handler(script_thread); + } + fn handler(self: Box>) { self.inner.handler() } @@ -982,7 +988,7 @@ impl ScriptThread { MainThreadScriptMsg::DOMManipulation(task) => task.handle_task(self), MainThreadScriptMsg::UserInteraction(task) => - task.handle_task(), + task.handle_task(self), } } @@ -1221,7 +1227,7 @@ impl ScriptThread { // https://html.spec.whatwg.org/multipage/#the-end step 7 let handler = box DocumentProgressHandler::new(Trusted::new(doc)); - self.dom_manipulation_task_source.queue(DOMManipulationTask::Runnable(handler)).unwrap(); + self.dom_manipulation_task_source.queue(handler, doc.window()).unwrap(); self.constellation_chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap(); } diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index a1c06f2c09e..b8bad662353 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -3,8 +3,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::refcounted::Trusted; -use dom::event::{EventBubbles, EventCancelable}; +use dom::event::{EventBubbles, EventCancelable, EventRunnable, SimpleEventRunnable}; use dom::eventtarget::EventTarget; +use dom::window::Window; use script_thread::{MainThreadScriptMsg, Runnable, ScriptThread}; use std::result::Result; use std::sync::mpsc::Sender; @@ -14,8 +15,9 @@ use task_source::TaskSource; #[derive(JSTraceable, Clone)] pub struct DOMManipulationTaskSource(pub Sender); -impl TaskSource for DOMManipulationTaskSource { - fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> { +impl TaskSource for DOMManipulationTaskSource { + fn queue(&self, msg: Box, window: &Window) -> Result<(), ()> { + let msg = DOMManipulationTask(window.get_runnable_wrapper().wrap_runnable(msg)); self.0.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ()) } } @@ -25,46 +27,34 @@ impl DOMManipulationTaskSource { target: &EventTarget, name: Atom, bubbles: EventBubbles, - cancelable: EventCancelable) { + cancelable: EventCancelable, + window: &Window) { let target = Trusted::new(target); - let _ = self.0.send(MainThreadScriptMsg::DOMManipulation(DOMManipulationTask::FireEvent( - target, name, bubbles, cancelable))); + let runnable = box EventRunnable { + target: target, + name: name, + bubbles: bubbles, + cancelable: cancelable, + }; + let _ = self.queue(runnable, window); } - pub fn queue_simple_event(&self, target: &EventTarget, name: Atom) { + pub fn queue_simple_event(&self, target: &EventTarget, name: Atom, window: &Window) { let target = Trusted::new(target); - let _ = self.0.send(MainThreadScriptMsg::DOMManipulation(DOMManipulationTask::FireSimpleEvent( - target, name))); + let runnable = box SimpleEventRunnable { + target: target, + name: name, + }; + let _ = self.queue(runnable, window); } } -pub enum DOMManipulationTask { - // https://dom.spec.whatwg.org/#concept-event-fire - FireEvent(Trusted, Atom, EventBubbles, EventCancelable), - // https://html.spec.whatwg.org/multipage/#fire-a-simple-event - FireSimpleEvent(Trusted, Atom), - - Runnable(Box), -} +pub struct DOMManipulationTask(pub Box); impl DOMManipulationTask { pub fn handle_task(self, script_thread: &ScriptThread) { - use self::DOMManipulationTask::*; - - match self { - FireEvent(element, name, bubbles, cancelable) => { - let target = element.root(); - target.fire_event(&*name, bubbles, cancelable); - } - FireSimpleEvent(element, name) => { - let target = element.root(); - target.fire_simple_event(&*name); - } - Runnable(runnable) => { - if !runnable.is_cancelled() { - runnable.main_thread_handler(script_thread); - } - } + if !self.0.is_cancelled() { + self.0.main_thread_handler(script_thread); } } } diff --git a/components/script/task_source/mod.rs b/components/script/task_source/mod.rs index fe2d159b04a..48fc775d959 100644 --- a/components/script/task_source/mod.rs +++ b/components/script/task_source/mod.rs @@ -8,8 +8,10 @@ pub mod history_traversal; pub mod networking; pub mod user_interaction; +use dom::window::Window; +use script_thread::Runnable; use std::result::Result; -pub trait TaskSource { - fn queue(&self, msg: T) -> Result<(), ()>; +pub trait TaskSource { + fn queue(&self, msg: Box, window: &Window) -> Result<(), ()>; } diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 24dd59af222..2f4c0923801 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -3,9 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::refcounted::Trusted; -use dom::event::{EventBubbles, EventCancelable}; +use dom::event::{EventBubbles, EventCancelable, EventRunnable}; use dom::eventtarget::EventTarget; -use script_thread::MainThreadScriptMsg; +use dom::window::Window; +use script_thread::{MainThreadScriptMsg, Runnable, ScriptThread}; use std::result::Result; use std::sync::mpsc::Sender; use string_cache::Atom; @@ -14,38 +15,37 @@ use task_source::TaskSource; #[derive(JSTraceable, Clone)] pub struct UserInteractionTaskSource(pub Sender); -impl TaskSource for UserInteractionTaskSource { - fn queue(&self, msg: UserInteractionTask) -> Result<(), ()> { +impl TaskSource for UserInteractionTaskSource { + fn queue(&self, msg: Box, window: &Window) -> Result<(), ()> { + let msg = UserInteractionTask(window.get_runnable_wrapper().wrap_runnable(msg)); self.0.send(MainThreadScriptMsg::UserInteraction(msg)).map_err(|_| ()) } } impl UserInteractionTaskSource { pub fn queue_event(&self, - target: &EventTarget, - name: Atom, - bubbles: EventBubbles, - cancelable: EventCancelable) { + target: &EventTarget, + name: Atom, + bubbles: EventBubbles, + cancelable: EventCancelable, + window: &Window) { let target = Trusted::new(target); - let _ = self.0.send(MainThreadScriptMsg::UserInteraction(UserInteractionTask::FireEvent( - target, name, bubbles, cancelable))); + let runnable = box EventRunnable { + target: target, + name: name, + bubbles: bubbles, + cancelable: cancelable, + }; + let _ = self.queue(runnable, window); } } -pub enum UserInteractionTask { - // https://dom.spec.whatwg.org/#concept-event-fire - FireEvent(Trusted, Atom, EventBubbles, EventCancelable), -} +pub struct UserInteractionTask(pub Box); impl UserInteractionTask { - pub fn handle_task(self) { - use self::UserInteractionTask::*; - - match self { - FireEvent(element, name, bubbles, cancelable) => { - let target = element.root(); - target.fire_event(&*name, bubbles, cancelable); - } + pub fn handle_task(self, script_thread: &ScriptThread) { + if !self.0.is_cancelled() { + self.0.main_thread_handler(script_thread); } } } diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/change_parentage.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/change_parentage.html.ini deleted file mode 100644 index 5c3ee2555e4..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/change_parentage.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[change_parentage.html] - type: testharness - disabled: https://github.com/servo/servo/issues/11703