Bug 1385392 - Avoid needlessly looking up the selection twice when DoTransaction() is called from TextEditRules::WillSetText(); r=masayuki
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 28 Jul 2017 14:49:58 -0400
changeset 420783 0ae424f348a38ef1d2f052b49f2822662300c129
parent 420782 780d578d1f74bf2d52a605890b322db55873464b
child 420784 423b51b215196a7da2b81b74cee28c836597dabc
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1385392
milestone56.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 1385392 - Avoid needlessly looking up the selection twice when DoTransaction() is called from TextEditRules::WillSetText(); r=masayuki
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/TextEditRules.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -685,16 +685,22 @@ EditorBase::GetSelection(SelectionType a
   }
 
   return sel->AsSelection();
 }
 
 NS_IMETHODIMP
 EditorBase::DoTransaction(nsITransaction* aTxn)
 {
+  return DoTransaction(nullptr, aTxn);
+}
+
+nsresult
+EditorBase::DoTransaction(Selection* aSelection, nsITransaction* aTxn)
+{
   if (mPlaceholderBatch && !mPlaceholderTransaction) {
     mPlaceholderTransaction =
       new PlaceholderTransaction(*this, mPlaceholderName, Move(mSelState));
 
     // We will recurse, but will not hit this case in the nested call
     DoTransaction(mPlaceholderTransaction);
 
     if (mTxnMgr) {
@@ -731,17 +737,17 @@ EditorBase::DoTransaction(nsITransaction
     // XXX: selection listeners have access to accurate frame data?
     // XXX:
     // XXX: Note that if we did add Begin/EndUpdateViewBatch() calls
     // XXX: we will need to make sure that they are disabled during
     // XXX: the init of the editor for text widgets to avoid layout
     // XXX: re-entry during initial reflow. - kin
 
     // get the selection and start a batch change
-    RefPtr<Selection> selection = GetSelection();
+    RefPtr<Selection> selection = aSelection ? aSelection : GetSelection();
     NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
     selection->StartBatchChanges();
 
     nsresult rv;
     if (mTxnMgr) {
       RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
       rv = txnMgr->DoTransaction(aTxn);
@@ -2709,17 +2715,18 @@ EditorBase::NotifyDocumentListeners(
     default:
       NS_NOTREACHED("Unknown notification");
   }
 
   return rv;
 }
 
 nsresult
-EditorBase::SetTextImpl(const nsAString& aString, Text& aCharData)
+EditorBase::SetTextImpl(Selection& aSelection, const nsAString& aString,
+                        Text& aCharData)
 {
   RefPtr<SetTextTransaction> transaction =
     CreateTxnForSetText(aString, aCharData);
   if (NS_WARN_IF(!transaction)) {
     return NS_ERROR_FAILURE;
   }
 
   uint32_t length = aCharData.Length();
@@ -2739,17 +2746,17 @@ EditorBase::SetTextImpl(const nsAString&
       if (!aString.IsEmpty()) {
         listener->WillInsertText(
           static_cast<nsIDOMCharacterData*>(aCharData.AsDOMNode()), 0,
           aString);
       }
     }
   }
 
-  nsresult rv = DoTransaction(transaction);
+  nsresult rv = DoTransaction(&aSelection, transaction);
 
   // Let listeners know what happened
   {
     AutoActionListenerArray listeners(mActionListeners);
     for (auto& listener : listeners) {
       if (length) {
         listener->DidDeleteText(
           static_cast<nsIDOMCharacterData*>(aCharData.AsDOMNode()), 0,
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -274,17 +274,18 @@ public:
   virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
                                   nsCOMPtr<nsINode>* aInOutNode,
                                   int32_t* aInOutOffset,
                                   nsIDocument* aDoc);
   nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
                                       Text& aTextNode, int32_t aOffset,
                                       bool aSuppressIME = false);
 
-  nsresult SetTextImpl(const nsAString& aString,
+  nsresult SetTextImpl(Selection& aSelection,
+                       const nsAString& aString,
                        Text& aTextNode);
 
   NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
                                  EStripWrappers aStripWrappers);
 
   already_AddRefed<Element> DeleteSelectionAndCreateElement(nsIAtom& aTag);
 
   /**
@@ -490,16 +491,20 @@ protected:
 
   void DoAfterUndoTransaction();
 
   /**
    * Called after a transaction is redone successfully.
    */
   void DoAfterRedoTransaction();
 
+  // Note that aSelection is optional and can be nullptr.
+  nsresult DoTransaction(Selection* aSelection,
+                         nsITransaction* aTxn);
+
   enum TDocumentListenerNotification
   {
     eDocumentCreated,
     eDocumentToBeDestroyed,
     eDocumentStateChanged
   };
 
   /**
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -898,17 +898,18 @@ TextEditRules::WillSetText(Selection& aS
 
   nsINode* curNode = rootElement->GetFirstChild();
   if (NS_WARN_IF(!EditorBase::IsTextNode(curNode))) {
     return NS_OK;
   }
 
   // Even if empty text, we don't remove text node and set empty text
   // for performance
-  nsresult rv = textEditor->SetTextImpl(tString, *curNode->GetAsText());
+  nsresult rv = textEditor->SetTextImpl(aSelection, tString,
+                                        *curNode->GetAsText());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   *aHandled = true;
 
   ASSERT_PASSWORD_LENGTHS_EQUAL();