Bug 1792639 - Make `SplitRangeOffFromNodeResult` treated as ok type of `Result` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 03 Oct 2022 07:52:45 +0000
changeset 636798 eb8ec4af521311b93b08fb992ab818446b20f7df
parent 636797 12df9b383a32e415c0940fdbdd5d27f408d831ac
child 636799 5fb7c60ced1b752486b6c8ab0ce4649a6b5f670a
push id170514
push usermasayuki@d-toybox.com
push dateMon, 03 Oct 2022 07:55:12 +0000
treeherderautoland@eb8ec4af5213 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1792639
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 1792639 - Make `SplitRangeOffFromNodeResult` treated as ok type of `Result` r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D158332
editor/libeditor/HTMLEditHelpers.h
editor/libeditor/HTMLEditSubActionHandler.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLStyleEditor.cpp
--- a/editor/libeditor/HTMLEditHelpers.h
+++ b/editor/libeditor/HTMLEditHelpers.h
@@ -695,84 +695,84 @@ class MOZ_STACK_CLASS JoinNodesResult fi
   nsCOMPtr<nsIContent> mRemovedContent;
 
   nsresult mRv;
 };
 
 /*****************************************************************************
  * SplitRangeOffFromNodeResult class is a simple class for methods which split a
  * node at 2 points for making part of the node split off from the node.
- * TODO: Perhaps, we can make this inherits mozilla::Result for guaranteeing
- *       same API.  Then, changing to/from Result<*, nsresult> can be easier.
- *       For now, we should give same API name rather than same as
- *       mozilla::ErrorResult.
  *****************************************************************************/
 class MOZ_STACK_CLASS SplitRangeOffFromNodeResult final {
  public:
-  // FYI: NS_SUCCEEDED and NS_FAILED contain MOZ_(UN)LIKELY so that isOk() and
-  //      isErr() must not required to wrap with them.
-  bool isOk() const { return NS_SUCCEEDED(mRv); }
-  bool isErr() const { return NS_FAILED(mRv); }
-  constexpr nsresult inspectErr() const { return mRv; }
-  constexpr nsresult unwrapErr() const { return inspectErr(); }
-  constexpr bool EditorDestroyed() const {
-    return MOZ_UNLIKELY(mRv == NS_ERROR_EDITOR_DESTROYED);
-  }
-
   /**
    * GetLeftContent() returns new created node before the part of quarried out.
    * This may return nullptr if the method didn't split at start edge of
    * the node.
    */
   MOZ_KNOWN_LIVE nsIContent* GetLeftContent() const { return mLeftContent; }
   template <typename ContentNodeType>
   MOZ_KNOWN_LIVE ContentNodeType* GetLeftContentAs() const {
     return ContentNodeType::FromNodeOrNull(GetLeftContent());
   }
+  constexpr nsCOMPtr<nsIContent>&& UnwrapLeftContent() {
+    mMovedContent = true;
+    return std::move(mLeftContent);
+  }
 
   /**
    * GetMiddleContent() returns new created node between left node and right
    * node.  I.e., this is quarried out from the node.  This may return nullptr
    * if the method unwrapped the middle node.
    */
   MOZ_KNOWN_LIVE nsIContent* GetMiddleContent() const { return mMiddleContent; }
   template <typename ContentNodeType>
   MOZ_KNOWN_LIVE ContentNodeType* GetMiddleContentAs() const {
     return ContentNodeType::FromNodeOrNull(GetMiddleContent());
   }
+  constexpr nsCOMPtr<nsIContent>&& UnwrapMiddleContent() {
+    mMovedContent = true;
+    return std::move(mMiddleContent);
+  }
 
   /**
    * GetRightContent() returns the right node after the part of quarried out.
    * This may return nullptr it the method didn't split at end edge of the
    * node.
    */
   MOZ_KNOWN_LIVE nsIContent* GetRightContent() const { return mRightContent; }
   template <typename ContentNodeType>
   MOZ_KNOWN_LIVE ContentNodeType* GetRightContentAs() const {
     return ContentNodeType::FromNodeOrNull(GetRightContent());
   }
+  constexpr nsCOMPtr<nsIContent>&& UnwrapRightContent() {
+    mMovedContent = true;
+    return std::move(mRightContent);
+  }
 
   /**
    * GetLeftmostContent() returns the leftmost content after trying to
    * split twice.  If the node was not split, this returns the original node.
    */
   MOZ_KNOWN_LIVE nsIContent* GetLeftmostContent() const {
+    MOZ_ASSERT(!mMovedContent);
     return mLeftContent ? mLeftContent
                         : (mMiddleContent ? mMiddleContent : mRightContent);
   }
   template <typename ContentNodeType>
   MOZ_KNOWN_LIVE ContentNodeType* GetLeftmostContentAs() const {
     return ContentNodeType::FromNodeOrNull(GetLeftmostContent());
   }
 
   /**
    * GetRightmostContent() returns the rightmost content after trying to
    * split twice.  If the node was not split, this returns the original node.
    */
   MOZ_KNOWN_LIVE nsIContent* GetRightmostContent() const {
+    MOZ_ASSERT(!mMovedContent);
     return mRightContent ? mRightContent
                          : (mMiddleContent ? mMiddleContent : mLeftContent);
   }
   template <typename ContentNodeType>
   MOZ_KNOWN_LIVE ContentNodeType* GetRightmostContentAs() const {
     return ContentNodeType::FromNodeOrNull(GetRightmostContent());
   }
 
@@ -811,59 +811,58 @@ class MOZ_STACK_CLASS SplitRangeOffFromN
 
   SplitRangeOffFromNodeResult() = delete;
 
   SplitRangeOffFromNodeResult(nsIContent* aLeftContent,
                               nsIContent* aMiddleContent,
                               nsIContent* aRightContent)
       : mLeftContent(aLeftContent),
         mMiddleContent(aMiddleContent),
-        mRightContent(aRightContent),
-        mRv(NS_OK) {}
+        mRightContent(aRightContent) {}
 
   SplitRangeOffFromNodeResult(nsIContent* aLeftContent,
                               nsIContent* aMiddleContent,
                               nsIContent* aRightContent,
                               EditorDOMPoint&& aPointToPutCaret)
       : mLeftContent(aLeftContent),
         mMiddleContent(aMiddleContent),
         mRightContent(aRightContent),
-        mCaretPoint(std::move(aPointToPutCaret)),
-        mRv(NS_OK) {}
-
-  explicit SplitRangeOffFromNodeResult(nsresult aRv) : mRv(aRv) {
-    MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(mRv));
-  }
+        mCaretPoint(std::move(aPointToPutCaret)) {}
 
   SplitRangeOffFromNodeResult(const SplitRangeOffFromNodeResult& aOther) =
       delete;
   SplitRangeOffFromNodeResult& operator=(
       const SplitRangeOffFromNodeResult& aOther) = delete;
-  SplitRangeOffFromNodeResult(SplitRangeOffFromNodeResult&& aOther) = default;
+  SplitRangeOffFromNodeResult(SplitRangeOffFromNodeResult&& aOther) noexcept
+      : mLeftContent(std::move(aOther.mLeftContent)),
+        mMiddleContent(std::move(aOther.mMiddleContent)),
+        mRightContent(std::move(aOther.mRightContent)),
+        mCaretPoint(std::move(aOther.mCaretPoint)) {
+    MOZ_ASSERT(!aOther.mMovedContent);
+  }
   SplitRangeOffFromNodeResult& operator=(SplitRangeOffFromNodeResult&& aOther) =
-      default;
+      delete;  // due to bug 1792638
 
 #ifdef DEBUG
   ~SplitRangeOffFromNodeResult() {
-    MOZ_ASSERT_IF(isOk(), !mCaretPoint.IsSet() || mHandledCaretPoint);
+    MOZ_ASSERT(!mCaretPoint.IsSet() || mHandledCaretPoint);
   }
 #endif
 
  private:
   MOZ_KNOWN_LIVE nsCOMPtr<nsIContent> mLeftContent;
   MOZ_KNOWN_LIVE nsCOMPtr<nsIContent> mMiddleContent;
   MOZ_KNOWN_LIVE nsCOMPtr<nsIContent> mRightContent;
 
   // The point which is a good point to put caret from point of view the
   // splitter.
   EditorDOMPoint mCaretPoint;
 
-  nsresult mRv;
-
   bool mutable mHandledCaretPoint = false;
+  bool mutable mMovedContent = false;
 };
 
 /*****************************************************************************
  * SplitRangeOffResult class is a simple class for methods which splits
  * specific ancestor elements at 2 DOM points.
  *****************************************************************************/
 class MOZ_STACK_CLASS SplitRangeOffResult final {
  public:
--- a/editor/libeditor/HTMLEditSubActionHandler.cpp
+++ b/editor/libeditor/HTMLEditSubActionHandler.cpp
@@ -17,16 +17,17 @@
 #include "HTMLEditHelpers.h"
 #include "HTMLEditUtils.h"
 #include "PendingStyles.h"  // for SpecifiedStyle
 #include "WSRunObject.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/ContentIterator.h"
+#include "mozilla/HTMLEditHelpers.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/OwningNonNull.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/RangeUtils.h"
 #include "mozilla/StaticPrefs_editor.h"  // for StaticPrefs::editor_*
@@ -5198,94 +5199,103 @@ Result<EditActionResult, nsresult> HTMLE
       NS_WARNING("Selection::SetBaseAndExtentInLimiter() failed");
       return Err(error.StealNSResult());
     }
   }
 
   // HandleOutdentAtSelectionInternal() creates AutoSelectionRestorer.
   // Therefore, even if it returns NS_OK, the editor might have been destroyed
   // at restoring Selection.
-  SplitRangeOffFromNodeResult outdentResult =
+  Result<SplitRangeOffFromNodeResult, nsresult> outdentResult =
       HandleOutdentAtSelectionInternal(aEditingHost);
   if (NS_WARN_IF(Destroyed())) {
+    if (outdentResult.isOk()) {
+      outdentResult.inspect().IgnoreCaretPointSuggestion();
+    }
     return Err(NS_ERROR_EDITOR_DESTROYED);
   }
-  if (outdentResult.isErr()) {
+  if (MOZ_UNLIKELY(outdentResult.isErr())) {
     NS_WARNING("HTMLEditor::HandleOutdentAtSelectionInternal() failed");
-    return Err(outdentResult.unwrapErr());
-  }
+    return outdentResult.propagateErr();
+  }
+  SplitRangeOffFromNodeResult unwrappedOutdentResult = outdentResult.unwrap();
 
   // Make sure selection didn't stick to last piece of content in old bq (only
   // a problem for collapsed selections)
-  if (!outdentResult.GetLeftContent() && !outdentResult.GetRightContent()) {
+  if (!unwrappedOutdentResult.GetLeftContent() &&
+      !unwrappedOutdentResult.GetRightContent()) {
     return EditActionResult::HandledResult();
   }
 
   if (!SelectionRef().IsCollapsed()) {
     return EditActionResult::HandledResult();
   }
 
   // Push selection past end of left element of last split indented element.
-  if (outdentResult.GetLeftContent()) {
+  if (unwrappedOutdentResult.GetLeftContent()) {
     const nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return EditActionResult::HandledResult();
     }
     const RangeBoundary& atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return Err(NS_ERROR_FAILURE);
     }
-    if (atStartOfSelection.Container() == outdentResult.GetLeftContent() ||
+    if (atStartOfSelection.Container() ==
+            unwrappedOutdentResult.GetLeftContent() ||
         EditorUtils::IsDescendantOf(*atStartOfSelection.Container(),
-                                    *outdentResult.GetLeftContent())) {
+                                    *unwrappedOutdentResult.GetLeftContent())) {
       // Selection is inside the left node - push it past it.
       EditorRawDOMPoint afterRememberedLeftBQ(
-          EditorRawDOMPoint::After(*outdentResult.GetLeftContent()));
+          EditorRawDOMPoint::After(*unwrappedOutdentResult.GetLeftContent()));
       NS_WARNING_ASSERTION(
           afterRememberedLeftBQ.IsSet(),
           "Failed to set after remembered left blockquote element");
       nsresult rv = CollapseSelectionTo(afterRememberedLeftBQ);
       if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
         return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       NS_WARNING_ASSERTION(
           NS_SUCCEEDED(rv),
           "EditorBase::CollapseSelectionTo() failed, but ignored");
     }
   }
   // And pull selection before beginning of right element of last split
   // indented element.
-  if (outdentResult.GetRightContent()) {
+  if (unwrappedOutdentResult.GetRightContent()) {
     const nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return EditActionResult::HandledResult();
     }
     const RangeBoundary& atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return Err(NS_ERROR_FAILURE);
     }
-    if (atStartOfSelection.Container() == outdentResult.GetRightContent() ||
-        EditorUtils::IsDescendantOf(*atStartOfSelection.Container(),
-                                    *outdentResult.GetRightContent())) {
+    if (atStartOfSelection.Container() ==
+            unwrappedOutdentResult.GetRightContent() ||
+        EditorUtils::IsDescendantOf(
+            *atStartOfSelection.Container(),
+            *unwrappedOutdentResult.GetRightContent())) {
       // Selection is inside the right element - push it before it.
-      EditorRawDOMPoint atRememberedRightBQ(outdentResult.GetRightContent());
+      EditorRawDOMPoint atRememberedRightBQ(
+          unwrappedOutdentResult.GetRightContent());
       nsresult rv = CollapseSelectionTo(atRememberedRightBQ);
       if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
         return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       NS_WARNING_ASSERTION(
           NS_SUCCEEDED(rv),
           "EditorBase::CollapseSelectionTo() failed, but ignored");
     }
   }
   return EditActionResult::HandledResult();
 }
 
-SplitRangeOffFromNodeResult HTMLEditor::HandleOutdentAtSelectionInternal(
-    const Element& aEditingHost) {
+Result<SplitRangeOffFromNodeResult, nsresult>
+HTMLEditor::HandleOutdentAtSelectionInternal(const Element& aEditingHost) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   AutoSelectionRestorer restoreSelectionLater(*this);
 
   bool useCSS = IsCSSEnabled();
 
   // Convert the selection ranges into "promoted" selection ranges: this
   // basically just expands the range to include the immediate block parent,
@@ -5298,33 +5308,33 @@ SplitRangeOffFromNodeResult HTMLEditor::
         EditSubAction::eOutdent, aEditingHost);
     nsresult rv = extendedSelectionRanges.CollectEditTargetNodes(
         *this, arrayOfContents, EditSubAction::eOutdent,
         AutoRangeArray::CollectNonEditableNodes::Yes);
     if (NS_FAILED(rv)) {
       NS_WARNING(
           "AutoRangeArray::CollectEditTargetNodes(EditSubAction::eOutdent, "
           "CollectNonEditableNodes::Yes) failed");
-      return SplitRangeOffFromNodeResult(rv);
-    }
-    const Result<EditorDOMPoint, nsresult> splitAtBRElementsResult =
+      return Err(rv);
+    }
+    Result<EditorDOMPoint, nsresult> splitAtBRElementsResult =
         MaybeSplitElementsAtEveryBRElement(arrayOfContents,
                                            EditSubAction::eOutdent);
     if (MOZ_UNLIKELY(splitAtBRElementsResult.isErr())) {
       NS_WARNING(
           "HTMLEditor::MaybeSplitElementsAtEveryBRElement(EditSubAction::"
           "eOutdent) failed");
-      return SplitRangeOffFromNodeResult(splitAtBRElementsResult.inspectErr());
+      return splitAtBRElementsResult.propagateErr();
     }
     if (AllowsTransactionsToChangeSelection() &&
         splitAtBRElementsResult.inspect().IsSet()) {
       nsresult rv = CollapseSelectionTo(splitAtBRElementsResult.inspect());
       if (NS_FAILED(rv)) {
         NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-        return SplitRangeOffFromNodeResult(rv);
+        return Err(rv);
       }
     }
   }
 
   nsCOMPtr<nsIContent> leftContentOfLastOutdented;
   nsCOMPtr<nsIContent> middleContentOfLastOutdented;
   nsCOMPtr<nsIContent> rightContentOfLastOutdented;
   RefPtr<Element> indentedParentElement;
@@ -5339,154 +5349,170 @@ SplitRangeOffFromNodeResult HTMLEditor::
 
     // If it's a `<blockquote>`, remove it to outdent its children.
     if (content->IsHTMLElement(nsGkAtoms::blockquote)) {
       // If we've already found an ancestor block element indented, we need to
       // split it and remove the block element first.
       if (indentedParentElement) {
         NS_WARNING_ASSERTION(indentedParentElement == content,
                              "Indented parent element is not the <blockquote>");
-        SplitRangeOffFromNodeResult outdentResult = OutdentPartOfBlock(
-            *indentedParentElement, *firstContentToBeOutdented,
-            *lastContentToBeOutdented, indentedParentIndentedWith,
-            aEditingHost);
-        if (outdentResult.isErr()) {
+        Result<SplitRangeOffFromNodeResult, nsresult> outdentResult =
+            OutdentPartOfBlock(*indentedParentElement,
+                               *firstContentToBeOutdented,
+                               *lastContentToBeOutdented,
+                               indentedParentIndentedWith, aEditingHost);
+        if (MOZ_UNLIKELY(outdentResult.isErr())) {
           NS_WARNING("HTMLEditor::OutdentPartOfBlock() failed");
           return outdentResult;
         }
-        leftContentOfLastOutdented = outdentResult.GetLeftContent();
-        middleContentOfLastOutdented = outdentResult.GetMiddleContent();
-        rightContentOfLastOutdented = outdentResult.GetRightContent();
+        SplitRangeOffFromNodeResult unwrappedOutdentResult =
+            outdentResult.unwrap();
+        unwrappedOutdentResult.IgnoreCaretPointSuggestion();
+        leftContentOfLastOutdented = unwrappedOutdentResult.UnwrapLeftContent();
+        middleContentOfLastOutdented =
+            unwrappedOutdentResult.UnwrapMiddleContent();
+        rightContentOfLastOutdented =
+            unwrappedOutdentResult.UnwrapRightContent();
         indentedParentElement = nullptr;
         firstContentToBeOutdented = nullptr;
         lastContentToBeOutdented = nullptr;
         indentedParentIndentedWith = BlockIndentedWith::HTML;
       }
-      const Result<EditorDOMPoint, nsresult> unwrapBlockquoteElementResult =
+      Result<EditorDOMPoint, nsresult> unwrapBlockquoteElementResult =
           RemoveBlockContainerWithTransaction(
               MOZ_KnownLive(*content->AsElement()));
       if (MOZ_UNLIKELY(unwrapBlockquoteElementResult.isErr())) {
         NS_WARNING("HTMLEditor::RemoveBlockContainerWithTransaction() failed");
-        return SplitRangeOffFromNodeResult(
-            unwrapBlockquoteElementResult.inspectErr());
+        return unwrapBlockquoteElementResult.propagateErr();
       }
       const EditorDOMPoint& pointToPutCaret =
           unwrapBlockquoteElementResult.inspect();
       if (AllowsTransactionsToChangeSelection() && pointToPutCaret.IsSet()) {
         nsresult rv = CollapseSelectionTo(pointToPutCaret);
         if (NS_FAILED(rv)) {
           NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-          return SplitRangeOffFromNodeResult(rv);
+          return Err(rv);
         }
       }
       continue;
     }
 
     // If we're using CSS and the node is a block element, check its start
     // margin whether it's indented with CSS.
     if (useCSS && HTMLEditUtils::IsBlockElement(content)) {
       nsStaticAtom& marginProperty =
           MarginPropertyAtomForIndent(MOZ_KnownLive(content));
       if (NS_WARN_IF(Destroyed())) {
-        return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+        return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       nsAutoString value;
       DebugOnly<nsresult> rvIgnored =
           CSSEditUtils::GetSpecifiedProperty(content, marginProperty, value);
       if (NS_WARN_IF(Destroyed())) {
-        return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+        return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       NS_WARNING_ASSERTION(
           NS_SUCCEEDED(rvIgnored),
           "CSSEditUtils::GetSpecifiedProperty() failed, but ignored");
       float startMargin = 0;
       RefPtr<nsAtom> unit;
       CSSEditUtils::ParseLength(value, &startMargin, getter_AddRefs(unit));
       // If indented with CSS, we should decrease the start margin.
       if (startMargin > 0) {
         const Result<EditorDOMPoint, nsresult> pointToPutCaretOrError =
             ChangeMarginStart(MOZ_KnownLive(*content->AsElement()),
                               ChangeMargin::Decrease, aEditingHost);
         if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
           if (NS_WARN_IF(pointToPutCaretOrError.inspectErr() ==
                          NS_ERROR_EDITOR_DESTROYED)) {
-            return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+            return Err(NS_ERROR_EDITOR_DESTROYED);
           }
           NS_WARNING(
               "HTMLEditor::ChangeMarginStart(ChangeMargin::Decrease) failed, "
               "but ignored");
         } else if (AllowsTransactionsToChangeSelection() &&
                    pointToPutCaretOrError.inspect().IsSet()) {
           nsresult rv = CollapseSelectionTo(pointToPutCaretOrError.inspect());
           if (NS_FAILED(rv)) {
             NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-            return SplitRangeOffFromNodeResult(rv);
+            return Err(rv);
           }
         }
         continue;
       }
     }
 
     // If it's a list item, we should treat as that it "indents" its children.
     if (HTMLEditUtils::IsListItem(content)) {
       // If it is a list item, that means we are not outdenting whole list.
       // XXX I don't understand this sentence...  We may meet parent list
       //     element, no?
       if (indentedParentElement) {
-        SplitRangeOffFromNodeResult outdentResult = OutdentPartOfBlock(
-            *indentedParentElement, *firstContentToBeOutdented,
-            *lastContentToBeOutdented, indentedParentIndentedWith,
-            aEditingHost);
-        if (outdentResult.isErr()) {
+        Result<SplitRangeOffFromNodeResult, nsresult> outdentResult =
+            OutdentPartOfBlock(*indentedParentElement,
+                               *firstContentToBeOutdented,
+                               *lastContentToBeOutdented,
+                               indentedParentIndentedWith, aEditingHost);
+        if (MOZ_UNLIKELY(outdentResult.isErr())) {
           NS_WARNING("HTMLEditor::OutdentPartOfBlock() failed");
           return outdentResult;
         }
-        leftContentOfLastOutdented = outdentResult.GetLeftContent();
-        middleContentOfLastOutdented = outdentResult.GetMiddleContent();
-        rightContentOfLastOutdented = outdentResult.GetRightContent();
+        SplitRangeOffFromNodeResult unwrappedOutdentResult =
+            outdentResult.unwrap();
+        unwrappedOutdentResult.IgnoreCaretPointSuggestion();
+        leftContentOfLastOutdented = unwrappedOutdentResult.UnwrapLeftContent();
+        middleContentOfLastOutdented =
+            unwrappedOutdentResult.UnwrapMiddleContent();
+        rightContentOfLastOutdented =
+            unwrappedOutdentResult.UnwrapRightContent();
         indentedParentElement = nullptr;
         firstContentToBeOutdented = nullptr;
         lastContentToBeOutdented = nullptr;
         indentedParentIndentedWith = BlockIndentedWith::HTML;
       }
       // XXX `content` could become different element since
       //     `OutdentPartOfBlock()` may run mutation event listeners.
       nsresult rv = LiftUpListItemElement(MOZ_KnownLive(*content->AsElement()),
                                           LiftUpFromAllParentListElements::No);
       if (NS_FAILED(rv)) {
         NS_WARNING(
             "HTMLEditor::LiftUpListItemElement(LiftUpFromAllParentListElements:"
             ":No) failed");
-        return SplitRangeOffFromNodeResult(rv);
+        return Err(rv);
       }
       continue;
     }
 
     // If we've found an ancestor block element which indents its children
     // and the current node is NOT a descendant of it, we should remove it to
     // outdent its children.  Otherwise, i.e., current node is a descendant of
     // it, we meet new node which should be outdented when the indented parent
     // is removed.
     if (indentedParentElement) {
       if (EditorUtils::IsDescendantOf(*content, *indentedParentElement)) {
         // Extend the range to be outdented at removing the
         // indentedParentElement.
         lastContentToBeOutdented = content;
         continue;
       }
-      SplitRangeOffFromNodeResult outdentResult = OutdentPartOfBlock(
-          *indentedParentElement, *firstContentToBeOutdented,
-          *lastContentToBeOutdented, indentedParentIndentedWith, aEditingHost);
-      if (outdentResult.isErr()) {
+      Result<SplitRangeOffFromNodeResult, nsresult> outdentResult =
+          OutdentPartOfBlock(*indentedParentElement, *firstContentToBeOutdented,
+                             *lastContentToBeOutdented,
+                             indentedParentIndentedWith, aEditingHost);
+      if (MOZ_UNLIKELY(outdentResult.isErr())) {
         NS_WARNING("HTMLEditor::OutdentPartOfBlock() failed");
         return outdentResult;
       }
-      leftContentOfLastOutdented = outdentResult.GetLeftContent();
-      middleContentOfLastOutdented = outdentResult.GetMiddleContent();
-      rightContentOfLastOutdented = outdentResult.GetRightContent();
+      SplitRangeOffFromNodeResult unwrappedOutdentResult =
+          outdentResult.unwrap();
+      unwrappedOutdentResult.IgnoreCaretPointSuggestion();
+      leftContentOfLastOutdented = unwrappedOutdentResult.UnwrapLeftContent();
+      middleContentOfLastOutdented =
+          unwrappedOutdentResult.UnwrapMiddleContent();
+      rightContentOfLastOutdented = unwrappedOutdentResult.UnwrapRightContent();
       indentedParentElement = nullptr;
       firstContentToBeOutdented = nullptr;
       lastContentToBeOutdented = nullptr;
       // curBlockIndentedWith = HTMLEditor::BlockIndentedWith::HTML;
 
       // Then, we need to look for next indentedParentElement.
     }
 
@@ -5509,26 +5535,26 @@ SplitRangeOffFromNodeResult HTMLEditor::
       if (!useCSS) {
         continue;
       }
 
       nsCOMPtr<nsINode> grandParentNode = parentContent->GetParentNode();
       nsStaticAtom& marginProperty =
           MarginPropertyAtomForIndent(MOZ_KnownLive(content));
       if (NS_WARN_IF(Destroyed())) {
-        return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+        return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_WARN_IF(grandParentNode != parentContent->GetParentNode())) {
-        return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
+        return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
       }
       nsAutoString value;
       DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetSpecifiedProperty(
           *parentContent, marginProperty, value);
       if (NS_WARN_IF(Destroyed())) {
-        return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+        return Err(NS_ERROR_EDITOR_DESTROYED);
       }
       NS_WARNING_ASSERTION(
           NS_SUCCEEDED(rvIgnored),
           "CSSEditUtils::GetSpecifiedProperty() failed, but ignored");
       // XXX Now, editing host may become different element.  If so, shouldn't
       //     we stop this handling?
       float startMargin;
       RefPtr<nsAtom> unit;
@@ -5556,33 +5582,32 @@ SplitRangeOffFromNodeResult HTMLEditor::
     // XXX This is buggy.  When both lists' item types are different,
     //     we create invalid tree.  E.g., `<ul>` may have `<dd>` as its
     //     list item element.
     if (HTMLEditUtils::IsAnyListElement(atContent.GetContainer())) {
       if (!HTMLEditUtils::IsAnyListElement(content)) {
         continue;
       }
       // Just unwrap this sublist
-      const Result<EditorDOMPoint, nsresult> unwrapSubListElementResult =
+      Result<EditorDOMPoint, nsresult> unwrapSubListElementResult =
           RemoveBlockContainerWithTransaction(
               MOZ_KnownLive(*content->AsElement()));
       if (MOZ_UNLIKELY(unwrapSubListElementResult.isErr())) {
         NS_WARNING("HTMLEditor::RemoveBlockContainerWithTransaction() failed");
-        return SplitRangeOffFromNodeResult(
-            unwrapSubListElementResult.inspectErr());
+        return unwrapSubListElementResult.propagateErr();
       }
       const EditorDOMPoint& pointToPutCaret =
           unwrapSubListElementResult.inspect();
       if (!AllowsTransactionsToChangeSelection() || !pointToPutCaret.IsSet()) {
         continue;
       }
       nsresult rv = CollapseSelectionTo(pointToPutCaret);
       if (NS_FAILED(rv)) {
         NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-        return SplitRangeOffFromNodeResult(rv);
+        return Err(rv);
       }
       continue;
     }
 
     // If current content is a list element but its parent is not a list
     // element, move children to where it is and remove it from the tree.
     if (HTMLEditUtils::IsAnyListElement(content)) {
       // XXX If mutation event listener appends new children forever, this
@@ -5593,186 +5618,190 @@ SplitRangeOffFromNodeResult HTMLEditor::
         if (HTMLEditUtils::IsListItem(lastChildContent)) {
           nsresult rv = LiftUpListItemElement(
               MOZ_KnownLive(*lastChildContent->AsElement()),
               LiftUpFromAllParentListElements::No);
           if (NS_FAILED(rv)) {
             NS_WARNING(
                 "HTMLEditor::LiftUpListItemElement("
                 "LiftUpFromAllParentListElements::No) failed");
-            return SplitRangeOffFromNodeResult(rv);
+            return Err(rv);
           }
           continue;
         }
 
         if (HTMLEditUtils::IsAnyListElement(lastChildContent)) {
           // We have an embedded list, so move it out from under the parent
           // list. Be sure to put it after the parent list because this
           // loop iterates backwards through the parent's list of children.
           EditorDOMPoint afterCurrentList(EditorDOMPoint::After(atContent));
           NS_WARNING_ASSERTION(
               afterCurrentList.IsSet(),
               "Failed to set it to after current list element");
           Result<MoveNodeResult, nsresult> moveListElementResult =
               MoveNodeWithTransaction(*lastChildContent, afterCurrentList);
           if (MOZ_UNLIKELY(moveListElementResult.isErr())) {
             NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
-            return SplitRangeOffFromNodeResult(
-                moveListElementResult.unwrapErr());
+            return moveListElementResult.propagateErr();
           }
           nsresult rv = moveListElementResult.inspect().SuggestCaretPointTo(
               *this, {SuggestCaret::OnlyIfHasSuggestion,
                       SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
                       SuggestCaret::AndIgnoreTrivialError});
           if (NS_FAILED(rv)) {
             NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
-            return SplitRangeOffFromNodeResult(rv);
+            return Err(rv);
           }
           NS_WARNING_ASSERTION(
               rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
               "MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
           continue;
         }
 
         // Delete any non-list items for now
         // XXX Chrome moves it from the list element.  We should follow it.
         nsresult rv = DeleteNodeWithTransaction(*lastChildContent);
         if (NS_FAILED(rv)) {
           NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
-          return SplitRangeOffFromNodeResult(rv);
+          return Err(rv);
         }
       }
       // Delete the now-empty list
-      const Result<EditorDOMPoint, nsresult> unwrapListElementResult =
+      Result<EditorDOMPoint, nsresult> unwrapListElementResult =
           RemoveBlockContainerWithTransaction(
               MOZ_KnownLive(*content->AsElement()));
       if (MOZ_UNLIKELY(unwrapListElementResult.isErr())) {
         NS_WARNING("HTMLEditor::RemoveBlockContainerWithTransaction() failed");
-        return SplitRangeOffFromNodeResult(
-            unwrapListElementResult.inspectErr());
+        return unwrapListElementResult.propagateErr();
       }
       const EditorDOMPoint& pointToPutCaret = unwrapListElementResult.inspect();
       if (!AllowsTransactionsToChangeSelection() || !pointToPutCaret.IsSet()) {
         continue;
       }
       nsresult rv = CollapseSelectionTo(pointToPutCaret);
       if (NS_FAILED(rv)) {
         NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-        return SplitRangeOffFromNodeResult(rv);
+        return Err(rv);
       }
       continue;
     }
 
     if (useCSS) {
       if (RefPtr<Element> element = content->GetAsElementOrParentElement()) {
         const Result<EditorDOMPoint, nsresult> pointToPutCaretOrError =
             ChangeMarginStart(*element, ChangeMargin::Decrease, aEditingHost);
         if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
           if (NS_WARN_IF(pointToPutCaretOrError.inspectErr() ==
                          NS_ERROR_EDITOR_DESTROYED)) {
-            return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+            return Err(NS_ERROR_EDITOR_DESTROYED);
           }
           NS_WARNING(
               "HTMLEditor::ChangeMarginStart(ChangeMargin::Decrease) failed, "
               "but ignored");
         } else if (AllowsTransactionsToChangeSelection() &&
                    pointToPutCaretOrError.inspect().IsSet()) {
           nsresult rv = CollapseSelectionTo(pointToPutCaretOrError.inspect());
           if (NS_FAILED(rv)) {
             NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-            return SplitRangeOffFromNodeResult(rv);
+            return Err(rv);
           }
         }
       }
       continue;
     }
   }
 
   if (!indentedParentElement) {
     return SplitRangeOffFromNodeResult(leftContentOfLastOutdented,
                                        middleContentOfLastOutdented,
                                        rightContentOfLastOutdented);
   }
 
   // We have a <blockquote> we haven't finished handling.
-  SplitRangeOffFromNodeResult outdentResult = OutdentPartOfBlock(
-      *indentedParentElement, *firstContentToBeOutdented,
-      *lastContentToBeOutdented, indentedParentIndentedWith, aEditingHost);
+  Result<SplitRangeOffFromNodeResult, nsresult> outdentResult =
+      OutdentPartOfBlock(*indentedParentElement, *firstContentToBeOutdented,
+                         *lastContentToBeOutdented, indentedParentIndentedWith,
+                         aEditingHost);
   NS_WARNING_ASSERTION(outdentResult.isOk(),
                        "HTMLEditor::OutdentPartOfBlock() failed");
   return outdentResult;
 }
 
-SplitRangeOffFromNodeResult
+Result<SplitRangeOffFromNodeResult, nsresult>
 HTMLEditor::RemoveBlockContainerElementWithTransactionBetween(
     Element& aBlockContainerElement, nsIContent& aStartOfRange,
     nsIContent& aEndOfRange) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   EditorDOMPoint pointToPutCaret;
-  SplitRangeOffFromNodeResult splitResult = SplitRangeOffFromBlock(
-      aBlockContainerElement, aStartOfRange, aEndOfRange);
-  if (splitResult.EditorDestroyed()) {
-    NS_WARNING("HTMLEditor::SplitRangeOffFromBlock() failed");
-    return splitResult;
-  }
-  if (splitResult.isOk()) {
-    splitResult.MoveCaretPointTo(pointToPutCaret,
-                                 {SuggestCaret::OnlyIfHasSuggestion});
-  } else {
+  Result<SplitRangeOffFromNodeResult, nsresult> splitResult =
+      SplitRangeOffFromBlock(aBlockContainerElement, aStartOfRange,
+                             aEndOfRange);
+  if (MOZ_UNLIKELY(splitResult.isErr())) {
+    if (splitResult.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
+      NS_WARNING("HTMLEditor::SplitRangeOffFromBlock() failed");
+      return splitResult;
+    }
     NS_WARNING(
         "HTMLEditor::SplitRangeOffFromBlock() failed, but might be ignored");
-  }
+    return SplitRangeOffFromNodeResult(nullptr, nullptr, nullptr);
+  }
+  SplitRangeOffFromNodeResult unwrappedSplitResult = splitResult.unwrap();
+  unwrappedSplitResult.MoveCaretPointTo(pointToPutCaret,
+                                        {SuggestCaret::OnlyIfHasSuggestion});
 
   // Even if either split aBlockContainerElement or did not split it, we should
   // unwrap the right most element which is split from aBlockContainerElement
   // (or aBlockContainerElement itself if it was not split without errors).
-  if (Element* rightmostElement =
-          splitResult.GetRightmostContentAs<Element>()) {
-    MOZ_DIAGNOSTIC_ASSERT(splitResult.isOk());
-    MOZ_ASSERT_IF(
-        GetSplitNodeDirection() == SplitNodeDirection::LeftNodeIsNewOne,
-        rightmostElement == &aBlockContainerElement);
-    // MOZ_KnownLive(rightmostElement) because it's grabbed by splitResult.
+  Element* rightmostElement =
+      unwrappedSplitResult.GetRightmostContentAs<Element>();
+  MOZ_ASSERT(rightmostElement);
+  if (NS_WARN_IF(!rightmostElement)) {
+    return Err(NS_ERROR_FAILURE);
+  }
+  MOZ_ASSERT_IF(GetSplitNodeDirection() == SplitNodeDirection::LeftNodeIsNewOne,
+                rightmostElement == &aBlockContainerElement);
+  {
+    // MOZ_KnownLive(rightmostElement) because it's grabbed by
+    // unwrappedSplitResult.
     Result<EditorDOMPoint, nsresult> unwrapBlockElementResult =
         RemoveBlockContainerWithTransaction(MOZ_KnownLive(*rightmostElement));
-    if (unwrapBlockElementResult.isErr()) {
+    if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
       NS_WARNING("HTMLEditor::RemoveBlockContainerWithTransaction() failed");
-      return SplitRangeOffFromNodeResult(unwrapBlockElementResult.inspectErr());
+      return unwrapBlockElementResult.propagateErr();
     }
     if (unwrapBlockElementResult.inspect().IsSet()) {
       pointToPutCaret = unwrapBlockElementResult.unwrap();
     }
-  } else {
-    MOZ_DIAGNOSTIC_ASSERT(splitResult.isErr());
-  }
-
-  return SplitRangeOffFromNodeResult(splitResult.GetLeftContent(), nullptr,
-                                     splitResult.GetRightContent(),
-                                     std::move(pointToPutCaret));
+  }
+
+  return SplitRangeOffFromNodeResult(
+      unwrappedSplitResult.GetLeftContent(), nullptr,
+      unwrappedSplitResult.GetRightContent(), std::move(pointToPutCaret));
 }
 
-SplitRangeOffFromNodeResult HTMLEditor::SplitRangeOffFromBlock(
-    Element& aBlockElement, nsIContent& aStartOfMiddleElement,
-    nsIContent& aEndOfMiddleElement) {
+Result<SplitRangeOffFromNodeResult, nsresult>
+HTMLEditor::SplitRangeOffFromBlock(Element& aBlockElement,
+                                   nsIContent& aStartOfMiddleElement,
+                                   nsIContent& aEndOfMiddleElement) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   // aStartOfMiddleElement and aEndOfMiddleElement must be exclusive
   // descendants of aBlockElement.
   MOZ_ASSERT(EditorUtils::IsDescendantOf(aStartOfMiddleElement, aBlockElement));
   MOZ_ASSERT(EditorUtils::IsDescendantOf(aEndOfMiddleElement, aBlockElement));
 
   EditorDOMPoint pointToPutCaret;
   // Split at the start.
   SplitNodeResult splitAtStartResult = SplitNodeDeepWithTransaction(
       aBlockElement, EditorDOMPoint(&aStartOfMiddleElement),
       SplitAtEdges::eDoNotCreateEmptyContainer);
   if (splitAtStartResult.EditorDestroyed()) {
     NS_WARNING("HTMLEditor::SplitNodeDeepWithTransaction() failed (at left)");
-    return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+    return Err(NS_ERROR_EDITOR_DESTROYED);
   }
   NS_WARNING_ASSERTION(
       splitAtStartResult.isOk(),
       "HTMLEditor::SplitNodeDeepWithTransaction(SplitAtEdges::"
       "eDoNotCreateEmptyContainer) at start of middle element failed");
   splitAtStartResult.MoveCaretPointTo(pointToPutCaret,
                                       {SuggestCaret::OnlyIfHasSuggestion});
 
@@ -5784,17 +5813,17 @@ SplitRangeOffFromNodeResult HTMLEditor::
           : &aBlockElement;
   // MOZ_KnownLive(rightElement) because it's grabbed by splitAtStartResult or
   // aBlockElement whose lifetime is guaranteed by the caller.
   SplitNodeResult splitAtEndResult =
       SplitNodeDeepWithTransaction(MOZ_KnownLive(*rightElement), atAfterEnd,
                                    SplitAtEdges::eDoNotCreateEmptyContainer);
   if (splitAtEndResult.EditorDestroyed()) {
     NS_WARNING("HTMLEditor::SplitNodeDeepWithTransaction() failed (at right)");
-    return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+    return Err(NS_ERROR_EDITOR_DESTROYED);
   }
   NS_WARNING_ASSERTION(
       splitAtEndResult.isOk(),
       "HTMLEditor::SplitNodeDeepWithTransaction(SplitAtEdges::"
       "eDoNotCreateEmptyContainer) after end of middle element failed");
   splitAtEndResult.MoveCaretPointTo(pointToPutCaret,
                                     {SuggestCaret::OnlyIfHasSuggestion});
 
@@ -5815,96 +5844,87 @@ SplitRangeOffFromNodeResult HTMLEditor::
     return SplitRangeOffFromNodeResult(
         nullptr, splitAtEndResult.GetPreviousContent(),
         splitAtEndResult.GetNextContent(), std::move(pointToPutCaret));
   }
   return SplitRangeOffFromNodeResult(nullptr, &aBlockElement, nullptr,
                                      std::move(pointToPutCaret));
 }
 
-SplitRangeOffFromNodeResult HTMLEditor::OutdentPartOfBlock(
+Result<SplitRangeOffFromNodeResult, nsresult> HTMLEditor::OutdentPartOfBlock(
     Element& aBlockElement, nsIContent& aStartOfOutdent,
     nsIContent& aEndOfOutdent, BlockIndentedWith aBlockIndentedWith,
     const Element& aEditingHost) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
-  SplitRangeOffFromNodeResult splitResult =
+  Result<SplitRangeOffFromNodeResult, nsresult> splitResult =
       SplitRangeOffFromBlock(aBlockElement, aStartOfOutdent, aEndOfOutdent);
-  if (splitResult.EditorDestroyed()) {
+  if (MOZ_UNLIKELY(splitResult.isErr())) {
     NS_WARNING("HTMLEditor::SplitRangeOffFromBlock() failed");
-    return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
-  }
-
-  if (!splitResult.GetMiddleContentAs<Element>()) {
+    return splitResult;
+  }
+
+  SplitRangeOffFromNodeResult unwrappedSplitResult = splitResult.unwrap();
+  Element* middleElement = unwrappedSplitResult.GetMiddleContentAs<Element>();
+  if (MOZ_UNLIKELY(!middleElement)) {
     NS_WARNING(
         "HTMLEditor::SplitRangeOffFromBlock() didn't return middle content");
-    splitResult.IgnoreCaretPointSuggestion();
-    return SplitRangeOffFromNodeResult(NS_ERROR_FAILURE);
-  }
-
-  if (splitResult.isOk()) {
-    nsresult rv = splitResult.SuggestCaretPointTo(
-        *this, {SuggestCaret::OnlyIfHasSuggestion,
-                SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
-                SuggestCaret::AndIgnoreTrivialError});
-    if (NS_FAILED(rv)) {
-      NS_WARNING("SplitRangeOffFromNodeResult::SuggestCaretPointTo() failed");
-      return SplitRangeOffFromNodeResult(rv);
-    }
-    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
-                         "SplitRangeOffFromNodeResult::SuggestCaretPointTo() "
-                         "failed, but ignored");
-  } else {
-    NS_WARNING(
-        "HTMLEditor::SplitRangeOffFromBlock() failed, but might be ignored");
-  }
+    unwrappedSplitResult.IgnoreCaretPointSuggestion();
+    return Err(NS_ERROR_FAILURE);
+  }
+
+  nsresult rv = unwrappedSplitResult.SuggestCaretPointTo(
+      *this, {SuggestCaret::OnlyIfHasSuggestion,
+              SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
+              SuggestCaret::AndIgnoreTrivialError});
+  if (NS_FAILED(rv)) {
+    NS_WARNING("SplitRangeOffFromNodeResult::SuggestCaretPointTo() failed");
+    return Err(rv);
+  }
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "SplitRangeOffFromNodeResult::SuggestCaretPointTo() "
+                       "failed, but ignored");
 
   if (aBlockIndentedWith == BlockIndentedWith::HTML) {
-    // MOZ_KnownLive: perhaps, it does not work with template methods.
+    // MOZ_KnownLive(middleElement) because of grabbed by unwrappedSplitResult.
     Result<EditorDOMPoint, nsresult> unwrapBlockElementResult =
-        RemoveBlockContainerWithTransaction(
-            MOZ_KnownLive(*splitResult.GetMiddleContentAs<Element>()));
+        RemoveBlockContainerWithTransaction(MOZ_KnownLive(*middleElement));
     if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
       NS_WARNING("HTMLEditor::RemoveBlockContainerWithTransaction() failed");
-      return SplitRangeOffFromNodeResult(unwrapBlockElementResult.inspectErr());
+      return unwrapBlockElementResult.propagateErr();
     }
     const EditorDOMPoint& pointToPutCaret = unwrapBlockElementResult.inspect();
     if (AllowsTransactionsToChangeSelection() && pointToPutCaret.IsSet()) {
       nsresult rv = CollapseSelectionTo(pointToPutCaret);
       if (NS_FAILED(rv)) {
         NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-        return SplitRangeOffFromNodeResult(rv);
-      }
-    }
-    return SplitRangeOffFromNodeResult(splitResult.GetLeftContent(), nullptr,
-                                       splitResult.GetRightContent());
-  }
-
-  if (!splitResult.GetMiddleContentAs<Element>()) {
-    return splitResult;
-  }
-
-  // MOZ_KnownLive: perhaps, it does not work with template methods.
-  const Result<EditorDOMPoint, nsresult> pointToPutCaretOrError =
-      ChangeMarginStart(
-          MOZ_KnownLive(*splitResult.GetMiddleContentAs<Element>()),
-          ChangeMargin::Decrease, aEditingHost);
+        return Err(rv);
+      }
+    }
+    return SplitRangeOffFromNodeResult(unwrappedSplitResult.GetLeftContent(),
+                                       nullptr,
+                                       unwrappedSplitResult.GetRightContent());
+  }
+
+  // MOZ_KnownLive(middleElement) because of grabbed by unwrappedSplitResult.
+  Result<EditorDOMPoint, nsresult> pointToPutCaretOrError = ChangeMarginStart(
+      MOZ_KnownLive(*middleElement), ChangeMargin::Decrease, aEditingHost);
   if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
     NS_WARNING("HTMLEditor::ChangeMarginStart(ChangeMargin::Decrease) failed");
-    return SplitRangeOffFromNodeResult(pointToPutCaretOrError.inspectErr());
+    return pointToPutCaretOrError.propagateErr();
   }
   if (AllowsTransactionsToChangeSelection() &&
       pointToPutCaretOrError.inspect().IsSet()) {
     nsresult rv = CollapseSelectionTo(pointToPutCaretOrError.inspect());
     if (NS_FAILED(rv)) {
       NS_WARNING("EditorBase::CollapseSelectionTo() failed");
-      return SplitRangeOffFromNodeResult(rv);
-    }
-  }
-  return splitResult;
+      return Err(rv);
+    }
+  }
+  return unwrappedSplitResult;
 }
 
 Result<CreateElementResult, nsresult> HTMLEditor::ChangeListElementType(
     Element& aListElement, nsAtom& aNewListTag, nsAtom& aNewListItemTag) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   EditorDOMPoint pointToPutCaret;
 
@@ -8265,26 +8285,26 @@ HTMLEditor::RemoveBlockContainerElements
   RefPtr<Element> blockElement;
   nsCOMPtr<nsIContent> firstContent, lastContent;
   EditorDOMPoint pointToPutCaret;
   for (auto& content : aArrayOfContents) {
     // If curNode is an <address>, <p>, <hn>, or <pre>, remove it.
     if (HTMLEditUtils::IsFormatNode(content)) {
       // Process any partial progress saved
       if (blockElement) {
-        SplitRangeOffFromNodeResult unwrapBlockElementResult =
+        Result<SplitRangeOffFromNodeResult, nsresult> unwrapBlockElementResult =
             RemoveBlockContainerElementWithTransactionBetween(
                 *blockElement, *firstContent, *lastContent);
-        if (unwrapBlockElementResult.isErr()) {
+        if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
           NS_WARNING(
               "HTMLEditor::RemoveBlockContainerElementWithTransactionBetween() "
               "failed");
-          return Err(unwrapBlockElementResult.unwrapErr());
-        }
-        unwrapBlockElementResult.MoveCaretPointTo(
+          return unwrapBlockElementResult.propagateErr();
+        }
+        unwrapBlockElementResult.unwrap().MoveCaretPointTo(
             pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
         firstContent = lastContent = blockElement = nullptr;
       }
       if (!EditorUtils::IsEditableContent(content, EditorType::HTML)) {
         continue;
       }
       // Remove current block
       Result<EditorDOMPoint, nsresult> unwrapFormatBlockResult =
@@ -8302,26 +8322,26 @@ HTMLEditor::RemoveBlockContainerElements
 
     // XXX How about, <th>, <thead>, <tfoot>, <dt>, <dl>?
     if (content->IsAnyOfHTMLElements(
             nsGkAtoms::table, nsGkAtoms::tr, nsGkAtoms::tbody, nsGkAtoms::td,
             nsGkAtoms::li, nsGkAtoms::blockquote, nsGkAtoms::div) ||
         HTMLEditUtils::IsAnyListElement(content)) {
       // Process any partial progress saved
       if (blockElement) {
-        SplitRangeOffFromNodeResult unwrapBlockElementResult =
+        Result<SplitRangeOffFromNodeResult, nsresult> unwrapBlockElementResult =
             RemoveBlockContainerElementWithTransactionBetween(
                 *blockElement, *firstContent, *lastContent);
-        if (unwrapBlockElementResult.isErr()) {
+        if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
           NS_WARNING(
               "HTMLEditor::RemoveBlockContainerElementWithTransactionBetween() "
               "failed");
-          return Err(unwrapBlockElementResult.unwrapErr());
-        }
-        unwrapBlockElementResult.MoveCaretPointTo(
+          return unwrapBlockElementResult.propagateErr();
+        }
+        unwrapBlockElementResult.unwrap().MoveCaretPointTo(
             pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
         firstContent = lastContent = blockElement = nullptr;
       }
       if (!EditorUtils::IsEditableContent(content, EditorType::HTML)) {
         continue;
       }
       // Recursion time
       AutoTArray<OwningNonNull<nsIContent>, 24> childContents;
@@ -8345,26 +8365,26 @@ HTMLEditor::RemoveBlockContainerElements
         if (EditorUtils::IsDescendantOf(*content, *blockElement)) {
           // Then we don't need to do anything different for this node
           lastContent = content;
           continue;
         }
         // Otherwise, we have progressed beyond end of blockElement, so let's
         // handle it now.  We need to remove the portion of blockElement that
         // contains [firstContent - lastContent].
-        SplitRangeOffFromNodeResult unwrapBlockElementResult =
+        Result<SplitRangeOffFromNodeResult, nsresult> unwrapBlockElementResult =
             RemoveBlockContainerElementWithTransactionBetween(
                 *blockElement, *firstContent, *lastContent);
-        if (unwrapBlockElementResult.isErr()) {
+        if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
           NS_WARNING(
               "HTMLEditor::RemoveBlockContainerElementWithTransactionBetween() "
               "failed");
-          return Err(unwrapBlockElementResult.unwrapErr());
-        }
-        unwrapBlockElementResult.MoveCaretPointTo(
+          return unwrapBlockElementResult.propagateErr();
+        }
+        unwrapBlockElementResult.unwrap().MoveCaretPointTo(
             pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
         firstContent = lastContent = blockElement = nullptr;
         // Fall out and handle content
       }
       blockElement = HTMLEditUtils::GetAncestorElement(
           content, HTMLEditUtils::ClosestEditableBlockElement);
       if (!blockElement || !HTMLEditUtils::IsFormatNode(blockElement) ||
           !HTMLEditUtils::IsRemovableNode(*blockElement)) {
@@ -8374,43 +8394,43 @@ HTMLEditor::RemoveBlockContainerElements
         firstContent = lastContent = content;
       }
       continue;
     }
 
     if (blockElement) {
       // Some node that is already sans block style.  Skip over it and process
       // any partial progress saved.
-      SplitRangeOffFromNodeResult unwrapBlockElementResult =
+      Result<SplitRangeOffFromNodeResult, nsresult> unwrapBlockElementResult =
           RemoveBlockContainerElementWithTransactionBetween(
               *blockElement, *firstContent, *lastContent);
-      if (unwrapBlockElementResult.isErr()) {
+      if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
         NS_WARNING(
             "HTMLEditor::RemoveBlockContainerElementWithTransactionBetween() "
             "failed");
-        return Err(unwrapBlockElementResult.unwrapErr());
-      }
-      unwrapBlockElementResult.MoveCaretPointTo(
+        return unwrapBlockElementResult.propagateErr();
+      }
+      unwrapBlockElementResult.unwrap().MoveCaretPointTo(
           pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
       firstContent = lastContent = blockElement = nullptr;
       continue;
     }
   }
   // Process any partial progress saved
   if (blockElement) {
-    SplitRangeOffFromNodeResult unwrapBlockElementResult =
+    Result<SplitRangeOffFromNodeResult, nsresult> unwrapBlockElementResult =
         RemoveBlockContainerElementWithTransactionBetween(
             *blockElement, *firstContent, *lastContent);
-    if (unwrapBlockElementResult.isErr()) {
+    if (MOZ_UNLIKELY(unwrapBlockElementResult.isErr())) {
       NS_WARNING(
           "HTMLEditor::RemoveBlockContainerElementWithTransactionBetween() "
           "failed");
-      return Err(unwrapBlockElementResult.unwrapErr());
-    }
-    unwrapBlockElementResult.MoveCaretPointTo(
+      return unwrapBlockElementResult.propagateErr();
+    }
+    unwrapBlockElementResult.unwrap().MoveCaretPointTo(
         pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
     firstContent = lastContent = blockElement = nullptr;
   }
   return pointToPutCaret;
 }
 
 Result<CreateElementResult, nsresult>
 HTMLEditor::CreateOrChangeBlockContainerElement(
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -1377,17 +1377,17 @@ class HTMLEditor final : public EditorBa
    * SplitRangeOffFromBlock() splits aBlockElement at two points, before
    * aStartOfMiddleElement and after aEndOfMiddleElement.  If they are very
    * start or very end of aBlockElement, this won't create empty block.
    *
    * @param aBlockElement           A block element which will be split.
    * @param aStartOfMiddleElement   Start node of middle block element.
    * @param aEndOfMiddleElement     End node of middle block element.
    */
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT SplitRangeOffFromNodeResult
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult>
   SplitRangeOffFromBlock(Element& aBlockElement,
                          nsIContent& aStartOfMiddleElement,
                          nsIContent& aEndOfMiddleElement);
 
   /**
    * RemoveBlockContainerElementWithTransactionBetween() splits the nodes
    * at aStartOfRange and aEndOfRange, then, removes the middle element which
    * was split off from aBlockContainerElement and moves the ex-children to
@@ -1402,17 +1402,17 @@ class HTMLEditor final : public EditorBa
    *                                aBlockContainerElement.
    * @return                        The left content is new created left
    *                                element of aBlockContainerElement.
    *                                The right content is split element,
    *                                i.e., must be aBlockContainerElement.
    *                                The middle content is nullptr since
    *                                removing it is the job of this method.
    */
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT SplitRangeOffFromNodeResult
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult>
   RemoveBlockContainerElementWithTransactionBetween(
       Element& aBlockContainerElement, nsIContent& aStartOfRange,
       nsIContent& aEndOfRange);
 
   /**
    * WrapContentsInBlockquoteElementsWithTransaction() inserts at least one
    * <blockquote> element and moves nodes in aArrayOfContents into new
    * <blockquote> elements. If aArrayOfContents includes a table related element
@@ -2422,19 +2422,19 @@ class HTMLEditor final : public EditorBa
    * @return                    The left content is new created element
    *                            splitting before aStartOfOutdent.
    *                            The right content is existing element.
    *                            The middle content is outdented element
    *                            if aBlockIndentedWith is `CSS`.
    *                            Otherwise, nullptr.
    */
   enum class BlockIndentedWith { CSS, HTML };
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT SplitRangeOffFromNodeResult
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult>
   OutdentPartOfBlock(Element& aBlockElement, nsIContent& aStartOfOutdent,
-                     nsIContent& aEndOutdent,
+                     nsIContent& aEndOfOutdent,
                      BlockIndentedWith aBlockIndentedWith,
                      const Element& aEditingHost);
 
   /**
    * HandleOutdentAtSelectionInternal() outdents contents around Selection.
    * This method creates AutoSelectionRestorer.  Therefore, each caller
    * needs to check if the editor is still available even if this returns
    * NS_OK.
@@ -2443,17 +2443,17 @@ class HTMLEditor final : public EditorBa
    * @param aEditingHost        The editing host.
    * @return                    The left content is left content of last
    *                            outdented element.
    *                            The right content is right content of last
    *                            outdented element.
    *                            The middle content is middle content of last
    *                            outdented element.
    */
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT SplitRangeOffFromNodeResult
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult>
   HandleOutdentAtSelectionInternal(const Element& aEditingHost);
 
   /**
    * HandleOutdentAtSelection() outdents contents around Selection.
    *
    * @param aEditingHost        The editing host.
    */
   [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
@@ -3974,17 +3974,17 @@ class HTMLEditor final : public EditorBa
    * SetInlinePropertyOnTextNode() splits aData if aStartOffset and/or
    * aEndOffset are not start/end of aData.  Then, the text node which was
    * contained in the range is wrapped into an element which applies the style.
    *
    * @return            The result of splitting aData.  Note that middle text
    *                    node may be moved in an element, so left/middle/right
    *                    nodes may not be siblings.
    */
-  [[nodiscard]] MOZ_CAN_RUN_SCRIPT SplitRangeOffFromNodeResult
+  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult>
   SetInlinePropertyOnTextNode(Text& aData, uint32_t aStartOffset,
                               uint32_t aEndOffset, nsAtom& aProperty,
                               nsAtom* aAttribute, const nsAString& aValue);
 
   nsresult PromoteInlineRange(nsRange& aRange);
   nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
 
   /**
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -266,30 +266,30 @@ nsresult HTMLEditor::SetInlineProperties
       if (NS_WARN_IF(!range.IsPositioned())) {
         continue;
       }
 
       // If range is in a text node, apply new style simply.
       if (range.InSameContainer() && range.StartRef().IsInTextNode()) {
         // MOZ_KnownLive(...ContainerAs<Text>()) because of grabbed by `range`.
         // MOZ_KnownLive(styleToSet.*) due to bug 1622253.
-        SplitRangeOffFromNodeResult wrapTextInStyledElementResult =
-            SetInlinePropertyOnTextNode(
+        Result<SplitRangeOffFromNodeResult, nsresult>
+            wrapTextInStyledElementResult = SetInlinePropertyOnTextNode(
                 MOZ_KnownLive(*range.StartRef().ContainerAs<Text>()),
                 range.StartRef().Offset(), range.EndRef().Offset(),
                 MOZ_KnownLive(styleToSet.HTMLPropertyRef()),
                 MOZ_KnownLive(styleToSet.mAttribute),
                 styleToSet.mAttributeValue);
-        if (wrapTextInStyledElementResult.isErr()) {
+        if (MOZ_UNLIKELY(wrapTextInStyledElementResult.isErr())) {
           NS_WARNING("HTMLEditor::SetInlinePropertyOnTextNode() failed");
           return wrapTextInStyledElementResult.unwrapErr();
         }
         // There is AutoTransactionsConserveSelection, so we don't need to
         // update selection here.
-        wrapTextInStyledElementResult.IgnoreCaretPointSuggestion();
+        wrapTextInStyledElementResult.inspect().IgnoreCaretPointSuggestion();
         continue;
       }
 
       // Collect editable nodes which are entirely contained in the range.
       AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContentsAroundRange;
       {
         ContentSubtreeIterator subtreeIter;
         // If there is no node which is entirely in the range,
@@ -313,31 +313,31 @@ nsresult HTMLEditor::SetInlineProperties
       }
 
       // If start node is a text node, apply new style to a part of it.
       if (range.StartRef().IsInTextNode() &&
           EditorUtils::IsEditableContent(*range.StartRef().ContainerAs<Text>(),
                                          EditorType::HTML)) {
         // MOZ_KnownLive(...ContainerAs<Text>()) because of grabbed by `range`.
         // MOZ_KnownLive(styleToSet.*) due to bug 1622253.
-        SplitRangeOffFromNodeResult wrapTextInStyledElementResult =
-            SetInlinePropertyOnTextNode(
+        Result<SplitRangeOffFromNodeResult, nsresult>
+            wrapTextInStyledElementResult = SetInlinePropertyOnTextNode(
                 MOZ_KnownLive(*range.StartRef().ContainerAs<Text>()),
                 range.StartRef().Offset(),
                 range.StartRef().ContainerAs<Text>()->TextDataLength(),
                 MOZ_KnownLive(styleToSet.HTMLPropertyRef()),
                 MOZ_KnownLive(styleToSet.mAttribute),
                 styleToSet.mAttributeValue);
-        if (wrapTextInStyledElementResult.isErr()) {
+        if (MOZ_UNLIKELY(wrapTextInStyledElementResult.isErr())) {
           NS_WARNING("HTMLEditor::SetInlinePropertyOnTextNode() failed");
           return wrapTextInStyledElementResult.unwrapErr();
         }
         // There is AutoTransactionsConserveSelection, so we don't need to
         // update selection here.
-        wrapTextInStyledElementResult.IgnoreCaretPointSuggestion();
+        wrapTextInStyledElementResult.inspect().IgnoreCaretPointSuggestion();
       }
 
       // Then, apply new style to all nodes in the range entirely.
       for (auto& content : arrayOfContentsAroundRange) {
         // MOZ_KnownLive due to bug 1622253.
         Result<EditorDOMPoint, nsresult> setStyleResult =
             SetInlinePropertyOnNode(MOZ_KnownLive(*content),
                                     MOZ_KnownLive(styleToSet.HTMLPropertyRef()),
@@ -352,30 +352,30 @@ nsresult HTMLEditor::SetInlineProperties
       }
 
       // Finally, if end node is a text node, apply new style to a part of it.
       if (range.EndRef().IsInTextNode() &&
           EditorUtils::IsEditableContent(*range.EndRef().ContainerAs<Text>(),
                                          EditorType::HTML)) {
         // MOZ_KnownLive(...ContainerAs<Text>()) because of grabbed by `range`.
         // MOZ_KnownLive(styleToSet.mAttribute) due to bug 1622253.
-        SplitRangeOffFromNodeResult wrapTextInStyledElementResult =
-            SetInlinePropertyOnTextNode(
+        Result<SplitRangeOffFromNodeResult, nsresult>
+            wrapTextInStyledElementResult = SetInlinePropertyOnTextNode(
                 MOZ_KnownLive(*range.EndRef().ContainerAs<Text>()), 0,
                 range.EndRef().Offset(),
                 MOZ_KnownLive(styleToSet.HTMLPropertyRef()),
                 MOZ_KnownLive(styleToSet.mAttribute),
                 styleToSet.mAttributeValue);
-        if (wrapTextInStyledElementResult.isErr()) {
+        if (MOZ_UNLIKELY(wrapTextInStyledElementResult.isErr())) {
           NS_WARNING("HTMLEditor::SetInlinePropertyOnTextNode() failed");
           return wrapTextInStyledElementResult.unwrapErr();
         }
         // There is AutoTransactionsConserveSelection, so we don't need to
         // update selection here.
-        wrapTextInStyledElementResult.IgnoreCaretPointSuggestion();
+        wrapTextInStyledElementResult.inspect().IgnoreCaretPointSuggestion();
       }
     }
     MOZ_ASSERT(selectionRanges.HasSavedRanges());
     selectionRanges.RestoreFromSavedRanges();
   }
 
   MOZ_ASSERT(!selectionRanges.HasSavedRanges());
   nsresult rv = selectionRanges.ApplyTo(SelectionRef());
@@ -465,19 +465,21 @@ Result<bool, nsresult> HTMLEditor::Eleme
   nsStyledElement* styledElement = nsStyledElement::FromNode(&aElement);
   if (!styledElement) {
     return false;
   }
   return CSSEditUtils::DoStyledElementsHaveSameStyle(*styledNewSpanElement,
                                                      *styledElement);
 }
 
-SplitRangeOffFromNodeResult HTMLEditor::SetInlinePropertyOnTextNode(
-    Text& aText, uint32_t aStartOffset, uint32_t aEndOffset, nsAtom& aProperty,
-    nsAtom* aAttribute, const nsAString& aValue) {
+Result<SplitRangeOffFromNodeResult, nsresult>
+HTMLEditor::SetInlinePropertyOnTextNode(Text& aText, uint32_t aStartOffset,
+                                        uint32_t aEndOffset, nsAtom& aProperty,
+                                        nsAtom* aAttribute,
+                                        const nsAString& aValue) {
   if (!aText.GetParentNode() ||
       !HTMLEditUtils::CanNodeContain(*aText.GetParentNode(), aProperty)) {
     return SplitRangeOffFromNodeResult(nullptr, &aText, nullptr);
   }
 
   // Don't need to do anything if no characters actually selected
   if (aStartOffset == aEndOffset) {
     return SplitRangeOffFromNodeResult(nullptr, &aText, nullptr);
@@ -486,21 +488,20 @@ SplitRangeOffFromNodeResult HTMLEditor::
   // Don't need to do anything if property already set on node
   if (CSSEditUtils::IsCSSEditableProperty(&aText, &aProperty, aAttribute)) {
     // The HTML styles defined by aProperty/aAttribute have a CSS equivalence
     // for node; let's check if it carries those CSS styles
     nsAutoString value(aValue);
     Result<bool, nsresult> isComputedCSSEquivalentToHTMLInlineStyleOrError =
         CSSEditUtils::IsComputedCSSEquivalentToHTMLInlineStyleSet(
             *this, aText, &aProperty, aAttribute, value);
-    if (isComputedCSSEquivalentToHTMLInlineStyleOrError.isErr()) {
+    if (MOZ_UNLIKELY(isComputedCSSEquivalentToHTMLInlineStyleOrError.isErr())) {
       NS_WARNING(
           "CSSEditUtils::IsComputedCSSEquivalentToHTMLInlineStyleSet() failed");
-      return SplitRangeOffFromNodeResult(
-          isComputedCSSEquivalentToHTMLInlineStyleOrError.unwrapErr());
+      return isComputedCSSEquivalentToHTMLInlineStyleOrError.propagateErr();
     }
     if (isComputedCSSEquivalentToHTMLInlineStyleOrError.unwrap()) {
       return SplitRangeOffFromNodeResult(nullptr, &aText, nullptr);
     }
   } else if (HTMLEditUtils::IsInlineStyleSetByElement(aText, aProperty,
                                                       aAttribute, &aValue)) {
     return SplitRangeOffFromNodeResult(nullptr, &aText, nullptr);
   }
@@ -521,17 +522,17 @@ SplitRangeOffFromNodeResult HTMLEditor::
       NS_WARNING(
           "HTMLEditor::SplitNodeWithTransaction() didn't suggest caret "
           "point");
       return SplitNodeResult(NS_ERROR_FAILURE);
     }
     return splitNodeResult;
   }();
   if (MOZ_UNLIKELY(splitAtEndResult.isErr())) {
-    return SplitRangeOffFromNodeResult(splitAtEndResult.unwrapErr());
+    return Err(splitAtEndResult.unwrapErr());
   }
   EditorDOMPoint pointToPutCaret = splitAtEndResult.UnwrapCaretPoint();
   SplitNodeResult splitAtStartResult = [&]() MOZ_CAN_RUN_SCRIPT {
     EditorDOMPoint atStart(splitAtEndResult.DidSplit()
                                ? splitAtEndResult.GetPreviousContent()
                                : &aText,
                            aStartOffset);
     if (atStart.IsStartOfContainer()) {
@@ -547,17 +548,17 @@ SplitRangeOffFromNodeResult HTMLEditor::
       NS_WARNING(
           "HTMLEditor::SplitNodeWithTransaction() didn't suggest caret "
           "point");
       return SplitNodeResult(NS_ERROR_FAILURE);
     }
     return splitNodeResult;
   }();
   if (MOZ_UNLIKELY(splitAtStartResult.isErr())) {
-    return SplitRangeOffFromNodeResult(splitAtStartResult.unwrapErr());
+    return Err(splitAtStartResult.unwrapErr());
   }
   if (splitAtStartResult.HasCaretPointSuggestion()) {
     pointToPutCaret = splitAtStartResult.UnwrapCaretPoint();
   }
 
   MOZ_ASSERT_IF(splitAtStartResult.DidSplit(),
                 splitAtStartResult.GetPreviousContent()->IsText());
   MOZ_ASSERT_IF(splitAtStartResult.DidSplit(),
@@ -588,26 +589,26 @@ SplitRangeOffFromNodeResult HTMLEditor::
     nsIContent* sibling = HTMLEditUtils::GetPreviousSibling(
         *middleTextNode, {WalkTreeOption::IgnoreNonEditableNode});
     if (sibling && sibling->IsElement()) {
       OwningNonNull<Element> element(*sibling->AsElement());
       Result<bool, nsresult> result = ElementIsGoodContainerForTheStyle(
           element, &aProperty, aAttribute, &aValue);
       if (MOZ_UNLIKELY(result.isErr())) {
         NS_WARNING("HTMLEditor::ElementIsGoodContainerForTheStyle() failed");
-        return SplitRangeOffFromNodeResult(result.unwrapErr());
+        return result.propagateErr();
       }
       if (result.inspect()) {
         // Previous sib is already right kind of inline node; slide this over
         Result<MoveNodeResult, nsresult> moveTextNodeResult =
             MoveNodeToEndWithTransaction(MOZ_KnownLive(*middleTextNode),
                                          element);
         if (MOZ_UNLIKELY(moveTextNodeResult.isErr())) {
           NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
-          return SplitRangeOffFromNodeResult(moveTextNodeResult.unwrapErr());
+          return moveTextNodeResult.propagateErr();
         }
         MoveNodeResult unwrappedMoveTextNodeResult =
             moveTextNodeResult.unwrap();
         unwrappedMoveTextNodeResult.MoveCaretPointTo(
             pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
         return SplitRangeOffFromNodeResult(leftTextNode, middleTextNode,
                                            rightTextNode,
                                            std::move(pointToPutCaret));
@@ -616,26 +617,26 @@ SplitRangeOffFromNodeResult HTMLEditor::
     sibling = HTMLEditUtils::GetNextSibling(
         *middleTextNode, {WalkTreeOption::IgnoreNonEditableNode});
     if (sibling && sibling->IsElement()) {
       OwningNonNull<Element> element(*sibling->AsElement());
       Result<bool, nsresult> result = ElementIsGoodContainerForTheStyle(
           element, &aProperty, aAttribute, &aValue);
       if (MOZ_UNLIKELY(result.isErr())) {
         NS_WARNING("HTMLEditor::ElementIsGoodContainerForTheStyle() failed");
-        return SplitRangeOffFromNodeResult(result.unwrapErr());
+        return result.propagateErr();
       }
       if (result.inspect()) {
         // Following sib is already right kind of inline node; slide this over
         Result<MoveNodeResult, nsresult> moveTextNodeResult =
             MoveNodeWithTransaction(MOZ_KnownLive(*middleTextNode),
                                     EditorDOMPoint(sibling, 0u));
         if (MOZ_UNLIKELY(moveTextNodeResult.isErr())) {
           NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
-          return SplitRangeOffFromNodeResult(moveTextNodeResult.unwrapErr());
+          return moveTextNodeResult.propagateErr();
         }
         MoveNodeResult unwrappedMoveTextNodeResult =
             moveTextNodeResult.unwrap();
         unwrappedMoveTextNodeResult.MoveCaretPointTo(
             pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
         return SplitRangeOffFromNodeResult(leftTextNode, middleTextNode,
                                            rightTextNode,
                                            std::move(pointToPutCaret));
@@ -643,17 +644,17 @@ SplitRangeOffFromNodeResult HTMLEditor::
     }
   }
 
   // Wrap the node inside inline node with appropriate {attribute,value}
   Result<EditorDOMPoint, nsresult> setStyleResult = SetInlinePropertyOnNode(
       MOZ_KnownLive(*middleTextNode), aProperty, aAttribute, aValue);
   if (MOZ_UNLIKELY(setStyleResult.isErr())) {
     NS_WARNING("HTMLEditor::SetInlinePropertyOnNode() failed");
-    return SplitRangeOffFromNodeResult(setStyleResult.unwrapErr());
+    return setStyleResult.propagateErr();
   }
   return SplitRangeOffFromNodeResult(leftTextNode, middleTextNode,
                                      rightTextNode, setStyleResult.unwrap());
 }
 
 Result<EditorDOMPoint, nsresult> HTMLEditor::SetInlinePropertyOnNodeImpl(
     nsIContent& aContent, nsAtom& aProperty, nsAtom* aAttribute,
     const nsAString& aValue) {
@@ -2450,38 +2451,40 @@ nsresult HTMLEditor::RemoveInlinePropert
           // may be multiple text nodes as adjacent siblings.  That's the
           // reason why we need to handle text nodes in this loop.
           uint32_t startOffset = content == splitRange.StartRef().GetContainer()
                                      ? splitRange.StartRef().Offset()
                                      : 0;
           uint32_t endOffset = content == splitRange.EndRef().GetContainer()
                                    ? splitRange.EndRef().Offset()
                                    : content->Length();
-          SplitRangeOffFromNodeResult wrapTextInStyledElementResult =
-              SetInlinePropertyOnTextNode(
+          Result<SplitRangeOffFromNodeResult, nsresult>
+              wrapTextInStyledElementResult = SetInlinePropertyOnTextNode(
                   MOZ_KnownLive(*content->AsText()), startOffset, endOffset,
                   *styleToRemove.mHTMLProperty, styleToRemove.mAttribute,
                   u"-moz-editor-invert-value"_ns);
-          if (wrapTextInStyledElementResult.isErr()) {
+          if (MOZ_UNLIKELY(wrapTextInStyledElementResult.isErr())) {
             NS_WARNING(
                 "HTMLEditor::SetInlinePropertyOnTextNode(-moz-editor-invert-"
                 "value) failed");
             return wrapTextInStyledElementResult.unwrapErr();
           }
+          SplitRangeOffFromNodeResult unwrappedWrapTextInStyledElementResult =
+              wrapTextInStyledElementResult.unwrap();
           // There is AutoTransactionsConserveSelection, so we don't need to
           // update selection here.
-          wrapTextInStyledElementResult.IgnoreCaretPointSuggestion();
+          unwrappedWrapTextInStyledElementResult.IgnoreCaretPointSuggestion();
           // If we've split the content, let's swap content in
           // arrayOfContentsToInvertStyle with the text node which is applied
           // the style.
           if (isCSSInvertibleStyle) {
-            MOZ_ASSERT(
-                wrapTextInStyledElementResult.GetMiddleContentAs<Text>());
-            if (Text* textNode =
-                    wrapTextInStyledElementResult.GetMiddleContentAs<Text>()) {
+            MOZ_ASSERT(unwrappedWrapTextInStyledElementResult
+                           .GetMiddleContentAs<Text>());
+            if (Text* textNode = unwrappedWrapTextInStyledElementResult
+                                     .GetMiddleContentAs<Text>()) {
               if (textNode != content) {
                 arrayOfContentsToInvertStyle.ReplaceElementAt(
                     arrayOfContentsToInvertStyle.Length() - 1,
                     OwningNonNull<nsIContent>(*textNode));
               }
             }
           }
         }
@@ -2514,30 +2517,30 @@ nsresult HTMLEditor::RemoveInlinePropert
               "failed");
           return isRemovableParentStyleOrError.unwrapErr();
         }
         if (!isRemovableParentStyleOrError.unwrap()) {
           continue;
         }
         // MOZ_KnownLive because 'leafTextNodes' is guaranteed to
         // keep it alive.
-        SplitRangeOffFromNodeResult wrapTextInStyledElementResult =
-            SetInlinePropertyOnTextNode(
+        Result<SplitRangeOffFromNodeResult, nsresult>
+            wrapTextInStyledElementResult = SetInlinePropertyOnTextNode(
                 MOZ_KnownLive(textNode), 0, textNode->TextLength(),
                 *styleToRemove.mHTMLProperty, styleToRemove.mAttribute,
                 u"-moz-editor-invert-value"_ns);
-        if (wrapTextInStyledElementResult.isErr()) {
+        if (MOZ_UNLIKELY(wrapTextInStyledElementResult.isErr())) {
           NS_WARNING(
               "HTMLEditor::SetInlinePropertyOnTextNode(-moz-editor-invert-"
               "value) failed");
           return wrapTextInStyledElementResult.unwrapErr();
         }
         // There is AutoTransactionsConserveSelection, so we don't need to
         // update selection here.
-        wrapTextInStyledElementResult.IgnoreCaretPointSuggestion();
+        wrapTextInStyledElementResult.inspect().IgnoreCaretPointSuggestion();
       }  // for-loop of leafTextNodes
     }    // for-loop of selectionRanges
     MOZ_ASSERT(selectionRanges.HasSavedRanges());
     selectionRanges.RestoreFromSavedRanges();
   }  // for-loop of styles
 
   MOZ_ASSERT(!selectionRanges.HasSavedRanges());
   nsresult rv = selectionRanges.ApplyTo(SelectionRef());