mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #19963 - paavininanda:Issue#19958, r=<try>
Correct default SelectionStart and SelectionEnd <!-- 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] Added unit tests and wpt for these changes - [x] These changes fix #19958 <!-- 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. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19963) <!-- Reviewable:end -->
This commit is contained in:
commit
62e1fc7899
8 changed files with 144 additions and 87 deletions
|
@ -651,7 +651,7 @@ impl HTMLFormElement {
|
|||
child.downcast::<HTMLSelectElement>().unwrap().reset();
|
||||
}
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
|
||||
child.downcast::<HTMLTextAreaElement>().unwrap().reset();
|
||||
child.downcast::<HTMLTextAreaElement>().unwrap().reset(true);
|
||||
}
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
|
||||
// Unimplemented
|
||||
|
|
|
@ -552,36 +552,7 @@ impl HTMLInputElementMethods for HTMLInputElement {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-input-value
|
||||
fn SetValue(&self, value: DOMString) -> ErrorResult {
|
||||
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(())
|
||||
self.update_text_contents(value, true)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-input-defaultvalue
|
||||
|
@ -937,7 +908,7 @@ impl HTMLInputElement {
|
|||
_ => ()
|
||||
}
|
||||
|
||||
self.SetValue(self.DefaultValue())
|
||||
self.update_text_contents(self.DefaultValue(), true)
|
||||
.expect("Failed to reset input value to default.");
|
||||
self.value_dirty.set(false);
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
|
@ -1065,7 +1036,7 @@ impl HTMLInputElement {
|
|||
let content = textinput.single_line_content_mut();
|
||||
content.make_ascii_lowercase();
|
||||
} else {
|
||||
textinput.set_content("#000000".into());
|
||||
textinput.set_content("#000000".into(), true);
|
||||
}
|
||||
}
|
||||
InputType::Time => {
|
||||
|
@ -1103,6 +1074,41 @@ impl HTMLInputElement {
|
|||
fn selection(&self) -> TextControlSelection<Self> {
|
||||
TextControlSelection::new(&self, &self.textinput)
|
||||
}
|
||||
|
||||
fn update_text_contents(&self, value: DOMString, update_text_cursor: bool) -> ErrorResult {
|
||||
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.
|
||||
if update_text_cursor {
|
||||
self.sanitize_value();
|
||||
}
|
||||
// Step 5.
|
||||
if *self.textinput.borrow().single_line_content() != old_value {
|
||||
self.textinput.borrow_mut().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 {
|
||||
|
@ -1112,7 +1118,6 @@ impl VirtualMethods for HTMLInputElement {
|
|||
|
||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||
|
||||
match attr.local_name() {
|
||||
&local_name!("disabled") => {
|
||||
let disabled_state = match mutation {
|
||||
|
@ -1214,7 +1219,7 @@ impl VirtualMethods for HTMLInputElement {
|
|||
|
||||
// Steps 7-9
|
||||
if !previously_selectable && self.selection_api_applies() {
|
||||
self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward);
|
||||
self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward, true);
|
||||
}
|
||||
},
|
||||
AttributeMutation::Removed => {
|
||||
|
@ -1236,7 +1241,7 @@ impl VirtualMethods for HTMLInputElement {
|
|||
&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));
|
||||
value.map_or(DOMString::new(), DOMString::from), true);
|
||||
self.sanitize_value();
|
||||
self.update_placeholder_shown_state();
|
||||
},
|
||||
|
|
|
@ -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();
|
||||
self.reset(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,26 +244,7 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea-value
|
||||
fn SetValue(&self, value: DOMString) {
|
||||
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);
|
||||
self.update_text_contents(value, true);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||
|
@ -325,9 +306,9 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
|||
|
||||
|
||||
impl HTMLTextAreaElement {
|
||||
pub fn reset(&self) {
|
||||
pub fn reset(&self, update_text_cursor: bool) {
|
||||
// https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control
|
||||
self.SetValue(self.DefaultValue());
|
||||
self.update_text_contents(self.DefaultValue(), update_text_cursor);
|
||||
self.value_dirty.set(false);
|
||||
}
|
||||
|
||||
|
@ -335,6 +316,30 @@ 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();
|
||||
let old_selection = textinput.selection_origin;
|
||||
|
||||
// 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);
|
||||
} else {
|
||||
textinput.selection_origin = old_selection;
|
||||
}
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,7 +432,7 @@ impl VirtualMethods for HTMLTextAreaElement {
|
|||
s.children_changed(mutation);
|
||||
}
|
||||
if !self.value_dirty.get() {
|
||||
self.reset();
|
||||
self.reset(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,7 +483,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();
|
||||
self.reset(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue