LibWeb: Use correct boundary point comparison in Selection.extend
Some checks are pending
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run

Previously Selection.extend() used only the relative node order to decide which
direction to extend the selection. This leads to incorrect behaviour if
both the existing and new boundary points are within the same DOM node
and the selection direction is reversed.

This change fixes all the failing subtests in the WPT extend-* test
suites.
This commit is contained in:
John Diamond 2024-10-13 13:22:48 +02:00 committed by Andreas Kling
parent ee35e93eb2
commit 18ade57ae9
Notes: github-actions[bot] 2024-10-13 13:12:39 +00:00
5 changed files with 47 additions and 2 deletions

View file

@ -0,0 +1 @@
PASS

View file

@ -0,0 +1 @@
PASS

View file

@ -0,0 +1,22 @@
<script src="include.js"></script>
<p id="p1">Well hello</p>
<p id="p2">friends</p>
<script>
test(() => {
var selection = window.getSelection();
selection.setBaseAndExtent(p1.firstChild, 0, p1.firstChild, 0);
selection.extend(p2.firstChild, 4);
if (selection.anchorNode !== p1.firstChild
|| selection.anchorOffset !== 0) {
println('FAIL: anchor has moved');
return;
}
if (selection.focusNode !== p2.firstChild
|| selection.focusOffset !== 4) {
println('FAIL: focus is not where we expected');
return;
}
println('PASS');
})
</script>

View file

@ -0,0 +1,21 @@
<script src="include.js"></script>
<p id="a">Uno</p>
<script>
test(() => {
var selection = window.getSelection();
selection.setBaseAndExtent(a.firstChild, 3, a.firstChild, 3);
selection.extend(a.firstChild, 0);
if (selection.anchorNode !== a.firstChild
|| selection.anchorOffset !== 3) {
println('FAIL: anchor has moved');
return;
}
if (selection.focusNode !== a.firstChild
|| selection.focusOffset !== 0) {
println('FAIL: focus is not where we expected');
return;
}
println('PASS');
})
</script>

View file

@ -290,7 +290,7 @@ WebIDL::ExceptionOr<void> Selection::extend(JS::NonnullGCPtr<DOM::Node> node, un
TRY(new_range->set_end(new_focus_node, new_focus_offset));
}
// 6. Otherwise, if oldAnchor is before or equal to newFocus, set the start newRange's start to oldAnchor, then set its end to newFocus.
else if (old_anchor_node.is_before(new_focus_node) || &old_anchor_node == new_focus_node.ptr()) {
else if (position_of_boundary_point_relative_to_other_boundary_point(old_anchor_node, old_anchor_offset, new_focus_node, new_focus_offset) != DOM::RelativeBoundaryPointPosition::After) {
TRY(new_range->set_start(old_anchor_node, old_anchor_offset));
TRY(new_range->set_end(new_focus_node, new_focus_offset));
}
@ -304,7 +304,7 @@ WebIDL::ExceptionOr<void> Selection::extend(JS::NonnullGCPtr<DOM::Node> node, un
set_range(new_range);
// 9. If newFocus is before oldAnchor, set this's direction to backwards. Otherwise, set it to forwards.
if (new_focus_node->is_before(old_anchor_node)) {
if (position_of_boundary_point_relative_to_other_boundary_point(new_focus_node, new_focus_offset, old_anchor_node, old_anchor_offset) == DOM::RelativeBoundaryPointPosition::Before) {
m_direction = Direction::Backwards;
} else {
m_direction = Direction::Forwards;