Bug 1655389 - part 3: Split the case deleting `<br>` element off from `AutoBlockElementsJoiner::HandleDeleteCollapsedSelectionAtOtherBlockBoundary()` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 05 Aug 2020 05:08:21 +0000
changeset 543352 de60b2f1987f7a02c012a90d653143fbff26800e
parent 543351 1e439a68f0e49fb2c1bec0169564a5d69222790d
child 543353 f212f223bee382b61b577eda2a9e952cd8e1623b
push id123402
push usermasayuki@d-toybox.com
push dateWed, 05 Aug 2020 06:52:10 +0000
treeherderautoland@de60b2f1987f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1655389
milestone81.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 1655389 - part 3: Split the case deleting `<br>` element off from `AutoBlockElementsJoiner::HandleDeleteCollapsedSelectionAtOtherBlockBoundary()` r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D85578
editor/libeditor/HTMLEditSubActionHandler.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditSubActionHandler.cpp
+++ b/editor/libeditor/HTMLEditSubActionHandler.cpp
@@ -3073,96 +3073,99 @@ bool HTMLEditor::AutoBlockElementsJoiner
   mMode = Mode::JoinOtherBlock;
 
   // Make sure it's not a table element.  If so, cancel the operation
   // (translation: users cannot backspace or delete across table cells)
   if (HTMLEditUtils::IsAnyTableElement(&aOtherBlockElement)) {
     return false;
   }
 
-  // Next to a block.  See if we are between a block and a br.  If so, we
-  // really want to delete the br.  Else join content at selection to the
-  // block.
-  WSScanResult scanFromCaretResult =
-      aDirectionAndAmount == nsIEditor::eNext
-          ? aWSRunScannerAtCaret.ScanPreviousVisibleNodeOrBlockBoundaryFrom(
-                aCaretPoint)
-          : aWSRunScannerAtCaret.ScanNextVisibleNodeOrBlockBoundaryFrom(
-                aCaretPoint);
-
   // First find the adjacent node in the block
   if (aDirectionAndAmount == nsIEditor::ePrevious) {
     mLeafContentInOtherBlock =
         aHTMLEditor.GetLastEditableLeaf(aOtherBlockElement);
     mLeftContent = mLeafContentInOtherBlock;
     mRightContent = aCaretPoint.GetContainerAsContent();
   } else {
     mLeafContentInOtherBlock =
         aHTMLEditor.GetFirstEditableLeaf(aOtherBlockElement);
     mLeftContent = aCaretPoint.GetContainerAsContent();
     mRightContent = mLeafContentInOtherBlock;
   }
 
+  // Next to a block.  See if we are between the block and a `<br>`.
+  // If so, we really want to delete the `<br>`.  Else join content at
+  // selection to the block.
+  WSScanResult scanFromCaretResult =
+      aDirectionAndAmount == nsIEditor::eNext
+          ? aWSRunScannerAtCaret.ScanPreviousVisibleNodeOrBlockBoundaryFrom(
+                aCaretPoint)
+          : aWSRunScannerAtCaret.ScanNextVisibleNodeOrBlockBoundaryFrom(
+                aCaretPoint);
   // If we found a `<br>` element, we need to delete it instead of joining the
   // contents.
   if (scanFromCaretResult.ReachedBRElement()) {
     mBRElement = scanFromCaretResult.BRElementPtr();
+    mMode = Mode::DeleteBRElement;
     return true;
   }
 
   return mLeftContent && mRightContent;
 }
 
+EditActionResult HTMLEditor::AutoBlockElementsJoiner::DeleteBRElement(
+    HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
+    const EditorDOMPoint& aCaretPoint) {
+  MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
+  MOZ_ASSERT(aCaretPoint.IsSetAndValid());
+  MOZ_ASSERT(mBRElement);
+
+  // If we found a `<br>` element, we should delete it instead of joining the
+  // contents.
+  nsresult rv =
+      aHTMLEditor.DeleteNodeWithTransaction(MOZ_KnownLive(*mBRElement));
+  if (NS_WARN_IF(aHTMLEditor.Destroyed())) {
+    return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
+  }
+  if (NS_FAILED(rv)) {
+    NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
+    return EditActionResult(rv);
+  }
+
+  if (mLeftContent && mRightContent &&
+      HTMLEditor::NodesInDifferentTableElements(*mLeftContent,
+                                                *mRightContent)) {
+    return EditActionHandled();
+  }
+
+  // Put selection at edge of block and we are done.
+  if (NS_WARN_IF(!mLeafContentInOtherBlock)) {
+    // XXX This must be odd case.  The other block can be empty.
+    return EditActionHandled(NS_ERROR_FAILURE);
+  }
+  EditorDOMPoint newCaretPosition = aHTMLEditor.GetGoodCaretPointFor(
+      *mLeafContentInOtherBlock, aDirectionAndAmount);
+  if (!newCaretPosition.IsSet()) {
+    NS_WARNING("HTMLEditor::GetGoodCaretPointFor() failed");
+    return EditActionHandled(NS_ERROR_FAILURE);
+  }
+  rv = aHTMLEditor.CollapseSelectionTo(newCaretPosition);
+  if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
+    return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
+  }
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "HTMLEditor::CollapseSelectionTo() failed, but ignored");
+  return EditActionHandled();
+}
+
 EditActionResult HTMLEditor::AutoBlockElementsJoiner::
     HandleDeleteCollapsedSelectionAtOtherBlockBoundary(
-        HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
-        const EditorDOMPoint& aCaretPoint) {
+        HTMLEditor& aHTMLEditor, const EditorDOMPoint& aCaretPoint) {
   MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
   MOZ_ASSERT(aCaretPoint.IsSetAndValid());
-
-  // If we found a `<br>` element, we should delete it instead of joinning the
-  // contents.
-  if (mBRElement) {
-    nsresult rv =
-        aHTMLEditor.DeleteNodeWithTransaction(MOZ_KnownLive(*mBRElement));
-    if (NS_WARN_IF(aHTMLEditor.Destroyed())) {
-      return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
-    }
-    if (NS_FAILED(rv)) {
-      NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
-      return EditActionResult(rv);
-    }
-
-    if (mLeftContent && mRightContent &&
-        HTMLEditor::NodesInDifferentTableElements(*mLeftContent,
-                                                  *mRightContent)) {
-      return EditActionHandled();
-    }
-
-    // Put selection at edge of block and we are done.
-    if (NS_WARN_IF(!mLeafContentInOtherBlock)) {
-      // XXX This must be odd case.  The other block can be empty.
-      return EditActionHandled(NS_ERROR_FAILURE);
-    }
-    EditorDOMPoint newCaretPosition = aHTMLEditor.GetGoodCaretPointFor(
-        *mLeafContentInOtherBlock, aDirectionAndAmount);
-    if (!newCaretPosition.IsSet()) {
-      NS_WARNING("HTMLEditor::GetGoodCaretPointFor() failed");
-      return EditActionHandled(NS_ERROR_FAILURE);
-    }
-    rv = aHTMLEditor.CollapseSelectionTo(newCaretPosition);
-    if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
-      return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
-    }
-    NS_WARNING_ASSERTION(
-        NS_SUCCEEDED(rv),
-        "HTMLEditor::CollapseSelectionTo() failed, but ignored");
-    return EditActionHandled();
-  }
-
   MOZ_ASSERT(mLeftContent);
   MOZ_ASSERT(mRightContent);
 
   if (HTMLEditor::NodesInDifferentTableElements(*mLeftContent,
                                                 *mRightContent)) {
     // If we have not deleted `<br>` element and are not called recursively,
     // we should call `DeleteSelectionWithTransaction()` here, but we cannot
     // detect it for now.  Therefore, we should just tell the caller of that
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -2742,24 +2742,32 @@ class HTMLEditor final : public TextEdit
           NS_WARNING_ASSERTION(
               result.Succeeded(),
               "AutoBlockElementsJoiner::"
               "HandleDeleteCollapsedSelectionAtCurrentBlockBoundary() failed");
           return result;
         }
         case Mode::JoinOtherBlock: {
           EditActionResult result =
-              HandleDeleteCollapsedSelectionAtOtherBlockBoundary(
-                  aHTMLEditor, aDirectionAndAmount, aCaretPoint);
+              HandleDeleteCollapsedSelectionAtOtherBlockBoundary(aHTMLEditor,
+                                                                 aCaretPoint);
           NS_WARNING_ASSERTION(
               result.Succeeded(),
               "AutoBlockElementsJoiner::"
               "HandleDeleteCollapsedSelectionAtOtherBlockBoundary() failed");
           return result;
         }
+        case Mode::DeleteBRElement: {
+          EditActionResult result =
+              DeleteBRElement(aHTMLEditor, aDirectionAndAmount, aCaretPoint);
+          NS_WARNING_ASSERTION(
+              result.Succeeded(),
+              "AutoBlockElementsJoiner::DeleteBRElement() failed");
+          return result;
+        }
         case Mode::NotInitialized:
           return EditActionIgnored();
       }
       return EditActionResult(NS_ERROR_NOT_INITIALIZED);
     }
 
     nsIContent* GetLeafContentInOtherBlockElement() const {
       MOZ_ASSERT(mMode == Mode::JoinOtherBlock);
@@ -2772,23 +2780,26 @@ class HTMLEditor final : public TextEdit
     }
 
    private:
     [[nodiscard]] MOZ_CAN_RUN_SCRIPT EditActionResult
     HandleDeleteCollapsedSelectionAtCurrentBlockBoundary(
         HTMLEditor& aHTMLEditor, const EditorDOMPoint& aCaretPoint);
     [[nodiscard]] MOZ_CAN_RUN_SCRIPT EditActionResult
     HandleDeleteCollapsedSelectionAtOtherBlockBoundary(
+        HTMLEditor& aHTMLEditor, const EditorDOMPoint& aCaretPoint);
+    [[nodiscard]] MOZ_CAN_RUN_SCRIPT EditActionResult DeleteBRElement(
         HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
         const EditorDOMPoint& aCaretPoint);
 
     enum class Mode {
       NotInitialized,
       JoinCurrentBlock,
       JoinOtherBlock,
+      DeleteBRElement,
     };
     nsCOMPtr<nsIContent> mLeftContent;
     nsCOMPtr<nsIContent> mRightContent;
     nsCOMPtr<nsIContent> mLeafContentInOtherBlock;
     RefPtr<dom::HTMLBRElement> mBRElement;
     Mode mMode = Mode::NotInitialized;
     bool mNeedsToFallbackToDeleteSelectionWithTransaction = false;
   };