Bug 1375502 - part2: Add nsIContentIterator::Init(nsINode*, uint32_t, nsINode*, uint32_t) r?mats
nsIContentIterator::Init() takes nsRange but it's too expensive for some users.
So, there should be another Init() which can be specified a range in DOM tree
with 2 pairs of nsINode* and uint32_t.
MozReview-Commit-ID: 6JXic0KOM2d
--- a/dom/base/nsContentIterator.cpp
+++ b/dom/base/nsContentIterator.cpp
@@ -108,16 +108,19 @@ public:
explicit nsContentIterator(bool aPre);
// nsIContentIterator interface methods ------------------------------
virtual nsresult Init(nsINode* aRoot) override;
virtual nsresult Init(nsIDOMRange* aRange) override;
+ virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset) override;
+
virtual void First() override;
virtual void Last() override;
virtual void Next() override;
virtual void Prev() override;
@@ -125,16 +128,25 @@ public:
virtual bool IsDone() override;
virtual nsresult PositionAt(nsINode* aCurNode) override;
protected:
virtual ~nsContentIterator();
+ /**
+ * Callers must guarantee that:
+ * - Neither aStartContainer nor aEndContainer is nullptr.
+ * - 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);
+
// Recursively get the deepest first/last child of aRoot. This will return
// aRoot itself if it has no children.
nsINode* GetDeepFirstChild(nsINode* aRoot,
nsTArray<int32_t>* aIndexes = nullptr);
nsIContent* GetDeepFirstChild(nsIContent* aRoot,
nsTArray<int32_t>* aIndexes = nullptr);
nsINode* GetDeepLastChild(nsINode* aRoot,
nsTArray<int32_t>* aIndexes = nullptr);
@@ -295,42 +307,55 @@ nsContentIterator::Init(nsINode* aRoot)
mCurNode = mFirst;
RebuildIndexStack();
return NS_OK;
}
nsresult
nsContentIterator::Init(nsIDOMRange* aDOMRange)
{
+ mIsDone = false;
+
if (NS_WARN_IF(!aDOMRange)) {
return NS_ERROR_INVALID_ARG;
}
+
nsRange* range = static_cast<nsRange*>(aDOMRange);
-
- mIsDone = false;
-
- // get common content parent
- mCommonParent = range->GetCommonAncestor();
- if (NS_WARN_IF(!mCommonParent)) {
- return NS_ERROR_FAILURE;
+ if (NS_WARN_IF(!range->IsPositioned())) {
+ return NS_ERROR_INVALID_ARG;
}
- // get the start node and offset
- int32_t startIndx = range->StartOffset();
- NS_WARNING_ASSERTION(startIndx >= 0, "bad startIndx");
- nsINode* startNode = range->GetStartContainer();
- if (NS_WARN_IF(!startNode)) {
- return NS_ERROR_FAILURE;
+ return InitInternal(range->GetStartContainer(), range->StartOffset(),
+ range->GetEndContainer(), range->EndOffset());
+}
+
+nsresult
+nsContentIterator::Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset)
+{
+ mIsDone = false;
+
+ if (NS_WARN_IF(!nsRange::IsValidPoints(aStartContainer, aStartOffset,
+ aEndContainer, aEndOffset))) {
+ return NS_ERROR_INVALID_ARG;
}
- // get the end node and offset
- int32_t endIndx = range->EndOffset();
- NS_WARNING_ASSERTION(endIndx >= 0, "bad endIndx");
- nsINode* endNode = range->GetEndContainer();
- if (NS_WARN_IF(!endNode)) {
+ return InitInternal(aStartContainer, aStartOffset,
+ aEndContainer, aEndOffset);
+}
+
+// XXX Argument names will be replaced in the following patch.
+nsresult
+nsContentIterator::InitInternal(nsINode* startNode, uint32_t startIndx,
+ nsINode* endNode, uint32_t endIndx)
+{
+ // get common content parent
+ mCommonParent =
+ nsContentUtils::GetCommonAncestor(startNode, endNode);
+ if (NS_WARN_IF(!mCommonParent)) {
return NS_ERROR_FAILURE;
}
bool startIsData = startNode->IsNodeOfType(nsINode::eDATA_NODE);
// short circuit when start node == end node
if (startNode == endNode) {
// Check to see if we have a collapsed range, if so, there is nothing to
@@ -1213,31 +1238,39 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsContentSubtreeIterator, nsContentIterator)
// nsContentIterator overrides ------------------------------
virtual nsresult Init(nsINode* aRoot) override;
virtual nsresult Init(nsIDOMRange* aRange) override;
+ virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset) override;
+
virtual void Next() override;
virtual void Prev() override;
virtual nsresult PositionAt(nsINode* aCurNode) override;
// Must override these because we don't do PositionAt
virtual void First() override;
// Must override these because we don't do PositionAt
virtual void Last() override;
protected:
virtual ~nsContentSubtreeIterator() {}
+ /**
+ * Callers must guarantee that mRange isn't nullptr and is positioned.
+ */
+ nsresult InitWithRange();
+
// Returns the highest inclusive ancestor of aNode that's in the range
// (possibly aNode itself). Returns null if aNode is null, or is not itself
// in the range. A node is in the range if (node, 0) comes strictly after
// the range endpoint, and (node, node.length) comes strictly before it, so
// the range's start and end nodes will never be considered "in" it.
nsIContent* GetTopAncestorInRange(nsINode* aNode);
// no copy's or assigns FIX ME
@@ -1296,17 +1329,58 @@ nsContentSubtreeIterator::Init(nsINode*
nsresult
nsContentSubtreeIterator::Init(nsIDOMRange* aRange)
{
MOZ_ASSERT(aRange);
mIsDone = false;
- mRange = static_cast<nsRange*>(aRange);
+ nsRange* range = static_cast<nsRange*>(aRange);
+ if (NS_WARN_IF(!range->IsPositioned())) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ mRange = range;
+
+ return InitWithRange();
+}
+
+nsresult
+nsContentSubtreeIterator::Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset)
+{
+ mIsDone = false;
+
+ RefPtr<nsRange> range;
+ nsresult rv = nsRange::CreateRange(aStartContainer, aStartOffset,
+ aEndContainer, aEndOffset,
+ 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)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mRange = Move(range);
+
+ return InitWithRange();
+}
+
+nsresult
+nsContentSubtreeIterator::InitWithRange()
+{
+ MOZ_ASSERT(mRange);
+ MOZ_ASSERT(mRange->IsPositioned());
// get the start node and offset, convert to nsINode
mCommonParent = mRange->GetCommonAncestor();
nsINode* startContainer = mRange->GetStartContainer();
int32_t startOffset = mRange->StartOffset();
nsINode* endContainer = mRange->GetEndContainer();
int32_t endOffset = mRange->EndOffset();
MOZ_ASSERT(mCommonParent && startContainer && endContainer);
--- a/dom/base/nsIContentIterator.h
+++ b/dom/base/nsIContentIterator.h
@@ -26,16 +26,24 @@ public:
*/
virtual nsresult Init(nsINode* aRoot) = 0;
/* Initializes an iterator for the subtree defined by the range aRange
Subclasses should make sure they implement both of these!
*/
virtual nsresult Init(nsIDOMRange* aRange) = 0;
+ /* Initializes an iterator for the subtree between
+ aStartContainer/aStartOffset and aEndContainer/aEndOffset
+ Callers should guarantee that the start point and end point are in
+ document order.
+ */
+ virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset) = 0;
+
/** First will reset the list.
*/
virtual void First() = 0;
/** Last will reset the list to the end.
*/
virtual void Last() = 0;
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -1258,16 +1258,51 @@ nsRange::ComputeRootNode(nsINode* aNode,
NS_ASSERTION(!root->IsNodeOfType(nsINode::eDOCUMENT),
"GetUncomposedDoc should have returned a doc");
// We allow this because of backward compatibility.
return root;
}
+/* static */
+bool
+nsRange::IsValidPoints(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset)
+{
+ // Use NS_WARN_IF() only for the cases where the arguments are unexpected.
+ if (NS_WARN_IF(!aStartContainer) || NS_WARN_IF(!aEndContainer) ||
+ NS_WARN_IF(!IsValidOffset(aStartContainer, aStartOffset)) ||
+ NS_WARN_IF(!IsValidOffset(aEndContainer, aEndOffset))) {
+ return false;
+ }
+
+ // Otherwise, don't use NS_WARN_IF() for preventing to make console messy.
+ // Instead, check one by one since it is easier to catch the error reason
+ // with debugger.
+
+ if (ComputeRootNode(aStartContainer) != ComputeRootNode(aEndContainer)) {
+ return false;
+ }
+
+ bool disconnected = false;
+ int32_t order =
+ nsContentUtils::ComparePoints(aStartContainer,
+ static_cast<int32_t>(aStartOffset),
+ aEndContainer,
+ static_cast<int32_t>(aEndOffset),
+ &disconnected);
+ // FYI: disconnected should be false unless |order| is 1.
+ if (order == 1 || NS_WARN_IF(disconnected)) {
+ return false;
+ }
+
+ return true;
+}
+
void
nsRange::SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
{
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetStart(aNode, aOffset, aErr);
}
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -323,16 +323,23 @@ public:
* fragment. If this returns nullptr, that means aNode can be neither the
* start container nor end container of any range.
*/
static nsINode* ComputeRootNode(nsINode* aNode)
{
return ComputeRootNode(aNode, false);
}
+ /**
+ * Return true if aStartContainer/aStartOffset and aEndContainer/aEndOffset
+ * are valid start and end points for a range. Otherwise, return false.
+ */
+ static bool IsValidPoints(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset);
+
/******************************************************************************
* Utility routine to detect if a content node starts before a range and/or
* ends after a range. If neither it is contained inside the range.
*
* XXX - callers responsibility to ensure node in same doc as range!
*
*****************************************************************************/
static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -195,25 +195,16 @@ ContentEventHandler::RawRange::SelectNod
}
mRoot = newRoot;
mStartContainer = mEndContainer = aNodeToSelectContents;
mStartOffset = 0;
mEndOffset = aNodeToSelectContents->Length();
return NS_OK;
}
-already_AddRefed<nsRange>
-ContentEventHandler::RawRange::CreateRange() const
-{
- RefPtr<nsRange> range = new nsRange(mRoot);
- range->SetStartAndEnd(mStartContainer, mStartOffset,
- mEndContainer, mEndOffset);
- return range.forget();
-}
-
/******************************************************************/
/* ContentEventHandler */
/******************************************************************/
// NOTE
//
// ContentEventHandler *creates* ranges as following rules:
// 1. Start of range:
@@ -863,18 +854,19 @@ ContentEventHandler::GenerateFlatTextCon
nsIContent* content = startNode->AsContent();
AppendSubString(aString, content, aRawRange.StartOffset(),
aRawRange.EndOffset() - aRawRange.StartOffset());
ConvertToNativeNewlines(aString);
return NS_OK;
}
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
- RefPtr<nsRange> range = aRawRange.CreateRange();
- nsresult rv = iter->Init(range);
+ nsresult rv =
+ iter->Init(aRawRange.GetStartContainer(), aRawRange.StartOffset(),
+ aRawRange.GetEndContainer(), aRawRange.EndOffset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
for (; !iter->IsDone(); iter->Next()) {
nsINode* node = iter->GetCurrentNode();
if (NS_WARN_IF(!node)) {
break;
}
@@ -1035,18 +1027,19 @@ ContentEventHandler::GenerateFlatFontRan
nsINode* endNode = aRawRange.GetEndContainer();
if (NS_WARN_IF(!startNode) || NS_WARN_IF(!endNode)) {
return NS_ERROR_FAILURE;
}
// baseOffset is the flattened offset of each content node.
int32_t baseOffset = 0;
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
- RefPtr<nsRange> range = aRawRange.CreateRange();
- nsresult rv = iter->Init(range);
+ nsresult rv =
+ iter->Init(aRawRange.GetStartContainer(), aRawRange.StartOffset(),
+ aRawRange.GetEndContainer(), aRawRange.EndOffset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
for (; !iter->IsDone(); iter->Next()) {
nsINode* node = iter->GetCurrentNode();
if (NS_WARN_IF(!node)) {
break;
}
@@ -1659,18 +1652,23 @@ ContentEventHandler::GetNodePositionHavi
return NodePosition();
}
ContentEventHandler::FrameAndNodeOffset
ContentEventHandler::GetFirstFrameInRangeForTextRect(const RawRange& aRawRange)
{
NodePosition nodePosition;
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
- RefPtr<nsRange> range = aRawRange.CreateRange();
- for (iter->Init(range); !iter->IsDone(); iter->Next()) {
+ nsresult rv =
+ iter->Init(aRawRange.GetStartContainer(), aRawRange.StartOffset(),
+ aRawRange.GetEndContainer(), aRawRange.EndOffset());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return FrameAndNodeOffset();
+ }
+ for (; !iter->IsDone(); iter->Next()) {
nsINode* node = iter->GetCurrentNode();
if (NS_WARN_IF(!node)) {
break;
}
if (!node->IsContent()) {
continue;
}
@@ -1707,18 +1705,22 @@ ContentEventHandler::GetFirstFrameInRang
return FrameAndNodeOffset(firstFrame, nodePosition.mOffset);
}
ContentEventHandler::FrameAndNodeOffset
ContentEventHandler::GetLastFrameInRangeForTextRect(const RawRange& aRawRange)
{
NodePosition nodePosition;
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
- RefPtr<nsRange> range = aRawRange.CreateRange();
- iter->Init(range);
+ nsresult rv =
+ iter->Init(aRawRange.GetStartContainer(), aRawRange.StartOffset(),
+ aRawRange.GetEndContainer(), aRawRange.EndOffset());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return FrameAndNodeOffset();
+ }
nsINode* endNode = aRawRange.GetEndContainer();
uint32_t endOffset = aRawRange.EndOffset();
// If the end point is start of a text node or specified by its parent and
// index, the node shouldn't be included into the range. For example,
// with this case, |<p>abc[<br>]def</p>|, the range ends at 3rd children of
// <p> (see the range creation rules, "2.4. Cases: <element/>]"). This causes
// following frames:
@@ -2316,18 +2318,21 @@ ContentEventHandler::OnQueryTextRect(Wid
true, &aEvent->mReply.mOffset,
getter_AddRefs(lastTextContent));
NS_ENSURE_SUCCESS(rv, rv);
rv = GenerateFlatTextContent(rawRange, aEvent->mReply.mString, lineBreakType);
NS_ENSURE_SUCCESS(rv, rv);
// used to iterate over all contents and their frames
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
- RefPtr<nsRange> range = rawRange.CreateRange();
- iter->Init(range);
+ rv = iter->Init(rawRange.GetStartContainer(), rawRange.StartOffset(),
+ rawRange.GetEndContainer(), rawRange.EndOffset());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return NS_ERROR_FAILURE;
+ }
// Get the first frame which causes some text after the offset.
FrameAndNodeOffset firstFrame = GetFirstFrameInRangeForTextRect(rawRange);
// If GetFirstFrameInRangeForTextRect() does not return valid frame, that
// means that there are no visible frames having text or the offset reached
// the end of contents.
if (!firstFrame.IsValid()) {
@@ -2941,30 +2946,32 @@ ContentEventHandler::GetFlatTextLengthIn
if (endPosition.OffsetIsValid()) {
// Offset is within node's length; set end of range to that offset
rv = prevRawRange.SetEnd(endPosition.mNode, endPosition.mOffset);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
iter = NS_NewPreContentIterator();
- RefPtr<nsRange> prevRange = prevRawRange.CreateRange();
- rv = iter->Init(prevRange);
+ rv =
+ iter->Init(prevRawRange.GetStartContainer(), prevRawRange.StartOffset(),
+ prevRawRange.GetEndContainer(), prevRawRange.EndOffset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else if (endPosition.mNode != aRootContent) {
// Offset is past node's length; set end of range to end of node
rv = prevRawRange.SetEndAfter(endPosition.mNode);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
iter = NS_NewPreContentIterator();
- RefPtr<nsRange> prevRange = prevRawRange.CreateRange();
- rv = iter->Init(prevRange);
+ rv =
+ iter->Init(prevRawRange.GetStartContainer(), prevRawRange.StartOffset(),
+ prevRawRange.GetEndContainer(), prevRawRange.EndOffset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
// Offset is past the root node; set end of range to end of root node
iter = NS_NewPreContentIterator();
rv = iter->Init(aRootContent);
if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/events/ContentEventHandler.h
+++ b/dom/events/ContentEventHandler.h
@@ -81,18 +81,16 @@ private:
nsresult SetEnd(nsINode* aEndContainer, uint32_t aEndOffset);
nsresult SetEndAfter(nsINode* aEndContainer);
void SetStartAndEnd(const nsRange* aRange);
nsresult SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset,
nsINode* aEndContainer, uint32_t aEndOffset);
nsresult SelectNodeContents(nsINode* aNodeToSelectContents);
- already_AddRefed<nsRange> CreateRange() const;
-
private:
bool IsValidOffset(nsINode* aContainer, uint32_t aOffset) const;
nsINode* IsValidBoundary(nsINode* aNode) const;
inline void AssertStartIsBeforeOrEqualToEnd();
nsCOMPtr<nsINode> mRoot;
nsCOMPtr<nsINode> mStartContainer;
nsCOMPtr<nsINode> mEndContainer;
--- a/editor/txtsvc/nsFilteredContentIterator.cpp
+++ b/editor/txtsvc/nsFilteredContentIterator.cpp
@@ -1,29 +1,32 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/mozalloc.h"
+#include "mozilla/Move.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsFilteredContentIterator.h"
#include "nsIAtom.h"
#include "nsIContent.h"
#include "nsIContentIterator.h"
#include "nsIDOMNode.h"
#include "nsINode.h"
#include "nsISupportsBase.h"
#include "nsISupportsUtils.h"
#include "nsITextServicesFilter.h"
#include "nsRange.h"
+using namespace mozilla;
+
//------------------------------------------------------------
nsFilteredContentIterator::nsFilteredContentIterator(nsITextServicesFilter* aFilter) :
mFilter(aFilter),
mDidSkip(false),
mIsOutOfRange(false),
mDirection(eDirNotSet)
{
mIterator = do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
@@ -73,27 +76,72 @@ nsFilteredContentIterator::Init(nsINode*
NS_ENSURE_SUCCESS(rv, rv);
return mIterator->Init(mRange);
}
//------------------------------------------------------------
nsresult
nsFilteredContentIterator::Init(nsIDOMRange* aRange)
{
- NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
- NS_ENSURE_ARG_POINTER(aRange);
- mIsOutOfRange = false;
- mDirection = eForward;
+ if (NS_WARN_IF(!aRange)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsRange* range = static_cast<nsRange*>(aRange);
+ if (NS_WARN_IF(!range->IsPositioned())) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ mRange = range->CloneRange();
+
+ return InitWithRange();
+}
+
+//------------------------------------------------------------
+nsresult
+nsFilteredContentIterator::Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset)
+{
+ RefPtr<nsRange> range;
+ nsresult rv = nsRange::CreateRange(aStartContainer, aStartOffset,
+ aEndContainer, aEndOffset,
+ 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);
+
+ mRange = Move(range);
+
+ return InitWithRange();
+}
+
+nsresult
+nsFilteredContentIterator::InitWithRange()
+{
+ MOZ_ASSERT(mRange);
+ MOZ_ASSERT(mRange->IsPositioned());
+
+ if (NS_WARN_IF(!mPreIterator) || NS_WARN_IF(!mIterator)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mIsOutOfRange = false;
+ mDirection = eForward;
mCurrentIterator = mPreIterator;
- mRange = static_cast<nsRange*>(aRange)->CloneRange();
-
nsresult rv = mPreIterator->Init(mRange);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return mIterator->Init(mRange);
}
//------------------------------------------------------------
nsresult
nsFilteredContentIterator::SwitchDirections(bool aChangeToForward)
{
nsINode *node = mCurrentIterator->GetCurrentNode();
--- a/editor/txtsvc/nsFilteredContentIterator.h
+++ b/editor/txtsvc/nsFilteredContentIterator.h
@@ -27,16 +27,18 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsFilteredContentIterator)
explicit nsFilteredContentIterator(nsITextServicesFilter* aFilter);
/* nsIContentIterator */
virtual nsresult Init(nsINode* aRoot) override;
virtual nsresult Init(nsIDOMRange* aRange) override;
+ virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset) override;
virtual void First() override;
virtual void Last() override;
virtual void Next() override;
virtual void Prev() override;
virtual nsINode *GetCurrentNode() override;
virtual bool IsDone() override;
virtual nsresult PositionAt(nsINode* aCurNode) override;
@@ -44,16 +46,21 @@ public:
bool DidSkip() { return mDidSkip; }
void ClearDidSkip() { mDidSkip = false; }
protected:
nsFilteredContentIterator() : mDidSkip(false), mIsOutOfRange(false) { }
virtual ~nsFilteredContentIterator();
+ /**
+ * Callers must guarantee that mRange isn't nullptr and it's positioned.
+ */
+ nsresult InitWithRange();
+
// enum to give us the direction
typedef enum {eDirNotSet, eForward, eBackward} eDirectionType;
nsresult AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir);
void CheckAdvNode(nsIDOMNode* aNode, bool& aDidSkip, eDirectionType aDir);
nsresult SwitchDirections(bool aChangeToForward);
nsCOMPtr<nsIContentIterator> mCurrentIterator;
nsCOMPtr<nsIContentIterator> mIterator;
--- a/toolkit/components/find/nsFind.cpp
+++ b/toolkit/components/find/nsFind.cpp
@@ -96,16 +96,22 @@ public:
NS_NOTREACHED("internal error");
return NS_ERROR_NOT_IMPLEMENTED;
}
virtual nsresult Init(nsIDOMRange* aRange) override
{
NS_NOTREACHED("internal error");
return NS_ERROR_NOT_IMPLEMENTED;
}
+ virtual nsresult Init(nsINode* aStartContainer, uint32_t aStartOffset,
+ nsINode* aEndContainer, uint32_t aEndOffset) 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);
virtual void First() override;
virtual void Last() override;
virtual void Next() override;
virtual void Prev() override;
virtual nsINode* GetCurrentNode() override;