Bug 1574852 - part 39: Move `HTMLEditRules::InsertBRIfNeeded()` to `HTMLEditor` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 02 Sep 2019 01:47:14 +0000
changeset 491295 4e7a78eb9a70765b4444f74c04478756a6eca95f
parent 491294 f92faadb300269dff89840f4929bc4b1060b1c4b
child 491296 a67e86b1c73f0b2f4ba097505c236b7f23381a82
push id36526
push userrmaries@mozilla.com
push dateTue, 03 Sep 2019 09:48:47 +0000
treeherdermozilla-central@08b1736b12e6 [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 39: Move `HTMLEditRules::InsertBRIfNeeded()` to `HTMLEditor` r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D44174
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -493,17 +493,20 @@ nsresult HTMLEditRules::AfterEditInner()
     if (HTMLEditorRef().GetTopLevelEditSubAction() ==
             EditSubAction::eDeleteSelectedContent &&
         HTMLEditorRef()
             .TopLevelEditSubActionDataRef()
             .mDidDeleteNonCollapsedRange &&
         !HTMLEditorRef()
              .TopLevelEditSubActionDataRef()
              .mDidDeleteEmptyParentBlocks) {
-      nsresult rv = InsertBRIfNeeded();
+      nsresult rv =
+          MOZ_KnownLive(HTMLEditorRef())
+              .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 = InsertBRElementToEmptyListItemsAndTableCellsInRange(
         HTMLEditorRef()
@@ -2457,21 +2460,23 @@ nsresult HTMLEditRules::WillDeleteSelect
         rv = wsObj.DeleteWSBackward();
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
-      rv = InsertBRIfNeeded();
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-      return NS_OK;
+      rv = MOZ_KnownLive(HTMLEditorRef())
+               .InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
+                   EditorBase::GetStartPoint(*SelectionRefPtr()));
+      NS_WARNING_ASSERTION(
+          NS_SUCCEEDED(rv),
+          "InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary() failed");
+      return rv;
     }
 
     if (wsType == WSType::text) {
       // Found normal text to delete.
       OwningNonNull<Text> nodeAsText = *visNode->GetAsText();
       int32_t so = visOffset;
       int32_t eo = visOffset + 1;
       if (aAction == nsIEditor::ePrevious) {
@@ -2535,17 +2540,19 @@ nsresult HTMLEditRules::WillDeleteSelect
       //     behavior same as Chromium for backward compatibility.
 
       rv = DeleteNodeIfCollapsedText(nodeAsText);
       if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove collapsed text");
 
-      rv = InsertBRIfNeeded();
+      rv = MOZ_KnownLive(HTMLEditorRef())
+               .InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
+                   EditorBase::GetStartPoint(*SelectionRefPtr()));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       // Remember that we did a ranged delete for the benefit of
       // AfterEditInner().
       HTMLEditorRef()
           .TopLevelEditSubActionDataRef()
@@ -2729,21 +2736,23 @@ nsresult HTMLEditRules::WillDeleteSelect
         if (NS_WARN_IF(!CanHandleEditAction())) {
           error.SuppressException();
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
       }
-      rv = InsertBRIfNeeded();
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-      return NS_OK;
+      rv = MOZ_KnownLive(HTMLEditorRef())
+               .InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
+                   EditorBase::GetStartPoint(*SelectionRefPtr()));
+      NS_WARNING_ASSERTION(
+          NS_SUCCEEDED(rv),
+          "InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary() failed");
+      return rv;
     }
 
     if (wsType == WSType::otherBlock) {
       // Make sure it's not a table element.  If so, cancel the operation
       // (translation: users cannot backspace or delete across table cells)
       if (HTMLEditUtils::IsTableElement(visNode)) {
         *aCancel = true;
         return NS_OK;
@@ -3262,53 +3271,51 @@ nsresult HTMLEditRules::DeleteNodeIfColl
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-nsresult HTMLEditRules::InsertBRIfNeeded() {
-  MOZ_ASSERT(IsEditorDataAvailable());
-
-  EditorDOMPoint atStartOfSelection(
-      EditorBase::GetStartPoint(*SelectionRefPtr()));
-  if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // inline elements don't need any br
-  if (!HTMLEditor::NodeIsBlockStatic(*atStartOfSelection.GetContainer())) {
+nsresult HTMLEditor::InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
+    const EditorDOMPoint& aPointToInsert) {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+  MOZ_ASSERT(aPointToInsert.IsSet());
+
+  // If container of the point is not in a block, we don't need to put a
+  // `<br>` element here.
+  if (!HTMLEditor::NodeIsBlockStatic(*aPointToInsert.GetContainer())) {
+    return NS_OK;
+  }
+
+  WSRunObject wsObj(this, aPointToInsert);
+  // If the point is not start of a hard line, we don't need to put a `<br>`
+  // element here.
+  if (!(wsObj.mStartReason & (WSType::block | WSType::br))) {
     return NS_OK;
   }
-
-  // examine selection
-  WSRunObject wsObj(&HTMLEditorRef(), atStartOfSelection);
-  if (((wsObj.mStartReason & WSType::block) ||
-       (wsObj.mStartReason & WSType::br)) &&
-      (wsObj.mEndReason & WSType::block)) {
-    // if we are tucked between block boundaries then insert a br
-    // first check that we are allowed to
-    if (HTMLEditorRef().CanContainTag(*atStartOfSelection.GetContainer(),
-                                      *nsGkAtoms::br)) {
-      RefPtr<Element> brElement =
-          MOZ_KnownLive(HTMLEditorRef())
-              .InsertBRElementWithTransaction(atStartOfSelection,
-                                              nsIEditor::ePrevious);
-      if (NS_WARN_IF(!CanHandleEditAction())) {
-        return NS_ERROR_EDITOR_DESTROYED;
-      }
-      if (NS_WARN_IF(!brElement)) {
-        return NS_ERROR_FAILURE;
-      }
-      return NS_OK;
-    }
-  }
-  return NS_OK;
+  // If the point is not end of a hard line or the hard line does not end with
+  // block boundary, we don't need to put a `<br>` element here.
+  if (!(wsObj.mEndReason & WSType::block)) {
+    return NS_OK;
+  }
+
+  // If we cannot insert a `<br>` element here, do nothing.
+  if (!CanContainTag(*aPointToInsert.GetContainer(), *nsGkAtoms::br)) {
+    return NS_OK;
+  }
+
+  RefPtr<Element> brElement =
+      InsertBRElementWithTransaction(aPointToInsert, nsIEditor::ePrevious);
+  if (NS_WARN_IF(Destroyed())) {
+    return NS_ERROR_EDITOR_DESTROYED;
+  }
+  NS_WARNING_ASSERTION(brElement, "Failed to insert <br> element");
+  return brElement ? NS_OK : NS_ERROR_FAILURE;
 }
 
 EditorDOMPoint HTMLEditRules::GetGoodSelPointForNode(
     nsINode& aNode, nsIEditor::EDirection aAction) {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aAction == nsIEditor::eNext || aAction == nsIEditor::eNextWord ||
              aAction == nsIEditor::ePrevious ||
              aAction == nsIEditor::ePreviousWord ||
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -154,23 +154,16 @@ class HTMLEditRules : public TextEditRul
   /**
    * Called after deleting selected content.
    * This method removes unnecessary empty nodes and/or inserts <br> if
    * necessary.
    */
   MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult DidDeleteSelection();
 
   /**
-   * InsertBRIfNeeded() determines if a br is needed for current selection to
-   * not be spastic.  If so, it inserts one.  Callers responsibility to only
-   * call with collapsed selection.
-   */
-  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult InsertBRIfNeeded();
-
-  /**
    * Insert normal <br> element into aNode when aNode is a block and it has
    * no children.
    */
   MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult InsertBRIfNeeded(nsINode& aNode) {
     return InsertBRIfNeededInternal(aNode, false);
   }
 
   /**
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -1708,16 +1708,26 @@ class HTMLEditor final : public TextEdit
    *                            MoveNodesIntoNewBlockquoteElement() will be
    *                            called.  Otherwise,
    *                            CreateOrChangeBlockContainerElement() will be
    *                            called.
    */
   MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
   FormatBlockContainer(nsAtom& aBlockType);
 
+  /**
+   * InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary() determines if
+   * aPointToInsert is start of a hard line and end of the line (i.e, the
+   * line is empty) and the line ends with block boundary, inserts a `<br>`
+   * element.
+   */
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
+  InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
+      const EditorDOMPoint& aPointToInsert);
+
  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();