mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #11906 - asajeffrey:textinput-ok-selection, r=ConnorGBrewster
Added checks that selection is valid, and fix set_selection_range. <!-- Please describe your changes on the following line: --> Fixed range checking for text inputs. Included some `debug_assert!` statements to check that the selection range is always valid. --- <!-- 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 #11901. - [X] These changes do not require tests because the code includes debug_asserts to ensure invariants are maintained. <!-- 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="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11906) <!-- Reviewable:end -->
This commit is contained in:
commit
aa9141277e
2 changed files with 44 additions and 4 deletions
|
@ -215,6 +215,16 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
})
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
debug_assert!(self.edit_point.line < self.lines.len());
|
||||
debug_assert!(self.edit_point.index <= self.lines[self.edit_point.line].len());
|
||||
}
|
||||
|
||||
/// 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.
|
||||
|
@ -319,6 +329,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
|
||||
self.lines = new_lines;
|
||||
}
|
||||
self.assert_ok_selection();
|
||||
}
|
||||
|
||||
/// Return the length in UTF-8 bytes of the current line under the editing point.
|
||||
|
@ -360,6 +371,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
|
||||
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.assert_ok_selection();
|
||||
}
|
||||
|
||||
/// Adjust the editing point position by a given number of bytes. If the adjustment
|
||||
|
@ -441,6 +453,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
self.edit_point.index + adjust as usize);
|
||||
}
|
||||
}
|
||||
self.assert_ok_selection();
|
||||
}
|
||||
|
||||
/// Deal with a newline input.
|
||||
|
@ -462,6 +475,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
let last_line = self.lines.len() - 1;
|
||||
self.edit_point.line = last_line;
|
||||
self.edit_point.index = self.lines[last_line].len();
|
||||
self.assert_ok_selection();
|
||||
}
|
||||
|
||||
/// Remove the current selection.
|
||||
|
@ -534,6 +548,7 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
}
|
||||
Key::End => {
|
||||
self.edit_point.index = self.current_line_length();
|
||||
self.assert_ok_selection();
|
||||
KeyReaction::RedrawSelection
|
||||
}
|
||||
Key::PageUp => {
|
||||
|
@ -598,6 +613,7 @@ 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.assert_ok_selection();
|
||||
}
|
||||
|
||||
/// Get the insertion point as a byte offset from the start of the content.
|
||||
|
@ -646,16 +662,16 @@ impl<T: ClipboardProvider> TextInput<T> {
|
|||
let mut end = end as usize;
|
||||
let text_end = self.get_content().len();
|
||||
|
||||
if start > text_end {
|
||||
start = text_end;
|
||||
} else if end > text_end {
|
||||
if end > text_end {
|
||||
end = text_end;
|
||||
} else if start >= end {
|
||||
}
|
||||
if start > end {
|
||||
start = end;
|
||||
}
|
||||
|
||||
self.selection_begin = Some(self.get_text_point_for_absolute_point(start));
|
||||
self.edit_point = self.get_text_point_for_absolute_point(end);
|
||||
self.assert_ok_selection();
|
||||
}
|
||||
|
||||
pub fn get_selection_start(&self) -> u32 {
|
||||
|
|
|
@ -31,6 +31,18 @@ test(function() {
|
|||
assert_equals(input.selectionEnd, input.value.length, "Arguments greater than the length of the value of the text field must be treated as pointing at the end of the text field");
|
||||
},'input setSelectionRange(0,input.value.length+1)');
|
||||
|
||||
test(function() {
|
||||
input.setSelectionRange(input.value.length+1,input.value.length+1)
|
||||
assert_equals(input.selectionStart, input.value.length, "Arguments (start) greater than the length of the value of the text field must be treated as pointing at the end of the text field");
|
||||
assert_equals(input.selectionEnd, input.value.length, "Arguments (end) greater than the length of the value of the text field must be treated as pointing at the end of the text field");
|
||||
},'input setSelectionRange(input.value.length+1,input.value.length+1)');
|
||||
|
||||
test(function() {
|
||||
input.setSelectionRange(input.value.length+1,1)
|
||||
assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
|
||||
assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
|
||||
},'input setSelectionRange(input.value.length+1,input.value.length+1)');
|
||||
|
||||
test(function() {
|
||||
input.setSelectionRange(2,2)
|
||||
assert_equals(input.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
|
||||
|
@ -73,6 +85,18 @@ test(function() {
|
|||
assert_equals(input.selectionDirection, "none", "if the argument is omitted");
|
||||
},'input direction of setSelectionRange(0,1)');
|
||||
|
||||
test(function() {
|
||||
input.setSelectionRange(1,-1);
|
||||
assert_equals(input.selectionStart, 1, "element.selectionStart should be 1");
|
||||
assert_equals(input.selectionEnd, input.value.length, "ECMAScript conversion to unsigned long");
|
||||
},'input setSelectionRange(1,-1)');
|
||||
|
||||
test(function() {
|
||||
input.setSelectionRange(-1,1);
|
||||
assert_equals(input.selectionStart, 1, "ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
|
||||
assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
|
||||
},'input setSelectionRange(-1,1)');
|
||||
|
||||
test(function() {
|
||||
input.setSelectionRange("string",1);
|
||||
assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue