From 940d191ef8b61309f4ea83d0fea77828f361251b Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 05:28:43 -0400 Subject: Bug 1367683 - Optimize initializing nsRange Tag #1375 --- dom/base/nsDocument.cpp | 2 +- dom/base/nsRange.cpp | 121 ++++++++++++++++----- dom/base/nsRange.h | 57 ++++++++-- dom/events/ContentEventHandler.cpp | 9 +- editor/libeditor/HTMLEditRules.cpp | 111 ++++++++++--------- editor/libeditor/HTMLEditor.cpp | 4 +- editor/libeditor/HTMLStyleEditor.cpp | 26 +++-- editor/libeditor/SelectionState.cpp | 3 +- editor/libeditor/WSRunObject.cpp | 2 +- editor/txtsvc/nsTextServicesDocument.cpp | 12 +- .../spellcheck/src/mozInlineSpellChecker.cpp | 68 +++++++----- extensions/spellcheck/src/mozInlineSpellChecker.h | 6 +- .../spellcheck/src/mozInlineSpellWordUtil.cpp | 8 +- layout/forms/nsTextControlFrame.cpp | 7 +- layout/generic/nsSelection.cpp | 85 ++++++--------- layout/printing/nsPrintEngine.cpp | 14 ++- 16 files changed, 330 insertions(+), 205 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index d0e861b1a..e16c1831c 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -6468,7 +6468,7 @@ already_AddRefed nsIDocument::CreateRange(ErrorResult& rv) { RefPtr range = new nsRange(this); - nsresult res = range->Set(this, 0, this, 0); + nsresult res = range->CollapseTo(this, 0); if (NS_FAILED(res)) { rv.Throw(res); return nullptr; diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp index d45a2c975..154b3428f 100644 --- a/dom/base/nsRange.cpp +++ b/dom/base/nsRange.cpp @@ -270,14 +270,17 @@ nsRange::CreateRange(nsINode* aStartParent, int32_t aStartOffset, nsINode* aEndParent, int32_t aEndOffset, nsRange** aRange) { - nsCOMPtr startDomNode = do_QueryInterface(aStartParent); - nsCOMPtr endDomNode = do_QueryInterface(aEndParent); - - nsresult rv = CreateRange(startDomNode, aStartOffset, endDomNode, aEndOffset, - aRange); - - return rv; + MOZ_ASSERT(aRange); + *aRange = nullptr; + RefPtr range = new nsRange(aStartParent); + nsresult rv = range->SetStartAndEnd(aStartParent, aStartOffset, + aEndParent, aEndOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + range.forget(aRange); + return NS_OK; } /* static */ @@ -286,22 +289,9 @@ nsRange::CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset, nsIDOMNode* aEndParent, int32_t aEndOffset, nsRange** aRange) { - MOZ_ASSERT(aRange); - *aRange = nullptr; - nsCOMPtr startParent = do_QueryInterface(aStartParent); - NS_ENSURE_ARG_POINTER(startParent); - - RefPtr range = new nsRange(startParent); - - nsresult rv = range->SetStart(startParent, aStartOffset); - NS_ENSURE_SUCCESS(rv, rv); - - rv = range->SetEnd(aEndParent, aEndOffset); - NS_ENSURE_SUCCESS(rv, rv); - - range.forget(aRange); - return NS_OK; + nsCOMPtr endParent = do_QueryInterface(aEndParent); + return CreateRange(startParent, aStartOffset, endParent, aEndOffset, aRange); } /* static */ @@ -1137,6 +1127,15 @@ nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent) return rv.StealNSResult(); } +/* static */ +bool +nsRange::IsValidOffset(nsINode* aNode, int32_t aOffset) +{ + return aNode && + aOffset >= 0 && + static_cast(aOffset) <= aNode->Length(); +} + nsINode* nsRange::IsValidBoundary(nsINode* aNode) { @@ -1217,7 +1216,7 @@ nsRange::SetStart(nsINode* aParent, int32_t aOffset) return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR; } - if (aOffset < 0 || uint32_t(aOffset) > aParent->Length()) { + if (!IsValidOffset(aParent, aOffset)) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } @@ -1246,7 +1245,9 @@ nsRange::SetStartBefore(nsINode& aNode, ErrorResult& aRv) } AutoInvalidateSelection atEndOfBlock(this); - aRv = SetStart(aNode.GetParentNode(), IndexOf(&aNode)); + int32_t offset = -1; + nsINode* parent = GetParentAndOffsetBefore(&aNode, &offset); + aRv = SetStart(parent, offset); } NS_IMETHODIMP @@ -1272,7 +1273,9 @@ nsRange::SetStartAfter(nsINode& aNode, ErrorResult& aRv) } AutoInvalidateSelection atEndOfBlock(this); - aRv = SetStart(aNode.GetParentNode(), IndexOf(&aNode) + 1); + int32_t offset = -1; + nsINode* parent = GetParentAndOffsetAfter(&aNode, &offset); + aRv = SetStart(parent, offset); } NS_IMETHODIMP @@ -1321,7 +1324,7 @@ nsRange::SetEnd(nsINode* aParent, int32_t aOffset) return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR; } - if (aOffset < 0 || uint32_t(aOffset) > aParent->Length()) { + if (!IsValidOffset(aParent, aOffset)) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } @@ -1340,6 +1343,64 @@ nsRange::SetEnd(nsINode* aParent, int32_t aOffset) return NS_OK; } +nsresult +nsRange::SetStartAndEnd(nsINode* aStartParent, int32_t aStartOffset, + nsINode* aEndParent, int32_t aEndOffset) +{ + if (NS_WARN_IF(!aStartParent) || NS_WARN_IF(!aEndParent)) { + return NS_ERROR_INVALID_ARG; + } + + nsINode* newStartRoot = IsValidBoundary(aStartParent); + if (!newStartRoot) { + return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR; + } + if (!IsValidOffset(aStartParent, aStartOffset)) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + if (aStartParent == aEndParent) { + if (!IsValidOffset(aEndParent, aEndOffset)) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + // If the end offset is less than the start offset, this should be + // collapsed at the end offset. + if (aStartOffset > aEndOffset) { + DoSetRange(aEndParent, aEndOffset, aEndParent, aEndOffset, newStartRoot); + } else { + DoSetRange(aStartParent, aStartOffset, + aEndParent, aEndOffset, newStartRoot); + } + return NS_OK; + } + + nsINode* newEndRoot = IsValidBoundary(aEndParent); + if (!newEndRoot) { + return NS_ERROR_DOM_INVALID_NODE_TYPE_ERR; + } + if (!IsValidOffset(aEndParent, aEndOffset)) { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + // If they have different root, this should be collapsed at the end point. + if (newStartRoot != newEndRoot) { + DoSetRange(aEndParent, aEndOffset, aEndParent, aEndOffset, newEndRoot); + return NS_OK; + } + + // If the end point is before the start point, this should be collapsed at + // the end point. + if (nsContentUtils::ComparePoints(aStartParent, aStartOffset, + aEndParent, aEndOffset) == 1) { + DoSetRange(aEndParent, aEndOffset, aEndParent, aEndOffset, newEndRoot); + return NS_OK; + } + + // Otherwise, set the range as specified. + DoSetRange(aStartParent, aStartOffset, aEndParent, aEndOffset, newStartRoot); + return NS_OK; +} + void nsRange::SetEndBefore(nsINode& aNode, ErrorResult& aRv) { @@ -1350,7 +1411,9 @@ nsRange::SetEndBefore(nsINode& aNode, ErrorResult& aRv) } AutoInvalidateSelection atEndOfBlock(this); - aRv = SetEnd(aNode.GetParentNode(), IndexOf(&aNode)); + int32_t offset = -1; + nsINode* parent = GetParentAndOffsetBefore(&aNode, &offset); + aRv = SetEnd(parent, offset); } NS_IMETHODIMP @@ -1376,7 +1439,9 @@ nsRange::SetEndAfter(nsINode& aNode, ErrorResult& aRv) } AutoInvalidateSelection atEndOfBlock(this); - aRv = SetEnd(aNode.GetParentNode(), IndexOf(&aNode) + 1); + int32_t offset = -1; + nsINode* parent = GetParentAndOffsetAfter(&aNode, &offset); + aRv = SetEnd(parent, offset); } NS_IMETHODIMP diff --git a/dom/base/nsRange.h b/dom/base/nsRange.h index 4b35c749a..70911338d 100644 --- a/dom/base/nsRange.h +++ b/dom/base/nsRange.h @@ -148,19 +148,61 @@ public: nsINode* GetCommonAncestor() const; void Reset(); + + /** + * SetStart() and SetEnd() sets start point or end point separately. + * However, this is expensive especially when it's a range of Selection. + * When you set both start and end of a range, you should use + * SetStartAndEnd() instead. + */ nsresult SetStart(nsINode* aParent, int32_t aOffset); nsresult SetEnd(nsINode* aParent, int32_t aOffset); + already_AddRefed CloneRange() const; - nsresult Set(nsINode* aStartParent, int32_t aStartOffset, - nsINode* aEndParent, int32_t aEndOffset) + /** + * SetStartAndEnd() works similar to call both SetStart() and SetEnd(). + * Different from calls them separately, this does nothing if either + * the start point or the end point is invalid point. + * If the specified start point is after the end point, the range will be + * collapsed at the end point. Similarly, if they are in different root, + * the range will be collapsed at the end point. + */ + nsresult SetStartAndEnd(nsINode* aStartParent, int32_t aStartOffset, + nsINode* aEndParent, int32_t aEndOffset); + + /** + * CollapseTo() works similar to call both SetStart() and SetEnd() with + * same node and offset. This just calls SetStartAndParent() to set + * collapsed range at aParent and aOffset. + */ + nsresult CollapseTo(nsINode* aParent, int32_t aOffset) { - // If this starts being hot, we may be able to optimize this a bit, - // but for now just set start and end separately. - nsresult rv = SetStart(aStartParent, aStartOffset); - NS_ENSURE_SUCCESS(rv, rv); + return SetStartAndEnd(aParent, aOffset, aParent, aOffset); + } - return SetEnd(aEndParent, aEndOffset); + /** + * Retrieves node and offset for setting start or end of a range to + * before or after aNode. + */ + static nsINode* GetParentAndOffsetAfter(nsINode* aNode, int32_t* aOffset) + { + MOZ_ASSERT(aNode); + MOZ_ASSERT(aOffset); + nsINode* parentNode = aNode->GetParentNode(); + *aOffset = parentNode ? parentNode->IndexOf(aNode) : -1; + if (*aOffset >= 0) { + (*aOffset)++; + } + return parentNode; + } + static nsINode* GetParentAndOffsetBefore(nsINode* aNode, int32_t* aOffset) + { + MOZ_ASSERT(aNode); + MOZ_ASSERT(aOffset); + nsINode* parentNode = aNode->GetParentNode(); + *aOffset = parentNode ? parentNode->IndexOf(aNode) : -1; + return parentNode; } NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult); @@ -296,6 +338,7 @@ protected: void RegisterCommonAncestor(nsINode* aNode); void UnregisterCommonAncestor(nsINode* aNode); nsINode* IsValidBoundary(nsINode* aNode); + static bool IsValidOffset(nsINode* aNode, int32_t aOffset); // CharacterDataChanged set aNotInsertedYet to true to disable an assertion // and suppress re-registering a range common ancestor node since diff --git a/dom/events/ContentEventHandler.cpp b/dom/events/ContentEventHandler.cpp index 935ade23f..df54a4d44 100644 --- a/dom/events/ContentEventHandler.cpp +++ b/dom/events/ContentEventHandler.cpp @@ -980,11 +980,7 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange, // Special case like
if (!mRootContent->HasChildren()) { - nsresult rv = aRange->SetStart(mRootContent, 0); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - rv = aRange->SetEnd(mRootContent, 0); + nsresult rv = aRange->CollapseTo(mRootContent, 0); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -2880,8 +2876,7 @@ ContentEventHandler::AdjustCollapsedRangeMaybeIntoTextNode(nsRange* aRange) return NS_OK; } - nsresult rv = aRange->Set(childNode, offsetInChildNode, - childNode, offsetInChildNode); + nsresult rv = aRange->CollapseTo(childNode, offsetInChildNode); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } diff --git a/editor/libeditor/HTMLEditRules.cpp b/editor/libeditor/HTMLEditRules.cpp index fcbb75ee6..0aa2bde8c 100644 --- a/editor/libeditor/HTMLEditRules.cpp +++ b/editor/libeditor/HTMLEditRules.cpp @@ -1422,16 +1422,15 @@ HTMLEditRules::WillInsertText(EditAction aAction, if (!mDocChangeRange) { mDocChangeRange = new nsRange(selNode); } - rv = mDocChangeRange->SetStart(selNode, selOffset); - NS_ENSURE_SUCCESS(rv, rv); if (curNode) { - rv = mDocChangeRange->SetEnd(curNode, curOffset); + rv = mDocChangeRange->SetStartAndEnd(selNode, selOffset, + curNode, curOffset); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } else { - rv = mDocChangeRange->SetEnd(selNode, selOffset); + rv = mDocChangeRange->CollapseTo(selNode, selOffset); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -5093,10 +5092,11 @@ HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection) // Create a range that represents expanded selection RefPtr range = new nsRange(selStartNode); - nsresult rv = range->SetStart(selStartNode, selStartOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = range->SetEnd(selEndNode, selEndOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = range->SetStartAndEnd(selStartNode, selStartOffset, + selEndNode, selEndOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } // Check if block is entirely inside range if (brBlock) { @@ -5558,26 +5558,27 @@ HTMLEditRules::PromoteRange(nsRange& aRange, // This is tricky. The basic idea is to push out the range endpoints to // truly enclose the blocks that we will affect. - nsCOMPtr opStartNode; - nsCOMPtr opEndNode; + nsCOMPtr opDOMStartNode; + nsCOMPtr opDOMEndNode; int32_t opStartOffset, opEndOffset; GetPromotedPoint(kStart, GetAsDOMNode(startNode), startOffset, - aOperationType, address_of(opStartNode), &opStartOffset); + aOperationType, address_of(opDOMStartNode), &opStartOffset); GetPromotedPoint(kEnd, GetAsDOMNode(endNode), endOffset, aOperationType, - address_of(opEndNode), &opEndOffset); + address_of(opDOMEndNode), &opEndOffset); // Make sure that the new range ends up to be in the editable section. if (!htmlEditor->IsDescendantOfEditorRoot( - EditorBase::GetNodeAtRangeOffsetPoint(opStartNode, opStartOffset)) || + EditorBase::GetNodeAtRangeOffsetPoint(opDOMStartNode, opStartOffset)) || !htmlEditor->IsDescendantOfEditorRoot( - EditorBase::GetNodeAtRangeOffsetPoint(opEndNode, opEndOffset - 1))) { + EditorBase::GetNodeAtRangeOffsetPoint(opDOMEndNode, opEndOffset - 1))) { return; } - DebugOnly rv = aRange.SetStart(opStartNode, opStartOffset); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - rv = aRange.SetEnd(opEndNode, opEndOffset); + nsCOMPtr opStartNode = do_QueryInterface(opDOMStartNode); + nsCOMPtr opEndNode = do_QueryInterface(opDOMEndNode); + DebugOnly rv = + aRange.SetStartAndEnd(opStartNode, opStartOffset, opEndNode, opEndOffset); MOZ_ASSERT(NS_SUCCEEDED(rv)); } @@ -7196,10 +7197,10 @@ HTMLEditRules::PinSelectionToNewBlock(Selection* aSelection) nsCOMPtr node = do_QueryInterface(selNode); NS_ENSURE_STATE(node); RefPtr range = new nsRange(node); - rv = range->SetStart(selNode, selOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = range->SetEnd(selNode, selOffset); - NS_ENSURE_SUCCESS(rv, rv); + rv = range->CollapseTo(node, selOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } bool nodeBefore, nodeAfter; rv = nsRange::CompareNodeToRange(mNewBlock, range, &nodeBefore, &nodeAfter); NS_ENSURE_SUCCESS(rv, rv); @@ -8095,10 +8096,13 @@ HTMLEditRules::DidSplitNode(nsIDOMNode* aExistingRightNode, if (!mListenerEnabled) { return NS_OK; } - nsresult rv = mUtilRange->SetStart(aNewLeftNode, 0); - NS_ENSURE_SUCCESS(rv, rv); - rv = mUtilRange->SetEnd(aExistingRightNode, 0); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr newLeftNode = do_QueryInterface(aNewLeftNode); + nsCOMPtr existingRightNode = do_QueryInterface(aExistingRightNode); + nsresult rv = mUtilRange->SetStartAndEnd(newLeftNode, 0, + existingRightNode, 0); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return UpdateDocChangeRange(mUtilRange); } @@ -8123,11 +8127,12 @@ HTMLEditRules::DidJoinNodes(nsIDOMNode* aLeftNode, if (!mListenerEnabled) { return NS_OK; } + nsCOMPtr rightNode = do_QueryInterface(aRightNode); // assumption that Join keeps the righthand node - nsresult rv = mUtilRange->SetStart(aRightNode, mJoinOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mUtilRange->SetEnd(aRightNode, mJoinOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = mUtilRange->CollapseTo(rightNode, mJoinOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return UpdateDocChangeRange(mUtilRange); } @@ -8149,11 +8154,12 @@ HTMLEditRules::DidInsertText(nsIDOMCharacterData* aTextNode, return NS_OK; } int32_t length = aString.Length(); - nsCOMPtr theNode = do_QueryInterface(aTextNode); - nsresult rv = mUtilRange->SetStart(theNode, aOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mUtilRange->SetEnd(theNode, aOffset+length); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr theNode = do_QueryInterface(aTextNode); + nsresult rv = mUtilRange->SetStartAndEnd(theNode, aOffset, + theNode, aOffset + length); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return UpdateDocChangeRange(mUtilRange); } @@ -8174,11 +8180,11 @@ HTMLEditRules::DidDeleteText(nsIDOMCharacterData* aTextNode, if (!mListenerEnabled) { return NS_OK; } - nsCOMPtr theNode = do_QueryInterface(aTextNode); - nsresult rv = mUtilRange->SetStart(theNode, aOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mUtilRange->SetEnd(theNode, aOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr theNode = do_QueryInterface(aTextNode); + nsresult rv = mUtilRange->CollapseTo(theNode, aOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return UpdateDocChangeRange(mUtilRange); } @@ -8193,22 +8199,27 @@ HTMLEditRules::WillDeleteSelection(nsISelection* aSelection) } RefPtr selection = aSelection->AsSelection(); // get the (collapsed) selection location - nsCOMPtr selNode; - int32_t selOffset; - + nsCOMPtr startNode; + int32_t startOffset; NS_ENSURE_STATE(mHTMLEditor); nsresult rv = mHTMLEditor->GetStartNodeAndOffset(selection, - getter_AddRefs(selNode), &selOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mUtilRange->SetStart(selNode, selOffset); - NS_ENSURE_SUCCESS(rv, rv); + getter_AddRefs(startNode), &startOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + nsCOMPtr endNode; + int32_t endOffset; NS_ENSURE_STATE(mHTMLEditor); rv = mHTMLEditor->GetEndNodeAndOffset(selection, - getter_AddRefs(selNode), &selOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mUtilRange->SetEnd(selNode, selOffset); - NS_ENSURE_SUCCESS(rv, rv); + getter_AddRefs(endNode), &endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + rv = mUtilRange->SetStartAndEnd(startNode, startOffset, endNode, endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return UpdateDocChangeRange(mUtilRange); } diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 532da7a15..73dd1673b 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -3284,8 +3284,8 @@ HTMLEditor::DoContentInserted(nsIDocument* aDocument, sibling = sibling->GetNextSibling(); } } - nsresult rv = range->Set(aContainer, aIndexInContainer, - aContainer, endIndex); + nsresult rv = range->SetStartAndEnd(aContainer, aIndexInContainer, + aContainer, endIndex); if (NS_SUCCEEDED(rv)) { mInlineSpellChecker->SpellCheckRange(range); } diff --git a/editor/libeditor/HTMLStyleEditor.cpp b/editor/libeditor/HTMLStyleEditor.cpp index 6a1ffe8b4..7141cfd61 100644 --- a/editor/libeditor/HTMLStyleEditor.cpp +++ b/editor/libeditor/HTMLStyleEditor.cpp @@ -541,9 +541,11 @@ HTMLEditor::SplitStyleAboveRange(nsRange* inRange, NS_ENSURE_SUCCESS(rv, rv); // reset the range - rv = inRange->SetStart(startNode, startOffset); - NS_ENSURE_SUCCESS(rv, rv); - return inRange->SetEnd(endNode, endOffset); + rv = inRange->SetStartAndEnd(startNode, startOffset, endNode, endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; } nsresult @@ -885,10 +887,11 @@ HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange) endOffset = endNode ? endNode->IndexOf(parent) + 1 : 0; } - nsresult rv = aRange.SetStart(startNode, startOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = aRange.SetEnd(endNode, endOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = aRange.SetStartAndEnd(startNode, startOffset, + endNode, endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return NS_OK; } @@ -918,10 +921,11 @@ HTMLEditor::PromoteInlineRange(nsRange& aRange) endNode = parent; } - nsresult rv = aRange.SetStart(startNode, startOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = aRange.SetEnd(endNode, endOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = aRange.SetStartAndEnd(startNode, startOffset, + endNode, endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return NS_OK; } diff --git a/editor/libeditor/SelectionState.cpp b/editor/libeditor/SelectionState.cpp index f9ad5947a..057e04875 100644 --- a/editor/libeditor/SelectionState.cpp +++ b/editor/libeditor/SelectionState.cpp @@ -686,7 +686,8 @@ already_AddRefed RangeItem::GetRange() { RefPtr range = new nsRange(startNode); - if (NS_FAILED(range->Set(startNode, startOffset, endNode, endOffset))) { + if (NS_FAILED(range->SetStartAndEnd(startNode, startOffset, + endNode, endOffset))) { return nullptr; } return range.forget(); diff --git a/editor/libeditor/WSRunObject.cpp b/editor/libeditor/WSRunObject.cpp index 39ac3fee8..0748f09e5 100644 --- a/editor/libeditor/WSRunObject.cpp +++ b/editor/libeditor/WSRunObject.cpp @@ -1315,7 +1315,7 @@ WSRunObject::DeleteChars(nsINode* aStartNode, if (!range) { range = new nsRange(aStartNode); nsresult rv = - range->Set(aStartNode, aStartOffset, aEndNode, aEndOffset); + range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, aEndOffset); NS_ENSURE_SUCCESS(rv, rv); } bool nodeBefore, nodeAfter; diff --git a/editor/txtsvc/nsTextServicesDocument.cpp b/editor/txtsvc/nsTextServicesDocument.cpp index e0c779683..ccf964d2c 100644 --- a/editor/txtsvc/nsTextServicesDocument.cpp +++ b/editor/txtsvc/nsTextServicesDocument.cpp @@ -406,11 +406,13 @@ nsTextServicesDocument::ExpandRangeToWordBoundaries(nsIDOMRange *aRange) // Now adjust the range so that it uses our new // end points. - - rv = range->SetEnd(rngEndNode, rngEndOffset); - NS_ENSURE_SUCCESS(rv, rv); - - return range->SetStart(rngStartNode, rngStartOffset); + nsCOMPtr startNode = do_QueryInterface(rngStartNode); + nsCOMPtr endNode = do_QueryInterface(rngEndNode); + rv = range->SetStartAndEnd(startNode, rngStartOffset, endNode, rngEndOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; } NS_IMETHODIMP diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.cpp b/extensions/spellcheck/src/mozInlineSpellChecker.cpp index 96011a37e..118035aa5 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp +++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp @@ -164,16 +164,23 @@ mozInlineSpellStatus::InitForEditorChange( NS_ENSURE_SUCCESS(rv, rv); if (cmpResult < 0) { // previous anchor node is before the current anchor - rv = mRange->SetStart(aPreviousNode, aPreviousOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mRange->SetEnd(aAnchorNode, aAnchorOffset); + nsCOMPtr previousNode = do_QueryInterface(aPreviousNode); + nsCOMPtr anchorNode = do_QueryInterface(aAnchorNode); + rv = mRange->SetStartAndEnd(previousNode, aPreviousOffset, + anchorNode, aAnchorOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } } else { // previous anchor node is after (or the same as) the current anchor - rv = mRange->SetStart(aAnchorNode, aAnchorOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = mRange->SetEnd(aPreviousNode, aPreviousOffset); + nsCOMPtr previousNode = do_QueryInterface(aPreviousNode); + nsCOMPtr anchorNode = do_QueryInterface(aAnchorNode); + rv = mRange->SetStartAndEnd(anchorNode, aAnchorOffset, + previousNode, aPreviousOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } } - NS_ENSURE_SUCCESS(rv, rv); // On insert save this range: DoSpellCheck optimizes things in this range. // Otherwise, just leave this nullptr. @@ -454,17 +461,19 @@ mozInlineSpellStatus::GetDocument(nsIDOMDocument** aDocument) nsresult mozInlineSpellStatus::PositionToCollapsedRange(nsIDOMDocument* aDocument, - nsIDOMNode* aNode, int32_t aOffset, nsIDOMRange** aRange) + nsIDOMNode* aNode, + int32_t aOffset, + nsRange** aRange) { *aRange = nullptr; - nsCOMPtr range; - nsresult rv = aDocument->CreateRange(getter_AddRefs(range)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr documentNode = do_QueryInterface(aDocument); + RefPtr range = new nsRange(documentNode); - rv = range->SetStart(aNode, aOffset); - NS_ENSURE_SUCCESS(rv, rv); - rv = range->SetEnd(aNode, aOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr node = do_QueryInterface(aNode); + nsresult rv = range->CollapseTo(node, aOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } range.swap(*aRange); return NS_OK; @@ -1164,9 +1173,8 @@ mozInlineSpellChecker::MakeSpellCheckRange( NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); - nsCOMPtr range; - rv = doc->CreateRange(getter_AddRefs(range)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr documentNode = do_QueryInterface(doc); + RefPtr range = new nsRange(documentNode); // possibly use full range of the editor nsCOMPtr rootElem; @@ -1198,15 +1206,23 @@ mozInlineSpellChecker::MakeSpellCheckRange( if (aStartNode == aEndNode && aStartOffset == aEndOffset) return NS_OK; - rv = range->SetStart(aStartNode, aStartOffset); - NS_ENSURE_SUCCESS(rv, rv); - if (aEndOffset) - rv = range->SetEnd(aEndNode, aEndOffset); - else - rv = range->SetEndAfter(aEndNode); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr startNode = do_QueryInterface(aStartNode); + nsCOMPtr endNode = do_QueryInterface(aEndNode); + if (aEndOffset) { + rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, aEndOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } else { + int32_t endOffset = -1; + endNode = nsRange::GetParentAndOffsetAfter(endNode, &endOffset); + rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } - *aRange = static_cast(range.forget().take()); + range.swap(*aRange); return NS_OK; } diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.h b/extensions/spellcheck/src/mozInlineSpellChecker.h index 86d91c2c0..52261f22b 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.h +++ b/extensions/spellcheck/src/mozInlineSpellChecker.h @@ -85,7 +85,7 @@ public: // (such as for the intial check of everything). // // For mOp == eOpNavigation, this is the NEW position of the cursor - nsCOMPtr mAnchorRange; + RefPtr mAnchorRange; // ----- // The following members are only for navigation events and are only @@ -93,7 +93,7 @@ public: // ----- // this is the OLD position of the cursor - nsCOMPtr mOldNavigationAnchorRange; + RefPtr mOldNavigationAnchorRange; // Set when we should force checking the current word. See // mozInlineSpellChecker::HandleNavigationEvent for a description of why we @@ -111,7 +111,7 @@ protected: nsresult GetDocument(nsIDOMDocument** aDocument); nsresult PositionToCollapsedRange(nsIDOMDocument* aDocument, nsIDOMNode* aNode, int32_t aOffset, - nsIDOMRange** aRange); + nsRange** aRange); }; class mozInlineSpellChecker final : public nsIInlineSpellChecker, diff --git a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp index 3aef1533d..460ac46b8 100644 --- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp +++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp @@ -336,9 +336,11 @@ mozInlineSpellWordUtil::MakeRange(NodeOffset aBegin, NodeOffset aEnd, return NS_ERROR_NOT_INITIALIZED; RefPtr range = new nsRange(aBegin.mNode); - nsresult rv = range->Set(aBegin.mNode, aBegin.mOffset, - aEnd.mNode, aEnd.mOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = range->SetStartAndEnd(aBegin.mNode, aBegin.mOffset, + aEnd.mNode, aEnd.mOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } range.forget(aRange); return NS_OK; diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index aa3185d39..b34e132e6 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -758,7 +758,12 @@ nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode, // we have access to the node. nsCOMPtr start = do_QueryInterface(aStartNode); nsCOMPtr end = do_QueryInterface(aEndNode); - nsresult rv = range->Set(start, aStartOffset, end, aEndOffset); + // XXXbz nsRange::SetStartAndEnd takes int32_t (and ranges generally work on + // int32_t), but we're passing uint32_t. The good news is that at this point + // our endpoints should really be within our length, so not really that big. + // And if they _are_ that big, SetStartAndEnd() will simply error out, which + // is not too bad for a case we don't expect to happen. + nsresult rv = range->SetStartAndEnd(start, aStartOffset, end, aEndOffset); NS_ENSURE_SUCCESS(rv, rv); // Get the selection, clear it and add the new range to it! diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 5ccb2d8bf..f44ff7ea1 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -1788,8 +1788,7 @@ nsFrameSelection::TakeFocus(nsIContent* aNewFocus, RefPtr newRange = new nsRange(aNewFocus); - newRange->SetStart(aNewFocus, aContentOffset); - newRange->SetEnd(aNewFocus, aContentOffset); + newRange->CollapseTo(aNewFocus, aContentOffset); mDomSelections[index]->AddRange(newRange); mBatching = batching; mChangesDuringBatching = changes; @@ -3352,10 +3351,11 @@ nsFrameSelection::CreateAndAddRange(nsINode *aParentNode, int32_t aOffset) RefPtr range = new nsRange(aParentNode); // Set range around child at given offset - nsresult result = range->SetStart(aParentNode, aOffset); - if (NS_FAILED(result)) return result; - result = range->SetEnd(aParentNode, aOffset+1); - if (NS_FAILED(result)) return result; + nsresult rv = range->SetStartAndEnd(aParentNode, aOffset, + aParentNode, aOffset + 1); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } int8_t index = GetIndexFromSelectionType(SelectionType::eNormal); if (!mDomSelections[index]) @@ -3780,13 +3780,12 @@ Selection::SubtractRange(RangeData* aRange, nsRange* aSubtract, // We need to add a new RangeData to the output, running from // the end of aSubtract to the end of range RefPtr postOverlap = new nsRange(aSubtract->GetEndParent()); - - rv = - postOverlap->SetStart(aSubtract->GetEndParent(), aSubtract->EndOffset()); - NS_ENSURE_SUCCESS(rv, rv); - rv = - postOverlap->SetEnd(range->GetEndParent(), range->EndOffset()); - NS_ENSURE_SUCCESS(rv, rv); + rv = postOverlap->SetStartAndEnd( + aSubtract->GetEndParent(), aSubtract->EndOffset(), + range->GetEndParent(), range->EndOffset()); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } if (!postOverlap->Collapsed()) { if (!aOutput->InsertElementAt(0, RangeData(postOverlap))) return NS_ERROR_OUT_OF_MEMORY; @@ -3799,12 +3798,12 @@ Selection::SubtractRange(RangeData* aRange, nsRange* aSubtract, // the start of the range to the start of aSubtract RefPtr preOverlap = new nsRange(range->GetStartParent()); - nsresult rv = - preOverlap->SetStart(range->GetStartParent(), range->StartOffset()); - NS_ENSURE_SUCCESS(rv, rv); - rv = - preOverlap->SetEnd(aSubtract->GetStartParent(), aSubtract->StartOffset()); - NS_ENSURE_SUCCESS(rv, rv); + rv = preOverlap->SetStartAndEnd( + range->GetStartParent(), range->StartOffset(), + aSubtract->GetStartParent(), aSubtract->StartOffset()); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } if (!preOverlap->Collapsed()) { if (!aOutput->InsertElementAt(0, RangeData(preOverlap))) @@ -5186,12 +5185,7 @@ Selection::Collapse(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } RefPtr range = new nsRange(parentNode); - result = range->SetEnd(parentNode, aOffset); - if (NS_FAILED(result)) { - aRv.Throw(result); - return; - } - result = range->SetStart(parentNode, aOffset); + result = range->CollapseTo(parentNode, aOffset); if (NS_FAILED(result)) { aRv.Throw(result); return; @@ -5579,11 +5573,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) return; } SetDirection(eDirNext); - res = difRange->SetEnd(range->GetEndParent(), range->EndOffset()); - nsresult tmp = difRange->SetStart(focusNode, focusOffset); - if (NS_FAILED(tmp)) { - res = tmp; - } + res = difRange->SetStartAndEnd(focusNode, focusOffset, + range->GetEndParent(), range->EndOffset()); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5611,11 +5602,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } else if (result3 <= 0 && result2 >= 0) {//a,2,1 or a2,1 or a,21 or a21 //deselect from 2 to 1 - res = difRange->SetEnd(focusNode, focusOffset); - difRange->SetStart(aParentNode, aOffset, aRv); - if (aRv.Failed()) { - return; - } + res = difRange->SetStartAndEnd(&aParentNode, aOffset, + focusNode, focusOffset); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5678,11 +5666,8 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } else if (result2 <= 0 && result3 >= 0) {//1,2,a or 12,a or 1,2a or 12a //deselect from 1 to 2 - difRange->SetEnd(aParentNode, aOffset, aRv); - res = difRange->SetStart(focusNode, focusOffset); - if (aRv.Failed()) { - return; - } + res = difRange->SetStartAndEnd(focusNode, focusOffset, + &aParentNode, aOffset); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5713,15 +5698,9 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) } //deselect from a to 1 if (focusNode != anchorNode || focusOffset!= anchorOffset) {//if collapsed diff dont do anything - res = difRange->SetStart(anchorNode, anchorOffset); - nsresult tmp = difRange->SetEnd(focusNode, focusOffset); - if (NS_FAILED(tmp)) { - res = tmp; - } - tmp = SetAnchorFocusToRange(range); - if (NS_FAILED(tmp)) { - res = tmp; - } + res = difRange->SetStartAndEnd(anchorNode, anchorOffset, + focusNode, focusOffset); + nsresult tmp = SetAnchorFocusToRange(range); if (NS_FAILED(res)) { aRv.Throw(res); return; @@ -5746,11 +5725,9 @@ Selection::Extend(nsINode& aParentNode, uint32_t aOffset, ErrorResult& aRv) return; } SetDirection(eDirPrevious); - res = difRange->SetEnd(focusNode, focusOffset); - nsresult tmp = difRange->SetStart(range->GetStartParent(), range->StartOffset()); - if (NS_FAILED(tmp)) { - res = tmp; - } + res = difRange->SetStartAndEnd( + range->GetStartParent(), range->StartOffset(), + focusNode, focusOffset); if (NS_FAILED(res)) { aRv.Throw(res); return; diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index f2db53250..0c455f563 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -2449,13 +2449,17 @@ CloneRangeToSelection(nsRange* aRange, nsIDocument* aDoc, NS_ENSURE_TRUE_VOID(newStart && newEnd); nsCOMPtr newStartNode = do_QueryInterface(newStart); - NS_ENSURE_TRUE_VOID(newStartNode); + nsCOMPtr newEndNode = do_QueryInterface(newEnd); + if (NS_WARN_IF(!newStartNode) || NS_WARN_IF(!newEndNode)) { + return; + } RefPtr range = new nsRange(newStartNode); - nsresult rv = range->SetStart(newStartNode, startOffset); - NS_ENSURE_SUCCESS_VOID(rv); - rv = range->SetEnd(newEnd, endOffset); - NS_ENSURE_SUCCESS_VOID(rv); + nsresult rv = + range->SetStartAndEnd(newStartNode, startOffset, newEndNode, endOffset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } aSelection->AddRange(range); } -- cgit v1.2.3