diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-12 09:00:14 -0700 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-12 09:00:14 -0700 |
commit | 42141870e764d0763bfbbdbed70b74399ee342de (patch) | |
tree | de8afbc81bf98ef03485d70faf3b0ae3db84bc9f | |
parent | 9189b9ee63df682a2fc2a57677a8197a69123696 (diff) | |
parent | f60de52aae628a114935ec5e7272596fd798fa1a (diff) | |
download | servo-42141870e764d0763bfbbdbed70b74399ee342de.tar.gz servo-42141870e764d0763bfbbdbed70b74399ee342de.zip |
Auto merge of #10714 - KiChjang:user-interaction-task, r=Ms2ger
Implement user interaction task source
Part of #7959.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10714)
<!-- Reviewable:end -->
-rw-r--r-- | components/script/dom/bindings/global.rs | 9 | ||||
-rw-r--r-- | components/script/dom/htmldetailselement.rs | 8 | ||||
-rw-r--r-- | components/script/dom/htmlinputelement.rs | 47 | ||||
-rw-r--r-- | components/script/dom/htmltextareaelement.rs | 19 | ||||
-rw-r--r-- | components/script/dom/window.rs | 2 | ||||
-rw-r--r-- | components/script/script_thread.rs | 10 | ||||
-rw-r--r-- | components/script/task_source/dom_manipulation.rs | 6 | ||||
-rw-r--r-- | components/script/task_source/mod.rs | 1 | ||||
-rw-r--r-- | components/script/task_source/user_interaction.rs | 48 | ||||
-rw-r--r-- | tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html | 26 |
10 files changed, 112 insertions, 64 deletions
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 17a2688a910..7dea10fd0a0 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -175,15 +175,6 @@ impl<'a> GlobalRef<'a> { /// `ScriptChan` used to send messages to the event loop of this global's /// thread. - pub fn user_interaction_task_source(&self) -> Box<ScriptChan + Send> { - match *self { - GlobalRef::Window(ref window) => window.user_interaction_task_source(), - GlobalRef::Worker(ref worker) => worker.script_chan(), - } - } - - /// `ScriptChan` used to send messages to the event loop of this global's - /// thread. pub fn networking_task_source(&self) -> Box<ScriptChan + Send> { match *self { GlobalRef::Window(ref window) => window.networking_task_source(), diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 3f00e53220c..724c9cff614 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -74,7 +74,7 @@ impl VirtualMethods for HTMLDetailsElement { let window = window.r(); let task_source = window.dom_manipulation_task_source(); let details = Trusted::new(self); - let runnable = box ToggleEventRunnable { + let runnable = box DetailsNotificationRunnable { element: details, toggle_number: counter }; @@ -83,13 +83,13 @@ impl VirtualMethods for HTMLDetailsElement { } } -pub struct ToggleEventRunnable { +pub struct DetailsNotificationRunnable { element: Trusted<HTMLDetailsElement>, toggle_number: u32 } -impl Runnable for ToggleEventRunnable { - fn handler(self: Box<ToggleEventRunnable>) { +impl Runnable for DetailsNotificationRunnable { + fn handler(self: Box<DetailsNotificationRunnable>) { let target = self.element.root(); if target.check_toggle_count(self.toggle_number) { target.upcast::<EventTarget>().fire_simple_event("toggle"); diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 0e675b35b27..a226a2e224c 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -12,10 +12,8 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; use dom::bindings::error::{Error, ErrorResult}; -use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, LayoutJS, Root, RootedReference}; -use dom::bindings::refcounted::Trusted; use dom::document::Document; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers, LayoutElementHelpers}; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -31,9 +29,7 @@ use dom::nodelist::NodeList; use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; -use script_runtime::CommonScriptMsg; -use script_runtime::ScriptThreadEventCategory::InputEvent; -use script_thread::Runnable; +use script_runtime::ScriptChan; use script_traits::ScriptMsg as ConstellationMsg; use std::borrow::ToOwned; use std::cell::Cell; @@ -549,6 +545,12 @@ impl HTMLInputElementMethods for HTMLInputElement { let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); self.textinput.borrow_mut().selection_direction = direction; self.textinput.borrow_mut().set_selection_range(start, end); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); } } @@ -919,7 +921,12 @@ impl VirtualMethods for HTMLInputElement { self.value_changed.set(true); if event.IsTrusted() { - ChangeEventRunnable::send(self.upcast::<Node>()); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("input"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); } self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); @@ -1148,31 +1155,3 @@ impl Activatable for HTMLInputElement { } } } - -pub struct ChangeEventRunnable { - element: Trusted<Node>, -} - -impl ChangeEventRunnable { - pub fn send(node: &Node) { - let handler = Trusted::new(node); - let dispatcher = ChangeEventRunnable { - element: handler, - }; - let chan = window_from_node(node).user_interaction_task_source(); - let _ = chan.send(CommonScriptMsg::RunnableMsg(InputEvent, box dispatcher)); - } -} - -impl Runnable for ChangeEventRunnable { - fn handler(self: Box<ChangeEventRunnable>) { - let target = self.element.root(); - let window = window_from_node(target.r()); - let window = window.r(); - let event = Event::new(GlobalRef::Window(window), - atom!("input"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable); - target.upcast::<EventTarget>().dispatch_event(&event); - } -} diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 597c9a2bb60..122d73e8553 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -14,18 +14,18 @@ use dom::bindings::reflector::{Reflectable}; use dom::document::Document; use dom::element::RawLayoutElementHelpers; use dom::element::{AttributeMutation, Element}; -use dom::event::{Event}; +use dom::event::{Event, EventBubbles, EventCancelable}; use dom::htmlelement::HTMLElement; use dom::htmlfieldsetelement::HTMLFieldSetElement; use dom::htmlformelement::{FormControl, HTMLFormElement}; -use dom::htmlinputelement::ChangeEventRunnable; use dom::keyboardevent::KeyboardEvent; use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext}; -use dom::node::{document_from_node}; +use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; +use script_runtime::ScriptChan; use script_traits::ScriptMsg as ConstellationMsg; use std::cell::Cell; use std::ops::Range; @@ -256,6 +256,12 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); self.textinput.borrow_mut().selection_direction = direction; self.textinput.borrow_mut().set_selection_range(start, end); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); } } @@ -373,7 +379,12 @@ impl VirtualMethods for HTMLTextAreaElement { self.value_changed.set(true); if event.IsTrusted() { - ChangeEventRunnable::send(self.upcast::<Node>()); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("input"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); } self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index cb8f0c59639..9f993c25461 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -275,7 +275,7 @@ impl Window { self.dom_manipulation_task_source.clone() } - pub fn user_interaction_task_source(&self) -> Box<ScriptChan + Send> { + pub fn user_interaction_task_source(&self) -> UserInteractionTaskSource { self.user_interaction_task_source.clone() } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 9bd7ce26c4f..02f8d9a83ea 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -99,7 +99,7 @@ use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTa use task_source::file_reading::FileReadingTaskSource; use task_source::history_traversal::HistoryTraversalTaskSource; use task_source::networking::NetworkingTaskSource; -use task_source::user_interaction::UserInteractionTaskSource; +use task_source::user_interaction::{UserInteractionTaskSource, UserInteractionTask}; use time::Tm; use url::{Url, Position}; use util::opts; @@ -222,6 +222,8 @@ pub enum MainThreadScriptMsg { Navigate(PipelineId, LoadData), /// Tasks that originate from the DOM manipulation task source DOMManipulation(DOMManipulationTask), + /// Tasks that originate from the user interaction task source + UserInteraction(UserInteractionTask), } impl OpaqueSender<CommonScriptMsg> for Box<ScriptChan + Send> { @@ -928,8 +930,10 @@ impl ScriptThread { LiveDOMReferences::cleanup(addr), MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => self.collect_reports(reports_chan), - MainThreadScriptMsg::DOMManipulation(msg) => - msg.handle_msg(self), + MainThreadScriptMsg::DOMManipulation(task) => + task.handle_task(self), + MainThreadScriptMsg::UserInteraction(task) => + task.handle_task(), } } diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index 5993825a1be..05b0722f889 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -18,8 +18,10 @@ impl TaskSource<DOMManipulationTask> for DOMManipulationTaskSource { fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> { self.0.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ()) } +} - fn clone(&self) -> Box<TaskSource<DOMManipulationTask> + Send> { +impl DOMManipulationTaskSource { + pub fn clone(&self) -> Box<TaskSource<DOMManipulationTask> + Send> { box DOMManipulationTaskSource((&self.0).clone()) } } @@ -42,7 +44,7 @@ pub enum DOMManipulationTask { } impl DOMManipulationTask { - pub fn handle_msg(self, script_thread: &ScriptThread) { + pub fn handle_task(self, script_thread: &ScriptThread) { use self::DOMManipulationTask::*; match self { diff --git a/components/script/task_source/mod.rs b/components/script/task_source/mod.rs index 74dd7347e9e..fe2d159b04a 100644 --- a/components/script/task_source/mod.rs +++ b/components/script/task_source/mod.rs @@ -12,5 +12,4 @@ use std::result::Result; pub trait TaskSource<T> { fn queue(&self, msg: T) -> Result<(), ()>; - fn clone(&self) -> Box<TaskSource<T> + Send>; } diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 8f79b8ddaed..59d7d728185 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -2,19 +2,55 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use script_runtime::{CommonScriptMsg, ScriptChan}; +use dom::bindings::refcounted::Trusted; +use dom::event::{EventBubbles, EventCancelable}; +use dom::eventtarget::EventTarget; +use script_runtime::ScriptChan; use script_thread::MainThreadScriptMsg; +use std::result::Result; use std::sync::mpsc::Sender; +use string_cache::Atom; +use task_source::TaskSource; #[derive(JSTraceable)] pub struct UserInteractionTaskSource(pub Sender<MainThreadScriptMsg>); -impl ScriptChan for UserInteractionTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) +impl TaskSource<UserInteractionTask> for UserInteractionTaskSource { + fn queue(&self, msg: UserInteractionTask) -> Result<(), ()> { + self.0.send(MainThreadScriptMsg::UserInteraction(msg)).map_err(|_| ()) } +} + +impl UserInteractionTaskSource { + pub fn queue_event(&self, + target: &EventTarget, + name: Atom, + bubbles: EventBubbles, + cancelable: EventCancelable) { + let target = Trusted::new(target); + let _ = self.0.send(MainThreadScriptMsg::UserInteraction(UserInteractionTask::FireEvent( + target, name, bubbles, cancelable))); + } + + pub fn clone(&self) -> UserInteractionTaskSource { + UserInteractionTaskSource((&self.0).clone()) + } +} + +pub enum UserInteractionTask { + // https://dom.spec.whatwg.org/#concept-event-fire + FireEvent(Trusted<EventTarget>, Atom, EventBubbles, EventCancelable), +} + +impl UserInteractionTask { + pub fn handle_task(self) { + use self::UserInteractionTask::*; - fn clone(&self) -> Box<ScriptChan + Send> { - box UserInteractionTaskSource((&self.0).clone()) + match self { + FireEvent(element, name, bubbles, cancelable) => { + let target = element.root(); + target.fire_event(&*name, bubbles, cancelable); + } + } } } diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html index 06915a81a8b..5f525736201 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html @@ -116,6 +116,19 @@ test(function() { },'input setSelectionRange(undefined,1)'); },"test of input.setSelectionRange"); +async_test(function() { + var q = false; + var input = document.getElementById("a"); + input.addEventListener("select", this.step_func_done(function(e) { + assert_true(q, "event should be queued"); + assert_true(e.isTrusted, "event is trusted"); + assert_true(e.bubbles, "event bubbles"); + assert_false(e.cancelable, "event is not cancelable"); + })); + input.setSelectionRange(0, 1); + q = true; +}, "input setSelectionRange fires a select event"); + test(function() { var textarea = document.getElementById("b"); test(function() { @@ -221,4 +234,17 @@ test(function() { assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1"); },'textarea setSelectionRange(undefined,1)'); },"test of textarea.setSelectionRange"); + +async_test(function() { + var q = false; + var textarea = document.getElementById("b"); + textarea.addEventListener("select", this.step_func_done(function(e) { + assert_true(q, "event should be queued"); + assert_true(e.isTrusted, "event is trusted"); + assert_true(e.bubbles, "event bubbles"); + assert_false(e.cancelable, "event is not cancelable"); + })); + textarea.setSelectionRange(0, 1); + q = true; +}, "textarea setSelectionRange fires a select event"); </script> |