Bug 1965664 - Fix some crashes in ContentSubtreeIterator r=jjaschke,dom-core

by skipping the shadow hosts that ShadowDOM selection doesn't
support at the moment.

Differential Revision: https://phabricator.services.mozilla.com/D248917
This commit is contained in:
Sean Feng
2025-05-12 20:40:53 +00:00
committed by sefeng@mozilla.com
parent 3c343a8e2b
commit e6a6045ffb
4 changed files with 35 additions and 4 deletions

View File

@@ -664,6 +664,13 @@ nsIContent* ContentIteratorBase<NodeType>::GetNextSibling(
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes) {
// Could have nested slots
while (HTMLSlotElement* slot = aNode->AsContent()->GetAssignedSlot()) {
if (!ShadowDOMSelectionHelpers::GetShadowRoot(
slot->GetContainingShadowHost(), aAllowCrossShadowBoundary)) {
// The corresponding shadow host isn't supported
// by ContentSubtreeIterator, so let's skip this slot.
break;
}
// Next sibling of a slotted node should be the next slotted node
auto currentIndex = slot->AssignedNodes().IndexOf(aNode);
if (currentIndex < slot->AssignedNodes().Length() - 1) {
@@ -726,6 +733,12 @@ nsIContent* ContentIteratorBase<NodeType>::GetPrevSibling(
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes) {
// Could have nested slots.
while (HTMLSlotElement* slot = aNode->AsContent()->GetAssignedSlot()) {
if (!ShadowDOMSelectionHelpers::GetShadowRoot(
slot->GetContainingShadowHost(), aAllowCrossShadowBoundary)) {
// The corresponding shadow host isn't supported
// by ContentSubtreeIterator, so let's skip this slot.
break;
}
// prev sibling of a slotted node should be the prev slotted node
auto currentIndex = slot->AssignedNodes().IndexOf(aNode);
if (currentIndex > 0) {
@@ -1026,15 +1039,19 @@ void ContentSubtreeIterator::CacheInclusiveAncestorsOfEndContainer() {
break;
}
const bool isDescendantInShadowTree =
IterAllowCrossShadowBoundary() && child->IsShadowRoot();
// `ShadowDOMSelectionHelpers::GetShadowRoot` would return non-null shadow
// root if parent is a shadow host that we support cross boundary selection.
const bool isChildAShadowRootForSelection =
ShadowDOMSelectionHelpers::GetShadowRoot(
parent, mAllowCrossShadowBoundary) == child;
info.mAncestor = parent->AsContent();
// mIsDescendantInShadowTree indicates that whether child is in the
// shadow tree of parent or in the regular light DOM tree of parent.
// So that later, when info.mAncestor is reached, we can decide whether
// we should dive into the shadow tree.
info.mIsDescendantInShadowTree = isDescendantInShadowTree;
info.mIsDescendantInShadowTree =
IterAllowCrossShadowBoundary() && isChildAShadowRootForSelection;
}
}
@@ -1255,6 +1272,7 @@ void ContentSubtreeIterator::Next() {
ShadowRoot* root = ShadowDOMSelectionHelpers::GetShadowRoot(
nextNode, mAllowCrossShadowBoundary);
if (mInclusiveAncestorsOfEndContainer[i].mIsDescendantInShadowTree) {
MOZ_ASSERT(root);
nextNode = root->GetFirstChild();
} else if (auto* slot = HTMLSlotElement::FromNode(nextNode);
slot && IterAllowCrossShadowBoundary()) {

View File

@@ -365,7 +365,9 @@ nsINode* ShadowDOMSelectionHelpers::GetParentNodeInSameSelection(
if (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() &&
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes) {
if (aNode.IsContent()) {
if (HTMLSlotElement* slot = aNode.AsContent()->GetAssignedSlot()) {
if (HTMLSlotElement* slot = aNode.AsContent()->GetAssignedSlot();
slot && GetShadowRoot(slot->GetContainingShadowHost(),
aAllowCrossShadowBoundary)) {
return slot;
}
}

View File

@@ -0,0 +1,10 @@
<script>
addEventListener("DOMContentLoaded", () => {
a.ownerDocument.designMode = "on"
document.execCommand("selectAll", false, null)
document.execCommand("superscript", false, null)
})
</script>
<s>
<h2>
<marquee id="a">

View File

@@ -283,3 +283,4 @@ load 1897248.html
load 1907464.html
asserts(0-1) load 1907228.html # see bug 1908485 for assert
load 1922153.html
load 1965664.html