LibWeb: Avoid cross-root Selection extend comparisons
Selection.extend() can keep an old anchor that is no longer orderable with the new focus after a selected shadow host is detached. Collapse to the new focus in that case and avoid comparing boundary points from different shadow-including roots. Add reduced crash coverage for extending a selection after detaching the shadow host that held the old anchor.
This commit is contained in:
parent
ecb3080ac6
commit
3fcd95327e
2 changed files with 17 additions and 2 deletions
|
|
@ -301,8 +301,10 @@ WebIDL::ExceptionOr<void> Selection::extend(GC::Ref<DOM::Node> node, unsigned of
|
|||
// 4. Let newRange be a new range.
|
||||
auto new_range = DOM::Range::create(*m_document);
|
||||
|
||||
auto old_anchor_and_new_focus_have_the_same_shadow_including_root = &old_anchor_node.shadow_including_root() == &new_focus_node->shadow_including_root();
|
||||
|
||||
// 5. If node's root is not the same as the this's range's root, set the start newRange's start and end to newFocus.
|
||||
if (&node->root() != &m_range->start_container()->root()) {
|
||||
if (&node->root() != &m_range->start_container()->root() || !old_anchor_and_new_focus_have_the_same_shadow_including_root) {
|
||||
TRY(new_range->set_start(new_focus_node, new_focus_offset));
|
||||
TRY(new_range->set_end(new_focus_node, new_focus_offset));
|
||||
}
|
||||
|
|
@ -321,7 +323,7 @@ WebIDL::ExceptionOr<void> Selection::extend(GC::Ref<DOM::Node> node, unsigned of
|
|||
set_range(new_range);
|
||||
|
||||
// 9. If newFocus is before oldAnchor, set this's direction to backwards. Otherwise, set it to forwards.
|
||||
if (DOM::position_of_boundary_point_relative_to_other_boundary_point({ new_focus_node, new_focus_offset }, { old_anchor_node, old_anchor_offset }) == DOM::RelativeBoundaryPointPosition::Before) {
|
||||
if (old_anchor_and_new_focus_have_the_same_shadow_including_root && DOM::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;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<div id="host"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
const shadowRoot = host.attachShadow({ mode: "open" });
|
||||
shadowRoot.innerHTML = "<span id=anchor>hello</span>";
|
||||
const anchor = shadowRoot.getElementById("anchor");
|
||||
|
||||
const selection = getSelection();
|
||||
selection.collapse(anchor, 0);
|
||||
host.remove();
|
||||
selection.extend(target, 0);
|
||||
</script>
|
||||
Loading…
Reference in a new issue