Bug 1792387 - part 8: Make `HTMLEditor::InsertParagraphSeparatorAsSubAction` put caret into right paragraph r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 30 Sep 2022 22:20:22 +0000
changeset 636761 acb7315965e5200e095442f887cc36ca438a9582
parent 636760 db9d682774cfd880340bbf9c90c5214531c222af
child 636762 6f315dbf947e95381be2b4c478c795197d8e0470
push id170484
push usermasayuki@d-toybox.com
push dateFri, 30 Sep 2022 22:23:25 +0000
treeherderautoland@f4c48015c119 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1792387
milestone107.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 1792387 - part 8: Make `HTMLEditor::InsertParagraphSeparatorAsSubAction` put caret into right paragraph r=m_kato If splitting element is a list item element, `HandleInsertParagraphInListItemElement` may just move it into a list element if it's followed by the list element, or may create new paragraph element if the list item element is empty and last list item element. If splitting element is a heading element, `HandleInsertParagraphInHeadingElement` may create new paragraph element if splitting at end of the heading element and not followed by `<br>`. Therefore, neither `SplitNodeResult` nor `CreateElementResult` is proper for their result type, and the caller `InsertParagraphSeparatorAsSubAction`, just wants to know the right handle element which should contain caret and a caret point suggestion. For solving these issues, this gives an alias to `CreateElementResult`, makes them return the right paragraph even if it's not newly created nor split element, and replaces `blockElementToPutCaret` with the returned element. Differential Revision: https://phabricator.services.mozilla.com/D158106
editor/libeditor/EditorForwards.h
editor/libeditor/HTMLEditSubActionHandler.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/EditorForwards.h
+++ b/editor/libeditor/EditorForwards.h
@@ -141,16 +141,21 @@ class ReplaceRangeDataBase;  // mozilla/
 /******************************************************************************
  * aliases
  ******************************************************************************/
 
 using CreateContentResult = CreateNodeResultBase<nsIContent>;
 using CreateElementResult = CreateNodeResultBase<dom::Element>;
 using CreateTextResult = CreateNodeResultBase<dom::Text>;
 
+// InsertParagraphResult is an alias of CreateElementResult because it returns
+// new paragraph from point of view of users (i.e., right paragraph if split)
+// instead of newly created paragraph element.
+using InsertParagraphResult = CreateElementResult;
+
 using EditorDOMRange = EditorDOMRangeBase<EditorDOMPoint>;
 using EditorRawDOMRange = EditorDOMRangeBase<EditorRawDOMPoint>;
 using EditorDOMRangeInTexts = EditorDOMRangeBase<EditorDOMPointInText>;
 using EditorRawDOMRangeInTexts = EditorDOMRangeBase<EditorRawDOMPointInText>;
 
 using ReplaceRangeData = ReplaceRangeDataBase<EditorDOMPoint>;
 using ReplaceRangeInTextsData = ReplaceRangeDataBase<EditorDOMPointInText>;
 
--- a/editor/libeditor/HTMLEditSubActionHandler.cpp
+++ b/editor/libeditor/HTMLEditSubActionHandler.cpp
@@ -1792,19 +1792,21 @@ HTMLEditor::InsertParagraphSeparatorAsSu
     if (NS_FAILED(rv) && MOZ_LIKELY(rv != NS_ERROR_EDITOR_DESTROYED) &&
         aOptions.contains(SuggestCaret::AndIgnoreTrivialError)) {
       rv = NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR;
     }
     return rv;
   };
 
   RefPtr<Element> blockElementToPutCaret;
+  // If the default paragraph separator is not <br> and selection is not in
+  // a splittable block element, we should wrap selected contents in a new
+  // paragraph, then, split it.
   if (!HTMLEditUtils::IsSplittableNode(*editableBlockElement) &&
       separator != ParagraphSeparator::br) {
-    // Insert a new block first
     MOZ_ASSERT(separator == ParagraphSeparator::div ||
                separator == ParagraphSeparator::p);
     Result<RefPtr<Element>, nsresult> suggestBlockElementToPutCaretOrError =
         FormatBlockContainerWithTransaction(
             selectionRanges,
             MOZ_KnownLive(HTMLEditor::ToParagraphSeparatorTagName(separator)),
             aEditingHost);
     if (MOZ_UNLIKELY(suggestBlockElementToPutCaretOrError.isErr())) {
@@ -1884,53 +1886,68 @@ HTMLEditor::InsertParagraphSeparatorAsSu
     }
   }
 
   RefPtr<Element> maybeNonEditableListItem =
       HTMLEditUtils::GetClosestAncestorListItemElement(*editableBlockElement,
                                                        &aEditingHost);
   if (maybeNonEditableListItem &&
       HTMLEditUtils::IsSplittableNode(*maybeNonEditableListItem)) {
-    Result<EditorDOMPoint, nsresult> pointToPutCaretOrError =
+    Result<InsertParagraphResult, nsresult> insertParagraphInListItemResult =
         HandleInsertParagraphInListItemElement(*maybeNonEditableListItem,
                                                pointToInsert, aEditingHost);
-    if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
-      if (NS_WARN_IF(pointToPutCaretOrError.unwrapErr() ==
+    if (MOZ_UNLIKELY(insertParagraphInListItemResult.isErr())) {
+      if (NS_WARN_IF(insertParagraphInListItemResult.unwrapErr() ==
                      NS_ERROR_EDITOR_DESTROYED)) {
         return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       NS_WARNING(
           "HTMLEditor::HandleInsertParagraphInListItemElement() failed, but "
           "ignored");
       return EditActionResult::HandledResult();
     }
-    nsresult rv = CollapseSelection(pointToPutCaretOrError.inspect(),
-                                    blockElementToPutCaret,
+    InsertParagraphResult unwrappedInsertParagraphInListItemResult =
+        insertParagraphInListItemResult.unwrap();
+    MOZ_ASSERT(unwrappedInsertParagraphInListItemResult.Handled());
+    MOZ_ASSERT(unwrappedInsertParagraphInListItemResult.GetNewNode());
+    const RefPtr<Element> listItemOrParagraphElement =
+        unwrappedInsertParagraphInListItemResult.UnwrapNewNode();
+    const EditorDOMPoint pointToPutCaret =
+        unwrappedInsertParagraphInListItemResult.UnwrapCaretPoint();
+    nsresult rv = CollapseSelection(pointToPutCaret, listItemOrParagraphElement,
                                     {SuggestCaret::AndIgnoreTrivialError});
     if (NS_FAILED(rv)) {
       NS_WARNING("CollapseSelection() failed");
       return Err(rv);
     }
     NS_WARNING_ASSERTION(rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
                          "CollapseSelection() failed, but ignored");
     return EditActionResult::HandledResult();
   }
 
   if (HTMLEditUtils::IsHeader(*editableBlockElement)) {
-    SplitNodeResult splitHeadingElementResult =
-        HandleInsertParagraphInHeadingElement(*editableBlockElement,
-                                              pointToInsert);
-    if (MOZ_UNLIKELY(splitHeadingElementResult.isErr())) {
+    Result<InsertParagraphResult, nsresult>
+        insertParagraphInHeadingElementResult =
+            HandleInsertParagraphInHeadingElement(*editableBlockElement,
+                                                  pointToInsert);
+    if (MOZ_UNLIKELY(insertParagraphInHeadingElementResult.isErr())) {
       NS_WARNING(
           "HTMLEditor::HandleInsertParagraphInHeadingElement() failed, but "
           "ignored");
       return EditActionResult::HandledResult();
     }
-    EditorDOMPoint pointToPutCaret =
-        splitHeadingElementResult.UnwrapCaretPoint();
+    InsertParagraphResult unwrappedInsertParagraphInHeadingElementResult =
+        insertParagraphInHeadingElementResult.unwrap();
+    if (unwrappedInsertParagraphInHeadingElementResult.Handled()) {
+      MOZ_ASSERT(unwrappedInsertParagraphInHeadingElementResult.GetNewNode());
+      blockElementToPutCaret =
+          unwrappedInsertParagraphInHeadingElementResult.UnwrapNewNode();
+    }
+    const EditorDOMPoint pointToPutCaret =
+        unwrappedInsertParagraphInHeadingElementResult.UnwrapCaretPoint();
     nsresult rv = CollapseSelection(pointToPutCaret, blockElementToPutCaret,
                                     {SuggestCaret::OnlyIfHasSuggestion,
                                      SuggestCaret::AndIgnoreTrivialError});
     if (NS_FAILED(rv)) {
       NS_WARNING("CollapseSelection() failed");
       return Err(rv);
     }
     NS_WARNING_ASSERTION(rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
@@ -1956,18 +1973,21 @@ HTMLEditor::InsertParagraphSeparatorAsSu
         insertedPaddingBRElement ? EditorDOMPoint(insertedPaddingBRElement)
                                  : pointToInsert,
         aEditingHost);
     if (splitResult.isErr()) {
       NS_WARNING("HTMLEditor::HandleInsertParagraphInParagraph() failed");
       return Err(splitResult.unwrapErr());
     }
     if (splitResult.Handled()) {
-      EditorDOMPoint pointToPutCaret = splitResult.UnwrapCaretPoint();
-      nsresult rv = CollapseSelection(pointToPutCaret, blockElementToPutCaret,
+      const RefPtr<Element> rightParagraphElement =
+          splitResult.DidSplit() ? splitResult.GetNextContent()->AsElement()
+                                 : blockElementToPutCaret.get();
+      const EditorDOMPoint pointToPutCaret = splitResult.UnwrapCaretPoint();
+      nsresult rv = CollapseSelection(pointToPutCaret, rightParagraphElement,
                                       {SuggestCaret::AndIgnoreTrivialError});
       if (NS_FAILED(rv)) {
         NS_WARNING("CollapseSelection() failed");
         return Err(rv);
       }
       NS_WARNING_ASSERTION(rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
                            "CollapseSelection() failed, but ignored");
       return EditActionResult::HandledResult();
@@ -7198,17 +7218,18 @@ void HTMLEditor::MakeTransitionList(
   nsINode* prevParent = nullptr;
   aTransitionArray.EnsureLengthAtLeast(aArrayOfContents.Length());
   for (uint32_t i = 0; i < aArrayOfContents.Length(); i++) {
     aTransitionArray[i] = aArrayOfContents[i]->GetParentNode() != prevParent;
     prevParent = aArrayOfContents[i]->GetParentNode();
   }
 }
 
-SplitNodeResult HTMLEditor::HandleInsertParagraphInHeadingElement(
+Result<InsertParagraphResult, nsresult>
+HTMLEditor::HandleInsertParagraphInHeadingElement(
     Element& aHeadingElement, const EditorDOMPoint& aPointToSplit) {
   MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable());
 
   SplitNodeResult splitHeadingResult = [this, &aPointToSplit,
                                         &aHeadingElement]() MOZ_CAN_RUN_SCRIPT {
     // Normalize collapsible white-spaces around the split point to keep
     // them visible after the split.  Note that this does not touch
     // selection because of using AutoTransactionsConserveSelection in
@@ -7232,24 +7253,24 @@ SplitNodeResult HTMLEditor::HandleInsert
     NS_WARNING_ASSERTION(
         splitResult.isOk(),
         "HTMLEditor::SplitNodeDeepWithTransaction(aHeadingElement, "
         "SplitAtEdges::eAllowToCreateEmptyContainer) failed");
     return splitResult;
   }();
   if (splitHeadingResult.isErr()) {
     NS_WARNING("Failed to splitting aHeadingElement");
-    return splitHeadingResult;
+    return Err(splitHeadingResult.unwrapErr());
   }
   splitHeadingResult.IgnoreCaretPointSuggestion();
   if (MOZ_UNLIKELY(!splitHeadingResult.DidSplit())) {
     NS_WARNING(
         "HTMLEditor::SplitNodeDeepWithTransaction(SplitAtEdges::"
         "eAllowToCreateEmptyContainer) didn't split aHeadingElement");
-    return SplitNodeResult(NS_ERROR_FAILURE);
+    return Err(NS_ERROR_FAILURE);
   }
 
   // If the left heading element is empty, put a padding <br> element for empty
   // last line into it.
   // FYI: leftHeadingElement is grabbed by splitHeadingResult so that it's safe
   //      to access anytime.
   Element* leftHeadingElement =
       Element::FromNode(splitHeadingResult.GetPreviousContent());
@@ -7262,41 +7283,41 @@ SplitNodeResult HTMLEditor::HandleInsert
           {EmptyCheckOption::TreatSingleBRElementAsVisible})) {
     Result<CreateElementResult, nsresult> insertPaddingBRElementResult =
         InsertPaddingBRElementForEmptyLastLineWithTransaction(
             EditorDOMPoint(leftHeadingElement, 0u));
     if (MOZ_UNLIKELY(insertPaddingBRElementResult.isErr())) {
       NS_WARNING(
           "HTMLEditor::InsertPaddingBRElementForEmptyLastLineWithTransaction("
           ") failed");
-      return SplitNodeResult(insertPaddingBRElementResult.unwrapErr());
+      return insertPaddingBRElementResult.propagateErr();
     }
     insertPaddingBRElementResult.inspect().IgnoreCaretPointSuggestion();
   }
 
   // Put caret at start of the right head element if it's not empty.
   Element* rightHeadingElement =
       Element::FromNode(splitHeadingResult.GetNextContent());
   MOZ_ASSERT(rightHeadingElement,
              "SplitNodeResult::GetNextContent() should return something if "
              "DidSplit() returns true");
   if (!HTMLEditUtils::IsEmptyBlockElement(*rightHeadingElement, {})) {
-    return SplitNodeResult(std::move(splitHeadingResult),
-                           EditorDOMPoint(rightHeadingElement, 0u));
+    return InsertParagraphResult(rightHeadingElement,
+                                 EditorDOMPoint(rightHeadingElement, 0u));
   }
 
   // If the right heading element is empty, delete it.
   // TODO: If we know the new heading element becomes empty, we stop spliting
   //       the heading element.
   // MOZ_KnownLive(rightHeadingElement) because it's grabbed by
   // splitHeadingResult.
   nsresult rv = DeleteNodeWithTransaction(MOZ_KnownLive(*rightHeadingElement));
   if (NS_FAILED(rv)) {
     NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
-    return SplitNodeResult(rv);
+    return Err(rv);
   }
 
   // Layout tells the caret to blink in a weird place if we don't place a
   // break after the header.
   // XXX This block is dead code unless the removed right heading element is
   //     reconnected by a mutation event listener.  This is a regression of
   //     bug 1405751:
   //     https://searchfox.org/mozilla-central/diff/879f3317d1331818718e18776caa47be7f426a22/editor/libeditor/HTMLEditRules.cpp#6389
@@ -7308,29 +7329,27 @@ SplitNodeResult HTMLEditor::HandleInsert
     //     <br> elements also work as <br> from point of view of layout.
     nsIContent* nextEditableSibling =
         HTMLEditUtils::GetNextSibling(*rightHeadingElement->GetNextSibling(),
                                       {WalkTreeOption::IgnoreNonEditableNode});
     if (nextEditableSibling &&
         nextEditableSibling->IsHTMLElement(nsGkAtoms::br)) {
       auto afterEditableBRElement = EditorDOMPoint::After(*nextEditableSibling);
       if (NS_WARN_IF(!afterEditableBRElement.IsSet())) {
-        return SplitNodeResult(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
+        return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
       }
       // Put caret at the <br> element.
-      return SplitNodeResult(
-          SplitNodeResult::HandledButDidNotSplitDueToEndOfContainer(
-              *leftHeadingElement, GetSplitNodeDirection()),
-          afterEditableBRElement);
+      return InsertParagraphResult::NotHandled(
+          std::move(afterEditableBRElement));
     }
   }
 
   if (MOZ_UNLIKELY(!leftHeadingElement->IsInComposedDoc())) {
     NS_WARNING("The left heading element was unexpectedly removed");
-    return SplitNodeResult(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
+    return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
   }
 
   TopLevelEditSubActionDataRef().mCachedPendingStyles->Clear();
   mPendingStylesToApplyToNewContent->ClearAllStyles();
 
   // Create a paragraph if the right heading element is not followed by an
   // editable <br> element.
   nsStaticAtom& newParagraphTagName =
@@ -7365,29 +7384,28 @@ SplitNodeResult HTMLEditor::HandleInsert
             }
             // We'll update selection after inserting the new paragraph.
             insertBRElementResult.inspect().IgnoreCaretPointSuggestion();
             return NS_OK;
           });
   if (MOZ_UNLIKELY(createNewParagraphElementResult.isErr())) {
     NS_WARNING(
         "HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed");
-    return SplitNodeResult(createNewParagraphElementResult.unwrapErr());
+    return createNewParagraphElementResult.propagateErr();
   }
   CreateElementResult unwrappedCreateNewParagraphElementResult =
       createNewParagraphElementResult.unwrap();
   // Put caret at the <br> element in the following paragraph.
   unwrappedCreateNewParagraphElementResult.IgnoreCaretPointSuggestion();
   MOZ_ASSERT(unwrappedCreateNewParagraphElementResult.GetNewNode());
-  return SplitNodeResult(
-      *leftHeadingElement,
-      *unwrappedCreateNewParagraphElementResult.GetNewNode(),
-      GetSplitNodeDirection(),
-      Some(EditorDOMPoint(unwrappedCreateNewParagraphElementResult.GetNewNode(),
-                          0u)));
+  EditorDOMPoint pointToPutCaret(
+      unwrappedCreateNewParagraphElementResult.GetNewNode(), 0u);
+  return InsertParagraphResult(
+      unwrappedCreateNewParagraphElementResult.UnwrapNewNode(),
+      std::move(pointToPutCaret));
 }
 
 SplitNodeResult HTMLEditor::HandleInsertParagraphInParagraph(
     Element& aParentDivOrP, const EditorDOMPoint& aCandidatePointToSplit,
     const Element& aEditingHost) {
   MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(aCandidatePointToSplit.IsSetAndValid());
 
@@ -7875,17 +7893,17 @@ SplitNodeResult HTMLEditor::SplitParagra
   }
   return child->IsText() || HTMLEditUtils::IsContainerNode(*child)
              ? SplitNodeResult(std::move(splitDivOrPResult),
                                EditorDOMPoint(child, 0u))
              : SplitNodeResult(std::move(splitDivOrPResult),
                                EditorDOMPoint(child));
 }
 
-Result<EditorDOMPoint, nsresult>
+Result<InsertParagraphResult, nsresult>
 HTMLEditor::HandleInsertParagraphInListItemElement(
     Element& aListItemElement, const EditorDOMPoint& aPointToSplit,
     const Element& aEditingHost) {
   MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(HTMLEditUtils::IsListItem(&aListItemElement));
 
   // If aListItemElement is empty, then we want to outdent its content.
   if (&aEditingHost != aListItemElement.GetParentElement() &&
@@ -7925,17 +7943,18 @@ HTMLEditor::HandleInsertParagraphInListI
     if (HTMLEditUtils::IsAnyListElement(afterLeftListElement.GetContainer())) {
       Result<MoveNodeResult, nsresult> moveListItemElementResult =
           MoveNodeWithTransaction(aListItemElement, afterLeftListElement);
       if (MOZ_UNLIKELY(moveListItemElementResult.isErr())) {
         NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
         return moveListItemElementResult.propagateErr();
       }
       moveListItemElementResult.inspect().IgnoreCaretPointSuggestion();
-      return EditorDOMPoint(&aListItemElement, 0u);
+      return InsertParagraphResult(&aListItemElement,
+                                   EditorDOMPoint(&aListItemElement, 0u));
     }
 
     // Otherwise, replace the empty aListItemElement with a new paragraph.
     nsresult rv = DeleteNodeWithTransaction(aListItemElement);
     if (NS_FAILED(rv)) {
       NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
       return Err(rv);
     }
@@ -7976,18 +7995,21 @@ HTMLEditor::HandleInsertParagraphInListI
             });
     if (MOZ_UNLIKELY(createNewParagraphElementResult.isErr())) {
       NS_WARNING(
           "HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed");
       return createNewParagraphElementResult.propagateErr();
     }
     createNewParagraphElementResult.inspect().IgnoreCaretPointSuggestion();
     MOZ_ASSERT(createNewParagraphElementResult.inspect().GetNewNode());
-    return EditorDOMPoint(
+    EditorDOMPoint pointToPutCaret(
         createNewParagraphElementResult.inspect().GetNewNode(), 0u);
+    return InsertParagraphResult(
+        createNewParagraphElementResult.inspect().GetNewNode(),
+        std::move(pointToPutCaret));
   }
 
   // If aListItemElement has some content or aListItemElement is empty but it's
   // a child of editing host, we want a new list item at the same list level.
   // First, sort out white-spaces.
   Result<EditorDOMPoint, nsresult> preparationResult =
       WhiteSpaceVisibilityKeeper::PrepareToSplitBlockElement(
           *this, aPointToSplit, aListItemElement);
@@ -8041,17 +8063,18 @@ HTMLEditor::HandleInsertParagraphInListI
       NS_WARNING(
           "HTMLEditor::InsertPaddingBRElementForEmptyLastLineWithTransaction("
           ") failed");
       return insertPaddingBRElementResult.propagateErr();
     }
     // We're returning a candidate point to put caret so that we don't need to
     // update now.
     insertPaddingBRElementResult.inspect().IgnoreCaretPointSuggestion();
-    return EditorDOMPoint(&rightListItemElement, 0u);
+    return InsertParagraphResult(&rightListItemElement,
+                                 EditorDOMPoint(&rightListItemElement, 0u));
   }
 
   if (HTMLEditUtils::IsEmptyNode(rightListItemElement)) {
     // If aListItemElement is a <dd> or a <dt> and the right list item is empty
     // or a direct child of the editing host, replace it a new list item element
     // whose type is the other one.
     if (aListItemElement.IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dt)) {
       nsStaticAtom& nextDefinitionListItemTagName =
@@ -8077,35 +8100,39 @@ HTMLEditor::HandleInsertParagraphInListI
       // MOZ_KnownLive(rightListItemElement) because it's grabbed by
       // splitListItemResult.
       nsresult rv =
           DeleteNodeWithTransaction(MOZ_KnownLive(rightListItemElement));
       if (NS_FAILED(rv)) {
         NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
         return Err(rv);
       }
-      return EditorDOMPoint(newListItemElement, 0u);
+      EditorDOMPoint pointToPutCaret(newListItemElement, 0u);
+      return InsertParagraphResult(std::move(newListItemElement),
+                                   std::move(pointToPutCaret));
     }
 
     // If aListItemElement is a <li> and the right list item becomes empty or a
     // direct child of the editing host, copy all inline elements affecting to
     // the style at end of the left list item element to the right list item
     // element.
-    // MOZ_KnownLive(*ListItemElement) because they are grabbed by
+    // MOZ_KnownLive(leftListItemElement) and
+    // MOZ_KnownLive(rightListItemElement) because they are grabbed by
     // splitListItemResult.
     Result<EditorDOMPoint, nsresult> pointToPutCaretOrError =
         CopyLastEditableChildStylesWithTransaction(
             MOZ_KnownLive(leftListItemElement),
             MOZ_KnownLive(rightListItemElement), aEditingHost);
     if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
       NS_WARNING(
           "HTMLEditor::CopyLastEditableChildStylesWithTransaction() failed");
-      return Err(pointToPutCaretOrError.unwrapErr());
-    }
-    return pointToPutCaretOrError.unwrap();
+      return pointToPutCaretOrError.propagateErr();
+    }
+    return InsertParagraphResult(&rightListItemElement,
+                                 pointToPutCaretOrError.unwrap());
   }
 
   // If the right list item element is not empty, we need to consider where to
   // put caret in it. If it has non-container inline elements, <br> or <hr>, at
   // the element is proper position.
   WSScanResult forwardScanFromStartOfListItemResult =
       WSRunScanner::ScanNextVisibleNodeOrBlockBoundary(
           &aEditingHost, EditorRawDOMPoint(&rightListItemElement, 0u));
@@ -8116,23 +8143,26 @@ HTMLEditor::HandleInsertParagraphInListI
   if (forwardScanFromStartOfListItemResult.ReachedSpecialContent() ||
       forwardScanFromStartOfListItemResult.ReachedBRElement() ||
       forwardScanFromStartOfListItemResult.ReachedHRElement()) {
     auto atFoundElement =
         forwardScanFromStartOfListItemResult.PointAtContent<EditorDOMPoint>();
     if (NS_WARN_IF(!atFoundElement.IsSetAndValid())) {
       return Err(NS_ERROR_FAILURE);
     }
-    return atFoundElement;
+    return InsertParagraphResult(&rightListItemElement,
+                                 std::move(atFoundElement));
   }
 
   // Otherwise, return the point at first visible thing.
   // XXX This may be not meaningful position if it reached block element
   //     in aListItemElement.
-  return forwardScanFromStartOfListItemResult.Point<EditorDOMPoint>();
+  return InsertParagraphResult(
+      &rightListItemElement,
+      forwardScanFromStartOfListItemResult.Point<EditorDOMPoint>());
 }
 
 Result<CreateElementResult, nsresult>
 HTMLEditor::WrapContentsInBlockquoteElementsWithTransaction(
     const nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents,
     const Element& aEditingHost) {
   MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable());
 
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -1568,31 +1568,36 @@ class HTMLEditor final : public EditorBa
    * HandleInsertParagraphInHeadingElement() handles insertParagraph command
    * (i.e., handling Enter key press) in a heading element.  This splits
    * aHeadingElement element at aPointToSplit.  Then, if right heading element
    * is empty, it'll be removed and new paragraph is created (its type is
    * decided with default paragraph separator).
    *
    * @param aHeadingElement     The heading element to be split.
    * @param aPointToSplit       The point to split aHeadingElement.
-   */
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT SplitNodeResult
+   * @return                    New paragraph element, meaning right heading
+   *                            element if aHeadingElement is split, or newly
+   *                            created or existing paragraph element.
+   */
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<InsertParagraphResult, nsresult>
   HandleInsertParagraphInHeadingElement(Element& aHeadingElement,
                                         const EditorDOMPoint& aPointToSplit);
 
   /**
    * HandleInsertParagraphInListItemElement() handles insertParagraph command
    * (i.e., handling Enter key press) in a list item element.
    *
    * @param aListItemElement    The list item which has the following point.
    * @param aPointToSplit       The point to split aListItemElement.
    * @param aEditingHost        The editing host.
-   * @return                    A candidate position to put caret.
-   */
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditorDOMPoint, nsresult>
+   * @return                    New paragraph element, meaning right list item
+   *                            element if aListItemElement is split, or newly
+   *                            created paragraph element.
+   */
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<InsertParagraphResult, nsresult>
   HandleInsertParagraphInListItemElement(Element& aListItemElement,
                                          const EditorDOMPoint& aPointToSplit,
                                          const Element& aEditingHost);
 
   /**
    * InsertParagraphSeparatorAsSubAction() handles insertPargraph commad
    * (i.e., handling Enter key press) with the above helper methods.
    *