зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #20089 - Revert previously merged code, better implementation for Default selectionStart and selectionEnd (from paavininanda:RevertChanges); r=jdm
<!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 0fa324872330715140c86e5125640ef23e8b072b --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 8c899d232d8559a68f2569c0f533bc2153b9708e
This commit is contained in:
Родитель
c9ba9539cc
Коммит
063498d9e9
|
@ -651,7 +651,7 @@ impl HTMLFormElement {
|
|||
child.downcast::<HTMLSelectElement>().unwrap().reset();
|
||||
}
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
|
||||
child.downcast::<HTMLTextAreaElement>().unwrap().reset(true);
|
||||
child.downcast::<HTMLTextAreaElement>().unwrap().reset();
|
||||
}
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
|
||||
// Unimplemented
|
||||
|
|
|
@ -550,8 +550,43 @@ impl HTMLInputElementMethods for HTMLInputElement {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-input-value
|
||||
fn SetValue(&self, value: DOMString) -> ErrorResult {
|
||||
self.update_text_contents(value, true)
|
||||
fn SetValue(&self, mut value: DOMString) -> 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();
|
||||
|
||||
// Step 5.
|
||||
if *textinput.single_line_content() != value {
|
||||
// Steps 1-2
|
||||
textinput.set_content(value);
|
||||
|
||||
// Step 5.
|
||||
textinput.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
|
||||
|
@ -906,9 +941,7 @@ impl HTMLInputElement {
|
|||
InputType::Image => (),
|
||||
_ => ()
|
||||
}
|
||||
|
||||
self.update_text_contents(self.DefaultValue(), true)
|
||||
.expect("Failed to reset input value to default.");
|
||||
self.textinput.borrow_mut().set_content(self.DefaultValue());
|
||||
self.value_dirty.set(false);
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
|
@ -1056,44 +1089,6 @@ impl HTMLInputElement {
|
|||
fn selection(&self) -> TextControlSelection<Self> {
|
||||
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 {
|
||||
|
@ -1203,11 +1198,11 @@ impl VirtualMethods for HTMLInputElement {
|
|||
let mut textinput = self.textinput.borrow_mut();
|
||||
let mut value = textinput.single_line_content().clone();
|
||||
self.sanitize_value(&mut value);
|
||||
textinput.set_content(value, true);
|
||||
textinput.set_content(value);
|
||||
|
||||
// Steps 7-9
|
||||
if !previously_selectable && self.selection_api_applies() {
|
||||
textinput.clear_selection_to_limit(Direction::Backward, true);
|
||||
textinput.clear_selection_to_limit(Direction::Backward);
|
||||
}
|
||||
},
|
||||
AttributeMutation::Removed => {
|
||||
|
@ -1231,7 +1226,7 @@ impl VirtualMethods for HTMLInputElement {
|
|||
let mut value = value.map_or(DOMString::new(), DOMString::from);
|
||||
|
||||
self.sanitize_value(&mut value);
|
||||
self.textinput.borrow_mut().set_content(value, true);
|
||||
self.textinput.borrow_mut().set_content(value);
|
||||
self.update_placeholder_shown_state();
|
||||
},
|
||||
&local_name!("name") if self.input_type() == InputType::Radio => {
|
||||
|
|
|
@ -233,7 +233,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_dirty.get() {
|
||||
self.reset(false);
|
||||
self.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,23 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea-value
|
||||
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();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||
|
@ -306,9 +322,10 @@ impl HTMLTextAreaElementMethods for 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
|
||||
self.update_text_contents(self.DefaultValue(), update_text_cursor);
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
textinput.set_content(self.DefaultValue());
|
||||
self.value_dirty.set(false);
|
||||
}
|
||||
|
||||
|
@ -316,27 +333,6 @@ impl HTMLTextAreaElement {
|
|||
fn selection(&self) -> TextControlSelection<Self> {
|
||||
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 +425,7 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
s.children_changed(mutation);
|
||||
}
|
||||
if !self.value_dirty.get() {
|
||||
self.reset(false);
|
||||
self.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,7 +476,7 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
self.super_type().unwrap().pop();
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#the-textarea-element:stack-of-open-elements
|
||||
self.reset(false);
|
||||
self.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
min_length: min_length,
|
||||
selection_direction: selection_direction,
|
||||
};
|
||||
i.set_content(initial, false);
|
||||
i.set_content(initial);
|
||||
i
|
||||
}
|
||||
|
||||
|
@ -568,9 +568,9 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
}
|
||||
|
||||
/// 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.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) {
|
||||
|
@ -662,20 +662,18 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
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) {
|
||||
return
|
||||
}
|
||||
if update_text_cursor {
|
||||
match direction {
|
||||
Direction::Backward => {
|
||||
self.edit_point.line = 0;
|
||||
self.edit_point.index = 0;
|
||||
},
|
||||
Direction::Forward => {
|
||||
self.edit_point.line = &self.lines.len() - 1;
|
||||
self.edit_point.index = (&self.lines[&self.lines.len() - 1]).len();
|
||||
}
|
||||
match direction {
|
||||
Direction::Backward => {
|
||||
self.edit_point.line = 0;
|
||||
self.edit_point.index = 0;
|
||||
},
|
||||
Direction::Forward => {
|
||||
self.edit_point.line = &self.lines.len() - 1;
|
||||
self.edit_point.index = (&self.lines[&self.lines.len() - 1]).len();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -765,12 +763,12 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(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
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(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
|
||||
},
|
||||
(None, Key::Left) if mods.contains(KeyModifiers::ALT) => {
|
||||
|
@ -871,7 +869,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
|
||||
/// 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.
|
||||
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 {
|
||||
// https://html.spec.whatwg.org/multipage/#textarea-line-break-normalisation-transformation
|
||||
content.replace("\r\n", "\n")
|
||||
|
@ -882,14 +880,11 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
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 {
|
||||
self.selection_origin = Some(origin.constrain_to(&self.lines));
|
||||
}
|
||||
|
||||
self.assert_ok_selection();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ fn test_set_content_ignores_max_length() {
|
|||
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"));
|
||||
}
|
||||
|
||||
|
@ -489,15 +489,16 @@ fn test_textinput_set_content() {
|
|||
let mut textinput = text_input(Lines::Multiple, "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.edit_point().line, 0);
|
||||
assert_eq!(textinput.edit_point().index, 0);
|
||||
|
||||
textinput.adjust_horizontal(3, Selection::Selected);
|
||||
assert_eq!(textinput.edit_point().line, 0);
|
||||
assert_eq!(textinput.edit_point().index, 3);
|
||||
textinput.set_content(DOMString::from("de"), true);
|
||||
textinput.set_content(DOMString::from("de"));
|
||||
assert_eq!(textinput.get_content(), "de");
|
||||
assert_eq!(textinput.edit_point().line, 0);
|
||||
assert_eq!(textinput.edit_point().index, 2);
|
||||
|
|
Загрузка…
Ссылка в новой задаче