diff options
author | Jon Leighton <j@jonathanleighton.com> | 2018-02-14 22:04:28 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2018-02-16 11:24:12 +0100 |
commit | 32f781234a07c6aa52e8105d5aa32bec3f4791a1 (patch) | |
tree | 741291c719a41f189cbb9e7a994824d9e4aa320f /tests/unit/script/textinput.rs | |
parent | 7e31ae35e1036467e25484ab30132f8bd49f0ee8 (diff) | |
download | servo-32f781234a07c6aa52e8105d5aa32bec3f4791a1.tar.gz servo-32f781234a07c6aa52e8105d5aa32bec3f4791a1.zip |
Disallow mutating the internals of TextInput
The TextInput::assert_ok_selection() method is meant to ensure that we
are not getting into a state where a selection refers to a location in
the control's contents which doesn't exist.
However, before this change we could have a situation where the
internals of the TextInput are changed by another part of the code,
without using its public API. This could lead to us having an invalid
selection.
I did manage to trigger such a situation (see the test added in this
commit) although it is quite contrived. There may be others that I
didn't think of, and it's also possible that future changes could
introduce new cases. (Including ones which trigger panics, if indexing
is used on the assumption that the selection indices are always valid.)
The current HTML specification doesn't explicitly say that
selectionStart/End must remain within the length of the content, but
that does seems to be the consensus reached in a discussion of this:
https://github.com/whatwg/html/issues/2424
The test case I've added here is currently undefined in the spec which
is why I've added it in tests/wpt/mozilla.
Diffstat (limited to 'tests/unit/script/textinput.rs')
-rw-r--r-- | tests/unit/script/textinput.rs | 231 |
1 files changed, 114 insertions, 117 deletions
diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs index 0bdeec59cda..916e26c9164 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] |