diff options
19 files changed, 519 insertions, 1258 deletions
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index ed153529889..e70afde60c2 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -8,6 +8,7 @@ use dom::attr::Attr; use dom::bindings::cell::DomRefCell; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::FileListBinding::FileListMethods; +use dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode; use dom::bindings::codegen::Bindings::HTMLInputElementBinding; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; @@ -52,7 +53,7 @@ use std::ops::Range; use style::attr::AttrValue; use style::element_state::ElementState; use style::str::split_commas; -use textinput::{Direction, Selection, SelectionDirection, TextInput}; +use textinput::{Direction, SelectionDirection, TextInput}; use textinput::KeyReaction::{DispatchInput, Nothing, RedrawSelection, TriggerDefaultAction}; use textinput::Lines::Single; @@ -188,7 +189,6 @@ pub struct HTMLInputElement { input_type: Cell<InputType>, checked_changed: Cell<bool>, placeholder: DomRefCell<DOMString>, - value_changed: Cell<bool>, size: Cell<u32>, maxlength: Cell<i32>, minlength: Cell<i32>, @@ -244,7 +244,6 @@ impl HTMLInputElement { input_type: Cell::new(Default::default()), placeholder: DomRefCell::new(DOMString::new()), checked_changed: Cell::new(false), - value_changed: Cell::new(false), maxlength: Cell::new(DEFAULT_MAX_LENGTH), minlength: Cell::new(DEFAULT_MIN_LENGTH), size: Cell::new(DEFAULT_INPUT_SIZE), @@ -374,7 +373,7 @@ impl LayoutHTMLInputElementHelpers for LayoutDom<HTMLInputElement> { match (*self.unsafe_get()).input_type() { InputType::Password => { let text = get_raw_textinput_value(self); - let sel = textinput.get_absolute_selection_range(); + let sel = textinput.sorted_selection_offsets_range(); // Translate indices from the raw value to indices in the replacement value. let char_start = text[.. sel.start].chars().count(); @@ -383,7 +382,7 @@ impl LayoutHTMLInputElementHelpers for LayoutDom<HTMLInputElement> { let bytes_per_char = PASSWORD_REPLACEMENT_CHAR.len_utf8(); Some(char_start * bytes_per_char .. char_end * bytes_per_char) } - input_type if input_type.is_textual() => Some(textinput.get_absolute_selection_range()), + input_type if input_type.is_textual() => Some(textinput.sorted_selection_offsets_range()), _ => None } } @@ -417,6 +416,35 @@ impl TextControl for HTMLInputElement { _ => false } } + + // https://html.spec.whatwg.org/multipage/#concept-input-apply + // + // Defines input types to which the select() IDL method applies. These are a superset of the + // types for which selection_api_applies() returns true. + // + // Types omitted which could theoretically be included if they were + // rendered as a text control: file + fn has_selectable_text(&self) -> bool { + match self.input_type() { + InputType::Text | InputType::Search | InputType::Url + | InputType::Tel | InputType::Password | InputType::Email + | InputType::Date | InputType::Month | InputType::Week + | InputType::Time | InputType::DatetimeLocal | InputType::Number + | InputType::Color => { + true + } + + InputType::Button | InputType::Checkbox | InputType::File + | InputType::Hidden | InputType::Image | InputType::Radio + | InputType::Range | InputType::Reset | InputType::Submit => { + false + } + } + } + + fn set_dirty_value_flag(&self, value: bool) { + self.value_dirty.set(value) + } } impl HTMLInputElementMethods for HTMLInputElement { @@ -538,8 +566,7 @@ impl HTMLInputElementMethods for HTMLInputElement { self.sanitize_value(); // Step 5. if *self.textinput.borrow().single_line_content() != old_value { - self.textinput.borrow_mut() - .adjust_horizontal_to_limit(Direction::Forward, Selection::NotSelected); + self.textinput.borrow_mut().clear_selection_to_limit(Direction::Forward); } } ValueMode::Default | @@ -557,7 +584,6 @@ impl HTMLInputElementMethods for HTMLInputElement { } } - self.value_changed.set(true); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); Ok(()) } @@ -687,6 +713,11 @@ impl HTMLInputElementMethods for HTMLInputElement { } } + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-select + fn Select(&self) { + self.dom_select(); // defined in TextControl trait + } + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart fn GetSelectionStart(&self) -> Option<u32> { self.get_dom_selection_start() @@ -722,6 +753,19 @@ impl HTMLInputElementMethods for HTMLInputElement { self.set_dom_selection_range(start, end, direction) } + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext + fn SetRangeText(&self, replacement: DOMString) -> ErrorResult { + // defined in TextControl trait + self.set_dom_range_text(replacement, None, None, Default::default()) + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext + fn SetRangeText_(&self, replacement: DOMString, start: u32, end: u32, + selection_mode: SelectionMode) -> ErrorResult { + // defined in TextControl trait + self.set_dom_range_text(replacement, Some(start), Some(end), selection_mode) + } + // Select the files based on filepaths passed in, // enabled by dom.htmlinputelement.select_files.enabled, // used for test purpose. @@ -902,7 +946,6 @@ impl HTMLInputElement { self.SetValue(self.DefaultValue()) .expect("Failed to reset input value to default."); self.value_dirty.set(false); - self.value_changed.set(false); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); } @@ -1116,6 +1159,8 @@ impl VirtualMethods for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#input-type-change let (old_value_mode, old_idl_value) = (self.value_mode(), self.Value()); + let previously_selectable = self.selection_api_applies(); + self.input_type.set(new_type); if new_type.is_textual() { @@ -1167,6 +1212,11 @@ impl VirtualMethods for HTMLInputElement { // Step 6 self.sanitize_value(); + + // Steps 7-9 + if !previously_selectable && self.selection_api_applies() { + self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward); + } }, AttributeMutation::Removed => { if self.input_type() == InputType::Radio { @@ -1184,7 +1234,7 @@ impl VirtualMethods for HTMLInputElement { self.update_placeholder_shown_state(); }, - &local_name!("value") if !self.value_changed.get() => { + &local_name!("value") if !self.value_dirty.get() => { let value = mutation.new_value(attr).map(|value| (**value).to_owned()); self.textinput.borrow_mut().set_content( value.map_or(DOMString::new(), DOMString::from)); @@ -1327,7 +1377,7 @@ impl VirtualMethods for HTMLInputElement { keyevent.MetaKey()); }, DispatchInput => { - self.value_changed.set(true); + self.value_dirty.set(true); self.update_placeholder_shown_state(); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); event.mark_as_handled(); diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index af69e227d60..bdb0020c616 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -5,6 +5,7 @@ use dom::attr::Attr; use dom::bindings::cell::DomRefCell; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; +use dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; @@ -35,7 +36,7 @@ use std::default::Default; use std::ops::Range; use style::attr::AttrValue; use style::element_state::ElementState; -use textinput::{Direction, KeyReaction, Lines, Selection, SelectionDirection, TextInput}; +use textinput::{Direction, KeyReaction, Lines, SelectionDirection, TextInput}; #[dom_struct] pub struct HTMLTextAreaElement { @@ -44,7 +45,7 @@ pub struct HTMLTextAreaElement { textinput: DomRefCell<TextInput<ScriptToConstellationChan>>, placeholder: DomRefCell<DOMString>, // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty - value_changed: Cell<bool>, + value_dirty: Cell<bool>, form_owner: MutNullableDom<HTMLFormElement>, } @@ -81,7 +82,7 @@ impl LayoutHTMLTextAreaElementHelpers for LayoutDom<HTMLTextAreaElement> { return None; } let textinput = (*self.unsafe_get()).textinput.borrow_for_layout(); - Some(textinput.get_absolute_selection_range()) + Some(textinput.sorted_selection_offsets_range()) } #[allow(unsafe_code)] @@ -122,7 +123,7 @@ impl HTMLTextAreaElement { placeholder: DomRefCell::new(DOMString::new()), textinput: DomRefCell::new(TextInput::new( Lines::Multiple, DOMString::new(), chan, None, None, SelectionDirection::None)), - value_changed: Cell::new(false), + value_dirty: Cell::new(false), form_owner: Default::default(), } } @@ -152,6 +153,14 @@ impl TextControl for HTMLTextAreaElement { fn selection_api_applies(&self) -> bool { true } + + fn has_selectable_text(&self) -> bool { + true + } + + fn set_dirty_value_flag(&self, value: bool) { + self.value_dirty.set(value) + } } impl HTMLTextAreaElementMethods for HTMLTextAreaElement { @@ -227,7 +236,7 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { // if the element's dirty value flag is false, then the element's // raw value must be set to the value of the element's textContent IDL attribute - if !self.value_changed.get() { + if !self.value_dirty.get() { self.reset(); } } @@ -243,19 +252,19 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { // Step 1 let old_value = textinput.get_content(); - let old_selection = textinput.selection_begin; + let old_selection = textinput.selection_origin; // Step 2 textinput.set_content(value); // Step 3 - self.value_changed.set(true); + self.value_dirty.set(true); if old_value != textinput.get_content() { // Step 4 - textinput.adjust_horizontal_to_limit(Direction::Forward, Selection::NotSelected); + textinput.clear_selection_to_limit(Direction::Forward); } else { - textinput.selection_begin = old_selection; + textinput.selection_origin = old_selection; } self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); @@ -266,6 +275,11 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { self.upcast::<HTMLElement>().labels() } + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-select + fn Select(&self) { + self.dom_select(); // defined in TextControl trait + } + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart fn GetSelectionStart(&self) -> Option<u32> { self.get_dom_selection_start() @@ -300,6 +314,19 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult { self.set_dom_selection_range(start, end, direction) } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext + fn SetRangeText(&self, replacement: DOMString) -> ErrorResult { + // defined in TextControl trait + self.set_dom_range_text(replacement, None, None, Default::default()) + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext + fn SetRangeText_(&self, replacement: DOMString, start: u32, end: u32, + selection_mode: SelectionMode) -> ErrorResult { + // defined in TextControl trait + self.set_dom_range_text(replacement, Some(start), Some(end), selection_mode) + } } @@ -307,7 +334,7 @@ impl HTMLTextAreaElement { pub fn reset(&self) { // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control self.SetValue(self.DefaultValue()); - self.value_changed.set(false); + self.value_dirty.set(false); } } @@ -400,7 +427,7 @@ impl VirtualMethods for HTMLTextAreaElement { if let Some(ref s) = self.super_type() { s.children_changed(mutation); } - if !self.value_changed.get() { + if !self.value_dirty.get() { self.reset(); } } @@ -423,7 +450,7 @@ impl VirtualMethods for HTMLTextAreaElement { match action { KeyReaction::TriggerDefaultAction => (), KeyReaction::DispatchInput => { - self.value_changed.set(true); + self.value_dirty.set(true); self.update_placeholder_shown_state(); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); event.mark_as_handled(); diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs index 9143c2bda23..342b081621d 100644 --- a/components/script/dom/textcontrol.rs +++ b/components/script/dom/textcontrol.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::cell::DomRefCell; +use dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode; use dom::bindings::conversions::DerivedFrom; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::str::DOMString; @@ -10,11 +11,24 @@ use dom::event::{EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; use dom::node::{Node, NodeDamage, window_from_node}; use script_traits::ScriptToConstellationChan; -use textinput::{SelectionDirection, TextInput}; +use textinput::{SelectionDirection, SelectionState, TextInput}; pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>; fn selection_api_applies(&self) -> bool; + fn has_selectable_text(&self) -> bool; + fn set_dirty_value_flag(&self, value: bool); + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-select + fn dom_select(&self) { + // Step 1 + if !self.has_selectable_text() { + return; + } + + // Step 2 + self.set_selection_range(Some(0), Some(u32::max_value()), None, None); + } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart fn get_dom_selection_start(&self) -> Option<u32> { @@ -45,7 +59,7 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { } // Step 4 - self.set_selection_range(start, Some(end), Some(self.selection_direction())); + self.set_selection_range(start, Some(end), Some(self.selection_direction()), None); Ok(()) } @@ -68,7 +82,7 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { } // Step 2 - self.set_selection_range(Some(self.selection_start()), end, Some(self.selection_direction())); + self.set_selection_range(Some(self.selection_start()), end, Some(self.selection_direction()), None); Ok(()) } @@ -93,7 +107,8 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { self.set_selection_range( Some(self.selection_start()), Some(self.selection_end()), - direction.map(|d| SelectionDirection::from(d)) + direction.map(|d| SelectionDirection::from(d)), + None ); Ok(()) } @@ -106,16 +121,125 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { } // Step 2 - self.set_selection_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d))); + self.set_selection_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d)), None); + Ok(()) + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext + fn set_dom_range_text(&self, replacement: DOMString, start: Option<u32>, end: Option<u32>, + selection_mode: SelectionMode) -> ErrorResult { + // Step 1 + if !self.selection_api_applies() { + return Err(Error::InvalidState); + } + + // Step 2 + self.set_dirty_value_flag(true); + + // Step 3 + let mut start = start.unwrap_or_else(|| self.selection_start()); + let mut end = end.unwrap_or_else(|| self.selection_end()); + + // Step 4 + if start > end { + return Err(Error::IndexSize); + } + + // Save the original selection state to later pass to set_selection_range, because we will + // change the selection state in order to replace the text in the range. + let original_selection_state = self.textinput().borrow().selection_state(); + + let content_length = self.textinput().borrow().len() as u32; + + // Step 5 + if start > content_length { + start = content_length; + } + + // Step 6 + if end > content_length { + end = content_length; + } + + // Step 7 + let mut selection_start = self.selection_start(); + + // Step 8 + let mut selection_end = self.selection_end(); + + // Step 11 + // Must come before the textinput.replace_selection() call, as replacement gets moved in + // that call. + let new_length = replacement.len() as u32; + + { + let mut textinput = self.textinput().borrow_mut(); + + // Steps 9-10 + textinput.set_selection_range(start, end, SelectionDirection::None); + textinput.replace_selection(replacement); + } + + // Step 12 + let new_end = start + new_length; + + // Step 13 + match selection_mode { + SelectionMode::Select => { + selection_start = start; + selection_end = new_end; + }, + + SelectionMode::Start => { + selection_start = start; + selection_end = start; + }, + + SelectionMode::End => { + selection_start = new_end; + selection_end = new_end; + }, + + SelectionMode::Preserve => { + // Sub-step 1 + let old_length = end - start; + + // Sub-step 2 + let delta = (new_length as isize) - (old_length as isize); + + // Sub-step 3 + if selection_start > end { + selection_start = ((selection_start as isize) + delta) as u32; + } else if selection_start > start { + selection_start = start; + } + + // Sub-step 4 + if selection_end > end { + selection_end = ((selection_end as isize) + delta) as u32; + } else if selection_end > start { + selection_end = new_end; + } + }, + } + + // Step 14 + self.set_selection_range( + Some(selection_start), + Some(selection_end), + None, + Some(original_selection_state) + ); + Ok(()) } fn selection_start(&self) -> u32 { - self.textinput().borrow().get_selection_start() + self.textinput().borrow().selection_start_offset() as u32 } fn selection_end(&self) -> u32 { - self.textinput().borrow().get_absolute_insertion_point() as u32 + self.textinput().borrow().selection_end_offset() as u32 } fn selection_direction(&self) -> SelectionDirection { @@ -123,7 +247,11 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { } // https://html.spec.whatwg.org/multipage/#set-the-selection-range - fn set_selection_range(&self, start: Option<u32>, end: Option<u32>, direction: Option<SelectionDirection>) { + fn set_selection_range(&self, start: Option<u32>, end: Option<u32>, direction: Option<SelectionDirection>, + original_selection_state: Option<SelectionState>) { + let mut textinput = self.textinput().borrow_mut(); + let original_selection_state = original_selection_state.unwrap_or_else(|| textinput.selection_state()); + // Step 1 let start = start.unwrap_or(0); @@ -131,16 +259,18 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { let end = end.unwrap_or(0); // Steps 3-5 - self.textinput().borrow_mut().set_selection_range(start, end, direction.unwrap_or(SelectionDirection::None)); + textinput.set_selection_range(start, end, direction.unwrap_or(SelectionDirection::None)); // Step 6 - let window = window_from_node(self); - let _ = window.user_interaction_task_source().queue_event( - &self.upcast::<EventTarget>(), - atom!("select"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable, - &window); + if textinput.selection_state() != original_selection_state { + let window = window_from_node(self); + window.user_interaction_task_source().queue_event( + &self.upcast::<EventTarget>(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable, + &window); + } self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); } diff --git a/components/script/dom/webidls/HTMLFormElement.webidl b/components/script/dom/webidls/HTMLFormElement.webidl index b4a2504fd60..1514e38b6f5 100644 --- a/components/script/dom/webidls/HTMLFormElement.webidl +++ b/components/script/dom/webidls/HTMLFormElement.webidl @@ -35,3 +35,11 @@ interface HTMLFormElement : HTMLElement { //boolean checkValidity(); //boolean reportValidity(); }; + +// https://html.spec.whatwg.org/multipage/#selectionmode +enum SelectionMode { + "preserve", // default + "select", + "start", + "end" +}; diff --git a/components/script/dom/webidls/HTMLInputElement.webidl b/components/script/dom/webidls/HTMLInputElement.webidl index 93a5a7f108b..e76ca054a6f 100644 --- a/components/script/dom/webidls/HTMLInputElement.webidl +++ b/components/script/dom/webidls/HTMLInputElement.webidl @@ -89,16 +89,18 @@ interface HTMLInputElement : HTMLElement { readonly attribute NodeList labels; - //void select(); + void select(); [SetterThrows] attribute unsigned long? selectionStart; [SetterThrows] attribute unsigned long? selectionEnd; [SetterThrows] attribute DOMString? selectionDirection; - //void setRangeText(DOMString replacement); - //void setRangeText(DOMString replacement, unsigned long start, unsigned long end, - // optional SelectionMode selectionMode = "preserve"); + [Throws] + void setRangeText(DOMString replacement); + [Throws] + void setRangeText(DOMString replacement, unsigned long start, unsigned long end, + optional SelectionMode selectionMode = "preserve"); [Throws] void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction); diff --git a/components/script/dom/webidls/HTMLTextAreaElement.webidl b/components/script/dom/webidls/HTMLTextAreaElement.webidl index f0e8a0be118..3ff20242bfe 100644 --- a/components/script/dom/webidls/HTMLTextAreaElement.webidl +++ b/components/script/dom/webidls/HTMLTextAreaElement.webidl @@ -50,16 +50,18 @@ interface HTMLTextAreaElement : HTMLElement { readonly attribute NodeList labels; - // void select(); + void select(); [SetterThrows] attribute unsigned long? selectionStart; [SetterThrows] attribute unsigned long? selectionEnd; [SetterThrows] attribute DOMString? selectionDirection; - // void setRangeText(DOMString replacement); - // void setRangeText(DOMString replacement, unsigned long start, unsigned long end, - // optional SelectionMode selectionMode = "preserve"); + [Throws] + void setRangeText(DOMString replacement); + [Throws] + void setRangeText(DOMString replacement, unsigned long start, unsigned long end, + optional SelectionMode selectionMode = "preserve"); [Throws] void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction); }; diff --git a/components/script/textinput.rs b/components/script/textinput.rs index 0fe0024a116..937ab38ed5d 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -48,7 +48,7 @@ impl From<SelectionDirection> for DOMString { } } -#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq, PartialOrd)] pub struct TextPoint { /// 0-based line number pub line: usize, @@ -56,6 +56,13 @@ pub struct TextPoint { pub index: usize, } +#[derive(Clone, Copy, PartialEq)] +pub struct SelectionState { + start: TextPoint, + end: TextPoint, + direction: SelectionDirection, +} + /// Encapsulated state for handling keyboard input in a single or multiline text input control. #[derive(JSTraceable, MallocSizeOf)] pub struct TextInput<T: ClipboardProvider> { @@ -63,8 +70,9 @@ pub struct TextInput<T: ClipboardProvider> { lines: Vec<DOMString>, /// Current cursor input point pub edit_point: TextPoint, - /// Beginning of selection range with edit_point as end that can span multiple lines. - pub selection_begin: Option<TextPoint>, + /// The current selection goes from the selection_origin until the edit_point. Note that the + /// selection_origin may be after the edit_point, in the case of a backward selection. + pub selection_origin: Option<TextPoint>, /// Is this a multiline input? multiline: bool, #[ignore_malloc_size_of = "Can't easily measure this generic type"] @@ -156,7 +164,7 @@ impl<T: ClipboardProvider> TextInput<T> { let mut i = TextInput { lines: vec!(), edit_point: Default::default(), - selection_begin: None, + selection_origin: None, multiline: lines == Lines::Multiple, clipboard_provider: clipboard_provider, max_length: max_length, @@ -169,7 +177,7 @@ impl<T: ClipboardProvider> TextInput<T> { /// Remove a character at the current editing point pub fn delete_char(&mut self, dir: Direction) { - if self.selection_begin.is_none() || self.selection_begin == Some(self.edit_point) { + if self.selection_origin.is_none() || self.selection_origin == Some(self.edit_point) { self.adjust_horizontal_by_one(dir, Selection::Selected); } self.replace_selection(DOMString::new()); @@ -182,46 +190,93 @@ impl<T: ClipboardProvider> TextInput<T> { /// Insert a string at the current editing point pub fn insert_string<S: Into<String>>(&mut self, s: S) { - if self.selection_begin.is_none() { - self.selection_begin = Some(self.edit_point); + if self.selection_origin.is_none() { + self.selection_origin = Some(self.edit_point); } self.replace_selection(DOMString::from(s.into())); } - pub fn get_sorted_selection(&self) -> Option<(TextPoint, TextPoint)> { - self.selection_begin.map(|begin| { - let end = self.edit_point; + /// The selection origin, or the edit point if there is no selection. Note that the selection + /// origin may be after the edit point, in the case of a backward selection. + pub fn selection_origin_or_edit_point(&self) -> TextPoint { + self.selection_origin.unwrap_or(self.edit_point) + } - if begin.line < end.line || (begin.line == end.line && begin.index < end.index) { - (begin, end) - } else { - (end, begin) - } - }) + /// The start of the selection (or the edit point, if there is no selection). Always less than + /// or equal to selection_end(), regardless of the selection direction. + pub fn selection_start(&self) -> TextPoint { + match self.selection_direction { + SelectionDirection::None | SelectionDirection::Forward => self.selection_origin_or_edit_point(), + SelectionDirection::Backward => self.edit_point, + } } - // Check that the selection is valid. - fn assert_ok_selection(&self) { - if let Some(begin) = self.selection_begin { - debug_assert!(begin.line < self.lines.len()); - debug_assert!(begin.index <= self.lines[begin.line].len()); + /// The UTF-8 byte offset of the selection_start() + pub fn selection_start_offset(&self) -> usize { + self.text_point_to_offset(&self.selection_start()) + } + + /// The end of the selection (or the edit point, if there is no selection). Always greater + /// than or equal to selection_start(), regardless of the selection direction. + pub fn selection_end(&self) -> TextPoint { + match self.selection_direction { + SelectionDirection::None | SelectionDirection::Forward => self.edit_point, + SelectionDirection::Backward => self.selection_origin_or_edit_point(), } - debug_assert!(self.edit_point.line < self.lines.len()); - debug_assert!(self.edit_point.index <= self.lines[self.edit_point.line].len()); + } + + /// The UTF-8 byte offset of the selection_end() + pub fn selection_end_offset(&self) -> usize { + self.text_point_to_offset(&self.selection_end()) + } + + /// Whether or not there is an active selection (the selection may be zero-length) + #[inline] + pub fn has_selection(&self) -> bool { + self.selection_origin.is_some() + } + + /// Returns a tuple of (start, end) giving the bounds of the current selection. start is always + /// less than or equal to end. + pub fn sorted_selection_bounds(&self) -> (TextPoint, TextPoint) { + (self.selection_start(), self.selection_end()) } /// Return the selection range as UTF-8 byte offsets from the start of the content. /// - /// If there is no selection, returns an empty range at the insertion point. - pub fn get_absolute_selection_range(&self) -> Range<usize> { - match self.get_sorted_selection() { - Some((begin, end)) => self.get_absolute_point_for_text_point(&begin) .. - self.get_absolute_point_for_text_point(&end), - None => { - let insertion_point = self.get_absolute_insertion_point(); - insertion_point .. insertion_point + /// If there is no selection, returns an empty range at the edit point. + pub fn sorted_selection_offsets_range(&self) -> Range<usize> { + self.selection_start_offset() .. self.selection_end_offset() + } + + /// The state of the current selection. Can be used to compare whether selection state has changed. + pub fn selection_state(&self) -> SelectionState { + SelectionState { + start: self.selection_start(), + end: self.selection_end(), + direction: self.selection_direction, + } + } + + // Check that the selection is valid. + fn assert_ok_selection(&self) { + if let Some(begin) = self.selection_origin { + debug_assert!(begin.line < self.lines.len()); + debug_assert!(begin.index <= self.lines[begin.line].len()); + + match self.selection_direction { + SelectionDirection::None | SelectionDirection::Forward => { + debug_assert!(begin <= self.edit_point) + }, + + SelectionDirection::Backward => { + debug_assert!(self.edit_point <= begin) + }, } } + + debug_assert!(self.edit_point.line < self.lines.len()); + debug_assert!(self.edit_point.index <= self.lines[self.edit_point.line].len()); } pub fn get_selection_text(&self) -> Option<String> { @@ -242,78 +297,83 @@ impl<T: ClipboardProvider> TextInput<T> { /// /// The accumulator `acc` can be mutated by the callback, and will be returned at the end. fn fold_selection_slices<B, F: FnMut(&mut B, &str)>(&self, mut acc: B, mut f: F) -> B { - match self.get_sorted_selection() { - Some((begin, end)) if begin.line == end.line => { - f(&mut acc, &self.lines[begin.line][begin.index..end.index]) - } - Some((begin, end)) => { - f(&mut acc, &self.lines[begin.line][begin.index..]); - for line in &self.lines[begin.line + 1 .. end.line] { + if self.has_selection() { + let (start, end) = self.sorted_selection_bounds(); + + if start.line == end.line { + f(&mut acc, &self.lines[start.line][start.index..end.index]) + } else { + f(&mut acc, &self.lines[start.line][start.index..]); + for line in &self.lines[start.line + 1 .. end.line] { f(&mut acc, "\n"); f(&mut acc, line); } f(&mut acc, "\n"); f(&mut acc, &self.lines[end.line][..end.index]) } - None => {} } + acc } pub fn replace_selection(&mut self, insert: DOMString) { - if let Some((begin, end)) = self.get_sorted_selection() { - let allowed_to_insert_count = if let Some(max_length) = self.max_length { - let len_after_selection_replaced = self.utf16_len() - self.selection_utf16_len(); - if len_after_selection_replaced >= max_length { - // If, after deleting the selection, the len is still greater than the max - // length, then don't delete/insert anything - return - } + if !self.has_selection() { + return + } - max_length - len_after_selection_replaced - } else { - usize::MAX - }; + let (start, end) = self.sorted_selection_bounds(); - let last_char_index = len_of_first_n_code_units(&*insert, allowed_to_insert_count); - let chars_to_insert = &insert[..last_char_index]; + let allowed_to_insert_count = if let Some(max_length) = self.max_length { + let len_after_selection_replaced = self.utf16_len() - self.selection_utf16_len(); + if len_after_selection_replaced >= max_length { + // If, after deleting the selection, the len is still greater than the max + // length, then don't delete/insert anything + return + } - self.clear_selection(); + max_length - len_after_selection_replaced + } else { + usize::MAX + }; - let new_lines = { - let prefix = &self.lines[begin.line][..begin.index]; - let suffix = &self.lines[end.line][end.index..]; - let lines_prefix = &self.lines[..begin.line]; - let lines_suffix = &self.lines[end.line + 1..]; + let last_char_index = len_of_first_n_code_units(&*insert, allowed_to_insert_count); + let chars_to_insert = &insert[..last_char_index]; - let mut insert_lines = if self.multiline { - chars_to_insert.split('\n').map(|s| DOMString::from(s)).collect() - } else { - vec!(DOMString::from(chars_to_insert)) - }; + self.clear_selection(); + + let new_lines = { + let prefix = &self.lines[start.line][..start.index]; + let suffix = &self.lines[end.line][end.index..]; + let lines_prefix = &self.lines[..start.line]; + let lines_suffix = &self.lines[end.line + 1..]; - // FIXME(ajeffrey): effecient append for DOMStrings - let mut new_line = prefix.to_owned(); + let mut insert_lines = if self.multiline { + chars_to_insert.split('\n').map(|s| DOMString::from(s)).collect() + } else { + vec!(DOMString::from(chars_to_insert)) + }; - new_line.push_str(&insert_lines[0]); - insert_lines[0] = DOMString::from(new_line); + // FIXME(ajeffrey): effecient append for DOMStrings + let mut new_line = prefix.to_owned(); - let last_insert_lines_index = insert_lines.len() - 1; - self.edit_point.index = insert_lines[last_insert_lines_index].len(); - self.edit_point.line = begin.line + last_insert_lines_index; + new_line.push_str(&insert_lines[0]); + insert_lines[0] = DOMString::from(new_line); - // FIXME(ajeffrey): effecient append for DOMStrings - insert_lines[last_insert_lines_index].push_str(suffix); + let last_insert_lines_index = insert_lines.len() - 1; + self.edit_point.index = insert_lines[last_insert_lines_index].len(); + self.edit_point.line = start.line + last_insert_lines_index; - let mut new_lines = vec!(); - new_lines.extend_from_slice(lines_prefix); - new_lines.extend_from_slice(&insert_lines); - new_lines.extend_from_slice(lines_suffix); - new_lines - }; + // FIXME(ajeffrey): effecient append for DOMStrings + insert_lines[last_insert_lines_index].push_str(suffix); - self.lines = new_lines; - } + let mut new_lines = vec!(); + new_lines.extend_from_slice(lines_prefix); + new_lines.extend_from_slice(&insert_lines); + new_lines.extend_from_slice(lines_suffix); + new_lines + }; + + self.lines = new_lines; self.assert_ok_selection(); } @@ -330,8 +390,8 @@ impl<T: ClipboardProvider> TextInput<T> { } if select == Selection::Selected { - if self.selection_begin.is_none() { - self.selection_begin = Some(self.edit_point); + if self.selection_origin.is_none() { + self.selection_origin = Some(self.edit_point); } } else { self.clear_selection(); @@ -398,14 +458,19 @@ impl<T: ClipboardProvider> TextInput<T> { fn adjust_selection_for_horizontal_change(&mut self, adjust: Direction, select: Selection) -> bool { if select == Selection::Selected { - if self.selection_begin.is_none() { - self.selection_begin = Some(self.edit_point); + if self.selection_origin.is_none() { + self.selection_origin = Some(self.edit_point); } + + self.selection_direction = match adjust { + Direction::Backward => SelectionDirection::Backward, + Direction::Forward => SelectionDirection::Forward, + }; } else { - if let Some((begin, end)) = self.get_sorted_selection() { + if self.has_selection() { self.edit_point = match adjust { - Direction::Backward => begin, - Direction::Forward => end, + Direction::Backward => self.selection_start(), + Direction::Forward => self.selection_end(), }; self.clear_selection(); return true @@ -451,7 +516,7 @@ impl<T: ClipboardProvider> TextInput<T> { /// Select all text in the input control. pub fn select_all(&mut self) { - self.selection_begin = Some(TextPoint { + self.selection_origin = Some(TextPoint { line: 0, index: 0, }); @@ -463,7 +528,14 @@ impl<T: ClipboardProvider> TextInput<T> { /// Remove the current selection. pub fn clear_selection(&mut self) { - self.selection_begin = None; + self.selection_origin = None; + self.selection_direction = SelectionDirection::None; + } + + /// Remove the current selection and set the edit point to the end of the content. + pub fn clear_selection_to_limit(&mut self, direction: Direction) { + self.clear_selection(); + self.adjust_horizontal_to_limit(direction, Selection::NotSelected); } pub fn adjust_horizontal_by_word(&mut self, direction: Direction, select: Selection) { @@ -780,17 +852,12 @@ impl<T: ClipboardProvider> TextInput<T> { }; self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1); self.edit_point.index = min(self.edit_point.index, self.current_line_length()); - self.selection_begin = None; + self.selection_origin = None; self.assert_ok_selection(); } - /// Get the insertion point as a byte offset from the start of the content. - pub fn get_absolute_insertion_point(&self) -> usize { - self.get_absolute_point_for_text_point(&self.edit_point) - } - /// Convert a TextPoint into a byte offset from the start of the content. - pub fn get_absolute_point_for_text_point(&self, text_point: &TextPoint) -> usize { + fn text_point_to_offset(&self, text_point: &TextPoint) -> usize { self.lines.iter().enumerate().fold(0, |acc, (i, val)| { if i < text_point.line { acc + val.len() + 1 // +1 for the \n @@ -801,7 +868,7 @@ impl<T: ClipboardProvider> TextInput<T> { } /// Convert a byte offset from the start of the content into a TextPoint. - pub fn get_text_point_for_absolute_point(&self, abs_point: usize) -> TextPoint { + fn offset_to_text_point(&self, abs_point: usize) -> TextPoint { let mut index = abs_point; let mut line = 0; @@ -842,28 +909,17 @@ impl<T: ClipboardProvider> TextInput<T> { match direction { SelectionDirection::None | SelectionDirection::Forward => { - self.selection_begin = Some(self.get_text_point_for_absolute_point(start)); - self.edit_point = self.get_text_point_for_absolute_point(end); + self.selection_origin = Some(self.offset_to_text_point(start)); + self.edit_point = self.offset_to_text_point(end); }, SelectionDirection::Backward => { - self.selection_begin = Some(self.get_text_point_for_absolute_point(end)); - self.edit_point = self.get_text_point_for_absolute_point(start); + self.selection_origin = Some(self.offset_to_text_point(end)); + self.edit_point = self.offset_to_text_point(start); } } self.assert_ok_selection(); } - pub fn get_selection_start(&self) -> u32 { - let selection_start = match self.selection_begin { - Some(selection_begin_point) => { - self.get_absolute_point_for_text_point(&selection_begin_point) - }, - None => self.get_absolute_insertion_point() - }; - - selection_start as u32 - } - pub fn set_edit_point_index(&mut self, index: usize) { let byte_size = self.lines[self.edit_point.line] .graphemes(true) diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs index 5b98dc934c6..2167efb0b6d 100644 --- a/tests/unit/script/textinput.rs +++ b/tests/unit/script/textinput.rs @@ -222,7 +222,7 @@ fn test_textinput_delete_char() { let mut textinput = text_input(Lines::Single, "abcdefg"); textinput.adjust_horizontal(2, Selection::NotSelected); // Set an empty selection range. - textinput.selection_begin = Some(textinput.edit_point); + textinput.selection_origin = Some(textinput.edit_point); textinput.delete_char(Direction::Backward); assert_eq!(textinput.get_content(), "acdefg"); } @@ -252,15 +252,15 @@ fn test_textinput_get_sorted_selection() { let mut textinput = text_input(Lines::Single, "abcdefg"); textinput.adjust_horizontal(2, Selection::NotSelected); textinput.adjust_horizontal(2, Selection::Selected); - let (begin, end) = textinput.get_sorted_selection().unwrap(); - assert_eq!(begin.index, 2); + let (start, end) = textinput.sorted_selection_bounds(); + assert_eq!(start.index, 2); assert_eq!(end.index, 4); textinput.clear_selection(); textinput.adjust_horizontal(-2, Selection::Selected); - let (begin, end) = textinput.get_sorted_selection().unwrap(); - assert_eq!(begin.index, 2); + let (start, end) = textinput.sorted_selection_bounds(); + assert_eq!(start.index, 2); assert_eq!(end.index, 4); } @@ -588,18 +588,18 @@ fn test_textinput_set_selection_with_direction() { assert_eq!(textinput.edit_point.index, 6); assert_eq!(textinput.selection_direction, SelectionDirection::Forward); - assert!(textinput.selection_begin.is_some()); - assert_eq!(textinput.selection_begin.unwrap().line, 0); - assert_eq!(textinput.selection_begin.unwrap().index, 2); + assert!(textinput.selection_origin.is_some()); + assert_eq!(textinput.selection_origin.unwrap().line, 0); + assert_eq!(textinput.selection_origin.unwrap().index, 2); textinput.set_selection_range(2, 6, SelectionDirection::Backward); assert_eq!(textinput.edit_point.line, 0); assert_eq!(textinput.edit_point.index, 2); assert_eq!(textinput.selection_direction, SelectionDirection::Backward); - assert!(textinput.selection_begin.is_some()); - assert_eq!(textinput.selection_begin.unwrap().line, 0); - assert_eq!(textinput.selection_begin.unwrap().index, 6); + assert!(textinput.selection_origin.is_some()); + assert_eq!(textinput.selection_origin.unwrap().line, 0); + assert_eq!(textinput.selection_origin.unwrap().index, 6); } #[test] @@ -611,3 +611,22 @@ fn test_textinput_unicode_handling() { textinput.set_edit_point_index(4); assert_eq!(textinput.edit_point.index, 8); } + +#[test] +fn test_selection_bounds() { + let mut textinput = text_input(Lines::Single, "abcdef"); + + textinput.set_selection_range(2, 5, SelectionDirection::Forward); + assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_origin_or_edit_point()); + assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_start()); + assert_eq!(TextPoint { line: 0, index: 5 }, textinput.selection_end()); + assert_eq!(2, textinput.selection_start_offset()); + assert_eq!(5, textinput.selection_end_offset()); + + textinput.set_selection_range(3, 6, SelectionDirection::Backward); + assert_eq!(TextPoint { line: 0, index: 6 }, textinput.selection_origin_or_edit_point()); + assert_eq!(TextPoint { line: 0, index: 3 }, textinput.selection_start()); + assert_eq!(TextPoint { line: 0, index: 6 }, textinput.selection_end()); + assert_eq!(3, textinput.selection_start_offset()); + assert_eq!(6, textinput.selection_end_offset()); +} diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 29e8265a446..f247ba70162 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -553039,7 +553039,7 @@ "testharness" ], "html/semantics/forms/textfieldselection/selection-start-end.html": [ - "3fd1c942f7ac3ed3097bbd1ec89db15fb0805476", + "0fd9c420f831943f0d992076a7828eac066b6596", "testharness" ], "html/semantics/forms/textfieldselection/selection-value-interactions.html": [ @@ -553459,7 +553459,7 @@ "testharness" ], "html/semantics/forms/the-input-element/type-change-state.html": [ - "d731573ee091b7e658ea0b1ded46a764e8165f6c", + "6ca94002609dae5548e5c832e4a84639c1094f69", "testharness" ], "html/semantics/forms/the-input-element/url.html": [ diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index d58a1b90b02..a8063201da4 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -3090,12 +3090,6 @@ [HTMLInputElement interface: operation setCustomValidity(DOMString)] expected: FAIL - [HTMLInputElement interface: operation select()] - expected: FAIL - - [HTMLInputElement interface: operation setRangeText(DOMString)] - expected: FAIL - [HTMLInputElement interface: operation setRangeText(DOMString,unsigned long,unsigned long,SelectionMode)] expected: FAIL @@ -3174,9 +3168,6 @@ [HTMLInputElement interface: document.createElement("input") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on document.createElement("input") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: document.createElement("input") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -3342,12 +3333,6 @@ [HTMLTextAreaElement interface: operation setCustomValidity(DOMString)] expected: FAIL - [HTMLTextAreaElement interface: operation select()] - expected: FAIL - - [HTMLTextAreaElement interface: operation setRangeText(DOMString)] - expected: FAIL - [HTMLTextAreaElement interface: operation setRangeText(DOMString,unsigned long,unsigned long,SelectionMode)] expected: FAIL @@ -3399,9 +3384,6 @@ [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "setRangeText" with the proper type (30)] expected: FAIL - [HTMLTextAreaElement interface: calling setRangeText(DOMString) on document.createElement("textarea") with too few arguments must throw TypeError] - expected: FAIL - [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "setRangeText" with the proper type (31)] expected: FAIL @@ -6297,9 +6279,6 @@ [HTMLInputElement interface: createInput("text") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("text") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("text") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6381,9 +6360,6 @@ [HTMLInputElement interface: createInput("hidden") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("hidden") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("hidden") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6465,9 +6441,6 @@ [HTMLInputElement interface: createInput("search") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("search") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("search") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6549,9 +6522,6 @@ [HTMLInputElement interface: createInput("tel") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("tel") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("tel") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6633,9 +6603,6 @@ [HTMLInputElement interface: createInput("url") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("url") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("url") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6717,9 +6684,6 @@ [HTMLInputElement interface: createInput("email") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("email") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("email") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6801,9 +6765,6 @@ [HTMLInputElement interface: createInput("password") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("password") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("password") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6885,9 +6846,6 @@ [HTMLInputElement interface: createInput("date") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("date") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("date") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -6969,9 +6927,6 @@ [HTMLInputElement interface: createInput("month") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("month") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("month") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7053,9 +7008,6 @@ [HTMLInputElement interface: createInput("week") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("week") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("week") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7137,9 +7089,6 @@ [HTMLInputElement interface: createInput("time") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("time") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("time") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7221,9 +7170,6 @@ [HTMLInputElement interface: createInput("datetime-local") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("datetime-local") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("datetime-local") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7305,9 +7251,6 @@ [HTMLInputElement interface: createInput("number") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("number") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("number") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7389,9 +7332,6 @@ [HTMLInputElement interface: createInput("range") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("range") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("range") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7473,9 +7413,6 @@ [HTMLInputElement interface: createInput("color") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("color") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("color") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7557,9 +7494,6 @@ [HTMLInputElement interface: createInput("checkbox") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("checkbox") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("checkbox") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7641,9 +7575,6 @@ [HTMLInputElement interface: createInput("radio") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("radio") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("radio") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7728,9 +7659,6 @@ [HTMLInputElement interface: createInput("file") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("file") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("file") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7812,9 +7740,6 @@ [HTMLInputElement interface: createInput("submit") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("submit") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("submit") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7896,9 +7821,6 @@ [HTMLInputElement interface: createInput("image") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("image") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("image") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -7980,9 +7902,6 @@ [HTMLInputElement interface: createInput("reset") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("reset") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("reset") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -8064,9 +7983,6 @@ [HTMLInputElement interface: createInput("button") must inherit property "setRangeText" with the proper type (53)] expected: FAIL - [HTMLInputElement interface: calling setRangeText(DOMString) on createInput("button") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("button") must inherit property "setRangeText" with the proper type (54)] expected: FAIL @@ -11736,9 +11652,6 @@ [HTMLInputElement interface: attribute files] expected: FAIL - [HTMLInputElement interface: operation setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)] - expected: FAIL - [HTMLInputElement interface: document.createElement("input") must inherit property "autocomplete" with the proper type] expected: FAIL @@ -11787,18 +11700,6 @@ [HTMLInputElement interface: document.createElement("input") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: document.createElement("input") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: document.createElement("input") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: document.createElement("input") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on document.createElement("input") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: document.createElement("input") must inherit property "align" with the proper type] expected: FAIL @@ -11853,18 +11754,6 @@ [HTMLInputElement interface: createInput("text") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("text") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("text") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("text") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("text") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("text") must inherit property "align" with the proper type] expected: FAIL @@ -11919,18 +11808,6 @@ [HTMLInputElement interface: createInput("hidden") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("hidden") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("hidden") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("hidden") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("hidden") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("hidden") must inherit property "align" with the proper type] expected: FAIL @@ -11985,18 +11862,6 @@ [HTMLInputElement interface: createInput("search") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("search") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("search") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("search") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("search") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("search") must inherit property "align" with the proper type] expected: FAIL @@ -12051,18 +11916,6 @@ [HTMLInputElement interface: createInput("tel") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("tel") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("tel") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("tel") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("tel") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("tel") must inherit property "align" with the proper type] expected: FAIL @@ -12117,18 +11970,6 @@ [HTMLInputElement interface: createInput("url") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("url") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("url") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("url") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("url") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("url") must inherit property "align" with the proper type] expected: FAIL @@ -12183,18 +12024,6 @@ [HTMLInputElement interface: createInput("email") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("email") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("email") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("email") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("email") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("email") must inherit property "align" with the proper type] expected: FAIL @@ -12249,18 +12078,6 @@ [HTMLInputElement interface: createInput("password") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("password") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("password") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("password") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("password") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("password") must inherit property "align" with the proper type] expected: FAIL @@ -12315,18 +12132,6 @@ [HTMLInputElement interface: createInput("date") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("date") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("date") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("date") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("date") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("date") must inherit property "align" with the proper type] expected: FAIL @@ -12381,18 +12186,6 @@ [HTMLInputElement interface: createInput("month") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("month") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("month") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("month") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("month") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("month") must inherit property "align" with the proper type] expected: FAIL @@ -12447,18 +12240,6 @@ [HTMLInputElement interface: createInput("week") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("week") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("week") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("week") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("week") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("week") must inherit property "align" with the proper type] expected: FAIL @@ -12513,18 +12294,6 @@ [HTMLInputElement interface: createInput("time") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("time") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("time") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("time") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("time") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("time") must inherit property "align" with the proper type] expected: FAIL @@ -12579,18 +12348,6 @@ [HTMLInputElement interface: createInput("datetime-local") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("datetime-local") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("datetime-local") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("datetime-local") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("datetime-local") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("datetime-local") must inherit property "align" with the proper type] expected: FAIL @@ -12645,18 +12402,6 @@ [HTMLInputElement interface: createInput("number") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("number") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("number") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("number") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("number") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("number") must inherit property "align" with the proper type] expected: FAIL @@ -12711,18 +12456,6 @@ [HTMLInputElement interface: createInput("range") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("range") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("range") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("range") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("range") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("range") must inherit property "align" with the proper type] expected: FAIL @@ -12777,18 +12510,6 @@ [HTMLInputElement interface: createInput("color") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("color") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("color") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("color") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("color") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("color") must inherit property "align" with the proper type] expected: FAIL @@ -12843,18 +12564,6 @@ [HTMLInputElement interface: createInput("checkbox") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("checkbox") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("checkbox") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("checkbox") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("checkbox") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("checkbox") must inherit property "align" with the proper type] expected: FAIL @@ -12909,18 +12618,6 @@ [HTMLInputElement interface: createInput("radio") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("radio") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("radio") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("radio") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("radio") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("radio") must inherit property "align" with the proper type] expected: FAIL @@ -12978,18 +12675,6 @@ [HTMLInputElement interface: createInput("file") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("file") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("file") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("file") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("file") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("file") must inherit property "align" with the proper type] expected: FAIL @@ -13044,18 +12729,6 @@ [HTMLInputElement interface: createInput("submit") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("submit") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("submit") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("submit") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("submit") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("submit") must inherit property "align" with the proper type] expected: FAIL @@ -13110,18 +12783,6 @@ [HTMLInputElement interface: createInput("image") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("image") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("image") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("image") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("image") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("image") must inherit property "align" with the proper type] expected: FAIL @@ -13176,18 +12837,6 @@ [HTMLInputElement interface: createInput("reset") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("reset") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("reset") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("reset") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("reset") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("reset") must inherit property "align" with the proper type] expected: FAIL @@ -13242,18 +12891,6 @@ [HTMLInputElement interface: createInput("button") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("button") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("button") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: createInput("button") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLInputElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on createInput("button") with too few arguments must throw TypeError] - expected: FAIL - [HTMLInputElement interface: createInput("button") must inherit property "align" with the proper type] expected: FAIL @@ -13335,9 +12972,6 @@ [HTMLOptionElement interface: new Option() must inherit property "index" with the proper type] expected: FAIL - [HTMLTextAreaElement interface: operation setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)] - expected: FAIL - [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type] expected: FAIL @@ -13377,18 +13011,6 @@ [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "setCustomValidity(DOMString)" with the proper type] expected: FAIL - [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "select()" with the proper type] - expected: FAIL - - [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "setRangeText(DOMString)" with the proper type] - expected: FAIL - - [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "setRangeText(DOMString, unsigned long, unsigned long, SelectionMode)" with the proper type] - expected: FAIL - - [HTMLTextAreaElement interface: calling setRangeText(DOMString, unsigned long, unsigned long, SelectionMode) on document.createElement("textarea") with too few arguments must throw TypeError] - expected: FAIL - [HTMLOutputElement interface: document.createElement("output") must inherit property "htmlFor" with the proper type] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini deleted file mode 100644 index 1f1def1f0da..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini +++ /dev/null @@ -1,146 +0,0 @@ -[select-event.html] - type: testharness - [textarea: select()] - expected: FAIL - - [textarea: select() a second time (must not fire select)] - expected: FAIL - - [textarea: selectionStart a second time (must not fire select)] - expected: FAIL - - [textarea: selectionEnd a second time (must not fire select)] - expected: FAIL - - [textarea: selectionDirection a second time (must not fire select)] - expected: FAIL - - [textarea: setSelectionRange() a second time (must not fire select)] - expected: FAIL - - [textarea: setRangeText()] - expected: FAIL - - [textarea: setRangeText() a second time (must not fire select)] - expected: FAIL - - [input type text: select()] - expected: FAIL - - [input type text: select() a second time (must not fire select)] - expected: FAIL - - [input type text: selectionStart a second time (must not fire select)] - expected: FAIL - - [input type text: selectionEnd a second time (must not fire select)] - expected: FAIL - - [input type text: selectionDirection a second time (must not fire select)] - expected: FAIL - - [input type text: setSelectionRange() a second time (must not fire select)] - expected: FAIL - - [input type text: setRangeText()] - expected: FAIL - - [input type text: setRangeText() a second time (must not fire select)] - expected: FAIL - - [input type search: select()] - expected: FAIL - - [input type search: select() a second time (must not fire select)] - expected: FAIL - - [input type search: selectionStart a second time (must not fire select)] - expected: FAIL - - [input type search: selectionEnd a second time (must not fire select)] - expected: FAIL - - [input type search: selectionDirection a second time (must not fire select)] - expected: FAIL - - [input type search: setSelectionRange() a second time (must not fire select)] - expected: FAIL - - [input type search: setRangeText()] - expected: FAIL - - [input type search: setRangeText() a second time (must not fire select)] - expected: FAIL - - [input type tel: select()] - expected: FAIL - - [input type tel: select() a second time (must not fire select)] - expected: FAIL - - [input type tel: selectionStart a second time (must not fire select)] - expected: FAIL - - [input type tel: selectionEnd a second time (must not fire select)] - expected: FAIL - - [input type tel: selectionDirection a second time (must not fire select)] - expected: FAIL - - [input type tel: setSelectionRange() a second time (must not fire select)] - expected: FAIL - - [input type tel: setRangeText()] - expected: FAIL - - [input type tel: setRangeText() a second time (must not fire select)] - expected: FAIL - - [input type url: select()] - expected: FAIL - - [input type url: select() a second time (must not fire select)] - expected: FAIL - - [input type url: selectionStart a second time (must not fire select)] - expected: FAIL - - [input type url: selectionEnd a second time (must not fire select)] - expected: FAIL - - [input type url: selectionDirection a second time (must not fire select)] - expected: FAIL - - [input type url: setSelectionRange() a second time (must not fire select)] - expected: FAIL - - [input type url: setRangeText()] - expected: FAIL - - [input type url: setRangeText() a second time (must not fire select)] - expected: FAIL - - [input type password: select()] - expected: FAIL - - [input type password: select() a second time (must not fire select)] - expected: FAIL - - [input type password: selectionStart a second time (must not fire select)] - expected: FAIL - - [input type password: selectionEnd a second time (must not fire select)] - expected: FAIL - - [input type password: selectionDirection a second time (must not fire select)] - expected: FAIL - - [input type password: setSelectionRange() a second time (must not fire select)] - expected: FAIL - - [input type password: setRangeText()] - expected: FAIL - - [input type password: setRangeText() a second time (must not fire select)] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-after-content-change.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-after-content-change.html.ini deleted file mode 100644 index 0703cbba621..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-after-content-change.html.ini +++ /dev/null @@ -1,56 +0,0 @@ -[selection-after-content-change.html] - type: testharness - [input out of document: selection must not change when setting the same value] - expected: FAIL - - [input out of document: selection must change when setting a different value] - expected: FAIL - - [input out of document: selection must not change when setting a value that becomes the same after the value sanitization algorithm] - expected: FAIL - - [input in document: selection must not change when setting the same value] - expected: FAIL - - [input in document: selection must change when setting a different value] - expected: FAIL - - [input in document: selection must not change when setting a value that becomes the same after the value sanitization algorithm] - expected: FAIL - - [input in document, with focus: selection must not change when setting the same value] - expected: FAIL - - [input in document, with focus: selection must change when setting a different value] - expected: FAIL - - [input in document, with focus: selection must not change when setting a value that becomes the same after the value sanitization algorithm] - expected: FAIL - - [textarea out of document: selection must not change when setting the same value] - expected: FAIL - - [textarea out of document: selection must change when setting a different value] - expected: FAIL - - [textarea out of document: selection must not change when setting the same normalized value] - expected: FAIL - - [textarea in document: selection must not change when setting the same value] - expected: FAIL - - [textarea in document: selection must change when setting a different value] - expected: FAIL - - [textarea in document: selection must not change when setting the same normalized value] - expected: FAIL - - [textarea in document, with focus: selection must not change when setting the same value] - expected: FAIL - - [textarea in document, with focus: selection must change when setting a different value] - expected: FAIL - - [textarea in document, with focus: selection must not change when setting the same normalized value] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini deleted file mode 100644 index 81dc9d94fb1..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini +++ /dev/null @@ -1,74 +0,0 @@ -[selection-not-application.html] - type: testharness - [setRangeText on an input[type=hidden\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=email\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=datetime-local\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=date\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=month\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=week\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=time\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=number\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=range\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=color\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=checkbox\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=radio\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=file\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=submit\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=image\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=reset\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=button\] throws InvalidStateError] - expected: FAIL - - [setRangeText on an input[type=text\] doesn't throw an exception] - expected: FAIL - - [setRangeText on an input[type=search\] doesn't throw an exception] - expected: FAIL - - [setRangeText on an input[type=tel\] doesn't throw an exception] - expected: FAIL - - [setRangeText on an input[type=url\] doesn't throw an exception] - expected: FAIL - - [setRangeText on an input[type=password\] doesn't throw an exception] - expected: FAIL - - [setRangeText on an input[type=null\] doesn't throw an exception] - expected: FAIL - - [setRangeText on an input[type=aninvalidtype\] doesn't throw an exception] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-value-interactions.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-value-interactions.html.ini deleted file mode 100644 index 6887a9cbe72..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-value-interactions.html.ini +++ /dev/null @@ -1,35 +0,0 @@ -[selection-value-interactions.html] - type: testharness - [value dirty flag behavior after setRangeText on textarea not in body] - expected: FAIL - - [value dirty flag behavior after setRangeText on input not in body] - expected: FAIL - - [value dirty flag behavior after setRangeText on textarea in body] - expected: FAIL - - [value dirty flag behavior after setRangeText on input in body] - expected: FAIL - - [value dirty flag behavior after setRangeText on textarea in body with parsed default value] - expected: FAIL - - [value dirty flag behavior after setRangeText on input in body with parsed default value] - expected: FAIL - - [value dirty flag behavior after setRangeText on focused textarea] - expected: FAIL - - [value dirty flag behavior after setRangeText on focused input] - expected: FAIL - - [value dirty flag behavior after setRangeText on focused then blurred textarea] - expected: FAIL - - [value dirty flag behavior after setRangeText on focused then blurred input] - expected: FAIL - - [selection is always collapsed to the end after setting values on textarea] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection.html.ini deleted file mode 100644 index f9483ec5a35..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection.html.ini +++ /dev/null @@ -1,44 +0,0 @@ -[selection.html] - type: testharness - [test if selection text is correct for input] - expected: FAIL - - [test if selection text is correct for textarea] - expected: FAIL - - [test if non-ascii selection text is correct for input] - expected: FAIL - - [test if non-ascii selection text is correct for textarea] - expected: FAIL - - [test SelectionStart offset for input] - expected: FAIL - - [test SelectionStart offset for textarea] - expected: FAIL - - [test SelectionEnd offset for input] - expected: FAIL - - [test SelectionEnd offset for textarea] - expected: FAIL - - [test SelectionDirection for input] - expected: FAIL - - [test SelectionDirection for textarea] - expected: FAIL - - [test SelectionStart offset for input that is appended] - expected: FAIL - - [test SelectionStart offset for textarea that is appended] - expected: FAIL - - [test SelectionEnd offset for input that is appended] - expected: FAIL - - [test SelectionEnd offset for textarea that is appended] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html.ini deleted file mode 100644 index 3ec8f92d09a..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html.ini +++ /dev/null @@ -1,194 +0,0 @@ -[textfieldselection-setRangeText.html] - type: testharness - [text setRangeText fires a select event] - expected: FAIL - - [text setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [text selectionMode missing] - expected: FAIL - - [text selectionMode 'select'] - expected: FAIL - - [text selectionMode 'start'] - expected: FAIL - - [text selectionMode 'end'] - expected: FAIL - - [text selectionMode 'preserve'] - expected: FAIL - - [text setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [search setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [search selectionMode missing] - expected: FAIL - - [search selectionMode 'select'] - expected: FAIL - - [search selectionMode 'start'] - expected: FAIL - - [search selectionMode 'end'] - expected: FAIL - - [search selectionMode 'preserve'] - expected: FAIL - - [search setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [search setRangeText fires a select event] - expected: FAIL - - [tel setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [tel selectionMode missing] - expected: FAIL - - [tel selectionMode 'select'] - expected: FAIL - - [tel selectionMode 'start'] - expected: FAIL - - [tel selectionMode 'end'] - expected: FAIL - - [tel selectionMode 'preserve'] - expected: FAIL - - [tel setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [tel setRangeText fires a select event] - expected: FAIL - - [url setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [url selectionMode missing] - expected: FAIL - - [url selectionMode 'select'] - expected: FAIL - - [url selectionMode 'start'] - expected: FAIL - - [url selectionMode 'end'] - expected: FAIL - - [url selectionMode 'preserve'] - expected: FAIL - - [url setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [url setRangeText fires a select event] - expected: FAIL - - [password setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [password selectionMode missing] - expected: FAIL - - [password selectionMode 'select'] - expected: FAIL - - [password selectionMode 'start'] - expected: FAIL - - [password selectionMode 'end'] - expected: FAIL - - [password selectionMode 'preserve'] - expected: FAIL - - [password setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [password setRangeText fires a select event] - expected: FAIL - - [display_none setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [display_none selectionMode missing] - expected: FAIL - - [display_none selectionMode 'select'] - expected: FAIL - - [display_none selectionMode 'start'] - expected: FAIL - - [display_none selectionMode 'end'] - expected: FAIL - - [display_none selectionMode 'preserve'] - expected: FAIL - - [display_none setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [display_none setRangeText fires a select event] - expected: FAIL - - [textarea setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [textarea selectionMode missing] - expected: FAIL - - [textarea selectionMode 'select'] - expected: FAIL - - [textarea selectionMode 'start'] - expected: FAIL - - [textarea selectionMode 'end'] - expected: FAIL - - [textarea selectionMode 'preserve'] - expected: FAIL - - [textarea setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [textarea setRangeText fires a select event] - expected: FAIL - - [input_not_in_doc setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments] - expected: FAIL - - [input_not_in_doc selectionMode missing] - expected: FAIL - - [input_not_in_doc selectionMode 'select'] - expected: FAIL - - [input_not_in_doc selectionMode 'start'] - expected: FAIL - - [input_not_in_doc selectionMode 'end'] - expected: FAIL - - [input_not_in_doc selectionMode 'preserve'] - expected: FAIL - - [input_not_in_doc setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception] - expected: FAIL - - [input_not_in_doc setRangeText fires a select event] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/selection.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/selection.html.ini deleted file mode 100644 index 11e799be3f6..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/selection.html.ini +++ /dev/null @@ -1,158 +0,0 @@ -[selection.html] - type: testharness - [input type text should support the select() method] - expected: FAIL - - [input type search should support the select() method] - expected: FAIL - - [input type url should support the select() method] - expected: FAIL - - [input type tel should support the select() method] - expected: FAIL - - [input type email should support the select() method] - expected: FAIL - - [input type password should support the select() method] - expected: FAIL - - [input type date should support the select() method] - expected: FAIL - - [input type month should support the select() method] - expected: FAIL - - [input type week should support the select() method] - expected: FAIL - - [input type time should support the select() method] - expected: FAIL - - [input type datetime-local should support the select() method] - expected: FAIL - - [input type number should support the select() method] - expected: FAIL - - [input type color should support the select() method] - expected: FAIL - - [input type file should support the select() method] - expected: FAIL - - [input type hidden should not support the select() method] - expected: FAIL - - [input type range should not support the select() method] - expected: FAIL - - [input type checkbox should not support the select() method] - expected: FAIL - - [input type radio should not support the select() method] - expected: FAIL - - [input type submit should not support the select() method] - expected: FAIL - - [input type image should not support the select() method] - expected: FAIL - - [input type reset should not support the select() method] - expected: FAIL - - [input type button should not support the select() method] - expected: FAIL - - [input type text should support all selection attributes and methods] - expected: FAIL - - [input type search should support all selection attributes and methods] - expected: FAIL - - [input type url should support all selection attributes and methods] - expected: FAIL - - [input type tel should support all selection attributes and methods] - expected: FAIL - - [input type password should support all selection attributes and methods] - expected: FAIL - - [input type hidden should not support variable-length selections] - expected: FAIL - - [input type email should not support variable-length selections] - expected: FAIL - - [input type date should not support variable-length selections] - expected: FAIL - - [input type month should not support variable-length selections] - expected: FAIL - - [input type week should not support variable-length selections] - expected: FAIL - - [input type time should not support variable-length selections] - expected: FAIL - - [input type datetime-local should not support variable-length selections] - expected: FAIL - - [input type number should not support variable-length selections] - expected: FAIL - - [input type range should not support variable-length selections] - expected: FAIL - - [input type color should not support variable-length selections] - expected: FAIL - - [input type checkbox should not support variable-length selections] - expected: FAIL - - [input type radio should not support variable-length selections] - expected: FAIL - - [input type file should not support variable-length selections] - expected: FAIL - - [input type submit should not support variable-length selections] - expected: FAIL - - [input type image should not support variable-length selections] - expected: FAIL - - [input type reset should not support variable-length selections] - expected: FAIL - - [input type button should not support variable-length selections] - expected: FAIL - - [input type hidden should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type range should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type checkbox should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type radio should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type submit should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type image should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type reset should do nothing when the select() method is called (but, not throw)] - expected: FAIL - - [input type button should do nothing when the select() method is called (but, not throw)] - expected: FAIL - diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end.html index 17fd28c2ef6..0c4deb93ed6 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end.html @@ -143,4 +143,30 @@ el.remove(); } }, "selectionEnd edge-case values"); + + test(() => { + for (let el of createTestElements(testValue)) { + const start = 1; + const end = testValue.length - 1; + + el.setSelectionRange(start, end); + + assert_equals(el.selectionStart, start, `selectionStart on ${el.id}`); + assert_equals(el.selectionEnd, end, `selectionEnd on ${el.id}`); + + el.selectionDirection = "backward"; + + assert_equals(el.selectionStart, start, + `selectionStart on ${el.id} after setting selectionDirection to "backward"`); + assert_equals(el.selectionEnd, end, + `selectionEnd on ${el.id} after setting selectionDirection to "backward"`); + + el.selectionDirection = "forward"; + + assert_equals(el.selectionStart, start, + `selectionStart on ${el.id} after setting selectionDirection to "forward"`); + assert_equals(el.selectionEnd, end, + `selectionEnd on ${el.id} after setting selectionDirection to "forward"`); + } + }, "selectionStart and selectionEnd should remain the same when selectionDirection is changed"); </script> diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html index 82d36cda481..34cfd438cb6 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html @@ -31,6 +31,11 @@ { type: "reset" }, { type: "button" } ]; + + const selectionStart = 2; + const selectionEnd = 5; + const selectionDirection = "backward"; + for (var i = 0; i < types.length; i++) { for (var j = 0; j < types.length; j++) { if (types[i] != types[j]) { @@ -49,6 +54,13 @@ assert_equals(input.value, ""); } else { input.value = expected; + + const previouslySelectable = (input.selectionStart !== null); + + if (previouslySelectable) { + input.setSelectionRange(selectionStart, selectionEnd, selectionDirection); + } + input.type = types[j].type; // change state // type[i] sanitization @@ -69,6 +81,20 @@ } assert_equals(input.value, expected, "input.value should be '" + expected + "' after change of state"); + + const nowSelectable = (input.selectionStart !== null); + + if (nowSelectable) { + if (previouslySelectable) { + assert_equals(input.selectionStart, selectionStart, "selectionStart should be unchanged"); + assert_equals(input.selectionEnd, selectionEnd, "selectionEnd should be unchanged"); + assert_equals(input.selectionDirection, selectionDirection, "selectionDirection should be unchanged"); + } else { + assert_equals(input.selectionStart, 0, "selectionStart should be 0"); + assert_equals(input.selectionEnd, 0, "selectionEnd should be 0"); + assert_equals(input.selectionDirection, "none", "selectionDirection should be 'none'"); + } + } } }, "change state from " + types[i].type + " to " + types[j].type); } |