Bug 1430982 - part 1: Make nsTextServicesDocument store editor with RefPtr<TextEditor> rather than nsWeakPtr r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 18 Jan 2018 14:33:31 +0900
changeset 722218 42293e1f61ab6edcd015d7cf690658315cbec2c1
parent 722217 903a1b79c50af3c4d090d5b4ab3309469aa843d9
child 722219 8d7a3b98ed42e41db2931768d9071a084ea32d13
push id96099
push usermasayuki@d-toybox.com
push dateThu, 18 Jan 2018 17:37:00 +0000
reviewersm_kato
bugs1430982
milestone59.0a1
Bug 1430982 - part 1: Make nsTextServicesDocument store editor with RefPtr<TextEditor> rather than nsWeakPtr r?m_kato nsTextServicesDocument stores editor with nsWeakPtr for avoiding circular reference. However, both TextEditor and nsTextServicesDocument are cycle collectable. So, we don't need to worry about the issue and we can simply make it store with RefPtr<TextEditor>. Then, we can make EditorBase and nsTextServicesDocument access each other directly. MozReview-Commit-ID: 9I4U8ivFlov
editor/txtsvc/nsTextServicesDocument.cpp
editor/txtsvc/nsTextServicesDocument.h
--- a/editor/txtsvc/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/nsTextServicesDocument.cpp
@@ -3,16 +3,17 @@
  * 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 <stddef.h>                     // for nullptr
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/dom/Selection.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
+#include "mozilla/TextEditor.h"         // for TextEditor
 #include "nsAString.h"                  // for nsAString::Length, etc
 #include "nsContentUtils.h"             // for nsContentUtils
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
 #include "nsDependentSubstring.h"       // for Substring
 #include "nsError.h"                    // for NS_OK, NS_ERROR_FAILURE, etc
 #include "nsFilteredContentIterator.h"  // for nsFilteredContentIterator
 #include "nsIContent.h"                 // for nsIContent, etc
 #include "nsIContentIterator.h"         // for nsIContentIterator
@@ -93,16 +94,17 @@ NS_INTERFACE_MAP_BEGIN(nsTextServicesDoc
   NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITextServicesDocument)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsTextServicesDocument)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION(nsTextServicesDocument,
                          mDOMDocument,
                          mSelCon,
+                         mTextEditor,
                          mIterator,
                          mPrevTextBlock,
                          mNextTextBlock,
                          mExtent,
                          mTxtSvcFilter)
 
 NS_IMETHODIMP
 nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
@@ -163,17 +165,17 @@ nsTextServicesDocument::InitWithEditor(n
     rv = FirstBlock();
 
     if (NS_FAILED(rv)) {
       UNLOCK_DOC(this);
       return rv;
     }
   }
 
-  mEditor = do_GetWeakReference(aEditor);
+  mTextEditor = aEditor->AsTextEditor();
 
   rv = aEditor->AddEditActionListener(this);
 
   UNLOCK_DOC(this);
 
   return rv;
 }
 
@@ -973,36 +975,26 @@ nsTextServicesDocument::ScrollSelectionI
   UNLOCK_DOC(this);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsTextServicesDocument::DeleteSelection()
 {
-  // We don't allow deletion during a collapsed selection!
-  nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
-  NS_ASSERTION(editor, "DeleteSelection called without an editor present!");
-  NS_ASSERTION(SelectionIsValid(), "DeleteSelection called without a valid selection!");
-
-  if (!editor || !SelectionIsValid()) {
+  if (NS_WARN_IF(!mTextEditor) || NS_WARN_IF(!SelectionIsValid())) {
     return NS_ERROR_FAILURE;
   }
+
   if (SelectionIsCollapsed()) {
     return NS_OK;
   }
 
   LOCK_DOC(this);
 
-  //**** KDEBUG ****
-  // printf("\n---- Before Delete\n");
-  // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
-  // PrintOffsetTable();
-  //**** KDEBUG ****
-
   // If we have an mExtent, save off its current set of
   // end points so we can compare them against mExtent's
   // set after the deletion of the content.
 
   nsCOMPtr<nsINode> origStartNode, origEndNode;
   int32_t origStartOffset = 0, origEndOffset = 0;
 
   if (mExtent) {
@@ -1064,22 +1056,16 @@ nsTextServicesDocument::DeleteSelection(
 
       if (selLength > 0 && mSelStartIndex < mSelEndIndex) {
         // The entire entry is contained in the selection. Mark the
         // entry invalid.
         entry->mIsValid = false;
       }
     }
 
-  //**** KDEBUG ****
-  // printf("\n---- Middle Delete\n");
-  // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
-  // PrintOffsetTable();
-  //**** KDEBUG ****
-
     if (i == mSelEndIndex) {
       if (entry->mIsInsertedText) {
         // Inserted text offset entries have no width when
         // talking in terms of string offsets! If the end
         // of the selection is in an inserted text offset entry,
         // the selection includes the entire entry!
 
         entry->mIsValid = false;
@@ -1125,20 +1111,19 @@ nsTextServicesDocument::DeleteSelection(
     }
   }
 
   // Make sure mIterator always points to something valid!
 
   AdjustContentIterator();
 
   // Now delete the actual content!
-
+  RefPtr<TextEditor> textEditor = mTextEditor;
   nsresult rv =
-    editor->DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
-
+    textEditor->DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
   if (NS_FAILED(rv)) {
     UNLOCK_DOC(this);
     return rv;
   }
 
   // Now that we've actually deleted the selected content,
   // check to see if our mExtent has changed, if so, then
   // we have to create a new content iterator!
@@ -1249,25 +1234,24 @@ nsTextServicesDocument::DeleteSelection(
   UNLOCK_DOC(this);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsTextServicesDocument::InsertText(const nsString *aText)
 {
-  nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
-  NS_ASSERTION(editor, "InsertText called without an editor present!");
-
-  if (!editor || !SelectionIsValid()) {
+  if (NS_WARN_IF(!aText)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  if (NS_WARN_IF(!mTextEditor) || NS_WARN_IF(!SelectionIsValid())) {
     return NS_ERROR_FAILURE;
   }
 
-  NS_ENSURE_TRUE(aText, NS_ERROR_NULL_POINTER);
-
   // If the selection is not collapsed, we need to save
   // off the selection offsets so we can restore the
   // selection and delete the selected content after we've
   // inserted the new text. This is necessary to try and
   // retain as much of the original style of the content
   // being deleted.
 
   bool collapsedSelection = SelectionIsCollapsed();
@@ -1281,40 +1265,30 @@ nsTextServicesDocument::InsertText(const
     nsresult rv = SetSelection(mSelStartOffset, 0);
 
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
 
   LOCK_DOC(this);
 
-  nsresult rv = editor->BeginTransaction();
-
+  RefPtr<TextEditor> textEditor = mTextEditor;
+  nsresult rv = textEditor->BeginTransaction();
   if (NS_FAILED(rv)) {
     UNLOCK_DOC(this);
     return rv;
   }
 
-  nsCOMPtr<nsIPlaintextEditor> textEditor (do_QueryInterface(editor, &rv));
-  if (textEditor) {
-    rv = textEditor->InsertText(*aText);
-  }
-
+  rv = textEditor->InsertText(*aText);
   if (NS_FAILED(rv)) {
-    editor->EndTransaction();
+    textEditor->EndTransaction();
     UNLOCK_DOC(this);
     return rv;
   }
 
-  //**** KDEBUG ****
-  // printf("\n---- Before Insert\n");
-  // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
-  // PrintOffsetTable();
-  //**** KDEBUG ****
-
   int32_t strLength = aText->Length();
 
   OffsetEntry *itEntry;
   OffsetEntry *entry = mOffsetTable[mSelStartIndex];
   void *node         = entry->mNode;
 
   NS_ASSERTION((entry->mIsValid), "Invalid insertion point!");
 
@@ -1326,26 +1300,26 @@ nsTextServicesDocument::InsertText(const
       entry->mLength += strLength;
     } else {
       // Insert an inserted text offset entry before the current
       // entry!
 
       itEntry = new OffsetEntry(entry->mNode, entry->mStrOffset, strLength);
 
       if (!itEntry) {
-        editor->EndTransaction();
+        textEditor->EndTransaction();
         UNLOCK_DOC(this);
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
       itEntry->mIsInsertedText = true;
       itEntry->mNodeOffset = entry->mNodeOffset;
 
       if (!mOffsetTable.InsertElementAt(mSelStartIndex, itEntry)) {
-        editor->EndTransaction();
+        textEditor->EndTransaction();
         UNLOCK_DOC(this);
         return NS_ERROR_FAILURE;
       }
     }
   } else if (entry->mStrOffset + entry->mLength == mSelStartOffset) {
     // We are inserting text at the end of the current offset entry.
     // Look at the next valid entry in the table. If it's an inserted
     // text entry, add to its length and adjust its node offset. If
@@ -1354,17 +1328,17 @@ nsTextServicesDocument::InsertText(const
     // XXX Rename this!
     uint32_t i = mSelStartIndex + 1;
     itEntry = 0;
 
     if (mOffsetTable.Length() > i) {
       itEntry = mOffsetTable[i];
 
       if (!itEntry) {
-        editor->EndTransaction();
+        textEditor->EndTransaction();
         UNLOCK_DOC(this);
         return NS_ERROR_FAILURE;
       }
 
       // Check if the entry is a match. If it isn't, set
       // iEntry to zero.
 
       if (!itEntry->mIsInsertedText || itEntry->mStrOffset != mSelStartOffset) {
@@ -1374,17 +1348,17 @@ nsTextServicesDocument::InsertText(const
 
     if (!itEntry) {
       // We didn't find an inserted text offset entry, so
       // create one.
 
       itEntry = new OffsetEntry(entry->mNode, mSelStartOffset, 0);
 
       if (!itEntry) {
-        editor->EndTransaction();
+        textEditor->EndTransaction();
         UNLOCK_DOC(this);
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
       itEntry->mNodeOffset = entry->mNodeOffset + entry->mLength;
       itEntry->mIsInsertedText = true;
 
       if (!mOffsetTable.InsertElementAt(i, itEntry)) {
@@ -1399,58 +1373,58 @@ nsTextServicesDocument::InsertText(const
 
     itEntry->mLength += strLength;
 
     mSelStartIndex = mSelEndIndex = i;
 
     RefPtr<Selection> selection =
       mSelCon->GetDOMSelection(nsISelectionController::SELECTION_NORMAL);
     if (NS_WARN_IF(!selection)) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return rv;
     }
 
     rv = selection->Collapse(itEntry->mNode,
                              itEntry->mNodeOffset + itEntry->mLength);
 
     if (NS_FAILED(rv)) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return rv;
     }
   } else if (entry->mStrOffset + entry->mLength > mSelStartOffset) {
     // We are inserting text into the middle of the current offset entry.
     // split the current entry into two parts, then insert an inserted text
     // entry between them!
 
     // XXX Rename this!
     uint32_t i = entry->mLength - (mSelStartOffset - entry->mStrOffset);
 
     rv = SplitOffsetEntry(mSelStartIndex, i);
 
     if (NS_FAILED(rv)) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return rv;
     }
 
     itEntry = new OffsetEntry(entry->mNode, mSelStartOffset, strLength);
 
     if (!itEntry) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     itEntry->mIsInsertedText = true;
     itEntry->mNodeOffset     = entry->mNodeOffset + entry->mLength;
 
     if (!mOffsetTable.InsertElementAt(mSelStartIndex + 1, itEntry)) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return NS_ERROR_FAILURE;
     }
 
     mSelEndIndex = ++mSelStartIndex;
   }
 
   // We've just finished inserting an inserted text offset entry.
@@ -1472,31 +1446,31 @@ nsTextServicesDocument::InsertText(const
   // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
   // PrintOffsetTable();
   //**** KDEBUG ****
 
   if (!collapsedSelection) {
     rv = SetSelection(savedSelOffset, savedSelLength);
 
     if (NS_FAILED(rv)) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return rv;
     }
 
     rv = DeleteSelection();
 
     if (NS_FAILED(rv)) {
-      editor->EndTransaction();
+      textEditor->EndTransaction();
       UNLOCK_DOC(this);
       return rv;
     }
   }
 
-  rv = editor->EndTransaction();
+  rv = textEditor->EndTransaction();
 
   UNLOCK_DOC(this);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsTextServicesDocument::DidInsertNode(nsIDOMNode* aNode,
--- a/editor/txtsvc/nsTextServicesDocument.h
+++ b/editor/txtsvc/nsTextServicesDocument.h
@@ -6,48 +6,51 @@
 #ifndef nsTextServicesDocument_h__
 #define nsTextServicesDocument_h__
 
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIEditActionListener.h"
 #include "nsISupportsImpl.h"
 #include "nsITextServicesDocument.h"
-#include "nsIWeakReferenceUtils.h"
 #include "nsStringFwd.h"
 #include "nsTArray.h"
 #include "nscore.h"
 
 class OffsetEntry;
 class nsIContent;
 class nsIContentIterator;
 class nsIDOMCharacterData;
 class nsIDOMDocument;
 class nsIDOMNode;
 class nsIEditor;
 class nsISelection;
 class nsISelectionController;
 class nsITextServicesFilter;
 
+namespace mozilla {
+class TextEditor;
+} // namespace mozilla
+
 /** implementation of a text services object.
  *
  */
 class nsTextServicesDocument final : public nsITextServicesDocument,
                                      public nsIEditActionListener
 {
 private:
   typedef enum { eIsDone=0,        // No iterator (I), or iterator doesn't point to anything valid.
                  eValid,           // I points to first text node (TN) in current block (CB).
                  ePrev,            // No TN in CB, I points to first TN in prev block.
                  eNext             // No TN in CB, I points to first TN in next block.
   } TSDIteratorStatus;
 
   nsCOMPtr<nsIDOMDocument>        mDOMDocument;
   nsCOMPtr<nsISelectionController>mSelCon;
-  nsWeakPtr                       mEditor;  // avoid a cycle with the spell checker and editor
+  RefPtr<mozilla::TextEditor>     mTextEditor;
   nsCOMPtr<nsIContentIterator>    mIterator;
   TSDIteratorStatus               mIteratorStatus;
   nsCOMPtr<nsIContent>            mPrevTextBlock;
   nsCOMPtr<nsIContent>            mNextTextBlock;
   nsTArray<OffsetEntry*>          mOffsetTable;
 
   int32_t                         mSelStartIndex;
   int32_t                         mSelStartOffset;