mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Auto merge of #9930 - rebstar6:htmlclick, r=jdm
Remove activatable element filter within HTMLElement#click() Address https://github.com/servo/servo/issues/6542 Ensure that click() calls are not limited to activatable elements. Also makes the isTrusted attribute false when synthetic click activation are called from a click() method (as per spec). <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9930) <!-- Reviewable:end -->
This commit is contained in:
commit
f2f6787189
9 changed files with 95 additions and 66 deletions
|
@ -29,14 +29,22 @@ pub trait Activatable {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
||||||
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
|
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether an activation was initiated via the click() method
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum ActivationSource {
|
||||||
|
FromClick,
|
||||||
|
NotFromClick,
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
|
||||||
fn synthetic_click_activation(&self,
|
pub fn synthetic_click_activation(element: &Element,
|
||||||
ctrlKey: bool,
|
ctrlKey: bool,
|
||||||
shiftKey: bool,
|
shiftKey: bool,
|
||||||
altKey: bool,
|
altKey: bool,
|
||||||
metaKey: bool) {
|
metaKey: bool,
|
||||||
let element = self.as_element();
|
source: ActivationSource) {
|
||||||
// Step 1
|
// Step 1
|
||||||
if element.click_in_progress() {
|
if element.click_in_progress() {
|
||||||
return;
|
return;
|
||||||
|
@ -44,12 +52,15 @@ pub trait Activatable {
|
||||||
// Step 2
|
// Step 2
|
||||||
element.set_click_in_progress(true);
|
element.set_click_in_progress(true);
|
||||||
// Step 3
|
// Step 3
|
||||||
self.pre_click_activation();
|
let activatable = element.as_maybe_activatable();
|
||||||
|
if let Some(a) = activatable {
|
||||||
|
a.pre_click_activation();
|
||||||
|
}
|
||||||
|
|
||||||
// Step 4
|
// Step 4
|
||||||
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
|
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
|
||||||
let win = window_from_node(element);
|
let win = window_from_node(element);
|
||||||
let target = element.upcast();
|
let target = element.upcast::<EventTarget>();
|
||||||
let mouse = MouseEvent::new(win.r(),
|
let mouse = MouseEvent::new(win.r(),
|
||||||
DOMString::from("click"),
|
DOMString::from("click"),
|
||||||
EventBubbles::DoesNotBubble,
|
EventBubbles::DoesNotBubble,
|
||||||
|
@ -67,17 +78,21 @@ pub trait Activatable {
|
||||||
0,
|
0,
|
||||||
None);
|
None);
|
||||||
let event = mouse.upcast::<Event>();
|
let event = mouse.upcast::<Event>();
|
||||||
event.fire(target);
|
if source == ActivationSource::FromClick {
|
||||||
|
event.set_trusted(false);
|
||||||
|
}
|
||||||
|
target.dispatch_event(event);
|
||||||
|
|
||||||
// Step 5
|
// Step 5
|
||||||
|
if let Some(a) = activatable {
|
||||||
if event.DefaultPrevented() {
|
if event.DefaultPrevented() {
|
||||||
self.canceled_activation();
|
a.canceled_activation();
|
||||||
} else {
|
} else {
|
||||||
// post click activation
|
// post click activation
|
||||||
self.activation_behavior(event, target);
|
a.activation_behavior(event, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6
|
// Step 6
|
||||||
element.set_click_in_progress(false);
|
element.set_click_in_progress(false);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use devtools_traits::CSSError;
|
use devtools_traits::CSSError;
|
||||||
use document_loader::{DocumentLoader, LoadType};
|
use document_loader::{DocumentLoader, LoadType};
|
||||||
|
use dom::activation::{ActivationSource, synthetic_click_activation};
|
||||||
use dom::attr::{Attr, AttrValue};
|
use dom::attr::{Attr, AttrValue};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
|
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
|
||||||
|
@ -1083,9 +1084,12 @@ impl Document {
|
||||||
Key::Space if !prevented && state == KeyState::Released => {
|
Key::Space if !prevented && state == KeyState::Released => {
|
||||||
let maybe_elem = target.downcast::<Element>();
|
let maybe_elem = target.downcast::<Element>();
|
||||||
if let Some(el) = maybe_elem {
|
if let Some(el) = maybe_elem {
|
||||||
if let Some(a) = el.as_maybe_activatable() {
|
synthetic_click_activation(el,
|
||||||
a.synthetic_click_activation(ctrl, alt, shift, meta);
|
false,
|
||||||
}
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
ActivationSource::NotFromClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Key::Enter if !prevented && state == KeyState::Released => {
|
Key::Enter if !prevented && state == KeyState::Released => {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::activation::Activatable;
|
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
|
||||||
|
@ -256,6 +256,11 @@ impl Activatable for HTMLButtonElement {
|
||||||
node.query_selector_iter(DOMString::from("button[type=submit]")).unwrap()
|
node.query_selector_iter(DOMString::from("button[type=submit]")).unwrap()
|
||||||
.filter_map(Root::downcast::<HTMLButtonElement>)
|
.filter_map(Root::downcast::<HTMLButtonElement>)
|
||||||
.find(|r| r.form_owner() == owner)
|
.find(|r| r.form_owner() == owner)
|
||||||
.map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
|
.map(|s| synthetic_click_activation(s.r().as_element(),
|
||||||
|
ctrlKey,
|
||||||
|
shiftKey,
|
||||||
|
altKey,
|
||||||
|
metaKey,
|
||||||
|
ActivationSource::NotFromClick));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::activation::{ActivationSource, synthetic_click_activation};
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::attr::AttrValue;
|
use dom::attr::AttrValue;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
|
@ -9,7 +10,6 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::HTMLElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::error::{Error, ErrorResult};
|
use dom::bindings::error::{Error, ErrorResult};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
|
@ -200,16 +200,15 @@ impl HTMLElementMethods for HTMLElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-click
|
// https://html.spec.whatwg.org/multipage/#dom-click
|
||||||
fn Click(&self) {
|
fn Click(&self) {
|
||||||
if let Some(i) = self.downcast::<HTMLInputElement>() {
|
if !self.upcast::<Element>().get_disabled_state() {
|
||||||
if i.Disabled() {
|
synthetic_click_activation(self.upcast::<Element>(),
|
||||||
return;
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
ActivationSource::FromClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27430 ?
|
|
||||||
self.upcast::<Element>()
|
|
||||||
.as_maybe_activatable()
|
|
||||||
.map(|a| a.synthetic_click_activation(false, false, false, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-focus
|
// https://html.spec.whatwg.org/multipage/#dom-focus
|
||||||
fn Focus(&self) {
|
fn Focus(&self) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use caseless::compatibility_caseless_match_str;
|
use caseless::compatibility_caseless_match_str;
|
||||||
use dom::activation::Activatable;
|
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
|
||||||
use dom::attr::{Attr, AttrValue};
|
use dom::attr::{Attr, AttrValue};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||||
|
@ -1091,7 +1091,12 @@ impl Activatable for HTMLInputElement {
|
||||||
match submit_button {
|
match submit_button {
|
||||||
Some(ref button) => {
|
Some(ref button) => {
|
||||||
if button.is_instance_activatable() {
|
if button.is_instance_activatable() {
|
||||||
button.synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey)
|
synthetic_click_activation(button.as_element(),
|
||||||
|
ctrlKey,
|
||||||
|
shiftKey,
|
||||||
|
altKey,
|
||||||
|
metaKey,
|
||||||
|
ActivationSource::NotFromClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::activation::Activatable;
|
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
|
||||||
use dom::attr::AttrValue;
|
use dom::attr::AttrValue;
|
||||||
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
|
||||||
|
@ -63,9 +63,12 @@ impl Activatable for HTMLLabelElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
|
||||||
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
|
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
|
||||||
self.upcast::<Element>()
|
synthetic_click_activation(self.upcast::<Element>(),
|
||||||
.as_maybe_activatable()
|
false,
|
||||||
.map(|a| a.synthetic_click_activation(false, false, false, false));
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
ActivationSource::NotFromClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
||||||
|
|
|
@ -15,6 +15,10 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[html]
|
[html]
|
||||||
skip: false
|
skip: false
|
||||||
|
[editing]
|
||||||
|
skip: true
|
||||||
|
[activation]
|
||||||
|
skip: false
|
||||||
[url]
|
[url]
|
||||||
skip: false
|
skip: false
|
||||||
[touch-events]
|
[touch-events]
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[throwing-in-listener-when-all-have-not-run-yet.html]
|
|
||||||
type: testharness
|
|
||||||
[Throwing in event listener]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
disabled: for now
|
|
Loading…
Add table
Add a link
Reference in a new issue