diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index b0fbfb36f365..05ca796abd28 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -48,7 +48,6 @@ use script_traits::ScriptToConstellationChan;
use servo_atoms::Atom;
use std::borrow::ToOwned;
use std::cell::Cell;
-use std::mem;
use std::ops::Range;
use style::attr::AttrValue;
use style::element_state::ElementState;
@@ -990,42 +989,34 @@ impl HTMLInputElement {
}
// https://html.spec.whatwg.org/multipage/#value-sanitization-algorithm
- fn sanitize_value(&self) {
+ fn sanitize_value(&self, value: &mut DOMString) {
match self.input_type() {
InputType::Text | InputType::Search | InputType::Tel | InputType::Password => {
- self.textinput.borrow_mut().single_line_content_mut().strip_newlines();
+ value.strip_newlines();
}
InputType::Url => {
- let mut textinput = self.textinput.borrow_mut();
- let content = textinput.single_line_content_mut();
- content.strip_newlines();
- content.strip_leading_and_trailing_ascii_whitespace();
+ value.strip_newlines();
+ value.strip_leading_and_trailing_ascii_whitespace();
}
InputType::Date => {
- let mut textinput = self.textinput.borrow_mut();
- if !textinput.single_line_content().is_valid_date_string() {
- textinput.single_line_content_mut().clear();
+ if !value.is_valid_date_string() {
+ value.clear();
}
}
InputType::Month => {
- let mut textinput = self.textinput.borrow_mut();
- if !textinput.single_line_content().is_valid_month_string() {
- textinput.single_line_content_mut().clear();
+ if !value.is_valid_month_string() {
+ value.clear();
}
}
InputType::Week => {
- let mut textinput = self.textinput.borrow_mut();
- if !textinput.single_line_content().is_valid_week_string() {
- textinput.single_line_content_mut().clear();
+ if !value.is_valid_week_string() {
+ value.clear();
}
}
InputType::Color => {
- let mut textinput = self.textinput.borrow_mut();
-
let is_valid = {
- let content = textinput.single_line_content();
- let mut chars = content.chars();
- if content.len() == 7 && chars.next() == Some('#') {
+ let mut chars = value.chars();
+ if value.len() == 7 && chars.next() == Some('#') {
chars.all(|c| c.is_digit(16))
} else {
false
@@ -1033,38 +1024,29 @@ impl HTMLInputElement {
};
if is_valid {
- let content = textinput.single_line_content_mut();
- content.make_ascii_lowercase();
+ value.make_ascii_lowercase();
} else {
- textinput.set_content("#000000".into(), true);
+ *value = "#000000".into();
}
}
InputType::Time => {
- let mut textinput = self.textinput.borrow_mut();
-
- if !textinput.single_line_content().is_valid_time_string() {
- textinput.single_line_content_mut().clear();
+ if !value.is_valid_time_string() {
+ value.clear();
}
}
InputType::DatetimeLocal => {
- let mut textinput = self.textinput.borrow_mut();
- if textinput.single_line_content_mut()
- .convert_valid_normalized_local_date_and_time_string().is_err() {
- textinput.single_line_content_mut().clear();
+ if value.convert_valid_normalized_local_date_and_time_string().is_err() {
+ value.clear();
}
}
InputType::Number => {
- let mut textinput = self.textinput.borrow_mut();
- if !textinput.single_line_content().is_valid_floating_point_number_string() {
- textinput.single_line_content_mut().clear();
+ if !value.is_valid_floating_point_number_string() {
+ value.clear();
}
}
// https://html.spec.whatwg.org/multipage/#range-state-(type=range):value-sanitization-algorithm
InputType::Range => {
- self.textinput
- .borrow_mut()
- .single_line_content_mut()
- .set_best_representation_of_the_floating_point_number();
+ value.set_best_representation_of_the_floating_point_number();
}
_ => ()
}
@@ -1075,20 +1057,23 @@ impl HTMLInputElement {
TextControlSelection::new(&self, &self.textinput)
}
- fn update_text_contents(&self, value: DOMString, update_text_cursor: bool) -> ErrorResult {
+ fn update_text_contents(&self, mut 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);
+ 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 |
@@ -1215,11 +1200,14 @@ impl VirtualMethods for HTMLInputElement {
}
// Step 6
- self.sanitize_value();
+ 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);
// Steps 7-9
if !previously_selectable && self.selection_api_applies() {
- self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward, true);
+ textinput.clear_selection_to_limit(Direction::Backward, true);
}
},
AttributeMutation::Removed => {
@@ -1240,9 +1228,10 @@ 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), true);
- self.sanitize_value();
+ let mut value = value.map_or(DOMString::new(), DOMString::from);
+
+ self.sanitize_value(&mut value);
+ self.textinput.borrow_mut().set_content(value, true);
self.update_placeholder_shown_state();
},
&local_name!("name") if self.input_type() == InputType::Radio => {
@@ -1252,10 +1241,12 @@ impl VirtualMethods for HTMLInputElement {
&local_name!("maxlength") => {
match *attr.value() {
AttrValue::Int(_, value) => {
+ let mut textinput = self.textinput.borrow_mut();
+
if value < 0 {
- self.textinput.borrow_mut().max_length = None
+ textinput.set_max_length(None);
} else {
- self.textinput.borrow_mut().max_length = Some(value as usize)
+ textinput.set_max_length(Some(value as usize))
}
},
_ => panic!("Expected an AttrValue::Int"),
@@ -1264,10 +1255,12 @@ impl VirtualMethods for HTMLInputElement {
&local_name!("minlength") => {
match *attr.value() {
AttrValue::Int(_, value) => {
+ let mut textinput = self.textinput.borrow_mut();
+
if value < 0 {
- self.textinput.borrow_mut().min_length = None
+ textinput.set_min_length(None);
} else {
- self.textinput.borrow_mut().min_length = Some(value as usize)
+ textinput.set_min_length(Some(value as usize))
}
},
_ => panic!("Expected an AttrValue::Int"),
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index a50389185173..a6899b05a06f 100755
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -323,7 +323,6 @@ impl HTMLTextAreaElement {
// Step 1
let old_value = textinput.get_content();
- let old_selection = textinput.selection_origin;
// Step 2
textinput.set_content(value, update_text_cursor);
@@ -334,8 +333,6 @@ impl HTMLTextAreaElement {
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::().dirty(NodeDamage::OtherNodeDamage);
diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs
index b47167ae9377..fa6c8d0b6043 100644
--- a/components/script/dom/textcontrol.rs
+++ b/components/script/dom/textcontrol.rs
@@ -257,7 +257,7 @@ impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
}
fn direction(&self) -> SelectionDirection {
- self.textinput.borrow().selection_direction
+ self.textinput.borrow().selection_direction()
}
// https://html.spec.whatwg.org/multipage/#set-the-selection-range
diff --git a/components/script/textinput.rs b/components/script/textinput.rs
index a4a5d5e89658..a61799dadb09 100644
--- a/components/script/textinput.rs
+++ b/components/script/textinput.rs
@@ -56,6 +56,18 @@ pub struct TextPoint {
pub index: usize,
}
+impl TextPoint {
+ /// Returns a TextPoint constrained to be a valid location within lines
+ fn constrain_to(&self, lines: &[DOMString]) -> TextPoint {
+ let line = min(self.line, lines.len() - 1);
+
+ TextPoint {
+ line,
+ index: min(self.index, lines[line].len()),
+ }
+ }
+}
+
#[derive(Clone, Copy, PartialEq)]
pub struct SelectionState {
start: TextPoint,
@@ -68,21 +80,26 @@ pub struct SelectionState {
pub struct TextInput {
/// Current text input content, split across lines without trailing '\n'
lines: Vec,
+
/// Current cursor input point
- pub edit_point: TextPoint,
+ edit_point: 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,
+ selection_origin: Option,
+ selection_direction: SelectionDirection,
+
/// Is this a multiline input?
multiline: bool,
+
#[ignore_malloc_size_of = "Can't easily measure this generic type"]
clipboard_provider: T,
+
/// The maximum number of UTF-16 code units this text input is allowed to hold.
///
///
- pub max_length: Option,
- pub min_length: Option,
- pub selection_direction: SelectionDirection,
+ max_length: Option,
+ min_length: Option,
}
/// Resulting action to be taken by the owner of a text input that is handling an event.
@@ -175,6 +192,32 @@ impl TextInput {
i
}
+ pub fn edit_point(&self) -> TextPoint {
+ self.edit_point
+ }
+
+ pub fn selection_origin(&self) -> Option {
+ self.selection_origin
+ }
+
+ /// 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)
+ }
+
+ pub fn selection_direction(&self) -> SelectionDirection {
+ self.selection_direction
+ }
+
+ pub fn set_max_length(&mut self, length: Option) {
+ self.max_length = length;
+ }
+
+ pub fn set_min_length(&mut self, length: Option) {
+ self.min_length = length;
+ }
+
/// Remove a character at the current editing point
pub fn delete_char(&mut self, dir: Direction) {
if self.selection_origin.is_none() || self.selection_origin == Some(self.edit_point) {
@@ -196,12 +239,6 @@ impl TextInput {
self.replace_selection(DOMString::from(s.into()));
}
- /// 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)
- }
-
/// 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 {
@@ -832,12 +869,6 @@ impl TextInput {
&self.lines[0]
}
- /// Get a mutable reference to the contents of a single-line text input. Panics if self is a multiline input.
- pub fn single_line_content_mut(&mut self) -> &mut DOMString {
- assert!(!self.multiline);
- &mut self.lines[0]
- }
-
/// 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) {
@@ -850,11 +881,15 @@ impl TextInput {
} else {
vec!(content)
};
+
if update_text_cursor {
- 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.edit_point = self.edit_point.constrain_to(&self.lines);
}
- self.selection_origin = None;
+
+ if let Some(origin) = self.selection_origin {
+ self.selection_origin = Some(origin.constrain_to(&self.lines));
+ }
+
self.assert_ok_selection();
}
diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs
index 0bdeec59cda1..916e26c9164e 100644
--- a/tests/unit/script/textinput.rs
+++ b/tests/unit/script/textinput.rs
@@ -42,7 +42,7 @@ fn test_textinput_when_inserting_multiple_lines_over_a_selection_respects_max_le
SelectionDirection::None,
);
- textinput.edit_point = TextPoint { line: 0, index: 1 };
+ textinput.adjust_horizontal(1, Selection::NotSelected);
textinput.adjust_horizontal(3, Selection::Selected);
textinput.adjust_vertical(1, Selection::Selected);
@@ -67,8 +67,7 @@ fn test_textinput_when_inserting_multiple_lines_still_respects_max_length() {
SelectionDirection::None
);
- textinput.edit_point = TextPoint { line: 1, index: 0 };
-
+ textinput.adjust_vertical(1, Selection::NotSelected);
textinput.insert_string("cruel\nterrible".to_string());
assert_eq!(textinput.get_content(), "hello\ncruel\nworld");
@@ -117,7 +116,7 @@ fn test_single_line_textinput_with_max_length_doesnt_allow_appending_characters_
SelectionDirection::None,
);
- textinput.edit_point = TextPoint { line: 0, index: 1 };
+ textinput.adjust_horizontal(1, Selection::NotSelected);
textinput.adjust_horizontal(3, Selection::Selected);
// Selection is now "abcde"
@@ -220,9 +219,7 @@ fn test_textinput_delete_char() {
assert_eq!(textinput.get_content(), "ab");
let mut textinput = text_input(Lines::Single, "abcdefg");
- textinput.adjust_horizontal(2, Selection::NotSelected);
- // Set an empty selection range.
- textinput.selection_origin = Some(textinput.edit_point);
+ textinput.set_selection_range(2, 2, SelectionDirection::None);
textinput.delete_char(Direction::Backward);
assert_eq!(textinput.get_content(), "acdefg");
}
@@ -300,16 +297,16 @@ fn test_textinput_adjust_vertical() {
let mut textinput = text_input(Lines::Multiple, "abc\nde\nf");
textinput.adjust_horizontal(3, Selection::NotSelected);
textinput.adjust_vertical(1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 2);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 2);
textinput.adjust_vertical(-1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 2);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 2);
textinput.adjust_vertical(2, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 2);
- assert_eq!(textinput.edit_point.index, 1);
+ assert_eq!(textinput.edit_point().line, 2);
+ assert_eq!(textinput.edit_point().index, 1);
}
#[test]
@@ -317,32 +314,32 @@ fn test_textinput_adjust_vertical_multibyte() {
let mut textinput = text_input(Lines::Multiple, "áé\nae");
textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 2);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 2);
textinput.adjust_vertical(1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 1);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 1);
}
#[test]
fn test_textinput_adjust_horizontal() {
let mut textinput = text_input(Lines::Multiple, "abc\nde\nf");
textinput.adjust_horizontal(4, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 0);
textinput.adjust_horizontal(1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 1);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 1);
textinput.adjust_horizontal(2, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 2);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().line, 2);
+ assert_eq!(textinput.edit_point().index, 0);
textinput.adjust_horizontal(-1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 2);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 2);
}
#[test]
@@ -351,45 +348,45 @@ fn test_textinput_adjust_horizontal_by_word() {
let mut textinput = text_input(Lines::Single, "abc def");
textinput.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
textinput.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 7);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 7);
textinput.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 4);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 4);
textinput.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 0);
// Test new line case of movement word by word based on UAX#29 rules
let mut textinput_2 = text_input(Lines::Multiple, "abc\ndef");
textinput_2.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
textinput_2.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_2.edit_point.line, 1);
- assert_eq!(textinput_2.edit_point.index, 3);
+ assert_eq!(textinput_2.edit_point().line, 1);
+ assert_eq!(textinput_2.edit_point().index, 3);
textinput_2.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput_2.edit_point.line, 1);
- assert_eq!(textinput_2.edit_point.index, 0);
+ assert_eq!(textinput_2.edit_point().line, 1);
+ assert_eq!(textinput_2.edit_point().index, 0);
textinput_2.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput_2.edit_point.line, 0);
- assert_eq!(textinput_2.edit_point.index, 0);
+ assert_eq!(textinput_2.edit_point().line, 0);
+ assert_eq!(textinput_2.edit_point().index, 0);
// Test non-standard sized characters case of movement word by word based on UAX#29 rules
let mut textinput_3 = text_input(Lines::Single, "áéc d🌠bc");
textinput_3.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 5);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 5);
textinput_3.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 7);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 7);
textinput_3.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 13);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 13);
textinput_3.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 11);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 11);
textinput_3.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 6);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 6);
}
#[test]
@@ -397,29 +394,29 @@ fn test_textinput_adjust_horizontal_to_line_end() {
// Test standard case of movement to end based on UAX#29 rules
let mut textinput = text_input(Lines::Single, "abc def");
textinput.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 7);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 7);
// Test new line case of movement to end based on UAX#29 rules
let mut textinput_2 = text_input(Lines::Multiple, "abc\ndef");
textinput_2.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_2.edit_point.line, 0);
- assert_eq!(textinput_2.edit_point.index, 3);
+ assert_eq!(textinput_2.edit_point().line, 0);
+ assert_eq!(textinput_2.edit_point().index, 3);
textinput_2.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_2.edit_point.line, 0);
- assert_eq!(textinput_2.edit_point.index, 3);
+ assert_eq!(textinput_2.edit_point().line, 0);
+ assert_eq!(textinput_2.edit_point().index, 3);
textinput_2.adjust_horizontal_to_line_end(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput_2.edit_point.line, 0);
- assert_eq!(textinput_2.edit_point.index, 0);
+ assert_eq!(textinput_2.edit_point().line, 0);
+ assert_eq!(textinput_2.edit_point().index, 0);
// Test non-standard sized characters case of movement to end based on UAX#29 rules
let mut textinput_3 = text_input(Lines::Single, "áéc d🌠bc");
textinput_3.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 13);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 13);
textinput_3.adjust_horizontal_to_line_end(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput_3.edit_point.line, 0);
- assert_eq!(textinput_3.edit_point.index, 0);
+ assert_eq!(textinput_3.edit_point().line, 0);
+ assert_eq!(textinput_3.edit_point().index, 0);
}
#[test]
@@ -429,29 +426,29 @@ fn test_navigation_keyboard_shortcuts() {
// Test that CMD + Right moves to the end of the current line.
textinput.handle_keydown_aux(None, Key::Right, KeyModifiers::SUPER);
- assert_eq!(textinput.edit_point.index, 11);
+ assert_eq!(textinput.edit_point().index, 11);
// Test that CMD + Right moves to the beginning of the current line.
textinput.handle_keydown_aux(None, Key::Left, KeyModifiers::SUPER);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
// Test that CTRL + ALT + E moves to the end of the current line also.
textinput.handle_keydown_aux(None, Key::E, KeyModifiers::CONTROL | KeyModifiers::ALT);
- assert_eq!(textinput.edit_point.index, 11);
+ assert_eq!(textinput.edit_point().index, 11);
// Test that CTRL + ALT + A moves to the beginning of the current line also.
textinput.handle_keydown_aux(None, Key::A, KeyModifiers::CONTROL | KeyModifiers::ALT);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
// Test that ALT + Right moves to the end of the word.
textinput.handle_keydown_aux(None, Key::Right, KeyModifiers::ALT);
- assert_eq!(textinput.edit_point.index, 5);
+ assert_eq!(textinput.edit_point().index, 5);
// Test that CTRL + ALT + F moves to the end of the word also.
textinput.handle_keydown_aux(None, Key::F, KeyModifiers::CONTROL | KeyModifiers::ALT);
- assert_eq!(textinput.edit_point.index, 11);
+ assert_eq!(textinput.edit_point().index, 11);
// Test that ALT + Left moves to the end of the word.
textinput.handle_keydown_aux(None, Key::Left, KeyModifiers::ALT);
- assert_eq!(textinput.edit_point.index, 6);
+ assert_eq!(textinput.edit_point().index, 6);
// Test that CTRL + ALT + B moves to the end of the word also.
textinput.handle_keydown_aux(None, Key::B, KeyModifiers::CONTROL | KeyModifiers::ALT);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
}
#[test]
@@ -470,12 +467,12 @@ fn test_textinput_handle_return() {
#[test]
fn test_textinput_select_all() {
let mut textinput = text_input(Lines::Multiple, "abc\nde\nf");
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 0);
textinput.select_all();
- assert_eq!(textinput.edit_point.line, 2);
- assert_eq!(textinput.edit_point.index, 1);
+ assert_eq!(textinput.edit_point().line, 2);
+ assert_eq!(textinput.edit_point().index, 1);
}
#[test]
@@ -495,15 +492,15 @@ fn test_textinput_set_content() {
textinput.set_content(DOMString::from("abc\nf"), true);
assert_eq!(textinput.get_content(), "abc\nf");
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 0);
+ 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);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 3);
textinput.set_content(DOMString::from("de"), true);
assert_eq!(textinput.get_content(), "de");
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 2);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 2);
}
#[test]
@@ -520,7 +517,7 @@ fn test_clipboard_paste() {
None,
SelectionDirection::None);
assert_eq!(textinput.get_content(), "defg");
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
textinput.handle_keydown_aux(Some('v'), Key::V, MODIFIERS);
assert_eq!(textinput.get_content(), "abcdefg");
}
@@ -532,23 +529,23 @@ fn test_textinput_cursor_position_correct_after_clearing_selection() {
// Single line - Forward
textinput.adjust_horizontal(3, Selection::Selected);
textinput.adjust_horizontal(1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 3);
+ assert_eq!(textinput.edit_point().index, 3);
textinput.adjust_horizontal(-3, Selection::NotSelected);
textinput.adjust_horizontal(3, Selection::Selected);
textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 3);
+ assert_eq!(textinput.edit_point().index, 3);
// Single line - Backward
textinput.adjust_horizontal(-3, Selection::NotSelected);
textinput.adjust_horizontal(3, Selection::Selected);
textinput.adjust_horizontal(-1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
textinput.adjust_horizontal(-3, Selection::NotSelected);
textinput.adjust_horizontal(3, Selection::Selected);
textinput.adjust_horizontal_by_one(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
let mut textinput = text_input(Lines::Multiple, "abc\nde\nf");
@@ -556,27 +553,27 @@ fn test_textinput_cursor_position_correct_after_clearing_selection() {
// Multiline - Forward
textinput.adjust_horizontal(4, Selection::Selected);
textinput.adjust_horizontal(1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 0);
- assert_eq!(textinput.edit_point.line, 1);
+ assert_eq!(textinput.edit_point().index, 0);
+ assert_eq!(textinput.edit_point().line, 1);
textinput.adjust_horizontal(-4, Selection::NotSelected);
textinput.adjust_horizontal(4, Selection::Selected);
textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 0);
- assert_eq!(textinput.edit_point.line, 1);
+ assert_eq!(textinput.edit_point().index, 0);
+ assert_eq!(textinput.edit_point().line, 1);
// Multiline - Backward
textinput.adjust_horizontal(-4, Selection::NotSelected);
textinput.adjust_horizontal(4, Selection::Selected);
textinput.adjust_horizontal(-1, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 0);
- assert_eq!(textinput.edit_point.line, 0);
+ assert_eq!(textinput.edit_point().index, 0);
+ assert_eq!(textinput.edit_point().line, 0);
textinput.adjust_horizontal(-4, Selection::NotSelected);
textinput.adjust_horizontal(4, Selection::Selected);
textinput.adjust_horizontal_by_one(Direction::Backward, Selection::NotSelected);
- assert_eq!(textinput.edit_point.index, 0);
- assert_eq!(textinput.edit_point.line, 0);
+ assert_eq!(textinput.edit_point().index, 0);
+ assert_eq!(textinput.edit_point().line, 0);
}
@@ -584,53 +581,53 @@ fn test_textinput_cursor_position_correct_after_clearing_selection() {
fn test_textinput_set_selection_with_direction() {
let mut textinput = text_input(Lines::Single, "abcdef");
textinput.set_selection_range(2, 6, SelectionDirection::Forward);
- assert_eq!(textinput.edit_point.line, 0);
- assert_eq!(textinput.edit_point.index, 6);
- assert_eq!(textinput.selection_direction, SelectionDirection::Forward);
+ assert_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 6);
+ assert_eq!(textinput.selection_direction(), SelectionDirection::Forward);
- assert!(textinput.selection_origin.is_some());
- assert_eq!(textinput.selection_origin.unwrap().line, 0);
- assert_eq!(textinput.selection_origin.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_eq!(textinput.edit_point().line, 0);
+ assert_eq!(textinput.edit_point().index, 2);
+ assert_eq!(textinput.selection_direction(), SelectionDirection::Backward);
- assert!(textinput.selection_origin.is_some());
- assert_eq!(textinput.selection_origin.unwrap().line, 0);
- assert_eq!(textinput.selection_origin.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);
textinput = text_input(Lines::Multiple, "\n\n");
textinput.set_selection_range(0, 1, SelectionDirection::Forward);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 0);
- assert_eq!(textinput.selection_direction, SelectionDirection::Forward);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 0);
+ assert_eq!(textinput.selection_direction(), SelectionDirection::Forward);
- assert!(textinput.selection_origin.is_some());
- assert_eq!(textinput.selection_origin.unwrap().line, 0);
- assert_eq!(textinput.selection_origin.unwrap().index, 0);
+ assert!(textinput.selection_origin().is_some());
+ assert_eq!(textinput.selection_origin().unwrap().line, 0);
+ assert_eq!(textinput.selection_origin().unwrap().index, 0);
textinput = text_input(Lines::Multiple, "\n");
textinput.set_selection_range(0, 1, SelectionDirection::Forward);
- assert_eq!(textinput.edit_point.line, 1);
- assert_eq!(textinput.edit_point.index, 0);
- assert_eq!(textinput.selection_direction, SelectionDirection::Forward);
+ assert_eq!(textinput.edit_point().line, 1);
+ assert_eq!(textinput.edit_point().index, 0);
+ assert_eq!(textinput.selection_direction(), SelectionDirection::Forward);
- assert!(textinput.selection_origin.is_some());
- assert_eq!(textinput.selection_origin.unwrap().line, 0);
- assert_eq!(textinput.selection_origin.unwrap().index, 0);
+ assert!(textinput.selection_origin().is_some());
+ assert_eq!(textinput.selection_origin().unwrap().line, 0);
+ assert_eq!(textinput.selection_origin().unwrap().index, 0);
}
#[test]
fn test_textinput_unicode_handling() {
let mut textinput = text_input(Lines::Single, "éèùµ$£");
- assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point().index, 0);
textinput.set_edit_point_index(1);
- assert_eq!(textinput.edit_point.index, 2);
+ assert_eq!(textinput.edit_point().index, 2);
textinput.set_edit_point_index(4);
- assert_eq!(textinput.edit_point.index, 8);
+ assert_eq!(textinput.edit_point().index, 8);
}
#[test]
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index f8a55cc49d51..3a750e74cfbe 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -39947,6 +39947,12 @@
{}
]
],
+ "mozilla/textcontrol-selection-cannot-exceed-content.html": [
+ [
+ "/_mozilla/mozilla/textcontrol-selection-cannot-exceed-content.html",
+ {}
+ ]
+ ],
"mozilla/timeout-in-discarded-document.html": [
[
"/_mozilla/mozilla/timeout-in-discarded-document.html",
@@ -71956,6 +71962,10 @@
"094fbd794b78520d6c2d8aae549557bed3529a7a",
"testharness"
],
+ "mozilla/textcontrol-selection-cannot-exceed-content.html": [
+ "f8b982ba0abb23f8e53ef28413e8da2f8dd7ca17",
+ "testharness"
+ ],
"mozilla/timeout-in-discarded-document.html": [
"7ff88491f20ee72ed40aa5ce4e84840b98d5eef5",
"testharness"
diff --git a/tests/wpt/mozilla/tests/mozilla/textcontrol-selection-cannot-exceed-content.html b/tests/wpt/mozilla/tests/mozilla/textcontrol-selection-cannot-exceed-content.html
new file mode 100644
index 000000000000..b162fba0ec54
--- /dev/null
+++ b/tests/wpt/mozilla/tests/mozilla/textcontrol-selection-cannot-exceed-content.html
@@ -0,0 +1,25 @@
+
+
+The selection bounds of a text control should never exceed the content
+
+
+
+
+
+