Bug 1456879 - Clean up spellchecker not to use nsIDOM* if possible. r=masayuki
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 25 Apr 2018 17:39:50 +0900
changeset 469273 c7a4c83d8d1578c582116f77666e03680e5e69ab
parent 469272 026aa1ecf5f3100c00ee77ba02ad975112c6c797
child 469274 ff80b014c00b8db7c29888497ad3fe3fad74471c
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1456879
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456879 - Clean up spellchecker not to use nsIDOM* if possible. r=masayuki Without XPCOM and related method, I want to remove dependencies of nsIDOM* from spellchecker. Also, it is unnecessary to use nsISelectionPrivate since we can use mozilla::dom::Selection instead. MozReview-Commit-ID: 1Zheq3Hsepj
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozInlineSpellChecker.h
extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
extensions/spellcheck/src/mozInlineSpellWordUtil.h
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -45,28 +45,23 @@
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/dom/Selection.h"
 #include "mozInlineSpellWordUtil.h"
 #include "mozISpellI18NManager.h"
 #include "mozISpellI18NUtil.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsIDOMNode.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMNodeList.h"
 #include "nsGenericHTMLElement.h"
 #include "nsRange.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIRunnable.h"
 #include "nsISelection.h"
-#include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsITextServicesFilter.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
@@ -362,17 +357,17 @@ mozInlineSpellStatus::FinishNavigationEv
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
   }
   uint32_t oldAnchorOffset = mOldNavigationAnchorRange->StartOffset();
 
   // find the word on the old caret position, this is the one that we MAY need
   // to check
   RefPtr<nsRange> oldWord;
-  nsresult rv = aWordUtil.GetRangeForWord(oldAnchorNode->AsDOMNode(),
+  nsresult rv = aWordUtil.GetRangeForWord(oldAnchorNode,
                                           static_cast<int32_t>(oldAnchorOffset),
                                           getter_AddRefs(oldWord));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // aWordUtil.GetRangeForWord flushes pending notifications, check editor again.
   if (!mSpellChecker->mTextEditor) {
     return NS_ERROR_FAILURE; // editor is gone
   }
@@ -423,24 +418,24 @@ mozInlineSpellStatus::FillNoCheckRangeFr
 {
   ErrorResult err;
   nsCOMPtr<nsINode> anchorNode = mAnchorRange->GetStartContainer(err);
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
   }
 
   uint32_t anchorOffset = mAnchorRange->StartOffset();
-  return aWordUtil.GetRangeForWord(anchorNode->AsDOMNode(),
+  return aWordUtil.GetRangeForWord(anchorNode,
                                    static_cast<int32_t>(anchorOffset),
                                    getter_AddRefs(mNoCheckRange));
 }
 
 // mozInlineSpellStatus::GetDocument
 //
-//    Returns the nsIDOMDocument object for the document for the
+//    Returns the nsIDocument object for the document for the
 //    current spellchecker.
 
 nsIDocument*
 mozInlineSpellStatus::GetDocument() const
 {
   if (!mSpellChecker->mTextEditor) {
     return nullptr;
   }
@@ -932,17 +927,17 @@ mozInlineSpellChecker::GetMisspelledWord
 {
   if (NS_WARN_IF(!aNode)) {
     return NS_ERROR_INVALID_ARG;
   }
   RefPtr<Selection> spellCheckSelection = GetSpellCheckSelection();
   if (NS_WARN_IF(!spellCheckSelection)) {
     return NS_ERROR_FAILURE;
   }
-  return IsPointInSelection(spellCheckSelection, aNode, aOffset, newword);
+  return IsPointInSelection(*spellCheckSelection, aNode, aOffset, newword);
 }
 
 // mozInlineSpellChecker::ReplaceWord
 
 NS_IMETHODIMP
 mozInlineSpellChecker::ReplaceWord(nsIDOMNode *aNode, int32_t aOffset,
                                    const nsAString &newword)
 {
@@ -1045,45 +1040,43 @@ mozInlineSpellChecker::IgnoreWords(const
 
 void
 mozInlineSpellChecker::DidSplitNode(nsINode* aExistingRightNode,
                                     nsINode* aNewLeftNode)
 {
   if (!mIsListeningToEditActions) {
     return;
   }
-  nsIDOMNode* newLeftDOMNode =
-    aNewLeftNode ? aNewLeftNode->AsDOMNode() : nullptr;
-  SpellCheckBetweenNodes(newLeftDOMNode, 0, newLeftDOMNode, 0);
+  SpellCheckBetweenNodes(aNewLeftNode, 0, aNewLeftNode, 0);
 }
 
 void
 mozInlineSpellChecker::DidJoinNodes(nsINode& aLeftNode,
                                     nsINode& aRightNode)
 {
   if (!mIsListeningToEditActions) {
     return;
   }
-  SpellCheckBetweenNodes(aRightNode.AsDOMNode(), 0, aRightNode.AsDOMNode(), 0);
+  SpellCheckBetweenNodes(&aRightNode, 0, &aRightNode, 0);
 }
 
 // mozInlineSpellChecker::MakeSpellCheckRange
 //
 //    Given begin and end positions, this function constructs a range as
 //    required for ScheduleSpellCheck. If the start and end nodes are nullptr,
 //    then the entire range will be selected, and you can supply -1 as the
 //    offset to the end range to select all of that node.
 //
 //    If the resulting range would be empty, nullptr is put into *aRange and the
 //    function succeeds.
 
 nsresult
 mozInlineSpellChecker::MakeSpellCheckRange(
-    nsIDOMNode* aStartNode, int32_t aStartOffset,
-    nsIDOMNode* aEndNode, int32_t aEndOffset,
+    nsINode* aStartNode, int32_t aStartOffset,
+    nsINode* aEndNode, int32_t aEndOffset,
     nsRange** aRange)
 {
   nsresult rv;
   *aRange = nullptr;
 
   if (NS_WARN_IF(!mTextEditor)) {
     return NS_ERROR_FAILURE;
   }
@@ -1092,66 +1085,62 @@ mozInlineSpellChecker::MakeSpellCheckRan
   if (NS_WARN_IF(!doc)) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<nsRange> range = new nsRange(doc);
 
   // possibly use full range of the editor
   if (! aStartNode || ! aEndNode) {
-    nsCOMPtr<nsIDOMElement> domRootElement =
-      do_QueryInterface(mTextEditor->GetRoot());
+    Element* domRootElement = mTextEditor->GetRoot();
     if (NS_WARN_IF(!domRootElement)) {
       return NS_ERROR_FAILURE;
     }
     aStartNode = aEndNode = domRootElement;
     aStartOffset = 0;
     aEndOffset = -1;
   }
 
   if (aEndOffset == -1) {
     // It's hard to say whether it's better to just do nsINode::GetChildCount or
     // get the ChildNodes() and then its length.  The latter is faster if we
     // keep going through this code for the same nodes (because it caches the
     // length).  The former is faster if we keep getting different nodes here...
     //
     // Let's do the thing which can't end up with bad O(N^2) behavior.
-    nsCOMPtr<nsINode> endNode = do_QueryInterface(aEndNode);
-    aEndOffset = endNode->ChildNodes()->Length();
+    aEndOffset = aEndNode->ChildNodes()->Length();
   }
 
   // sometimes we are are requested to check an empty range (possibly an empty
   // document). This will result in assertions later.
   if (aStartNode == aEndNode && aStartOffset == aEndOffset)
     return NS_OK;
 
-  nsCOMPtr<nsINode> startNode = do_QueryInterface(aStartNode);
-  nsCOMPtr<nsINode> endNode = do_QueryInterface(aEndNode);
   if (aEndOffset) {
-    rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, aEndOffset);
+    rv = range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, aEndOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
     uint32_t endOffset;
-    endNode = nsRange::GetContainerAndOffsetAfter(endNode, &endOffset);
-    rv = range->SetStartAndEnd(startNode, aStartOffset, endNode, endOffset);
+    aEndNode = nsRange::GetContainerAndOffsetAfter(aEndNode, &endOffset);
+    rv = range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, endOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   range.swap(*aRange);
   return NS_OK;
 }
 
 nsresult
-mozInlineSpellChecker::SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
+mozInlineSpellChecker::SpellCheckBetweenNodes(nsINode* aStartNode,
                                               int32_t aStartOffset,
-                                              nsIDOMNode *aEndNode,
+                                              nsINode* aEndNode,
                                               int32_t aEndOffset)
 {
   RefPtr<nsRange> range;
   nsresult rv = MakeSpellCheckRange(aStartNode, aStartOffset,
                                     aEndNode, aEndOffset,
                                     getter_AddRefs(range));
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1626,29 +1615,28 @@ mozInlineSpellChecker::ResumeCheck(Uniqu
 //    Determines if a given (node,offset) point is inside the given
 //    selection. If so, the specific range of the selection that
 //    intersects is places in *aRange. (There may be multiple disjoint
 //    ranges in a selection.)
 //
 //    If there is no intersection, *aRange will be nullptr.
 
 nsresult
-mozInlineSpellChecker::IsPointInSelection(nsISelection *aSelection,
+mozInlineSpellChecker::IsPointInSelection(Selection& aSelection,
                                           nsIDOMNode *aNode,
                                           int32_t aOffset,
                                           nsIDOMRange **aRange)
 {
   *aRange = nullptr;
 
-  nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
-
   nsTArray<nsRange*> ranges;
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-  nsresult rv = privSel->GetRangesForIntervalArray(node, aOffset, node, aOffset,
-                                                   true, &ranges);
+  nsresult rv = aSelection.GetRangesForIntervalArray(node, aOffset,
+                                                     node, aOffset,
+                                                     true, &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (ranges.Length() == 0)
     return NS_OK; // no matches
 
   // there may be more than one range returned, and we don't know what do
   // do with that, so just get the first one
   NS_ADDREF(*aRange = ranges[0]);
--- a/extensions/spellcheck/src/mozInlineSpellChecker.h
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.h
@@ -57,18 +57,20 @@ public:
   RefPtr<mozInlineSpellChecker> mSpellChecker;
 
   // The total number of words checked in this sequence, using this tally tells
   // us when to stop. This count is preserved as we continue checking in new
   // messages.
   int32_t mWordCount;
 
   // what happened?
-  enum Operation { eOpChange,       // for SpellCheckAfterChange except deleteSelection
-                   eOpChangeDelete, // for SpellCheckAfterChange deleteSelection
+  enum Operation { eOpChange,       // for SpellCheckAfterEditorChange except
+                                    // deleteSelection
+                   eOpChangeDelete, // for SpellCheckAfterEditorChange with
+                                    // deleteSelection
                    eOpNavigation,   // for HandleNavigationEvent
                    eOpSelection,    // re-check all misspelled words
                    eOpResume };     // for resuming a previously started check
   Operation mOp;
 
   // Used for events where we have already computed the range to use. It can
   // also be nullptr in these cases where we need to check the entire range.
   RefPtr<nsRange> mRange;
@@ -196,57 +198,53 @@ public:
 
   nsresult OnBlur(mozilla::dom::Event* aEvent);
   nsresult OnMouseClick(mozilla::dom::Event* aMouseEvent);
   nsresult OnKeyPress(mozilla::dom::Event* aKeyEvent);
 
   mozInlineSpellChecker();
 
   // spell checks all of the words between two nodes
-  nsresult SpellCheckBetweenNodes(nsIDOMNode *aStartNode,
+  nsresult SpellCheckBetweenNodes(nsINode* aStartNode,
                                   int32_t aStartOffset,
-                                  nsIDOMNode *aEndNode,
+                                  nsINode* aEndNode,
                                   int32_t aEndOffset);
 
   // examines the dom node in question and returns true if the inline spell
   // checker should skip the node (i.e. the text is inside of a block quote
   // or an e-mail signature...)
   bool ShouldSpellCheckNode(mozilla::TextEditor* aTextEditor, nsINode *aNode);
 
-  nsresult SpellCheckAfterChange(nsIDOMNode* aCursorNode, int32_t aCursorOffset,
-                                 nsIDOMNode* aPreviousNode, int32_t aPreviousOffset,
-                                 nsISelection* aSpellCheckSelection);
-
   // spell check the text contained within aRange, potentially scheduling
   // another check in the future if the time threshold is reached
   nsresult ScheduleSpellCheck(mozilla::UniquePtr<mozInlineSpellStatus>&& aStatus);
 
   nsresult DoSpellCheckSelection(mozInlineSpellWordUtil& aWordUtil,
                                  mozilla::dom::Selection* aSpellCheckSelection);
   nsresult DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
                         mozilla::dom::Selection *aSpellCheckSelection,
                         const mozilla::UniquePtr<mozInlineSpellStatus>& aStatus,
                         bool* aDoneChecking);
 
   // helper routine to determine if a point is inside of the passed in selection.
-  nsresult IsPointInSelection(nsISelection *aSelection,
+  nsresult IsPointInSelection(mozilla::dom::Selection& aSelection,
                               nsIDOMNode *aNode,
                               int32_t aOffset,
                               nsIDOMRange **aRange);
 
   nsresult CleanupRangesInSelection(mozilla::dom::Selection *aSelection);
 
   nsresult RemoveRange(mozilla::dom::Selection *aSpellCheckSelection,
                        nsRange *aRange);
   nsresult AddRange(mozilla::dom::Selection *aSpellCheckSelection,
                     nsRange* aRange);
   bool     SpellCheckSelectionIsFull() { return mNumWordsInSpellSelection >= mMaxNumWordsInSpellSelection; }
 
-  nsresult MakeSpellCheckRange(nsIDOMNode* aStartNode, int32_t aStartOffset,
-                               nsIDOMNode* aEndNode, int32_t aEndOffset,
+  nsresult MakeSpellCheckRange(nsINode* aStartNode, int32_t aStartOffset,
+                               nsINode* aEndNode, int32_t aEndOffset,
                                nsRange** aRange);
 
   // DOM and editor event registration helper routines
   nsresult RegisterEventListeners();
   nsresult UnregisterEventListeners();
   nsresult HandleNavigationEvent(bool aForceWordSpellCheck, int32_t aNewPositionOffset = 0);
 
   already_AddRefed<mozilla::dom::Selection> GetSpellCheckSelection();
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -7,20 +7,17 @@
 
 #include "mozilla/BinarySearch.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/dom/Element.h"
 
 #include "nsDebug.h"
 #include "nsAtom.h"
 #include "nsComponentManagerUtils.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMRange.h"
 #include "nsIEditor.h"
-#include "nsIDOMNode.h"
 #include "nsUnicodeProperties.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIContent.h"
 #include "nsTextFragment.h"
 #include "nsRange.h"
 #include "nsContentUtils.h"
 #include "nsIFrame.h"
 #include <algorithm>
@@ -57,17 +54,16 @@ mozInlineSpellWordUtil::Init(TextEditor*
   if (NS_WARN_IF(!aTextEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   mDocument = aTextEditor->GetDocument();
   if (NS_WARN_IF(!mDocument)) {
     return NS_ERROR_FAILURE;
   }
-  mDOMDocument = do_QueryInterface(mDocument);
 
   // Find the root node for the editor. For contenteditable we'll need something
   // cleverer here.
   mRootNode = aTextEditor->GetRoot();
   if (NS_WARN_IF(!mRootNode)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
@@ -237,23 +233,22 @@ mozInlineSpellWordUtil::MakeNodeOffsetRa
   NodeOffset begin = MapSoftTextOffsetToDOMPosition(aWord.mSoftTextOffset, HINT_BEGIN);
   NodeOffset end = MapSoftTextOffsetToDOMPosition(aWord.EndOffset(), HINT_END);
   *aNodeOffsetRange = NodeOffsetRange(begin, end);
 }
 
 // mozInlineSpellWordUtil::GetRangeForWord
 
 nsresult
-mozInlineSpellWordUtil::GetRangeForWord(nsIDOMNode* aWordNode,
+mozInlineSpellWordUtil::GetRangeForWord(nsINode* aWordNode,
                                         int32_t aWordOffset,
                                         nsRange** aRange)
 {
   // Set our soft end and start
-  nsCOMPtr<nsINode> wordNode = do_QueryInterface(aWordNode);
-  NodeOffset pt = NodeOffset(wordNode, aWordOffset);
+  NodeOffset pt(aWordNode, aWordOffset);
 
   if (!mSoftTextValid || pt != mSoftBegin || pt != mSoftEnd) {
     InvalidateWords();
     mSoftBegin = mSoftEnd = pt;
     nsresult rv = EnsureWords();
     if (NS_FAILED(rv)) {
       return rv;
     }
@@ -330,18 +325,19 @@ mozInlineSpellWordUtil::GetNextWord(nsAS
 //
 //    Convenience function for creating a range over the current document.
 
 nsresult
 mozInlineSpellWordUtil::MakeRange(NodeOffset aBegin, NodeOffset aEnd,
                                   nsRange** aRange)
 {
   NS_ENSURE_ARG_POINTER(aBegin.mNode);
-  if (!mDOMDocument)
+  if (!mDocument) {
     return NS_ERROR_NOT_INITIALIZED;
+  }
 
   RefPtr<nsRange> range = new nsRange(aBegin.mNode);
   nsresult rv = range->SetStartAndEnd(aBegin.mNode, aBegin.mOffset,
                                       aEnd.mNode, aEnd.mOffset);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   range.forget(aRange);
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.h
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.h
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
 #ifndef mozInlineSpellWordUtil_h
 #define mozInlineSpellWordUtil_h
 
+#include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
-#include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 //#define DEBUG_SPELLCHECK
 
 class nsRange;
 class nsINode;
@@ -83,17 +83,17 @@ public:
  *    2. Call SetEnd to set where you want to stop spellchecking. We'll stop
  *       at the word boundary after that. If SetEnd is not called, we'll stop
  *       at the end of the document's root element.
  *    3. Call SetPosition to initialize the current position inside the
  *       previously given range.
  *    4. Call GetNextWord over and over until it returns false.
  */
 
-class mozInlineSpellWordUtil
+class MOZ_STACK_CLASS mozInlineSpellWordUtil
 {
 public:
   mozInlineSpellWordUtil()
     : mRootNode(nullptr),
       mSoftBegin(nullptr, 0), mSoftEnd(nullptr, 0),
       mNextWordIndex(-1), mSoftTextValid(false) {}
 
   nsresult Init(mozilla::TextEditor* aTextEditor);
@@ -108,17 +108,17 @@ public:
   // DOM range that exactly encloses that word's characters. The current
   // position will be at the end of the word. This will find the previous
   // word if the current position is space, so if you care that the point is
   // inside the word, you should check the range.
   //
   // THIS CHANGES THE CURRENT POSITION AND RANGE. It is designed to be called
   // before you actually generate the range you are interested in and iterate
   // the words in it.
-  nsresult GetRangeForWord(nsIDOMNode* aWordNode, int32_t aWordOffset,
+  nsresult GetRangeForWord(nsINode* aWordNode, int32_t aWordOffset,
                            nsRange** aRange);
 
   // Convenience functions, object must be initialized
   nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsRange** aRange);
 
   // Moves to the the next word in the range, and retrieves it's text and range.
   // An empty word and a nullptr range are returned when we are done checking.
   // aSkipChecking will be set if the word is "special" and shouldn't be
@@ -126,24 +126,22 @@ public:
   nsresult GetNextWord(nsAString& aText,
                        NodeOffsetRange* aNodeOffsetRange,
                        bool* aSkipChecking);
 
   // Call to normalize some punctuation. This function takes an autostring
   // so we can access characters directly.
   static void NormalizeWord(nsAString& aWord);
 
-  nsIDOMDocument* GetDOMDocument() const { return mDOMDocument; }
   nsIDocument* GetDocument() const { return mDocument; }
   nsINode* GetRootNode() { return mRootNode; }
 
 private:
 
   // cached stuff for the editor, set by Init
-  nsCOMPtr<nsIDOMDocument> mDOMDocument;
   nsCOMPtr<nsIDocument>         mDocument;
 
   // range to check, see SetPosition and SetEnd
   nsINode*    mRootNode;
   NodeOffset  mSoftBegin;
   NodeOffset  mSoftEnd;
 
   // DOM text covering the soft range, with newlines added at block boundaries