зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1399626 - Part 4: Allow initializing nsIContentIterator with RangeBoundaries, r=masayuki
This patch adds an overload to nsIContentIterator::Init which accepts RangeBoundary objects, and modifies the codepath to avoid using the offset of the start or end nodes to construct the nsIContentIterator. MozReview-Commit-ID: 5ZqKeiUunoN
This commit is contained in:
Родитель
7a623e996f
Коммит
cbc8fa8a3b
|
@ -18,55 +18,37 @@
|
|||
#include "nsElementTable.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::RawRangeBoundary;
|
||||
|
||||
// couple of utility static functs
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// NodeToParentOffset: returns the node's parent and offset.
|
||||
//
|
||||
|
||||
static nsINode*
|
||||
NodeToParentOffset(nsINode* aNode, int32_t* aOffset)
|
||||
{
|
||||
*aOffset = 0;
|
||||
|
||||
nsINode* parent = aNode->GetParentNode();
|
||||
|
||||
if (parent) {
|
||||
*aOffset = parent->IndexOf(aNode);
|
||||
NS_WARNING_ASSERTION(*aOffset >= 0, "bad offset");
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// NodeIsInTraversalRange: returns true if content is visited during
|
||||
// the traversal of the range in the specified mode.
|
||||
//
|
||||
static bool
|
||||
NodeIsInTraversalRange(nsINode* aNode, bool aIsPreMode,
|
||||
nsINode* aStartContainer, int32_t aStartOffset,
|
||||
nsINode* aEndContainer, int32_t aEndOffset)
|
||||
const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd)
|
||||
{
|
||||
if (NS_WARN_IF(!aStartContainer) || NS_WARN_IF(!aEndContainer) ||
|
||||
if (NS_WARN_IF(!aStart.IsSet()) || NS_WARN_IF(!aEnd.IsSet()) ||
|
||||
NS_WARN_IF(!aNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a leaf node contains an end point of the traversal range, it is
|
||||
// always in the traversal range.
|
||||
if (aNode == aStartContainer || aNode == aEndContainer) {
|
||||
if (aNode == aStart.Container() || aNode == aEnd.Container()) {
|
||||
if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
|
||||
return true; // text node or something
|
||||
}
|
||||
if (!aNode->HasChildren()) {
|
||||
MOZ_ASSERT(aNode != aStartContainer || !aStartOffset,
|
||||
"aStartContainer doesn't have children and not a data node, "
|
||||
"aStartOffset should be 0");
|
||||
MOZ_ASSERT(aNode != aEndContainer || !aEndOffset,
|
||||
"aEndContainer doesn't have children and not a data node, "
|
||||
"aEndOffset should be 0");
|
||||
MOZ_ASSERT(aNode != aStart.Container() || aStart.IsStartOfContainer(),
|
||||
"aStart.Container() doesn't have children and not a data node, "
|
||||
"aStart should be at the beginning of its container");
|
||||
MOZ_ASSERT(aNode != aEnd.Container() || aEnd.IsStartOfContainer(),
|
||||
"aEnd.Container() doesn't have children and not a data node, "
|
||||
"aEnd should be at the beginning of its container");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -76,22 +58,22 @@ NodeIsInTraversalRange(nsINode* aNode, bool aIsPreMode,
|
|||
return false;
|
||||
}
|
||||
|
||||
int32_t indx = parent->IndexOf(aNode);
|
||||
NS_WARNING_ASSERTION(indx != -1, "bad indx");
|
||||
|
||||
if (!aIsPreMode) {
|
||||
// aNode should always be content, as we have a parent, but let's just be
|
||||
// extra careful and check.
|
||||
nsIContent* content = NS_WARN_IF(!aNode->IsContent())
|
||||
? nullptr
|
||||
: aNode->AsContent();
|
||||
// Post mode: start < node <= end.
|
||||
return nsContentUtils::ComparePoints(aStartContainer, aStartOffset,
|
||||
parent, indx + 1) < 0 &&
|
||||
nsContentUtils::ComparePoints(aEndContainer, aEndOffset,
|
||||
parent, indx + 1) >= 0;
|
||||
RawRangeBoundary afterNode(parent, content);
|
||||
return nsContentUtils::ComparePoints(aStart, afterNode) < 0 &&
|
||||
nsContentUtils::ComparePoints(aEnd, afterNode) >= 0;
|
||||
}
|
||||
|
||||
// Pre mode: start <= node < end.
|
||||
return nsContentUtils::ComparePoints(aStartContainer, aStartOffset,
|
||||
parent, indx) <= 0 &&
|
||||
nsContentUtils::ComparePoints(aEndContainer, aEndOffset,
|
||||
parent, indx) > 0;
|
||||
RawRangeBoundary beforeNode(parent, aNode->GetPreviousSibling());
|
||||
return nsContentUtils::ComparePoints(aStart, beforeNode) <= 0 &&
|
||||
nsContentUtils::ComparePoints(aEnd, beforeNode) > 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,6 +98,9 @@ public:
|
|||
virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset) override;
|
||||
|
||||
virtual nsresult Init(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd) override;
|
||||
|
||||
virtual void First() override;
|
||||
|
||||
virtual void Last() override;
|
||||
|
@ -139,8 +124,8 @@ protected:
|
|||
* - aStartOffset and aEndOffset are valid for its container.
|
||||
* - The start point and the end point are in document order.
|
||||
*/
|
||||
nsresult InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset);
|
||||
nsresult InitInternal(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd);
|
||||
|
||||
// Recursively get the deepest first/last child of aRoot. This will return
|
||||
// aRoot itself if it has no children.
|
||||
|
@ -287,8 +272,7 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return InitInternal(range->GetStartContainer(), range->StartOffset(),
|
||||
range->GetEndContainer(), range->EndOffset());
|
||||
return InitInternal(range->StartRef().AsRaw(), range->EndRef().AsRaw());
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -302,57 +286,67 @@ nsContentIterator::Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return InitInternal(aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset);
|
||||
return InitInternal(RawRangeBoundary(aStartContainer, aStartOffset),
|
||||
RawRangeBoundary(aEndContainer, aEndOffset));
|
||||
}
|
||||
|
||||
// XXX Argument names will be replaced in the following patch.
|
||||
nsresult
|
||||
nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset)
|
||||
nsContentIterator::Init(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd)
|
||||
{
|
||||
mIsDone = false;
|
||||
|
||||
|
||||
if (NS_WARN_IF(!nsRange::IsValidPoints(aStart.Container(), aStart.Offset(),
|
||||
aEnd.Container(), aEnd.Offset()))) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return InitInternal(aStart, aEnd);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentIterator::InitInternal(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd)
|
||||
{
|
||||
// get common content parent
|
||||
mCommonParent =
|
||||
nsContentUtils::GetCommonAncestor(aStartContainer, aEndContainer);
|
||||
nsContentUtils::GetCommonAncestor(aStart.Container(), aEnd.Container());
|
||||
if (NS_WARN_IF(!mCommonParent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool startIsData = aStartContainer->IsNodeOfType(nsINode::eDATA_NODE);
|
||||
bool startIsData = aStart.Container()->IsNodeOfType(nsINode::eDATA_NODE);
|
||||
|
||||
// short circuit when start node == end node
|
||||
if (aStartContainer == aEndContainer) {
|
||||
// Check to see if we have a collapsed range, if so, there is nothing to
|
||||
// iterate over.
|
||||
//
|
||||
// XXX: CharacterDataNodes (text nodes) are currently an exception, since
|
||||
// we always want to be able to iterate text nodes at the end points
|
||||
// of a range.
|
||||
// Check to see if we have a collapsed range, if so, there is nothing to
|
||||
// iterate over.
|
||||
//
|
||||
// XXX: CharacterDataNodes (text nodes) are currently an exception, since
|
||||
// we always want to be able to iterate text nodes at the end points
|
||||
// of a range.
|
||||
|
||||
if (!startIsData && aStartOffset == aEndOffset) {
|
||||
MakeEmpty();
|
||||
return NS_OK;
|
||||
}
|
||||
if (!startIsData && aStart == aEnd) {
|
||||
MakeEmpty();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (startIsData) {
|
||||
// It's a character data node.
|
||||
mFirst = aStartContainer->AsContent();
|
||||
mLast = mFirst;
|
||||
mCurNode = mFirst;
|
||||
// Handle ranges within a single character data node.
|
||||
if (startIsData && aStart.Container() == aEnd.Container()) {
|
||||
mFirst = aStart.Container()->AsContent();
|
||||
mLast = mFirst;
|
||||
mCurNode = mFirst;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find first node in range.
|
||||
|
||||
nsIContent* cChild = nullptr;
|
||||
|
||||
// Valid start indices are 0 <= aStartOffset <= childCount. That means if
|
||||
// start node has no children, only offset 0 is valid.
|
||||
if (!startIsData && aStartOffset < aStartContainer->GetChildCount()) {
|
||||
cChild = aStartContainer->GetChildAt(aStartOffset);
|
||||
NS_WARNING_ASSERTION(cChild, "GetChildAt returned null");
|
||||
// Try to get the child at our starting point. This might return null if
|
||||
// aStart is immediately after the last node in aStart.Container().
|
||||
if (!startIsData) {
|
||||
cChild = aStart.GetChildAtOffset();
|
||||
}
|
||||
|
||||
if (!cChild) {
|
||||
|
@ -368,33 +362,31 @@ nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
// is a non-container node (e.g. <br>), we don't skip the node in this
|
||||
// case in order to address bug 1215798.
|
||||
bool startIsContainer = true;
|
||||
if (aStartContainer->IsHTMLElement()) {
|
||||
nsIAtom* name = aStartContainer->NodeInfo()->NameAtom();
|
||||
if (aStart.Container()->IsHTMLElement()) {
|
||||
nsIAtom* name = aStart.Container()->NodeInfo()->NameAtom();
|
||||
startIsContainer =
|
||||
nsHTMLElement::IsContainer(nsHTMLTags::AtomTagToId(name));
|
||||
}
|
||||
if (!startIsData && (startIsContainer || aStartOffset)) {
|
||||
mFirst = GetNextSibling(aStartContainer);
|
||||
if (!startIsData && (startIsContainer || !aStart.IsStartOfContainer())) {
|
||||
mFirst = GetNextSibling(aStart.Container());
|
||||
NS_WARNING_ASSERTION(mFirst, "GetNextSibling returned null");
|
||||
|
||||
// Does mFirst node really intersect the range? The range could be
|
||||
// 'degenerate', i.e., not collapsed but still contain no content.
|
||||
if (mFirst &&
|
||||
NS_WARN_IF(!NodeIsInTraversalRange(mFirst, mPre,
|
||||
aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset))) {
|
||||
NS_WARN_IF(!NodeIsInTraversalRange(mFirst, mPre, aStart, aEnd))) {
|
||||
mFirst = nullptr;
|
||||
}
|
||||
} else {
|
||||
mFirst = aStartContainer->AsContent();
|
||||
mFirst = aStart.Container()->AsContent();
|
||||
}
|
||||
} else {
|
||||
// post-order
|
||||
if (NS_WARN_IF(!aStartContainer->IsContent())) {
|
||||
if (NS_WARN_IF(!aStart.Container()->IsContent())) {
|
||||
// What else can we do?
|
||||
mFirst = nullptr;
|
||||
} else {
|
||||
mFirst = aStartContainer->AsContent();
|
||||
mFirst = aStart.Container()->AsContent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -408,9 +400,7 @@ nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
// Does mFirst node really intersect the range? The range could be
|
||||
// 'degenerate', i.e., not collapsed but still contain no content.
|
||||
|
||||
if (mFirst &&
|
||||
!NodeIsInTraversalRange(mFirst, mPre, aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset)) {
|
||||
if (mFirst && !NodeIsInTraversalRange(mFirst, mPre, aStart, aEnd)) {
|
||||
mFirst = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -419,11 +409,11 @@ nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
|
||||
// Find last node in range.
|
||||
|
||||
bool endIsData = aEndContainer->IsNodeOfType(nsINode::eDATA_NODE);
|
||||
bool endIsData = aEnd.Container()->IsNodeOfType(nsINode::eDATA_NODE);
|
||||
|
||||
if (endIsData || !aEndContainer->HasChildren() || !aEndOffset) {
|
||||
if (endIsData || !aEnd.Container()->HasChildren() || aEnd.IsStartOfContainer()) {
|
||||
if (mPre) {
|
||||
if (NS_WARN_IF(!aEndContainer->IsContent())) {
|
||||
if (NS_WARN_IF(!aEnd.Container()->IsContent())) {
|
||||
// Not much else to do here...
|
||||
mLast = nullptr;
|
||||
} else {
|
||||
|
@ -431,22 +421,22 @@ nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
// the last element should be the previous node (i.e., shouldn't
|
||||
// include the end node in the range).
|
||||
bool endIsContainer = true;
|
||||
if (aEndContainer->IsHTMLElement()) {
|
||||
nsIAtom* name = aEndContainer->NodeInfo()->NameAtom();
|
||||
if (aEnd.Container()->IsHTMLElement()) {
|
||||
nsIAtom* name = aEnd.Container()->NodeInfo()->NameAtom();
|
||||
endIsContainer =
|
||||
nsHTMLElement::IsContainer(nsHTMLTags::AtomTagToId(name));
|
||||
}
|
||||
if (!endIsData && !endIsContainer && !aEndOffset) {
|
||||
mLast = PrevNode(aEndContainer);
|
||||
if (!endIsData && !endIsContainer && aEnd.IsStartOfContainer()) {
|
||||
mLast = PrevNode(aEnd.Container());
|
||||
NS_WARNING_ASSERTION(mLast, "PrevNode returned null");
|
||||
if (mLast && mLast != mFirst &&
|
||||
NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre,
|
||||
mFirst, 0,
|
||||
aEndContainer, aEndOffset))) {
|
||||
RawRangeBoundary(mFirst, 0),
|
||||
aEnd))) {
|
||||
mLast = nullptr;
|
||||
}
|
||||
} else {
|
||||
mLast = aEndContainer->AsContent();
|
||||
mLast = aEnd.Container()->AsContent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -456,22 +446,18 @@ nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
// cdata node, should we set mLast to the prev sibling?
|
||||
|
||||
if (!endIsData) {
|
||||
mLast = GetPrevSibling(aEndContainer);
|
||||
mLast = GetPrevSibling(aEnd.Container());
|
||||
NS_WARNING_ASSERTION(mLast, "GetPrevSibling returned null");
|
||||
|
||||
if (!NodeIsInTraversalRange(mLast, mPre,
|
||||
aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset)) {
|
||||
if (!NodeIsInTraversalRange(mLast, mPre, aStart, aEnd)) {
|
||||
mLast = nullptr;
|
||||
}
|
||||
} else {
|
||||
mLast = aEndContainer->AsContent();
|
||||
mLast = aEnd.Container()->AsContent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int32_t indx = aEndOffset;
|
||||
|
||||
cChild = aEndContainer->GetChildAt(--indx);
|
||||
cChild = aEnd.Ref();
|
||||
|
||||
if (NS_WARN_IF(!cChild)) {
|
||||
// No child at offset!
|
||||
|
@ -483,9 +469,7 @@ nsContentIterator::InitInternal(nsINode* aStartContainer, uint32_t aStartOffset,
|
|||
mLast = GetDeepLastChild(cChild);
|
||||
NS_WARNING_ASSERTION(mLast, "GetDeepLastChild returned null");
|
||||
|
||||
if (NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre,
|
||||
aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset))) {
|
||||
if (NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre, aStart, aEnd))) {
|
||||
mLast = nullptr;
|
||||
}
|
||||
} else {
|
||||
|
@ -784,51 +768,42 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
|
|||
|
||||
// Check to see if the node falls within the traversal range.
|
||||
|
||||
nsINode* firstNode = mFirst;
|
||||
nsINode* lastNode = mLast;
|
||||
int32_t firstOffset = 0, lastOffset = 0;
|
||||
RawRangeBoundary first(mFirst, 0);
|
||||
RawRangeBoundary last(mLast, 0);
|
||||
|
||||
if (firstNode && lastNode) {
|
||||
if (mFirst && mLast) {
|
||||
if (mPre) {
|
||||
firstNode = NodeToParentOffset(mFirst, &firstOffset);
|
||||
NS_WARNING_ASSERTION(firstNode, "NodeToParentOffset returned null");
|
||||
NS_WARNING_ASSERTION(firstOffset >= 0, "bad firstOffset");
|
||||
// In pre we want to record the point immediately before mFirst, which is
|
||||
// the point immediately after mFirst's previous sibling.
|
||||
first.SetAfterRef(mFirst->GetParentNode(), mFirst->GetPreviousSibling());
|
||||
|
||||
if (lastNode->GetChildCount()) {
|
||||
lastOffset = 0;
|
||||
} else {
|
||||
lastNode = NodeToParentOffset(mLast, &lastOffset);
|
||||
NS_WARNING_ASSERTION(lastNode, "NodeToParentOffset returned null");
|
||||
NS_WARNING_ASSERTION(lastOffset >= 0, "bad lastOffset");
|
||||
++lastOffset;
|
||||
// If mLast has no children, then we want to make sure to include it.
|
||||
if (!mLast->HasChildren()) {
|
||||
last.SetAfterRef(mLast->GetParentNode(), mLast->AsContent());
|
||||
}
|
||||
} else {
|
||||
uint32_t numChildren = firstNode->GetChildCount();
|
||||
|
||||
if (numChildren) {
|
||||
firstOffset = numChildren;
|
||||
NS_WARNING_ASSERTION(firstOffset >= 0, "bad firstOffset");
|
||||
// If the first node has any children, we want to be immediately after the
|
||||
// last. Otherwise we want to be immediately before mFirst.
|
||||
if (mFirst->HasChildren()) {
|
||||
first.SetAfterRef(mFirst, mFirst->GetLastChild());
|
||||
} else {
|
||||
firstNode = NodeToParentOffset(mFirst, &firstOffset);
|
||||
NS_WARNING_ASSERTION(firstNode, "NodeToParentOffset returned null");
|
||||
NS_WARNING_ASSERTION(firstOffset >= 0, "bad firstOffset");
|
||||
first.SetAfterRef(mFirst->GetParentNode(), mFirst->GetPreviousSibling());
|
||||
}
|
||||
|
||||
lastNode = NodeToParentOffset(mLast, &lastOffset);
|
||||
NS_WARNING_ASSERTION(lastNode, "NodeToParentOffset returned null");
|
||||
NS_WARNING_ASSERTION(lastOffset >= 0, "bad lastOffset");
|
||||
++lastOffset;
|
||||
// Set the last point immediately after the final node.
|
||||
last.SetAfterRef(mLast->GetParentNode(), mLast->AsContent());
|
||||
}
|
||||
}
|
||||
|
||||
NS_WARNING_ASSERTION(first.IsSetAndValid(), "first is not valid");
|
||||
NS_WARNING_ASSERTION(last.IsSetAndValid(), "last is not valid");
|
||||
|
||||
// The end positions are always in the range even if it has no parent. We
|
||||
// need to allow that or 'iter->Init(root)' would assert in Last() or First()
|
||||
// for example, bug 327694.
|
||||
if (mFirst != mCurNode && mLast != mCurNode &&
|
||||
(NS_WARN_IF(!firstNode) || NS_WARN_IF(!lastNode) ||
|
||||
NS_WARN_IF(!NodeIsInTraversalRange(mCurNode, mPre,
|
||||
firstNode, firstOffset,
|
||||
lastNode, lastOffset)))) {
|
||||
(NS_WARN_IF(!first.IsSet()) || NS_WARN_IF(!last.IsSet()) ||
|
||||
NS_WARN_IF(!NodeIsInTraversalRange(mCurNode, mPre, first, last)))) {
|
||||
mIsDone = true;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -886,6 +861,9 @@ public:
|
|||
virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset) override;
|
||||
|
||||
virtual nsresult Init(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd) override;
|
||||
|
||||
virtual void Next() override;
|
||||
|
||||
virtual void Prev() override;
|
||||
|
@ -987,22 +965,26 @@ nsContentSubtreeIterator::Init(nsIDOMRange* aRange)
|
|||
nsresult
|
||||
nsContentSubtreeIterator::Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset)
|
||||
{
|
||||
return Init(RawRangeBoundary(aStartContainer, aStartOffset),
|
||||
RawRangeBoundary(aEndContainer, aEndOffset));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentSubtreeIterator::Init(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd)
|
||||
{
|
||||
mIsDone = false;
|
||||
|
||||
RefPtr<nsRange> range;
|
||||
nsresult rv = nsRange::CreateRange(aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset,
|
||||
getter_AddRefs(range));
|
||||
nsresult rv = nsRange::CreateRange(aStart, aEnd, getter_AddRefs(range));
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!range) ||
|
||||
NS_WARN_IF(!range->IsPositioned())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(range->GetStartContainer() != aStartContainer) ||
|
||||
NS_WARN_IF(range->GetEndContainer() != aEndContainer) ||
|
||||
NS_WARN_IF(range->StartOffset() != aStartOffset) ||
|
||||
NS_WARN_IF(range->EndOffset() != aEndOffset)) {
|
||||
if (NS_WARN_IF(range->StartRef() != aStart) ||
|
||||
NS_WARN_IF(range->EndRef() != aEnd)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/RangeBoundary.h"
|
||||
|
||||
class nsINode;
|
||||
class nsIDOMRange;
|
||||
|
@ -39,6 +40,13 @@ public:
|
|||
virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset) = 0;
|
||||
|
||||
/* Initializes an iterator for the subtree between aStart and aEnd.
|
||||
Callers should guarantee that the start point and end point are in
|
||||
document order.
|
||||
*/
|
||||
virtual nsresult Init(const mozilla::RawRangeBoundary& aStart,
|
||||
const mozilla::RawRangeBoundary& aEnd) = 0;
|
||||
|
||||
/** First will reset the list.
|
||||
*/
|
||||
virtual void First() = 0;
|
||||
|
|
|
@ -99,20 +99,24 @@ nsFilteredContentIterator::Init(nsIDOMRange* aRange)
|
|||
nsresult
|
||||
nsFilteredContentIterator::Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset)
|
||||
{
|
||||
return Init(RawRangeBoundary(aStartContainer, aStartOffset),
|
||||
RawRangeBoundary(aEndContainer, aEndOffset));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFilteredContentIterator::Init(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd)
|
||||
{
|
||||
RefPtr<nsRange> range;
|
||||
nsresult rv = nsRange::CreateRange(aStartContainer, aStartOffset,
|
||||
aEndContainer, aEndOffset,
|
||||
getter_AddRefs(range));
|
||||
nsresult rv = nsRange::CreateRange(aStart, aEnd, getter_AddRefs(range));
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!range) ||
|
||||
NS_WARN_IF(!range->IsPositioned())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(range->GetStartContainer() == aStartContainer);
|
||||
MOZ_ASSERT(range->GetEndContainer() == aEndContainer);
|
||||
MOZ_ASSERT(range->StartOffset() == aStartOffset);
|
||||
MOZ_ASSERT(range->EndOffset() == aEndOffset);
|
||||
MOZ_ASSERT(range->StartRef() == aStart);
|
||||
MOZ_ASSERT(range->EndRef() == aEnd);
|
||||
|
||||
mRange = Move(range);
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
virtual nsresult Init(nsIDOMRange* aRange) override;
|
||||
virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset) override;
|
||||
virtual nsresult Init(const mozilla::RawRangeBoundary& aStart,
|
||||
const mozilla::RawRangeBoundary& aEnd) override;
|
||||
virtual void First() override;
|
||||
virtual void Last() override;
|
||||
virtual void Next() override;
|
||||
|
|
|
@ -107,6 +107,12 @@ public:
|
|||
NS_NOTREACHED("internal error");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
virtual nsresult Init(const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd) override
|
||||
{
|
||||
NS_NOTREACHED("internal error");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
// Not a range because one of the endpoints may be anonymous.
|
||||
nsresult Init(nsIDOMNode* aStartNode, int32_t aStartOffset,
|
||||
nsIDOMNode* aEndNode, int32_t aEndOffset);
|
||||
|
|
Загрузка…
Ссылка в новой задаче