LibWeb: Assert that nodes share shadow-including root in BP calculation

Previously, it was assumed that nodes must share the same root, prior
to the calculation of their relative boundary point positions. This is
no longer the case, since `Selection.setBaseAndExtent()` now accepts
anchor and focus nodes that may be in different shadow trees.
This commit is contained in:
Tim Ledbetter 2024-12-02 14:41:07 +00:00 committed by Andreas Kling
parent a7b3360fb6
commit 163b8a69e3
Notes: github-actions[bot] 2024-12-03 14:32:29 +00:00
3 changed files with 82 additions and 1 deletions

View file

@ -120,7 +120,9 @@ GC::Ref<Node> Range::root() const
RelativeBoundaryPointPosition position_of_boundary_point_relative_to_other_boundary_point(GC::Ref<Node> node_a, u32 offset_a, GC::Ref<Node> node_b, u32 offset_b)
{
// 1. Assert: nodeA and nodeB have the same root.
VERIFY(&node_a->root() == &node_b->root());
// NOTE: Nodes may not share the same root if they belong to different shadow trees,
// so we assert that they share the same shadow-including root instead.
VERIFY(&node_a->shadow_including_root() == &node_b->shadow_including_root());
// 2. If nodeA is nodeB, then return equal if offsetA is offsetB, before if offsetA is less than offsetB, and after if offsetA is greater than offsetB.
if (node_a == node_b) {

View file

@ -0,0 +1,13 @@
Harness status: OK
Found 7 tests
6 Pass
1 Fail
Pass direction returns "none" when there is no selection
Pass direction returns "forward" when there is a forward-direction selection in the document tree
Pass direction returns "backward" when there is a backward-direction selection in the document tree
Pass direction returns "forward" when there is a forward selection in the shadow tree
Pass direction returns "backward" when there is a backward selection in the shadow tree
Pass direction returns "forward" when there is a forward selection that crosses shadow boundaries
Fail direction returns "backward" when there is a forward selection that crosses shadow boundaries

View file

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<body>
<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
<meta name="assert" content="Selection's direction should return none, forwad, or backward">
<link rel="help" href="https://w3c.github.io/selection-api/#dom-selection-direction">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../../resources/testdriver.js"></script>
<script src="../../../resources/testdriver-actions.js"></script>
<script src='../../../resources/testdriver-vendor.js'></script>
<div id="container"></div>
<script>
test(() => {
getSelection().removeAllRanges();
assert_equals(getSelection().direction, 'none');
}, 'direction returns "none" when there is no selection');
test(() => {
container.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(container.firstChild, 0, container.firstChild, 5);
assert_equals(getSelection().direction, 'forward');
}, 'direction returns "forward" when there is a forward-direction selection in the document tree');
test(() => {
container.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(container.firstChild, 4, container.firstChild, 3);
assert_equals(getSelection().direction, 'backward');
}, 'direction returns "backward" when there is a backward-direction selection in the document tree');
test(() => {
container.innerHTML = 'a<div id="host"></div>b';
const shadowRoot = host.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 0, shadowRoot.firstChild, 5);
assert_equals(getSelection().direction, 'forward');
}, 'direction returns "forward" when there is a forward selection in the shadow tree');
test(() => {
container.innerHTML = 'a<div id="host"></div>b';
const shadowRoot = host.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 5, shadowRoot.firstChild, 3);
assert_equals(getSelection().direction, 'backward');
}, 'direction returns "backward" when there is a backward selection in the shadow tree');
test(() => {
container.innerHTML = 'a<div id="host"></div>b';
const shadowRoot = host.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 7, container, 2);
assert_equals(getSelection().direction, 'forward');
}, 'direction returns "forward" when there is a forward selection that crosses shadow boundaries');
test(() => {
container.innerHTML = 'a<div id="host"></div>b';
const shadowRoot = host.attachShadow({mode: 'closed'});
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 7, container, 1);
assert_equals(getSelection().direction, 'backward');
}, 'direction returns "backward" when there is a forward selection that crosses shadow boundaries');
</script>
</body>
</html>