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