aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmlinputelement.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/htmlinputelement.rs')
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs209
1 files changed, 90 insertions, 119 deletions
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index a8a34a7357e..441206c9dad 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-use crate::dom::activation::{synthetic_click_activation, Activatable, ActivationSource};
+use crate::dom::activation::Activatable;
use crate::dom::attr::Attr;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
@@ -11,12 +11,11 @@ use crate::dom::bindings::codegen::Bindings::FileListBinding::FileListMethods;
use crate::dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode;
use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding;
use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
-use crate::dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods};
use crate::dom::bindings::error::{Error, ErrorResult};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::DomObject;
-use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
+use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::compositionevent::CompositionEvent;
use crate::dom::document::Document;
@@ -246,7 +245,6 @@ pub struct HTMLInputElement {
minlength: Cell<i32>,
#[ignore_malloc_size_of = "#7193"]
textinput: DomRefCell<TextInput<ScriptToConstellationChan>>,
- activation_state: DomRefCell<InputActivationState>,
// https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag
value_dirty: Cell<bool>,
// not specified explicitly, but implied by the fact that sanitization can't
@@ -260,30 +258,13 @@ pub struct HTMLInputElement {
}
#[derive(JSTraceable)]
-#[unrooted_must_root_lint::must_root]
-#[derive(MallocSizeOf)]
-struct InputActivationState {
+pub struct InputActivationState {
indeterminate: bool,
checked: bool,
- checked_changed: bool,
- checked_radio: Option<Dom<HTMLInputElement>>,
- // In case mutability changed
- was_mutable: bool,
+ checked_radio: Option<DomRoot<HTMLInputElement>>,
// In case the type changed
old_type: InputType,
-}
-
-impl InputActivationState {
- fn new() -> InputActivationState {
- InputActivationState {
- indeterminate: false,
- checked: false,
- checked_changed: false,
- checked_radio: None,
- was_mutable: false,
- old_type: Default::default(),
- }
- }
+ // was_mutable is implied: pre-activation would return None if it wasn't
}
static DEFAULT_INPUT_SIZE: u32 = 20;
@@ -323,7 +304,6 @@ impl HTMLInputElement {
None,
SelectionDirection::None,
)),
- activation_state: DomRefCell::new(InputActivationState::new()),
value_dirty: Cell::new(false),
sanitization_flag: Cell::new(true),
filelist: MutNullableDom::new(None),
@@ -1756,7 +1736,7 @@ impl HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#implicit-submission
#[allow(unsafe_code)]
- fn implicit_submission(&self, ctrl_key: bool, shift_key: bool, alt_key: bool, meta_key: bool) {
+ fn implicit_submission(&self) {
let doc = document_from_node(self);
let node = doc.upcast::<Node>();
let owner = self.form_owner();
@@ -1777,14 +1757,11 @@ impl HTMLInputElement {
match submit_button {
Some(ref button) => {
if button.is_instance_activatable() {
- synthetic_click_activation(
- button.as_element(),
- ctrl_key,
- shift_key,
- alt_key,
- meta_key,
- ActivationSource::NotFromClick,
- )
+ // spec does not actually say to set the not trusted flag,
+ // but we can get here from synthetic keydown events
+ button
+ .upcast::<Node>()
+ .fire_synthetic_mouse_event_not_trusted(DOMString::from("click"));
}
},
None => {
@@ -2199,14 +2176,19 @@ impl VirtualMethods for HTMLInputElement {
}
}
+ // This represents behavior for which the UIEvents spec and the
+ // DOM/HTML specs are out of sync.
+ // Compare:
+ // https://w3c.github.io/uievents/#default-action
+ // https://dom.spec.whatwg.org/#action-versus-occurance
fn handle_event(&self, event: &Event) {
if let Some(s) = self.super_type() {
s.handle_event(event);
}
if event.type_() == atom!("click") && !event.DefaultPrevented() {
- // TODO: Dispatch events for non activatable inputs
- // https://html.spec.whatwg.org/multipage/#common-input-element-events
+ // WHATWG-specified activation behaviors are handled elsewhere;
+ // this is for all the other things a UI click might do
//TODO: set the editing position for text inputs
@@ -2242,12 +2224,7 @@ impl VirtualMethods for HTMLInputElement {
let action = self.textinput.borrow_mut().handle_keydown(keyevent);
match action {
TriggerDefaultAction => {
- self.implicit_submission(
- keyevent.CtrlKey(),
- keyevent.ShiftKey(),
- keyevent.AltKey(),
- keyevent.MetaKey(),
- );
+ self.implicit_submission();
},
DispatchInput => {
self.value_dirty.set(true);
@@ -2365,91 +2342,90 @@ impl Activatable for HTMLInputElement {
}
}
- // https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps
- #[allow(unsafe_code)]
- fn pre_click_activation(&self) {
- let mut cache = self.activation_state.borrow_mut();
+ // https://dom.spec.whatwg.org/#eventtarget-legacy-pre-activation-behavior
+ fn legacy_pre_activation_behavior(&self) -> Option<InputActivationState> {
+ if !self.is_mutable() {
+ return None;
+ }
+
let ty = self.input_type();
- cache.old_type = ty;
- cache.was_mutable = self.is_mutable();
- if cache.was_mutable {
- match ty {
- // https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):activation-behavior
- // InputType::Submit => (), // No behavior defined
- // https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset):activation-behavior
- // InputType::Submit => (), // No behavior defined
- InputType::Checkbox => {
- /*
- https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):pre-click-activation-steps
- cache current values of `checked` and `indeterminate`
- we may need to restore them later
- */
- cache.indeterminate = self.Indeterminate();
- cache.checked = self.Checked();
- cache.checked_changed = self.checked_changed.get();
- self.SetIndeterminate(false);
- self.SetChecked(!cache.checked);
- },
- // https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):pre-click-activation-steps
- InputType::Radio => {
- let checked_member = radio_group_iter(self, self.radio_group_name().as_ref())
- .find(|r| r.Checked());
- cache.checked_radio = checked_member.as_deref().map(Dom::from_ref);
- cache.checked_changed = self.checked_changed.get();
- self.SetChecked(true);
- },
- _ => (),
- }
+ match ty {
+ InputType::Checkbox => {
+ let was_checked = self.Checked();
+ let was_indeterminate = self.Indeterminate();
+ self.SetIndeterminate(false);
+ self.SetChecked(!was_checked);
+ return Some(InputActivationState {
+ checked: was_checked,
+ indeterminate: was_indeterminate,
+ checked_radio: None,
+ old_type: InputType::Checkbox,
+ });
+ },
+ InputType::Radio => {
+ let checked_member =
+ radio_group_iter(self, self.radio_group_name().as_ref()).find(|r| r.Checked());
+ let was_checked = self.Checked();
+ self.SetChecked(true);
+ return Some(InputActivationState {
+ checked: was_checked,
+ indeterminate: false,
+ checked_radio: checked_member.as_deref().map(DomRoot::from_ref),
+ old_type: InputType::Radio,
+ });
+ },
+ _ => (),
}
+ return None;
}
- // https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps
- fn canceled_activation(&self) {
- let cache = self.activation_state.borrow();
- let ty = self.input_type();
- if cache.old_type != ty {
- // Type changed, abandon ship
- // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27414
+ // https://dom.spec.whatwg.org/#eventtarget-legacy-canceled-activation-behavior
+ fn legacy_canceled_activation_behavior(&self, cache: Option<InputActivationState>) {
+ // Step 1
+ if !self.is_mutable() {
return;
}
+ let ty = self.input_type();
+ let cache = match cache {
+ Some(cache) => {
+ if cache.old_type != ty {
+ // Type changed, abandon ship
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27414
+ return;
+ }
+ cache
+ },
+ None => {
+ return;
+ },
+ };
+
match ty {
- // https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):activation-behavior
- // InputType::Submit => (), // No behavior defined
- // https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset):activation-behavior
- // InputType::Reset => (), // No behavior defined
- // https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):canceled-activation-steps
+ // Step 2
InputType::Checkbox => {
- // We want to restore state only if the element had been changed in the first place
- if cache.was_mutable {
- self.SetIndeterminate(cache.indeterminate);
- self.SetChecked(cache.checked);
- self.checked_changed.set(cache.checked_changed);
- }
+ self.SetIndeterminate(cache.indeterminate);
+ self.SetChecked(cache.checked);
},
- // https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):canceled-activation-steps
+ // Step 3
InputType::Radio => {
- // We want to restore state only if the element had been changed in the first place
- if cache.was_mutable {
- if let Some(ref o) = cache.checked_radio {
- let tree_root = self
- .upcast::<Node>()
- .GetRootNode(&GetRootNodeOptions::empty());
- // Avoiding iterating through the whole tree here, instead
- // we can check if the conditions for radio group siblings apply
- if in_same_group(
- &o,
- self.form_owner().as_deref(),
- self.radio_group_name().as_ref(),
- Some(&*tree_root),
- ) {
- o.SetChecked(true);
- } else {
- self.SetChecked(false);
- }
+ if let Some(ref o) = cache.checked_radio {
+ let tree_root = self
+ .upcast::<Node>()
+ .GetRootNode(&GetRootNodeOptions::empty());
+ // Avoiding iterating through the whole tree here, instead
+ // we can check if the conditions for radio group siblings apply
+ if in_same_group(
+ &o,
+ self.form_owner().as_deref(),
+ self.radio_group_name().as_ref(),
+ Some(&*tree_root),
+ ) {
+ o.SetChecked(true);
} else {
self.SetChecked(false);
}
- self.checked_changed.set(cache.checked_changed);
+ } else {
+ self.SetChecked(false);
}
},
_ => (),
@@ -2459,11 +2435,6 @@ impl Activatable for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
let ty = self.input_type();
- if self.activation_state.borrow().old_type != ty || !self.is_mutable() {
- // Type changed or input is immutable, abandon ship
- // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27414
- return;
- }
match ty {
InputType::Submit => {
// https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):activation-behavior