Bug 1574852 - part 95: Move `HTMLEditRules::AfterEditInner()` to `HTMLEditor` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 11 Sep 2019 10:39:38 +0000
changeset 492649 f59ebdb53f9ac6a62759c4588904cbe7bc76dc5c
parent 492648 d41ae182072c6cb884ab09f8e39368151f4f6e38
child 492650 30509dab7f702a13cb37d8244f8f49f33ac4d68e
push id95049
push usermasayuki@d-toybox.com
push dateWed, 11 Sep 2019 10:54:24 +0000
treeherderautoland@f59ebdb53f9a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1574852
milestone71.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 1574852 - part 95: Move `HTMLEditRules::AfterEditInner()` to `HTMLEditor` r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D44799
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -392,17 +392,18 @@ nsresult HTMLEditRules::AfterEdit() {
 #ifdef DEBUG
   MOZ_ASSERT(mIsHandling);
   mIsHandling = false;
 #endif  // #ifdef DEBUG
 
   AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // Do all the tricky stuff
-  nsresult rv = AfterEditInner();
+  nsresult rv = MOZ_KnownLive(HTMLEditorRef())
+                    .OnEndHandlingTopLevelEditSubActionInternal();
   // Perhaps, we need to do the following jobs even if the editor has been
   // destroyed since they adjust some states of HTML document but don't
   // modify the DOM tree nor Selection.
 
   // Free up selectionState range item
   HTMLEditorRef().RangeUpdaterRef().DropRangeItem(
       HTMLEditorRef().TopLevelEditSubActionDataRef().mSelectedRange);
 
@@ -414,313 +415,284 @@ nsresult HTMLEditRules::AfterEdit() {
     if (NS_WARN_IF(!doc)) {
       return NS_ERROR_FAILURE;
     }
     if (doc->GetEditingState() == Document::EditingState::eContentEditable) {
       doc->ChangeContentEditableCount(nullptr, -1);
     }
   }
 
-  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AfterEditInner() failed");
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "OnEndHandlingTopLevelEditSubActionInternal() failed");
   return rv;
 }
 
-nsresult HTMLEditRules::AfterEditInner() {
-  MOZ_ASSERT(IsEditorDataAvailable());
-
-  nsresult rv =
-      MOZ_KnownLive(HTMLEditorRef()).EnsureSelectionInBodyOrDocumentElement();
+nsresult HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal() {
+  MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable());
+
+  nsresult rv = EnsureSelectionInBodyOrDocumentElement();
   if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(
       NS_SUCCEEDED(rv),
       "EnsureSelectionInBodyOrDocumentElement() failed, but ignored");
-  switch (HTMLEditorRef().GetTopLevelEditSubAction()) {
+
+  switch (GetTopLevelEditSubAction()) {
     case EditSubAction::eReplaceHeadWithHTMLSource:
     case EditSubAction::eCreatePaddingBRElementForEmptyEditor:
       return NS_OK;
     default:
       break;
   }
 
-  if (HTMLEditorRef()
-          .TopLevelEditSubActionDataRef()
-          .mChangedRange->IsPositioned() &&
-      HTMLEditorRef().GetTopLevelEditSubAction() != EditSubAction::eUndo &&
-      HTMLEditorRef().GetTopLevelEditSubAction() != EditSubAction::eRedo) {
+  if (TopLevelEditSubActionDataRef().mChangedRange->IsPositioned() &&
+      GetTopLevelEditSubAction() != EditSubAction::eUndo &&
+      GetTopLevelEditSubAction() != EditSubAction::eRedo) {
     // don't let any txns in here move the selection around behind our back.
     // Note that this won't prevent explicit selection setting from working.
-    AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
-
-    switch (HTMLEditorRef().GetTopLevelEditSubAction()) {
+    AutoTransactionsConserveSelection dontChangeMySelection(*this);
+
+    switch (GetTopLevelEditSubAction()) {
       case EditSubAction::eInsertText:
       case EditSubAction::eInsertTextComingFromIME:
       case EditSubAction::eInsertLineBreak:
       case EditSubAction::eInsertParagraphSeparator:
       case EditSubAction::eDeleteText: {
         // XXX We should investigate whether this is really needed because it
         //     seems that the following code does not handle the whitespaces.
         RefPtr<nsRange> extendedChangedRange =
-            HTMLEditorRef().CreateRangeIncludingAdjuscentWhiteSpaces(
-                *HTMLEditorRef().TopLevelEditSubActionDataRef().mChangedRange);
+            CreateRangeIncludingAdjuscentWhiteSpaces(
+                *TopLevelEditSubActionDataRef().mChangedRange);
         if (extendedChangedRange) {
           MOZ_ASSERT(extendedChangedRange->IsPositioned());
           // Use extended range temporarily.
-          HTMLEditorRef().TopLevelEditSubActionDataRef().mChangedRange =
+          TopLevelEditSubActionDataRef().mChangedRange =
               std::move(extendedChangedRange);
         }
         break;
       }
       default: {
         RefPtr<nsRange> extendedChangedRange =
-            HTMLEditorRef().CreateRangeExtendedToHardLineStartAndEnd(
-                *HTMLEditorRef().TopLevelEditSubActionDataRef().mChangedRange,
-                HTMLEditorRef().GetTopLevelEditSubAction());
+            CreateRangeExtendedToHardLineStartAndEnd(
+                *TopLevelEditSubActionDataRef().mChangedRange,
+                GetTopLevelEditSubAction());
         if (extendedChangedRange) {
           MOZ_ASSERT(extendedChangedRange->IsPositioned());
           // Use extended range temporarily.
-          HTMLEditorRef().TopLevelEditSubActionDataRef().mChangedRange =
+          TopLevelEditSubActionDataRef().mChangedRange =
               std::move(extendedChangedRange);
         }
         break;
       }
     }
 
     // if we did a ranged deletion or handling backspace key, make sure we have
     // a place to put caret.
     // Note we only want to do this if the overall operation was deletion,
     // not if deletion was done along the way for
     // EditSubAction::eInsertHTMLSource, EditSubAction::eInsertText, etc.
     // That's why this is here rather than DidDeleteSelection().
     // However, we shouldn't insert <br> elements if we've already removed
     // empty block parents because users may want to disappear the line by
     // the deletion.
-    if (HTMLEditorRef().GetTopLevelEditSubAction() ==
-            EditSubAction::eDeleteSelectedContent &&
-        HTMLEditorRef()
-            .TopLevelEditSubActionDataRef()
-            .mDidDeleteNonCollapsedRange &&
-        !HTMLEditorRef()
-             .TopLevelEditSubActionDataRef()
-             .mDidDeleteEmptyParentBlocks) {
-      nsresult rv =
-          MOZ_KnownLive(HTMLEditorRef())
-              .InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
-                  EditorBase::GetStartPoint(*SelectionRefPtr()));
+    if (GetTopLevelEditSubAction() == EditSubAction::eDeleteSelectedContent &&
+        TopLevelEditSubActionDataRef().mDidDeleteNonCollapsedRange &&
+        !TopLevelEditSubActionDataRef().mDidDeleteEmptyParentBlocks) {
+      nsresult rv = InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
+          EditorBase::GetStartPoint(*SelectionRefPtr()));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // add in any needed <br>s, and remove any unneeded ones.
-    nsresult rv = MOZ_KnownLive(HTMLEditorRef())
-                      .InsertBRElementToEmptyListItemsAndTableCellsInRange(
-                          HTMLEditorRef()
-                              .TopLevelEditSubActionDataRef()
-                              .mChangedRange->StartRef()
-                              .AsRaw(),
-                          HTMLEditorRef()
-                              .TopLevelEditSubActionDataRef()
-                              .mChangedRange->EndRef()
-                              .AsRaw());
+    nsresult rv = InsertBRElementToEmptyListItemsAndTableCellsInRange(
+        TopLevelEditSubActionDataRef().mChangedRange->StartRef().AsRaw(),
+        TopLevelEditSubActionDataRef().mChangedRange->EndRef().AsRaw());
     if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
-    NS_WARNING_ASSERTION(
-        NS_SUCCEEDED(rv),
-        "Failed to insert <br> elements to empty list items and table cells");
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "InsertBRElementToEmptyListItemsAndTableCellsInRange()"
+                         " failed, but ignored");
 
     // merge any adjacent text nodes
-    switch (HTMLEditorRef().GetTopLevelEditSubAction()) {
+    switch (GetTopLevelEditSubAction()) {
       case EditSubAction::eInsertText:
       case EditSubAction::eInsertTextComingFromIME:
         break;
       default: {
-        nsresult rv = MOZ_KnownLive(HTMLEditorRef())
-                          .CollapseAdjacentTextNodes(
-                              MOZ_KnownLive(HTMLEditorRef()
-                                                .TopLevelEditSubActionDataRef()
-                                                .mChangedRange));
-        if (NS_WARN_IF(!CanHandleEditAction())) {
+        nsresult rv = CollapseAdjacentTextNodes(
+            MOZ_KnownLive(TopLevelEditSubActionDataRef().mChangedRange));
+        if (NS_WARN_IF(Destroyed())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         break;
       }
     }
 
     // clean up any empty nodes in the selection
-    rv =
-        MOZ_KnownLive(HTMLEditorRef())
-            .RemoveEmptyNodesIn(MOZ_KnownLive(
-                *HTMLEditorRef().TopLevelEditSubActionDataRef().mChangedRange));
+    rv = RemoveEmptyNodesIn(
+        MOZ_KnownLive(*TopLevelEditSubActionDataRef().mChangedRange));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // attempt to transform any unneeded nbsp's into spaces after doing various
     // operations
-    switch (HTMLEditorRef().GetTopLevelEditSubAction()) {
+    switch (GetTopLevelEditSubAction()) {
       case EditSubAction::eInsertText:
       case EditSubAction::eInsertTextComingFromIME:
       case EditSubAction::eDeleteSelectedContent:
       case EditSubAction::eInsertLineBreak:
       case EditSubAction::eInsertParagraphSeparator:
       case EditSubAction::ePasteHTMLContent:
       case EditSubAction::eInsertHTMLSource: {
         // TODO: Temporarily, WSRunObject replaces ASCII whitespaces with NPSPs
         //       and then, we'll replace them with ASCII whitespaces here.  We
         //       should avoid this overwriting things as far as possible because
         //       replacing characters in text nodes causes running mutation
         //       event listeners which are really expensive.
         // Adjust end of composition string if there is composition string.
-        EditorRawDOMPoint pointToAdjust(
-            HTMLEditorRef().GetCompositionEndPoint());
+        EditorRawDOMPoint pointToAdjust(GetCompositionEndPoint());
         if (!pointToAdjust.IsSet()) {
           // Otherwise, adjust current selection start point.
           pointToAdjust = EditorBase::GetStartPoint(*SelectionRefPtr());
           if (NS_WARN_IF(!pointToAdjust.IsSet())) {
             return NS_ERROR_FAILURE;
           }
         }
-        rv = WSRunObject(&HTMLEditorRef(), pointToAdjust).AdjustWhitespace();
-        if (NS_WARN_IF(!CanHandleEditAction())) {
+        rv = WSRunObject(this, pointToAdjust).AdjustWhitespace();
+        if (NS_WARN_IF(Destroyed())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
         // also do this for original selection endpoints.
-        if (NS_WARN_IF(!HTMLEditorRef()
-                            .TopLevelEditSubActionDataRef()
-                            .mSelectedRange->IsSet())) {
+        // XXX Hmm, if `AdjustWhitespace()` runs mutation event listener
+        //     and that causes changing `mSelectedRange`, what we should do?
+        if (NS_WARN_IF(
+                !TopLevelEditSubActionDataRef().mSelectedRange->IsSet())) {
           return NS_ERROR_FAILURE;
         }
-        WSRunObject(&HTMLEditorRef(), HTMLEditorRef()
-                                          .TopLevelEditSubActionDataRef()
-                                          .mSelectedRange->StartRawPoint())
+        WSRunObject(
+            this,
+            TopLevelEditSubActionDataRef().mSelectedRange->StartRawPoint())
             .AdjustWhitespace();
+        if (NS_WARN_IF(Destroyed())) {
+          return NS_ERROR_EDITOR_DESTROYED;
+        }
         // we only need to handle old selection endpoint if it was different
         // from start
-        if (HTMLEditorRef()
-                .TopLevelEditSubActionDataRef()
-                .mSelectedRange->IsCollapsed()) {
-          WSRunObject(&HTMLEditorRef(), HTMLEditorRef()
-                                            .TopLevelEditSubActionDataRef()
-                                            .mSelectedRange->EndRawPoint())
+        if (TopLevelEditSubActionDataRef().mSelectedRange->IsCollapsed()) {
+          WSRunObject(
+              this,
+              TopLevelEditSubActionDataRef().mSelectedRange->EndRawPoint())
               .AdjustWhitespace();
+          if (NS_WARN_IF(Destroyed())) {
+            return NS_ERROR_EDITOR_DESTROYED;
+          }
         }
         break;
       }
       default:
         break;
     }
 
     // If we created a new block, make sure caret is in it.
-    if (HTMLEditorRef().TopLevelEditSubActionDataRef().mNewBlockElement &&
+    if (TopLevelEditSubActionDataRef().mNewBlockElement &&
         SelectionRefPtr()->IsCollapsed()) {
-      nsresult rv = MOZ_KnownLive(HTMLEditorRef())
-                        .EnsureCaretInBlockElement(
-                            MOZ_KnownLive(*HTMLEditorRef()
-                                               .TopLevelEditSubActionDataRef()
-                                               .mNewBlockElement));
+      nsresult rv = EnsureCaretInBlockElement(
+          MOZ_KnownLive(*TopLevelEditSubActionDataRef().mNewBlockElement));
       if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(
           NS_SUCCEEDED(rv),
           "EnsureSelectionInBlockElement() failed, but ignored");
     }
 
     // Adjust selection for insert text, html paste, and delete actions if
     // we haven't removed new empty blocks.  Note that if empty block parents
     // are removed, Selection should've been adjusted by the method which
     // did it.
-    if (!HTMLEditorRef()
-             .TopLevelEditSubActionDataRef()
-             .mDidDeleteEmptyParentBlocks &&
+    if (!TopLevelEditSubActionDataRef().mDidDeleteEmptyParentBlocks &&
         SelectionRefPtr()->IsCollapsed()) {
-      switch (HTMLEditorRef().GetTopLevelEditSubAction()) {
+      switch (GetTopLevelEditSubAction()) {
         case EditSubAction::eInsertText:
         case EditSubAction::eInsertTextComingFromIME:
         case EditSubAction::eDeleteSelectedContent:
         case EditSubAction::eInsertLineBreak:
         case EditSubAction::eInsertParagraphSeparator:
         case EditSubAction::ePasteHTMLContent:
         case EditSubAction::eInsertHTMLSource:
           // XXX AdjustCaretPositionAndEnsurePaddingBRElement() intentionally
           //     does not create padding `<br>` element for empty editor.
           //     Investigate which is better that whether this should does it
           //     or wait MaybeCreatePaddingBRElementForEmptyEditor().
-          rv = MOZ_KnownLive(HTMLEditorRef())
-                   .AdjustCaretPositionAndEnsurePaddingBRElement(
-                       HTMLEditorRef().GetDirectionOfTopLevelEditSubAction());
+          rv = AdjustCaretPositionAndEnsurePaddingBRElement(
+              GetDirectionOfTopLevelEditSubAction());
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           break;
         default:
           break;
       }
     }
 
     // check for any styles which were removed inappropriately
     bool reapplyCachedStyle;
-    switch (HTMLEditorRef().GetTopLevelEditSubAction()) {
+    switch (GetTopLevelEditSubAction()) {
       case EditSubAction::eInsertText:
       case EditSubAction::eInsertTextComingFromIME:
       case EditSubAction::eDeleteSelectedContent:
         reapplyCachedStyle = true;
         break;
       default:
-        reapplyCachedStyle = IsStyleCachePreservingSubAction(
-            HTMLEditorRef().GetTopLevelEditSubAction());
+        reapplyCachedStyle =
+            IsStyleCachePreservingSubAction(GetTopLevelEditSubAction());
         break;
     }
     if (reapplyCachedStyle) {
-      HTMLEditorRef().mTypeInState->UpdateSelState(SelectionRefPtr());
-      rv = MOZ_KnownLive(HTMLEditorRef()).ReapplyCachedStyles();
+      mTypeInState->UpdateSelState(SelectionRefPtr());
+      rv = ReapplyCachedStyles();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
-      HTMLEditorRef()
-          .TopLevelEditSubActionDataRef()
-          .mCachedInlineStyles.Clear();
-    }
-  }
-
-  rv = HTMLEditorRef().HandleInlineSpellCheck(
-      HTMLEditorRef()
-          .TopLevelEditSubActionDataRef()
-          .mSelectedRange->StartPoint(),
-      HTMLEditorRef().TopLevelEditSubActionDataRef().mChangedRange);
+      TopLevelEditSubActionDataRef().mCachedInlineStyles.Clear();
+    }
+  }
+
+  rv = HandleInlineSpellCheck(
+      TopLevelEditSubActionDataRef().mSelectedRange->StartPoint(),
+      TopLevelEditSubActionDataRef().mChangedRange);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // detect empty doc
   // XXX Need to investigate when the padding <br> element is removed because
   //     I don't see the <br> element with testing manually.  If it won't be
   //     used, we can get rid of this cost.
-  rv = MOZ_KnownLive(HTMLEditorRef())
-           .MaybeCreatePaddingBRElementForEmptyEditor();
+  rv = MaybeCreatePaddingBRElementForEmptyEditor();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // adjust selection HINT if needed
-  if (!HTMLEditorRef()
-           .TopLevelEditSubActionDataRef()
-           .mDidExplicitlySetInterLine &&
+  if (!TopLevelEditSubActionDataRef().mDidExplicitlySetInterLine &&
       SelectionRefPtr()->IsCollapsed()) {
-    HTMLEditorRef().SetSelectionInterlinePosition();
+    SetSelectionInterlinePosition();
   }
 
   return NS_OK;
 }
 
 EditActionResult HTMLEditor::CanHandleHTMLEditSubAction() const {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -177,22 +177,16 @@ class HTMLEditRules : public TextEditRul
    */
   MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult DidAbsolutePosition();
 
   nsresult AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray,
                                   nsINode* aNode);
   nsresult GetFormatString(nsINode* aNode, nsAString& outFormat);
 
-  /**
-   * Called after handling edit action.  This may adjust Selection, remove
-   * unnecessary empty nodes, create <br> elements if needed, etc.
-   */
-  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult AfterEditInner();
-
   MOZ_CAN_RUN_SCRIPT
   nsresult GetParagraphFormatNodes(
       nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
 
   /**
    * DocumentModifiedWorker() is called by DocumentModified() either
    * synchronously or asynchronously.
    */
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -2643,16 +2643,23 @@ class HTMLEditor final : public TextEdit
   /**
    * EnsureSelectionInBlockElement() may move caret into aElement or its
    * parent block if caret is outside of them.  Don't call this when
    * `Selection` is not collapsed.
    */
   MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
   EnsureCaretInBlockElement(dom::Element& aElement);
 
+  /**
+   * Called by `HTMLEditRules::AfterEdit()`.  This may adjust Selection, remove
+   * unnecessary empty nodes, create `<br>` elements if needed, etc.
+   */
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
+  OnEndHandlingTopLevelEditSubActionInternal();
+
  protected:  // Called by helper classes.
   virtual void OnStartToHandleTopLevelEditSubAction(
       EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
   MOZ_CAN_RUN_SCRIPT
   virtual void OnEndHandlingTopLevelEditSubAction() override;
 
  protected:  // Shouldn't be used by friend classes
   virtual ~HTMLEditor();