diff options
Diffstat (limited to 'dom/base/nsINode.cpp')
-rw-r--r-- | dom/base/nsINode.cpp | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index d5455e5596..6c77574df7 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -287,11 +287,17 @@ static const nsINode* GetClosestCommonInclusiveAncestorForRangeInSelection( const nsINode* aNode) { while (aNode && !aNode->IsClosestCommonInclusiveAncestorForRangeInSelection()) { + const bool isNodeInShadowTree = + StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() && + aNode->IsInShadowTree(); if (!aNode - ->IsDescendantOfClosestCommonInclusiveAncestorForRangeInSelection()) { + ->IsDescendantOfClosestCommonInclusiveAncestorForRangeInSelection() && + !isNodeInShadowTree) { return nullptr; } - aNode = aNode->GetParentNode(); + aNode = StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() + ? aNode->GetParentOrShadowHostNode() + : aNode->GetParentNode(); } return aNode; } @@ -315,12 +321,12 @@ class IsItemInRangeComparator { int operator()(const AbstractRange* const aRange) const { int32_t cmp = nsContentUtils::ComparePoints_Deprecated( - &mNode, mEndOffset, aRange->GetStartContainer(), aRange->StartOffset(), - nullptr, mCache); + &mNode, mEndOffset, aRange->GetMayCrossShadowBoundaryStartContainer(), + aRange->MayCrossShadowBoundaryStartOffset(), nullptr, mCache); if (cmp == 1) { cmp = nsContentUtils::ComparePoints_Deprecated( - &mNode, mStartOffset, aRange->GetEndContainer(), aRange->EndOffset(), - nullptr, mCache); + &mNode, mStartOffset, aRange->GetMayCrossShadowBoundaryEndContainer(), + aRange->MayCrossShadowBoundaryEndOffset(), nullptr, mCache); if (cmp == -1) { return 0; } @@ -386,6 +392,18 @@ bool nsINode::IsSelected(const uint32_t aStartOffset, return true; } + if (range->MayCrossShadowBoundary()) { + MOZ_ASSERT(range->IsDynamicRange(), + "range->MayCrossShadowBoundary() can only return true for " + "dynamic range"); + StaticRange* crossBoundaryRange = + range->AsDynamicRange()->GetCrossShadowBoundaryRange(); + MOZ_ASSERT(crossBoundaryRange); + if (!crossBoundaryRange->Collapsed()) { + return true; + } + } + const AbstractRange* middlePlus1; const AbstractRange* middleMinus1; // if node end > start of middle+1, result = 1 @@ -552,7 +570,8 @@ static nsIContent* GetRootForContentSubtree(nsIContent* aContent) { return nsIContent::FromNode(aContent->SubtreeRoot()); } -nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) { +nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell, + bool aAllowCrossShadowBoundary) { NS_ENSURE_TRUE(aPresShell, nullptr); if (IsDocument()) return AsDocument()->GetRootElement(); @@ -596,7 +615,7 @@ nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) { } RefPtr<nsFrameSelection> fs = aPresShell->FrameSelection(); - nsIContent* content = fs->GetLimiter(); + nsCOMPtr<nsIContent> content = fs->GetLimiter(); if (!content) { content = fs->GetAncestorLimiter(); if (!content) { @@ -616,6 +635,10 @@ nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) { // Use the host as the root. if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(content)) { content = shadowRoot->GetHost(); + if (content && aAllowCrossShadowBoundary) { + content = content->GetSelectionRootContent(aPresShell, + aAllowCrossShadowBoundary); + } } } @@ -3826,6 +3849,33 @@ void nsINode::FireNodeRemovedForChildren() { } } +ShadowRoot* nsINode::GetShadowRoot() const { + return IsContent() ? AsContent()->GetShadowRoot() : nullptr; +} + +ShadowRoot* nsINode::GetShadowRootForSelection() const { + if (!StaticPrefs::dom_shadowdom_selection_across_boundary_enabled()) { + return nullptr; + } + + ShadowRoot* shadowRoot = GetShadowRoot(); + if (!shadowRoot) { + return nullptr; + } + + // ie. <details> and <video> + if (shadowRoot->IsUAWidget()) { + return nullptr; + } + + // ie. <use> element + if (IsElement() && !AsElement()->CanAttachShadowDOM()) { + return nullptr; + } + + return shadowRoot; +} + NS_IMPL_ISUPPORTS(nsNodeWeakReference, nsIWeakReference) nsNodeWeakReference::nsNodeWeakReference(nsINode* aNode) |