Bug 1932150 - Fix some inconsistency about indicating whether the selection is allowed to cross the shadow boundary r=jjaschke,dom-core
Differential Revision: https://phabricator.services.mozilla.com/D246949
This commit is contained in:
committed by
sefeng@mozilla.com
parent
0422c9dc82
commit
322a5282b6
@@ -249,14 +249,10 @@ nsINode* AbstractRange::GetClosestCommonInclusiveAncestor(
|
||||
if (!mIsPositioned) {
|
||||
return nullptr;
|
||||
}
|
||||
nsINode* startContainer =
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes
|
||||
? GetMayCrossShadowBoundaryStartContainer()
|
||||
: GetStartContainer();
|
||||
nsINode* endContainer =
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes
|
||||
? GetMayCrossShadowBoundaryEndContainer()
|
||||
: GetEndContainer();
|
||||
nsINode* startContainer = ShadowDOMSelectionHelpers::GetStartContainer(
|
||||
this, aAllowCrossShadowBoundary);
|
||||
nsINode* endContainer = ShadowDOMSelectionHelpers::GetEndContainer(
|
||||
this, aAllowCrossShadowBoundary);
|
||||
|
||||
if (MayCrossShadowBoundary() &&
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes) {
|
||||
|
||||
@@ -550,7 +550,8 @@ nsINode* ContentIteratorBase<NodeType>::GetDeepFirstChild(nsINode* aRoot) {
|
||||
// static
|
||||
template <typename NodeType>
|
||||
nsIContent* ContentIteratorBase<NodeType>::GetDeepFirstChild(
|
||||
nsIContent* aRoot, bool aAllowCrossShadowBoundary) {
|
||||
nsIContent* aRoot,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
if (NS_WARN_IF(!aRoot)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -567,7 +568,7 @@ nsIContent* ContentIteratorBase<NodeType>::GetDeepFirstChild(
|
||||
// shadowRoot->GetFirstChild() should be able to return the <slot> element.
|
||||
// It's probably correct I think. Then it's up to the caller of this
|
||||
// iterator to decide whether to use the slot's assigned nodes or not.
|
||||
MOZ_ASSERT(aAllowCrossShadowBoundary);
|
||||
MOZ_ASSERT(aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes);
|
||||
child = shadowRoot->GetFirstChild();
|
||||
} else {
|
||||
child = node->GetFirstChild();
|
||||
@@ -607,7 +608,8 @@ nsINode* ContentIteratorBase<NodeType>::GetDeepLastChild(nsINode* aRoot) {
|
||||
// static
|
||||
template <typename NodeType>
|
||||
nsIContent* ContentIteratorBase<NodeType>::GetDeepLastChild(
|
||||
nsIContent* aRoot, bool aAllowCrossShadowBoundary) {
|
||||
nsIContent* aRoot,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
if (NS_WARN_IF(!aRoot)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -640,7 +642,7 @@ nsIContent* ContentIteratorBase<NodeType>::GetDeepLastChild(
|
||||
//
|
||||
template <typename NodeType>
|
||||
nsIContent* ContentIteratorBase<NodeType>::GetNextSibling(
|
||||
nsINode* aNode, bool aAllowCrossShadowBoundary) {
|
||||
nsINode* aNode, AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary,
|
||||
if (NS_WARN_IF(!aNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -655,7 +657,7 @@ nsIContent* ContentIteratorBase<NodeType>::GetNextSibling(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aAllowCrossShadowBoundary) {
|
||||
if (aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes) {
|
||||
// This is temporary solution.
|
||||
// For shadow root, instead of getting to the sibling of the parent
|
||||
// directly, we need to get into the light tree of the parent to handle
|
||||
@@ -674,7 +676,7 @@ nsIContent* ContentIteratorBase<NodeType>::GetNextSibling(
|
||||
// (when aAllowCrossShadowBoundary is true), or grandpa's prev sibling... static
|
||||
template <typename NodeType>
|
||||
nsIContent* ContentIteratorBase<NodeType>::GetPrevSibling(
|
||||
nsINode* aNode, bool aAllowCrossShadowBoundary) {
|
||||
nsINode* aNode, AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
if (NS_WARN_IF(!aNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -947,7 +949,7 @@ nsresult ContentSubtreeIterator::InitWithAllowCrossShadowBoundary(
|
||||
void ContentSubtreeIterator::CacheInclusiveAncestorsOfEndContainer() {
|
||||
mInclusiveAncestorsOfEndContainer.Clear();
|
||||
nsINode* const endContainer = ShadowDOMSelectionHelpers::GetEndContainer(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
mRange, mAllowCrossShadowBoundary);
|
||||
nsIContent* endNode =
|
||||
endContainer->IsContent() ? endContainer->AsContent() : nullptr;
|
||||
while (endNode) {
|
||||
@@ -964,7 +966,7 @@ void ContentSubtreeIterator::CacheInclusiveAncestorsOfEndContainer() {
|
||||
|
||||
nsIContent* ContentSubtreeIterator::DetermineCandidateForFirstContent() const {
|
||||
nsINode* startContainer = ShadowDOMSelectionHelpers::GetStartContainer(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
mRange, mAllowCrossShadowBoundary);
|
||||
nsIContent* firstCandidate = nullptr;
|
||||
// find first node in range
|
||||
nsINode* node = nullptr;
|
||||
@@ -979,7 +981,7 @@ nsIContent* ContentSubtreeIterator::DetermineCandidateForFirstContent() const {
|
||||
|
||||
MOZ_ASSERT(child == startContainer->GetChildAt_Deprecated(
|
||||
ShadowDOMSelectionHelpers::StartOffset(
|
||||
mRange, IterAllowCrossShadowBoundary())));
|
||||
mRange, mAllowCrossShadowBoundary)));
|
||||
if (!child) {
|
||||
// offset after last child
|
||||
node = startContainer;
|
||||
@@ -990,13 +992,13 @@ nsIContent* ContentSubtreeIterator::DetermineCandidateForFirstContent() const {
|
||||
|
||||
if (!firstCandidate) {
|
||||
// then firstCandidate is next node after node
|
||||
firstCandidate = ContentIteratorBase::GetNextSibling(
|
||||
node, IterAllowCrossShadowBoundary());
|
||||
firstCandidate =
|
||||
ContentIteratorBase::GetNextSibling(node, mAllowCrossShadowBoundary);
|
||||
}
|
||||
|
||||
if (firstCandidate) {
|
||||
firstCandidate = ContentIteratorBase::GetDeepFirstChild(
|
||||
firstCandidate, IterAllowCrossShadowBoundary());
|
||||
firstCandidate, mAllowCrossShadowBoundary);
|
||||
}
|
||||
|
||||
return firstCandidate;
|
||||
@@ -1026,10 +1028,10 @@ nsIContent* ContentSubtreeIterator::DetermineFirstContent() const {
|
||||
nsIContent* ContentSubtreeIterator::DetermineCandidateForLastContent() const {
|
||||
nsIContent* lastCandidate{nullptr};
|
||||
nsINode* endContainer = ShadowDOMSelectionHelpers::GetEndContainer(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
mRange, mAllowCrossShadowBoundary);
|
||||
// now to find the last node
|
||||
int32_t offset = ShadowDOMSelectionHelpers::EndOffset(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
int32_t offset =
|
||||
ShadowDOMSelectionHelpers::EndOffset(mRange, mAllowCrossShadowBoundary);
|
||||
|
||||
int32_t numChildren = endContainer->GetChildCount();
|
||||
|
||||
@@ -1044,20 +1046,21 @@ nsIContent* ContentSubtreeIterator::DetermineCandidateForLastContent() const {
|
||||
lastCandidate = IterAllowCrossShadowBoundary()
|
||||
? mRange->MayCrossShadowBoundaryEndRef().Ref()
|
||||
: mRange->EndRef().Ref();
|
||||
MOZ_ASSERT(lastCandidate == endContainer->GetChildAt_Deprecated(--offset));
|
||||
MOZ_ASSERT(lastCandidate ==
|
||||
endContainer->GetChildAt_Deprecated(offset - 1));
|
||||
NS_ASSERTION(lastCandidate,
|
||||
"tree traversal trouble in ContentSubtreeIterator::Init");
|
||||
}
|
||||
|
||||
if (!lastCandidate) {
|
||||
// then lastCandidate is prev node before node
|
||||
lastCandidate = ContentIteratorBase::GetPrevSibling(
|
||||
node, IterAllowCrossShadowBoundary());
|
||||
lastCandidate =
|
||||
ContentIteratorBase::GetPrevSibling(node, mAllowCrossShadowBoundary);
|
||||
}
|
||||
|
||||
if (lastCandidate) {
|
||||
lastCandidate = ContentIteratorBase::GetDeepLastChild(
|
||||
lastCandidate, IterAllowCrossShadowBoundary());
|
||||
lastCandidate, mAllowCrossShadowBoundary);
|
||||
}
|
||||
|
||||
return lastCandidate;
|
||||
@@ -1072,13 +1075,13 @@ nsresult ContentSubtreeIterator::InitWithRange() {
|
||||
mRange->GetClosestCommonInclusiveAncestor(mAllowCrossShadowBoundary);
|
||||
|
||||
nsINode* startContainer = ShadowDOMSelectionHelpers::GetStartContainer(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
const int32_t startOffset = ShadowDOMSelectionHelpers::StartOffset(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
mRange, mAllowCrossShadowBoundary);
|
||||
const int32_t startOffset =
|
||||
ShadowDOMSelectionHelpers::StartOffset(mRange, mAllowCrossShadowBoundary);
|
||||
nsINode* endContainer = ShadowDOMSelectionHelpers::GetEndContainer(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
const int32_t endOffset = ShadowDOMSelectionHelpers::EndOffset(
|
||||
mRange, IterAllowCrossShadowBoundary());
|
||||
mRange, mAllowCrossShadowBoundary);
|
||||
const int32_t endOffset =
|
||||
ShadowDOMSelectionHelpers::EndOffset(mRange, mAllowCrossShadowBoundary);
|
||||
MOZ_ASSERT(mClosestCommonInclusiveAncestor && startContainer && endContainer);
|
||||
// Bug 767169
|
||||
MOZ_ASSERT(uint32_t(startOffset) <= startContainer->Length() &&
|
||||
@@ -1156,8 +1159,8 @@ void ContentSubtreeIterator::Next() {
|
||||
return;
|
||||
}
|
||||
|
||||
nsINode* nextNode = ContentIteratorBase::GetNextSibling(
|
||||
mCurNode, IterAllowCrossShadowBoundary());
|
||||
nsINode* nextNode =
|
||||
ContentIteratorBase::GetNextSibling(mCurNode, mAllowCrossShadowBoundary);
|
||||
|
||||
NS_ASSERTION(nextNode, "No next sibling!?! This could mean deadlock!");
|
||||
|
||||
@@ -1223,7 +1226,7 @@ nsresult ContentSubtreeIterator::PositionAt(nsINode* aCurNode) {
|
||||
nsIContent* ContentSubtreeIterator::GetTopAncestorInRange(
|
||||
nsINode* aNode) const {
|
||||
if (!aNode || !ShadowDOMSelectionHelpers::GetParentNodeInSameSelection(
|
||||
*aNode, IterAllowCrossShadowBoundary())) {
|
||||
*aNode, mAllowCrossShadowBoundary)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1242,7 +1245,7 @@ nsIContent* ContentSubtreeIterator::GetTopAncestorInRange(
|
||||
nsIContent* lastContentInShadowTree = nullptr;
|
||||
while (content) {
|
||||
nsINode* parent = ShadowDOMSelectionHelpers::GetParentNodeInSameSelection(
|
||||
*content, IterAllowCrossShadowBoundary());
|
||||
*content, mAllowCrossShadowBoundary);
|
||||
|
||||
// content always has a parent. If its parent is the root, however --
|
||||
// i.e., either it's not content, or it is content but its own parent is
|
||||
@@ -1255,7 +1258,7 @@ nsIContent* ContentSubtreeIterator::GetTopAncestorInRange(
|
||||
// We have to special-case this because CompareNodeToRange treats the root
|
||||
// node differently -- see bug 765205.
|
||||
if (!parent || !ShadowDOMSelectionHelpers::GetParentNodeInSameSelection(
|
||||
*parent, IterAllowCrossShadowBoundary())) {
|
||||
*parent, mAllowCrossShadowBoundary)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,13 +87,15 @@ class ContentIteratorBase {
|
||||
static nsINode* GetDeepFirstChild(nsINode* aRoot);
|
||||
// If aAllowCrossShadowBoundary is true, it'll continue with the shadow tree
|
||||
// when it reaches to a shadow host.
|
||||
static nsIContent* GetDeepFirstChild(nsIContent* aRoot,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static nsIContent* GetDeepFirstChild(
|
||||
nsIContent* aRoot,
|
||||
dom::AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
static nsINode* GetDeepLastChild(nsINode* aRoot);
|
||||
// If aAllowCrossShadowBoundary is true, it'll continue with the shadow tree
|
||||
// when it reaches to a shadow host.
|
||||
static nsIContent* GetDeepLastChild(nsIContent* aRoot,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static nsIContent* GetDeepLastChild(
|
||||
nsIContent* aRoot,
|
||||
dom::AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
// Get the next/previous sibling of aNode, or its parent's, or grandparent's,
|
||||
// etc. Returns null if aNode and all its ancestors have no next/previous
|
||||
@@ -101,10 +103,14 @@ class ContentIteratorBase {
|
||||
//
|
||||
// If aAllowCrossShadowBoundary is true, it'll continue with the shadow host
|
||||
// when it reaches to a shadow root.
|
||||
static nsIContent* GetNextSibling(nsINode* aNode,
|
||||
bool aAllowCrossShadowBoundary = false);
|
||||
static nsIContent* GetPrevSibling(nsINode* aNode,
|
||||
bool aAllowCrossShadowBoundary = false);
|
||||
static nsIContent* GetNextSibling(
|
||||
nsINode* aNode,
|
||||
dom::AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary =
|
||||
dom::AllowRangeCrossShadowBoundary::No,
|
||||
static nsIContent* GetPrevSibling(
|
||||
nsINode* aNode,
|
||||
dom::AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary =
|
||||
dom::AllowRangeCrossShadowBoundary::No);
|
||||
|
||||
nsINode* NextNode(nsINode* aNode);
|
||||
nsINode* PrevNode(nsINode* aNode);
|
||||
|
||||
@@ -266,47 +266,52 @@ nsresult RangeUtils::CompareNodeToRangeBoundaries(
|
||||
|
||||
// static
|
||||
nsINode* ShadowDOMSelectionHelpers::GetStartContainer(
|
||||
const AbstractRange* aRange, bool aAllowCrossShadowBoundary) {
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
MOZ_ASSERT(aRange);
|
||||
return (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() &&
|
||||
aAllowCrossShadowBoundary)
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes)
|
||||
? aRange->GetMayCrossShadowBoundaryStartContainer()
|
||||
: aRange->GetStartContainer();
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t ShadowDOMSelectionHelpers::StartOffset(
|
||||
const AbstractRange* aRange, bool aAllowCrossShadowBoundary) {
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
MOZ_ASSERT(aRange);
|
||||
return (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() &&
|
||||
aAllowCrossShadowBoundary)
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes)
|
||||
? aRange->MayCrossShadowBoundaryStartOffset()
|
||||
: aRange->StartOffset();
|
||||
}
|
||||
|
||||
// static
|
||||
nsINode* ShadowDOMSelectionHelpers::GetEndContainer(
|
||||
const AbstractRange* aRange, bool aAllowCrossShadowBoundary) {
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
MOZ_ASSERT(aRange);
|
||||
return (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() &&
|
||||
aAllowCrossShadowBoundary)
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes)
|
||||
? aRange->GetMayCrossShadowBoundaryEndContainer()
|
||||
: aRange->GetEndContainer();
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t ShadowDOMSelectionHelpers::EndOffset(const AbstractRange* aRange,
|
||||
bool aAllowCrossShadowBoundary) {
|
||||
uint32_t ShadowDOMSelectionHelpers::EndOffset(
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
MOZ_ASSERT(aRange);
|
||||
return (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() &&
|
||||
aAllowCrossShadowBoundary)
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes)
|
||||
? aRange->MayCrossShadowBoundaryEndOffset()
|
||||
: aRange->EndOffset();
|
||||
}
|
||||
|
||||
// static
|
||||
nsINode* ShadowDOMSelectionHelpers::GetParentNodeInSameSelection(
|
||||
nsINode& aNode, bool aAllowCrossShadowBoundary) {
|
||||
const nsINode& aNode,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
if (!ParentNodeIsInSameSelection(aNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -318,10 +323,11 @@ nsINode* ShadowDOMSelectionHelpers::GetParentNodeInSameSelection(
|
||||
|
||||
// static
|
||||
ShadowRoot* ShadowDOMSelectionHelpers::GetShadowRoot(
|
||||
const nsINode* aNode, bool aAllowCrossShadowBoundary) {
|
||||
const nsINode* aNode,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
MOZ_ASSERT(aNode);
|
||||
return (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() &&
|
||||
aAllowCrossShadowBoundary)
|
||||
aAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes)
|
||||
? aNode->GetShadowRootForSelection()
|
||||
: nullptr;
|
||||
} // namespace dom
|
||||
|
||||
@@ -25,23 +25,29 @@ class AbstractRange;
|
||||
struct ShadowDOMSelectionHelpers {
|
||||
ShadowDOMSelectionHelpers() = delete;
|
||||
|
||||
static nsINode* GetStartContainer(const AbstractRange* aRange,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static nsINode* GetStartContainer(
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
static uint32_t StartOffset(const AbstractRange* aRange,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static uint32_t StartOffset(
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
static nsINode* GetEndContainer(const AbstractRange* aRange,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static nsINode* GetEndContainer(
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
static uint32_t EndOffset(const AbstractRange* aRange,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static uint32_t EndOffset(
|
||||
const AbstractRange* aRange,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
static nsINode* GetParentNodeInSameSelection(nsINode& aNode,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static nsINode* GetParentNodeInSameSelection(
|
||||
const nsINode& aNode,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
static ShadowRoot* GetShadowRoot(const nsINode* aNode,
|
||||
bool aAllowCrossShadowBoundary);
|
||||
static ShadowRoot* GetShadowRoot(
|
||||
const nsINode* aNode,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
};
|
||||
} // namespace dom
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/AbstractRange.h"
|
||||
#include "mozilla/dom/Text.h"
|
||||
#include "mozilla/dom/AbstractRange.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
#include "mozilla/IntegerRange.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
@@ -245,7 +246,8 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
|
||||
virtual ~nsDocumentEncoder();
|
||||
|
||||
void Initialize(bool aClearCachedSerializer = true,
|
||||
bool aAllowCrossShadowBoundary = false);
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary =
|
||||
AllowRangeCrossShadowBoundary::No);
|
||||
|
||||
/**
|
||||
* @param aMaxLength As described at
|
||||
@@ -431,7 +433,7 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
|
||||
mNodeSerializer{aNodeSerializer},
|
||||
mRangeContextSerializer{aRangeContextSerializer} {}
|
||||
|
||||
void Initialize(bool aAllowCrossShadowBoundary);
|
||||
void Initialize(AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary);
|
||||
|
||||
/**
|
||||
* @param aDepth the distance (number of `GetParent` calls) from aNode to
|
||||
@@ -498,14 +500,15 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
|
||||
const NodeSerializer& mNodeSerializer;
|
||||
RangeContextSerializer& mRangeContextSerializer;
|
||||
|
||||
bool mAllowCrossShadowBoundary = false;
|
||||
AllowRangeCrossShadowBoundary mAllowCrossShadowBoundary =
|
||||
AllowRangeCrossShadowBoundary::No;
|
||||
};
|
||||
|
||||
RangeSerializer mRangeSerializer;
|
||||
};
|
||||
|
||||
void nsDocumentEncoder::RangeSerializer::Initialize(
|
||||
bool aAllowCrossShadowBoundary) {
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
mContextInfoDepth = {};
|
||||
mStartRootIndex = 0;
|
||||
mEndRootIndex = 0;
|
||||
@@ -548,8 +551,9 @@ nsDocumentEncoder::nsDocumentEncoder(
|
||||
nsDocumentEncoder::nsDocumentEncoder()
|
||||
: nsDocumentEncoder(MakeUnique<RangeNodeContext>()) {}
|
||||
|
||||
void nsDocumentEncoder::Initialize(bool aClearCachedSerializer,
|
||||
bool aAllowCrossShadowBoundary) {
|
||||
void nsDocumentEncoder::Initialize(
|
||||
bool aClearCachedSerializer,
|
||||
AllowRangeCrossShadowBoundary aAllowCrossShadowBoundary) {
|
||||
mFlags = 0;
|
||||
mWrapColumn = 72;
|
||||
mRangeSerializer.Initialize(aAllowCrossShadowBoundary);
|
||||
@@ -570,6 +574,13 @@ static bool ParentIsTR(nsIContent* aContent) {
|
||||
return parent->IsHTMLElement(nsGkAtoms::tr);
|
||||
}
|
||||
|
||||
static AllowRangeCrossShadowBoundary GetAllowRangeCrossShadowBoundary(
|
||||
const uint32_t aFlags) {
|
||||
return (aFlags & nsIDocumentEncoder::AllowCrossShadowBoundary)
|
||||
? AllowRangeCrossShadowBoundary::Yes
|
||||
: AllowRangeCrossShadowBoundary::No;
|
||||
}
|
||||
|
||||
nsresult nsDocumentEncoder::SerializeDependingOnScope(uint32_t aMaxLength) {
|
||||
nsresult rv = NS_OK;
|
||||
if (mEncodingScope.mSelection) {
|
||||
@@ -608,7 +619,7 @@ nsresult nsDocumentEncoder::SerializeSelection() {
|
||||
// by the immediate context. This assumes that you can't select cells that
|
||||
// are multiple selections from two tables simultaneously.
|
||||
node = ShadowDOMSelectionHelpers::GetStartContainer(
|
||||
range, mFlags & nsIDocumentEncoder::AllowCrossShadowBoundary);
|
||||
range, GetAllowRangeCrossShadowBoundary(mFlags));
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
|
||||
if (node != prevNode) {
|
||||
if (prevNode) {
|
||||
@@ -725,7 +736,7 @@ nsDocumentEncoder::NativeInit(Document* aDocument, const nsAString& aMimeType,
|
||||
if (!aDocument) return NS_ERROR_INVALID_ARG;
|
||||
|
||||
Initialize(!mMimeType.Equals(aMimeType),
|
||||
aFlags & nsIDocumentEncoder::AllowCrossShadowBoundary);
|
||||
GetAllowRangeCrossShadowBoundary(aFlags));
|
||||
|
||||
mDocument = aDocument;
|
||||
|
||||
@@ -959,7 +970,7 @@ nsresult nsDocumentEncoder::NodeSerializer::SerializeToStringRecursive(
|
||||
}
|
||||
|
||||
ShadowRoot* shadowRoot = ShadowDOMSelectionHelpers::GetShadowRoot(
|
||||
aNode, mFlags & nsIDocumentEncoder::AllowCrossShadowBoundary);
|
||||
aNode, GetAllowRangeCrossShadowBoundary(mFlags));
|
||||
|
||||
if (shadowRoot) {
|
||||
MOZ_ASSERT(StaticPrefs::dom_shadowdom_selection_across_boundary_enabled());
|
||||
@@ -1314,7 +1325,9 @@ bool nsDocumentEncoder::RangeSerializer::HasInvisibleParentAndShouldBeSkipped(
|
||||
|
||||
nsresult nsDocumentEncoder::RangeSerializer::SerializeRangeToString(
|
||||
const nsRange* aRange) {
|
||||
if (!aRange || (aRange->Collapsed() && (!mAllowCrossShadowBoundary ||
|
||||
if (!aRange ||
|
||||
(aRange->Collapsed() &&
|
||||
(mAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::No ||
|
||||
!aRange->MayCrossShadowBoundary()))) {
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1325,9 +1338,7 @@ nsresult nsDocumentEncoder::RangeSerializer::SerializeRangeToString(
|
||||
// boundary can return the host element as the container.
|
||||
// SerializeRangeContextStart doesn't support this case.
|
||||
mClosestCommonInclusiveAncestorOfRange =
|
||||
aRange->GetClosestCommonInclusiveAncestor(
|
||||
mAllowCrossShadowBoundary ? AllowRangeCrossShadowBoundary::Yes
|
||||
: AllowRangeCrossShadowBoundary::No);
|
||||
aRange->GetClosestCommonInclusiveAncestor(mAllowCrossShadowBoundary);
|
||||
|
||||
if (!mClosestCommonInclusiveAncestorOfRange) {
|
||||
return NS_OK;
|
||||
@@ -1362,7 +1373,7 @@ nsresult nsDocumentEncoder::RangeSerializer::SerializeRangeToString(
|
||||
|
||||
nsContentUtils::GetInclusiveAncestors(mClosestCommonInclusiveAncestorOfRange,
|
||||
mCommonInclusiveAncestors);
|
||||
if (mAllowCrossShadowBoundary) {
|
||||
if (mAllowCrossShadowBoundary == AllowRangeCrossShadowBoundary::Yes) {
|
||||
nsContentUtils::GetShadowIncludingAncestorsAndOffsets(
|
||||
startContainer, startOffset, inclusiveAncestorsOfStart,
|
||||
inclusiveAncestorsOffsetsOfStart);
|
||||
@@ -1611,7 +1622,7 @@ nsHTMLCopyEncoder::Init(Document* aDocument, const nsAString& aMimeType,
|
||||
if (!aDocument) return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mIsTextWidget = false;
|
||||
Initialize(true, aFlags & nsIDocumentEncoder::AllowCrossShadowBoundary);
|
||||
Initialize(true, GetAllowRangeCrossShadowBoundary(aFlags));
|
||||
|
||||
mIsCopying = true;
|
||||
mDocument = aDocument;
|
||||
@@ -1856,19 +1867,13 @@ nsresult nsHTMLCopyEncoder::PromoteRange(nsRange* inRange) {
|
||||
|
||||
// set the range to the new values
|
||||
ErrorResult err;
|
||||
const bool allowRangeCrossShadowBoundary =
|
||||
mFlags & nsIDocumentEncoder::AllowCrossShadowBoundary;
|
||||
inRange->SetStart(*opStartNode, static_cast<uint32_t>(opStartOffset), err,
|
||||
allowRangeCrossShadowBoundary
|
||||
? AllowRangeCrossShadowBoundary::Yes
|
||||
: AllowRangeCrossShadowBoundary::No);
|
||||
GetAllowRangeCrossShadowBoundary(mFlags));
|
||||
if (NS_WARN_IF(err.Failed())) {
|
||||
return err.StealNSResult();
|
||||
}
|
||||
inRange->SetEnd(*opEndNode, static_cast<uint32_t>(opEndOffset), err,
|
||||
allowRangeCrossShadowBoundary
|
||||
? AllowRangeCrossShadowBoundary::Yes
|
||||
: AllowRangeCrossShadowBoundary::No);
|
||||
GetAllowRangeCrossShadowBoundary(mFlags));
|
||||
if (NS_WARN_IF(err.Failed())) {
|
||||
return err.StealNSResult();
|
||||
}
|
||||
@@ -2057,8 +2062,7 @@ nsresult nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsINode* aNode,
|
||||
const bool isGeneratedContent =
|
||||
offset == -1 &&
|
||||
ShadowDOMSelectionHelpers::GetShadowRoot(
|
||||
parent,
|
||||
mFlags & nsIDocumentEncoder::AllowCrossShadowBoundary) != node;
|
||||
parent, GetAllowRangeCrossShadowBoundary(mFlags)) != node;
|
||||
if (isGeneratedContent) // we hit generated content; STOP
|
||||
{
|
||||
// back up a bit
|
||||
|
||||
Reference in New Issue
Block a user