Revert "Correct default Selectionstart and SelectionEnd"

This reverts commit b2c1f89b93.
This commit is contained in:
paavininanda 2018-02-06 22:33:12 +05:30
parent 267f9db314
commit b517410a34
8 changed files with 86 additions and 131 deletions

View file

@ -651,7 +651,7 @@ impl HTMLFormElement {
child.downcast::<HTMLSelectElement>().unwrap().reset(); child.downcast::<HTMLSelectElement>().unwrap().reset();
} }
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
child.downcast::<HTMLTextAreaElement>().unwrap().reset(true); child.downcast::<HTMLTextAreaElement>().unwrap().reset();
} }
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
// Unimplemented // Unimplemented

View file

@ -551,7 +551,36 @@ impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#dom-input-value // https://html.spec.whatwg.org/multipage/#dom-input-value
fn SetValue(&self, value: DOMString) -> ErrorResult { fn SetValue(&self, value: DOMString) -> ErrorResult {
self.update_text_contents(value, true) match self.value_mode() {
ValueMode::Value => {
// Steps 1-2.
let old_value = mem::replace(self.textinput.borrow_mut().single_line_content_mut(), value);
// Step 3.
self.value_dirty.set(true);
// Step 4.
self.sanitize_value();
// Step 5.
if *self.textinput.borrow().single_line_content() != old_value {
self.textinput.borrow_mut().clear_selection_to_limit(Direction::Forward);
}
}
ValueMode::Default |
ValueMode::DefaultOn => {
self.upcast::<Element>().set_string_attribute(&local_name!("value"), value);
}
ValueMode::Filename => {
if value.is_empty() {
let window = window_from_node(self);
let fl = FileList::new(&window, vec![]);
self.filelist.set(Some(&fl));
} else {
return Err(Error::InvalidState);
}
}
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
Ok(())
} }
// https://html.spec.whatwg.org/multipage/#dom-input-defaultvalue // https://html.spec.whatwg.org/multipage/#dom-input-defaultvalue
@ -906,8 +935,7 @@ impl HTMLInputElement {
InputType::Image => (), InputType::Image => (),
_ => () _ => ()
} }
self.SetValue(self.DefaultValue())
self.update_text_contents(self.DefaultValue(), true)
.expect("Failed to reset input value to default."); .expect("Failed to reset input value to default.");
self.value_dirty.set(false); self.value_dirty.set(false);
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
@ -1056,44 +1084,6 @@ impl HTMLInputElement {
fn selection(&self) -> TextControlSelection<Self> { fn selection(&self) -> TextControlSelection<Self> {
TextControlSelection::new(&self, &self.textinput) TextControlSelection::new(&self, &self.textinput)
} }
fn update_text_contents(&self, mut value: DOMString, update_text_cursor: bool) -> ErrorResult {
match self.value_mode() {
ValueMode::Value => {
// Step 3.
self.value_dirty.set(true);
// Step 4.
self.sanitize_value(&mut value);
let mut textinput = self.textinput.borrow_mut();
if *textinput.single_line_content() != value {
// Steps 1-2
textinput.set_content(value, update_text_cursor);
// Step 5.
textinput.clear_selection_to_limit(Direction::Forward, update_text_cursor);
}
}
ValueMode::Default |
ValueMode::DefaultOn => {
self.upcast::<Element>().set_string_attribute(&local_name!("value"), value);
}
ValueMode::Filename => {
if value.is_empty() {
let window = window_from_node(self);
let fl = FileList::new(&window, vec![]);
self.filelist.set(Some(&fl));
} else {
return Err(Error::InvalidState);
}
}
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
Ok(())
}
} }
impl VirtualMethods for HTMLInputElement { impl VirtualMethods for HTMLInputElement {
@ -1103,6 +1093,7 @@ impl VirtualMethods for HTMLInputElement {
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type().unwrap().attribute_mutated(attr, mutation);
match attr.local_name() { match attr.local_name() {
&local_name!("disabled") => { &local_name!("disabled") => {
let disabled_state = match mutation { let disabled_state = match mutation {
@ -1207,7 +1198,7 @@ impl VirtualMethods for HTMLInputElement {
// Steps 7-9 // Steps 7-9
if !previously_selectable && self.selection_api_applies() { if !previously_selectable && self.selection_api_applies() {
textinput.clear_selection_to_limit(Direction::Backward, true); self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward);
} }
}, },
AttributeMutation::Removed => { AttributeMutation::Removed => {
@ -1231,7 +1222,9 @@ impl VirtualMethods for HTMLInputElement {
let mut value = value.map_or(DOMString::new(), DOMString::from); let mut value = value.map_or(DOMString::new(), DOMString::from);
self.sanitize_value(&mut value); self.sanitize_value(&mut value);
self.textinput.borrow_mut().set_content(value, true);
self.textinput.borrow_mut().set_content(
value.map_or(DOMString::new(), DOMString::from));
self.update_placeholder_shown_state(); self.update_placeholder_shown_state();
}, },
&local_name!("name") if self.input_type() == InputType::Radio => { &local_name!("name") if self.input_type() == InputType::Radio => {

View file

@ -233,7 +233,7 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// if the element's dirty value flag is false, then the element's // 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 // raw value must be set to the value of the element's textContent IDL attribute
if !self.value_dirty.get() { if !self.value_dirty.get() {
self.reset(false); self.reset();
} }
} }
@ -244,7 +244,26 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// https://html.spec.whatwg.org/multipage/#dom-textarea-value // https://html.spec.whatwg.org/multipage/#dom-textarea-value
fn SetValue(&self, value: DOMString) { fn SetValue(&self, value: DOMString) {
self.update_text_contents(value, true); let mut textinput = self.textinput.borrow_mut();
// Step 1
let old_value = textinput.get_content();
let old_selection = textinput.selection_origin;
// Step 2
textinput.set_content(value);
// Step 3
self.value_dirty.set(true);
if old_value != textinput.get_content() {
// Step 4
textinput.clear_selection_to_limit(Direction::Forward);
} else {
textinput.selection_origin = old_selection;
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
} }
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels // https://html.spec.whatwg.org/multipage/#dom-lfe-labels
@ -306,9 +325,9 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
impl HTMLTextAreaElement { impl HTMLTextAreaElement {
pub fn reset(&self, update_text_cursor: bool) { pub fn reset(&self) {
// https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control
self.update_text_contents(self.DefaultValue(), update_text_cursor); self.SetValue(self.DefaultValue());
self.value_dirty.set(false); self.value_dirty.set(false);
} }
@ -316,27 +335,6 @@ impl HTMLTextAreaElement {
fn selection(&self) -> TextControlSelection<Self> { fn selection(&self) -> TextControlSelection<Self> {
TextControlSelection::new(&self, &self.textinput) TextControlSelection::new(&self, &self.textinput)
} }
// Helper function to check if text_cursor is to be updated or not
fn update_text_contents(&self, value: DOMString, update_text_cursor: bool) {
let mut textinput = self.textinput.borrow_mut();
// Step 1
let old_value = textinput.get_content();
// Step 2
textinput.set_content(value, update_text_cursor);
// Step 3
self.value_dirty.set(true);
if old_value != textinput.get_content() {
// Step 4
textinput.clear_selection_to_limit(Direction::Forward, update_text_cursor);
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
}
} }
@ -429,7 +427,7 @@ impl VirtualMethods for HTMLTextAreaElement {
s.children_changed(mutation); s.children_changed(mutation);
} }
if !self.value_dirty.get() { if !self.value_dirty.get() {
self.reset(false); self.reset();
} }
} }
@ -480,7 +478,7 @@ impl VirtualMethods for HTMLTextAreaElement {
self.super_type().unwrap().pop(); self.super_type().unwrap().pop();
// https://html.spec.whatwg.org/multipage/#the-textarea-element:stack-of-open-elements // https://html.spec.whatwg.org/multipage/#the-textarea-element:stack-of-open-elements
self.reset(false); self.reset();
} }
} }

View file

@ -188,7 +188,7 @@ impl<T: ClipboardProvider> TextInput<T> {
min_length: min_length, min_length: min_length,
selection_direction: selection_direction, selection_direction: selection_direction,
}; };
i.set_content(initial, false); i.set_content(initial);
i i
} }
@ -448,7 +448,9 @@ impl<T: ClipboardProvider> TextInput<T> {
return; return;
} }
let col = self.lines[self.edit_point.line][..self.edit_point.index].chars().count(); let col = self.lines[self.edit_point.line][..self.edit_point.index].chars().count();
self.edit_point.line = target_line as usize; self.edit_point.line = target_line as usize;
self.edit_point.index = len_of_first_n_chars(&self.lines[self.edit_point.line], col); self.edit_point.index = len_of_first_n_chars(&self.lines[self.edit_point.line], col);
self.assert_ok_selection(); self.assert_ok_selection();
@ -568,9 +570,9 @@ impl<T: ClipboardProvider> TextInput<T> {
} }
/// Remove the current selection and set the edit point to the end of the content. /// 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, update_text_cursor: bool) { pub fn clear_selection_to_limit(&mut self, direction: Direction) {
self.clear_selection(); self.clear_selection();
self.adjust_horizontal_to_limit(direction, Selection::NotSelected, update_text_cursor); self.adjust_horizontal_to_limit(direction, Selection::NotSelected);
} }
pub fn adjust_horizontal_by_word(&mut self, direction: Direction, select: Selection) { pub fn adjust_horizontal_by_word(&mut self, direction: Direction, select: Selection) {
@ -662,20 +664,18 @@ impl<T: ClipboardProvider> TextInput<T> {
self.perform_horizontal_adjustment(shift, select); self.perform_horizontal_adjustment(shift, select);
} }
pub fn adjust_horizontal_to_limit(&mut self, direction: Direction, select: Selection, update_text_cursor: bool) { pub fn adjust_horizontal_to_limit(&mut self, direction: Direction, select: Selection) {
if self.adjust_selection_for_horizontal_change(direction, select) { if self.adjust_selection_for_horizontal_change(direction, select) {
return return
} }
if update_text_cursor { match direction {
match direction { Direction::Backward => {
Direction::Backward => { self.edit_point.line = 0;
self.edit_point.line = 0; self.edit_point.index = 0;
self.edit_point.index = 0; },
}, Direction::Forward => {
Direction::Forward => { self.edit_point.line = &self.lines.len() - 1;
self.edit_point.line = &self.lines.len() - 1; self.edit_point.index = (&self.lines[&self.lines.len() - 1]).len();
self.edit_point.index = (&self.lines[&self.lines.len() - 1]).len();
}
} }
} }
} }
@ -765,12 +765,12 @@ impl<T: ClipboardProvider> TextInput<T> {
}, },
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
(None, Key::Up) if mods.contains(KeyModifiers::SUPER) => { (None, Key::Up) if mods.contains(KeyModifiers::SUPER) => {
self.adjust_horizontal_to_limit(Direction::Backward, maybe_select, true); self.adjust_horizontal_to_limit(Direction::Backward, maybe_select);
KeyReaction::RedrawSelection KeyReaction::RedrawSelection
}, },
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
(None, Key::Down) if mods.contains(KeyModifiers::SUPER) => { (None, Key::Down) if mods.contains(KeyModifiers::SUPER) => {
self.adjust_horizontal_to_limit(Direction::Forward, maybe_select, true); self.adjust_horizontal_to_limit(Direction::Forward, maybe_select);
KeyReaction::RedrawSelection KeyReaction::RedrawSelection
}, },
(None, Key::Left) if mods.contains(KeyModifiers::ALT) => { (None, Key::Left) if mods.contains(KeyModifiers::ALT) => {
@ -871,7 +871,7 @@ impl<T: ClipboardProvider> TextInput<T> {
/// Set the current contents of the text input. If this is control supports multiple lines, /// Set the current contents of the text input. If this is control supports multiple lines,
/// any \n encountered will be stripped and force a new logical line. /// any \n encountered will be stripped and force a new logical line.
pub fn set_content(&mut self, content: DOMString, update_text_cursor: bool) { pub fn set_content(&mut self, content: DOMString) {
self.lines = if self.multiline { self.lines = if self.multiline {
// https://html.spec.whatwg.org/multipage/#textarea-line-break-normalisation-transformation // https://html.spec.whatwg.org/multipage/#textarea-line-break-normalisation-transformation
content.replace("\r\n", "\n") content.replace("\r\n", "\n")
@ -882,9 +882,7 @@ impl<T: ClipboardProvider> TextInput<T> {
vec!(content) vec!(content)
}; };
if update_text_cursor { self.edit_point = self.edit_point.constrain_to(&self.lines);
self.edit_point = self.edit_point.constrain_to(&self.lines);
}
if let Some(origin) = self.selection_origin { if let Some(origin) = self.selection_origin {
self.selection_origin = Some(origin.constrain_to(&self.lines)); self.selection_origin = Some(origin.constrain_to(&self.lines));

View file

@ -27,7 +27,7 @@ fn test_set_content_ignores_max_length() {
Lines::Single, DOMString::from(""), DummyClipboardContext::new(""), Some(1), None, SelectionDirection::None Lines::Single, DOMString::from(""), DummyClipboardContext::new(""), Some(1), None, SelectionDirection::None
); );
textinput.set_content(DOMString::from("mozilla rocks"), true); textinput.set_content(DOMString::from("mozilla rocks"));
assert_eq!(textinput.get_content(), DOMString::from("mozilla rocks")); assert_eq!(textinput.get_content(), DOMString::from("mozilla rocks"));
} }
@ -489,7 +489,7 @@ fn test_textinput_set_content() {
let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); let mut textinput = text_input(Lines::Multiple, "abc\nde\nf");
assert_eq!(textinput.get_content(), "abc\nde\nf"); assert_eq!(textinput.get_content(), "abc\nde\nf");
textinput.set_content(DOMString::from("abc\nf"), true); textinput.set_content(DOMString::from("abc\nf"));
assert_eq!(textinput.get_content(), "abc\nf"); assert_eq!(textinput.get_content(), "abc\nf");
assert_eq!(textinput.edit_point().line, 0); assert_eq!(textinput.edit_point().line, 0);
@ -634,10 +634,6 @@ fn test_textinput_unicode_handling() {
fn test_selection_bounds() { fn test_selection_bounds() {
let mut textinput = text_input(Lines::Single, "abcdef"); let mut textinput = text_input(Lines::Single, "abcdef");
assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_origin_or_edit_point());
assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_start());
assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_end());
textinput.set_selection_range(2, 5, SelectionDirection::Forward); 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_origin_or_edit_point());
assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_start()); assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_start());

View file

@ -330871,12 +330871,6 @@
{} {}
] ]
], ],
"html/semantics/forms/textfieldselection/defaultSelection.html": [
[
"/html/semantics/forms/textfieldselection/defaultSelection.html",
{}
]
],
"html/semantics/forms/textfieldselection/select-event.html": [ "html/semantics/forms/textfieldselection/select-event.html": [
[ [
"/html/semantics/forms/textfieldselection/select-event.html", "/html/semantics/forms/textfieldselection/select-event.html",

View file

@ -0,0 +1,4 @@
[setSelectionRange.html]
[setSelectionRange on line boundaries]
expected: FAIL

View file

@ -1,28 +0,0 @@
<!doctype html>
<meta charset="utf-8">
<title></title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<textarea>foo</textarea>
<input type="text" value="foo"></input>
<script>
for (let el of [document.querySelector("textarea"), document.querySelector("input")]) {
test(function() {
assert_equals(el.selectionStart, 0);
assert_equals(el.selectionEnd, 0);
}, `Default selectionStart and selectionEnd for ${el}`);
test(function() {
el.value="foo";
assert_equals(el.selectionStart, 0);
assert_equals(el.selectionEnd, 0);
}, `selectionStart and selectionEnd do not change when same value set again for ${el}`);
test(function() {
el.value="Foo";
assert_equals(el.selectionStart, 3);
assert_equals(el.selectionEnd, 3);
}, `selectionStart and selectionEnd change when value changed to upper case for ${el}`);
}
</script>