Bug 1457083 - part 5: Make all users of Selection in TextEditRules and HTMLEditRules use TextEditRules::SelectionRef() r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 08 May 2018 17:30:05 +0900
changeset 797732 24497df2e459a743efbe7038c2a2fb979988115a
parent 797731 e2d749d9b3b3a95d064f897de76818e173d74a62
child 797733 86a6fc9fba61cb12fb33b3418ff6395b5796ef46
push id110553
push usermasayuki@d-toybox.com
push dateMon, 21 May 2018 14:13:13 +0000
reviewersm_kato
bugs1457083
milestone62.0a1
Bug 1457083 - part 5: Make all users of Selection in TextEditRules and HTMLEditRules use TextEditRules::SelectionRef() r?m_kato After this patch applies, most methods of TextEditRules and HTMLEditRules don't need to take Selection as their arguments. Therefore, next patch will remove them. MozReview-Commit-ID: 99r3ZkfG2In
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/TextEditRules.cpp
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -463,19 +463,16 @@ HTMLEditRules::AfterEditInner(EditAction
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   ConfirmSelectionInBody();
   if (aAction == EditAction::ignore) {
     return NS_OK;
   }
 
-  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-  NS_ENSURE_STATE(selection);
-
   nsCOMPtr<nsINode> rangeStartContainer, rangeEndContainer;
   uint32_t rangeStartOffset = 0, rangeEndOffset = 0;
   // do we have a real range to act on?
   bool bDamagedRange = false;
   if (mDocChangeRange) {
     rangeStartContainer = mDocChangeRange->GetStartContainer();
     rangeEndContainer = mDocChangeRange->GetEndContainer();
     rangeStartOffset = mDocChangeRange->StartOffset();
@@ -495,108 +492,122 @@ HTMLEditRules::AfterEditInner(EditAction
     PromoteRange(*mDocChangeRange, aAction);
 
     // if we did a ranged deletion or handling backspace key, make sure we have
     // a place to put caret.
     // Note we only want to do this if the overall operation was deletion,
     // not if deletion was done along the way for EditAction::loadHTML, EditAction::insertText, etc.
     // That's why this is here rather than DidDeleteSelection().
     if (aAction == EditAction::deleteSelection && mDidRangedDelete) {
-      nsresult rv = InsertBRIfNeeded(selection);
-      NS_ENSURE_SUCCESS(rv, rv);
+      nsresult rv = InsertBRIfNeeded(&SelectionRef());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     }
 
     // add in any needed <br>s, and remove any unneeded ones.
     AdjustSpecialBreaks();
 
     // merge any adjacent text nodes
     if (aAction != EditAction::insertText &&
         aAction != EditAction::insertIMEText) {
       nsresult rv = HTMLEditorRef().CollapseAdjacentTextNodes(mDocChangeRange);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // clean up any empty nodes in the selection
     nsresult rv = RemoveEmptyNodes();
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
 
     // attempt to transform any unneeded nbsp's into spaces after doing various operations
     if (aAction == EditAction::insertText ||
         aAction == EditAction::insertIMEText ||
         aAction == EditAction::deleteSelection ||
         aAction == EditAction::insertBreak ||
         aAction == EditAction::htmlPaste ||
         aAction == EditAction::loadHTML) {
-      rv = AdjustWhitespace(selection);
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = AdjustWhitespace(&SelectionRef());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
       // also do this for original selection endpoints.
       NS_ENSURE_STATE(mRangeItem->mStartContainer);
       NS_ENSURE_STATE(mRangeItem->mEndContainer);
       WSRunObject(&HTMLEditorRef(), mRangeItem->mStartContainer,
                   mRangeItem->mStartOffset).AdjustWhitespace();
       // we only need to handle old selection endpoint if it was different from start
       if (mRangeItem->mStartContainer != mRangeItem->mEndContainer ||
           mRangeItem->mStartOffset != mRangeItem->mEndOffset) {
         WSRunObject(&HTMLEditorRef(), mRangeItem->mEndContainer,
                     mRangeItem->mEndOffset).AdjustWhitespace();
       }
     }
 
     // if we created a new block, make sure selection lands in it
     if (mNewBlock) {
-      rv = PinSelectionToNewBlock(selection);
+      rv = PinSelectionToNewBlock(&SelectionRef());
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+        "Failed to pin selection to the new block");
       mNewBlock = nullptr;
     }
 
     // adjust selection for insert text, html paste, and delete actions
     if (aAction == EditAction::insertText ||
         aAction == EditAction::insertIMEText ||
         aAction == EditAction::deleteSelection ||
         aAction == EditAction::insertBreak ||
         aAction == EditAction::htmlPaste ||
         aAction == EditAction::loadHTML) {
-      rv = AdjustSelection(selection, aDirection);
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = AdjustSelection(&SelectionRef(), aDirection);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     }
 
     // check for any styles which were removed inappropriately
     if (aAction == EditAction::insertText ||
         aAction == EditAction::insertIMEText ||
         aAction == EditAction::deleteSelection ||
         IsStyleCachePreservingAction(aAction)) {
-      HTMLEditorRef().mTypeInState->UpdateSelState(selection);
+      HTMLEditorRef().mTypeInState->UpdateSelState(&SelectionRef());
       rv = ReapplyCachedStyles();
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       ClearCachedStyles();
     }
   }
 
   nsresult rv =
     HTMLEditorRef().HandleInlineSpellCheck(
-                      aAction, *selection,
+                      aAction, SelectionRef(),
                       mRangeItem->mStartContainer,
                       mRangeItem->mStartOffset,
                       rangeStartContainer,
                       rangeStartOffset,
                       rangeEndContainer,
                       rangeEndOffset);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // detect empty doc
-  rv = CreateBogusNodeIfNeeded(selection);
-  NS_ENSURE_SUCCESS(rv, rv);
+  rv = CreateBogusNodeIfNeeded(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // adjust selection HINT if needed
   if (!mDidExplicitlySetInterline) {
-    CheckInterlinePosition(*selection);
+    CheckInterlinePosition(SelectionRef());
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillDoAction(Selection* aSelection,
                             RulesInfo* aInfo,
@@ -626,17 +637,17 @@ HTMLEditRules::WillDoAction(Selection* a
 
   AutoSafeEditorData setData(*this, *mHTMLEditor, *aSelection);
 
   // Nothing to do if there's no selection to act on
   if (NS_WARN_IF(!SelectionRef().RangeCount())) {
     return NS_OK;
   }
 
-  RefPtr<nsRange> range = aSelection->GetRangeAt(0);
+  RefPtr<nsRange> range = SelectionRef().GetRangeAt(0);
   nsCOMPtr<nsINode> selStartNode = range->GetStartContainer();
 
   if (!HTMLEditorRef().IsModifiableNode(selStartNode)) {
     *aCancel = true;
     return NS_OK;
   }
 
   nsCOMPtr<nsINode> selEndNode = range->GetEndContainer();
@@ -915,17 +926,17 @@ HTMLEditRules::GetAlignment(bool* aMixed
   EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
   // Is the selection collapsed?
   nsCOMPtr<nsINode> nodeToExamine;
-  if (selection->IsCollapsed() || atStartOfSelection.GetContainerAsText()) {
+  if (SelectionRef().IsCollapsed() || atStartOfSelection.GetContainerAsText()) {
     // If selection is collapsed, we want to look at the container of selection
     // start and its ancestors for divs with alignment on them.  If we are in a
     // text node, then that is the node of interest.
     nodeToExamine = atStartOfSelection.GetContainer();
     if (NS_WARN_IF(!nodeToExamine)) {
       return NS_ERROR_FAILURE;
     }
   } else if (atStartOfSelection.IsContainerHTMLElement(nsGkAtoms::html) &&
@@ -1315,29 +1326,29 @@ HTMLEditRules::GetFormatString(nsINode* 
 
 void
 HTMLEditRules::WillInsert(Selection& aSelection,
                           bool* aCancel)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel);
 
-  TextEditRules::WillInsert(aSelection, aCancel);
+  TextEditRules::WillInsert(SelectionRef(), aCancel);
 
   // Adjust selection to prevent insertion after a moz-BR.  This next only
   // works for collapsed selections right now, because selection is a pain to
   // work with when not collapsed.  (no good way to extend start or end of
   // selection), so we ignore those types of selections.
-  if (!aSelection.IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     return;
   }
 
   // If we are after a mozBR in the same block, then move selection to be
   // before it
-  nsRange* firstRange = aSelection.GetRangeAt(0);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return;
   }
 
   EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return;
   }
@@ -1352,17 +1363,17 @@ HTMLEditRules::WillInsert(Selection& aSe
     RefPtr<Element> block2 = HTMLEditorRef().GetBlockNodeParent(priorNode);
 
     if (block1 && block1 == block2) {
       // If we are here then the selection is right after a mozBR that is in
       // the same block as the selection.  We need to move the selection start
       // to be before the mozBR.
       EditorRawDOMPoint point(priorNode);
       IgnoredErrorResult error;
-      aSelection.Collapse(point, error);
+      SelectionRef().Collapse(point, error);
       if (NS_WARN_IF(error.Failed())) {
         return;
       }
     }
   }
 
   if (mDidDeleteSelection &&
       (mTheAction == EditAction::insertText ||
@@ -1395,44 +1406,44 @@ HTMLEditRules::WillInsertText(EditAction
     return NS_ERROR_NULL_POINTER;
   }
 
   // initialize out param
   *aCancel = false;
   *aHandled = true;
   // If the selection isn't collapsed, delete it.  Don't delete existing inline
   // tags, because we're hopefully going to insert text (bug 787432).
-  if (!aSelection->IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     nsresult rv =
       HTMLEditorRef().DeleteSelectionAsAction(nsIEditor::eNone,
                                               nsIEditor::eNoStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
 
   // we need to get the doc
   nsCOMPtr<nsIDocument> doc = HTMLEditorRef().GetDocument();
   if (NS_WARN_IF(!doc)) {
     return NS_ERROR_FAILURE;
   }
 
   // for every property that is set, insert a new inline style node
-  nsresult rv = CreateStyleForInsertText(*aSelection, *doc);
+  nsresult rv = CreateStyleForInsertText(SelectionRef(), *doc);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // get the (collapsed) selection location
-  nsRange* firstRange = aSelection->GetRangeAt(0);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return NS_ERROR_FAILURE;
   }
   EditorDOMPoint pointToInsert(firstRange->StartRef());
   if (NS_WARN_IF(!pointToInsert.IsSet())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(pointToInsert.IsSetAndValid());
@@ -1520,17 +1531,17 @@ HTMLEditRules::WillInsertText(EditAction
           pos = tString.Length();
         }
 
         nsDependentSubstring subStr(tString, oldPos, subStrLen);
 
         // is it a return?
         if (subStr.Equals(newlineStr)) {
           RefPtr<Element> brElement =
-            HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+            HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                            currentPoint,
                                                            nsIEditor::eNone);
           if (NS_WARN_IF(!brElement)) {
             return NS_ERROR_FAILURE;
           }
           pos++;
           if (brElement->GetNextSibling()) {
             pointToInsert.Set(brElement->GetNextSibling());
@@ -1594,17 +1605,17 @@ HTMLEditRules::WillInsertText(EditAction
           }
           pos++;
           currentPoint = pointAfterInsertedSpaces;
           pointToInsert = pointAfterInsertedSpaces;
         }
         // is it a return?
         else if (subStr.Equals(newlineStr)) {
           RefPtr<Element> newBRElement =
-            wsObj.InsertBreak(*aSelection, currentPoint, nsIEditor::eNone);
+            wsObj.InsertBreak(SelectionRef(), currentPoint, nsIEditor::eNone);
           if (NS_WARN_IF(!newBRElement)) {
             return NS_ERROR_FAILURE;
           }
           pos++;
           if (newBRElement->GetNextSibling()) {
             pointToInsert.Set(newBRElement->GetNextSibling());
           } else {
             pointToInsert.SetToEndOf(currentPoint.GetContainer());
@@ -1630,21 +1641,24 @@ HTMLEditRules::WillInsertText(EditAction
           pointToInsert = pointAfterInsertedString;
         }
       }
     }
 
     // After this block, pointToInsert is updated by AutoTrackDOMPoint.
   }
 
-  aSelection->SetInterlinePosition(false, IgnoreErrors());
+  IgnoredErrorResult ignoredError;
+  SelectionRef().SetInterlinePosition(false, ignoredError);
+  NS_WARNING_ASSERTION(!ignoredError.Failed(),
+    "Failed to unset interline position");
 
   if (currentPoint.IsSet()) {
     ErrorResult error;
-    aSelection->Collapse(currentPoint, error);
+    SelectionRef().Collapse(currentPoint, error);
     if (error.Failed()) {
       NS_WARNING("Failed to collapse at current point");
       error.SuppressException();
     }
   }
 
   // manually update the doc changed range so that AfterEdit will clean up
   // the correct portion of the document.
@@ -1725,42 +1739,44 @@ HTMLEditRules::WillInsertBreak(Selection
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   MOZ_ASSERT(aCancel && aHandled);
   *aCancel = false;
   *aHandled = false;
 
   // If the selection isn't collapsed, delete it.
-  if (!aSelection.IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     nsresult rv =
       HTMLEditorRef().DeleteSelectionAsAction(nsIEditor::eNone,
                                               nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  WillInsert(aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // Initialize out param.  We want to ignore result of WillInsert().
   *aCancel = false;
 
   // Split any mailcites in the way.  Should we abort this if we encounter
   // table cell boundaries?
   if (IsMailEditor()) {
-    nsresult rv = SplitMailCites(&aSelection, aHandled);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsresult rv = SplitMailCites(&SelectionRef(), aHandled);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (*aHandled) {
       return NS_OK;
     }
   }
 
   // Smart splitting rules
-  nsRange* firstRange = aSelection.GetRangeAt(0);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return NS_ERROR_FAILURE;
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
@@ -1816,36 +1832,36 @@ HTMLEditRules::WillInsertBreak(Selection
          blockAncestor = HTMLEditor::GetBlockNodeParent(blockAncestor, host)) {
       insertBRElement = !CanContainParagraph(*blockAncestor);
     }
   }
 
   // If we cannot insert a <p>/<div> element at the selection, we should insert
   // a <br> element instead.
   if (insertBRElement) {
-    nsresult rv = InsertBRElement(aSelection, atStartOfSelection);
+    nsresult rv = InsertBRElement(SelectionRef(), atStartOfSelection);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     *aHandled = true;
     return NS_OK;
   }
 
   if (host == blockParent && separator != ParagraphSeparator::br) {
     // Insert a new block first
     MOZ_ASSERT(separator == ParagraphSeparator::div ||
                separator == ParagraphSeparator::p);
-    nsresult rv = MakeBasicBlock(aSelection,
+    nsresult rv = MakeBasicBlock(SelectionRef(),
                                  ParagraphSeparatorElement(separator));
     // We warn on failure, but don't handle it, because it might be harmless.
     // Instead we just check that a new block was actually created.
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                          "HTMLEditRules::MakeBasicBlock() failed");
 
-    firstRange = aSelection.GetRangeAt(0);
+    firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -1853,17 +1869,17 @@ HTMLEditRules::WillInsertBreak(Selection
 
     blockParent =
       HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), host);
     if (NS_WARN_IF(!blockParent)) {
       return NS_ERROR_UNEXPECTED;
     }
     if (NS_WARN_IF(blockParent == host)) {
       // Didn't create a new block for some reason, fall back to <br>
-      rv = InsertBRElement(aSelection, atStartOfSelection);
+      rv = InsertBRElement(SelectionRef(), atStartOfSelection);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       *aHandled = true;
       return NS_OK;
     }
     // Now, mNewBlock is last created block element for wrapping inline
     // elements around the caret position and AfterEditInner() will move
@@ -1879,34 +1895,36 @@ HTMLEditRules::WillInsertBreak(Selection
   // contains the word "text".  The user selects "text" and types return.
   // "Text" is deleted leaving an empty block.  We want to put in one br to
   // make block have a line.  Then code further below will put in a second br.)
   if (IsEmptyBlockElement(*blockParent, IgnoreSingleBR::eNo)) {
     AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
     EditorRawDOMPoint endOfBlockParent;
     endOfBlockParent.SetToEndOf(blockParent);
     RefPtr<Element> brElement =
-      HTMLEditorRef().InsertBrElementWithTransaction(aSelection,
+      HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                      endOfBlockParent);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   nsCOMPtr<Element> listItem = IsInListItem(blockParent);
   if (listItem && listItem != host) {
-    ReturnInListItem(aSelection, *listItem, *atStartOfSelection.GetContainer(),
+    ReturnInListItem(SelectionRef(),
+                     *listItem, *atStartOfSelection.GetContainer(),
                      atStartOfSelection.Offset());
     *aHandled = true;
     return NS_OK;
   }
 
   if (HTMLEditUtils::IsHeader(*blockParent)) {
     // Headers: close (or split) header
-    ReturnInHeader(aSelection, *blockParent, *atStartOfSelection.GetContainer(),
+    ReturnInHeader(SelectionRef(),
+                   *blockParent, *atStartOfSelection.GetContainer(),
                    atStartOfSelection.Offset());
     *aHandled = true;
     return NS_OK;
   }
 
   // XXX Ideally, we should take same behavior with both <p> container and
   //     <div> container.  However, we are still using <br> as default
   //     paragraph separator (non-standard) and we've split only <p> container
@@ -1915,17 +1933,17 @@ HTMLEditRules::WillInsertBreak(Selection
   //     paragraph separator is <br>.  Otherwise, take consistent behavior
   //     between <p> container and <div> container.
   if ((separator == ParagraphSeparator::br &&
        blockParent->IsHTMLElement(nsGkAtoms::p)) ||
       (separator != ParagraphSeparator::br &&
        blockParent->IsAnyOfHTMLElements(nsGkAtoms::p, nsGkAtoms::div))) {
     AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
     // Paragraphs: special rules to look for <br>s
-    EditActionResult result = ReturnInParagraph(aSelection, *blockParent);
+    EditActionResult result = ReturnInParagraph(SelectionRef(), *blockParent);
     if (NS_WARN_IF(result.Failed())) {
       return result.Rv();
     }
     *aHandled = result.Handled();
     *aCancel = result.Canceled();
     if (result.Handled()) {
       // Now, atStartOfSelection may be invalid because the left paragraph
       // may have less children than its offset.  For avoiding warnings of
@@ -1936,17 +1954,17 @@ HTMLEditRules::WillInsertBreak(Selection
     // Fall through, if ReturnInParagraph() didn't handle it.
     MOZ_ASSERT(!*aCancel, "ReturnInParagraph canceled this edit action, "
                           "WillInsertBreak() needs to handle such case");
   }
 
   // If nobody handles this edit action, let's insert new <br> at the selection.
   MOZ_ASSERT(!*aHandled, "Reached last resort of WillInsertBreak() "
                          "after the edit action is handled");
-  nsresult rv = InsertBRElement(aSelection, atStartOfSelection);
+  nsresult rv = InsertBRElement(SelectionRef(), atStartOfSelection);
   *aHandled = true;
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
@@ -1961,17 +1979,18 @@ HTMLEditRules::InsertBRElement(Selection
 
   bool brElementIsAfterBlock = false;
   bool brElementIsBeforeBlock = false;
 
   // First, insert a <br> element.
   RefPtr<Element> brElement;
   if (IsPlaintextEditor()) {
     brElement =
-      HTMLEditorRef().InsertBrElementWithTransaction(aSelection, aPointToBreak);
+      HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
+                                                     aPointToBreak);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   } else {
     EditorDOMPoint pointToBreak(aPointToBreak);
     WSRunObject wsObj(&HTMLEditorRef(), pointToBreak);
     int32_t visOffset = 0;
     WSType wsType;
@@ -1999,17 +2018,18 @@ HTMLEditRules::InsertBRElement(Selection
         HTMLEditorRef().SplitNodeDeepWithTransaction(
                           *linkNode, pointToBreak,
                           SplitAtEdges::eDoNotCreateEmptyContainer);
       if (NS_WARN_IF(splitLinkNodeResult.Failed())) {
         return splitLinkNodeResult.Rv();
       }
       pointToBreak = splitLinkNodeResult.SplitPoint();
     }
-    brElement = wsObj.InsertBreak(aSelection, pointToBreak, nsIEditor::eNone);
+    brElement =
+      wsObj.InsertBreak(SelectionRef(), pointToBreak, nsIEditor::eNone);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   // If the <br> element has already been removed from the DOM tree by a
   // mutation observer, don't continue handling this.
   if (NS_WARN_IF(!brElement->GetParentNode())) {
@@ -2018,20 +2038,22 @@ HTMLEditRules::InsertBRElement(Selection
 
   if (brElementIsAfterBlock && brElementIsBeforeBlock) {
     // We just placed a <br> between block boundaries.  This is the one case
     // where we want the selection to be before the br we just placed, as the
     // br will be on a new line, rather than at end of prior line.
     // XXX brElementIsAfterBlock and brElementIsBeforeBlock were set before
     //     modifying the DOM tree.  So, now, the <br> element may not be
     //     between blocks.
-    aSelection.SetInterlinePosition(true, IgnoreErrors());
+    ErrorResult error;
+    SelectionRef().SetInterlinePosition(true, error);
+    NS_WARNING_ASSERTION(!error.Failed(), "Failed to set interline position");
     EditorRawDOMPoint point(brElement);
-    ErrorResult error;
-    aSelection.Collapse(point, error);
+    error = NS_OK;
+    SelectionRef().Collapse(point, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
   }
 
   EditorDOMPoint afterBRElement(brElement);
   DebugOnly<bool> advanced = afterBRElement.AdvanceOffset();
@@ -2064,21 +2086,24 @@ HTMLEditRules::InsertBRElement(Selection
   // SetInterlinePosition(true) means we want the caret to stick to the
   // content on the "right".  We want the caret to stick to whatever is past
   // the break.  This is because the break is on the same line we were on,
   // but the next content will be on the following line.
 
   // An exception to this is if the break has a next sibling that is a block
   // node.  Then we stick to the left to avoid an uber caret.
   nsIContent* nextSiblingOfBRElement = brElement->GetNextSibling();
-  aSelection.SetInterlinePosition(!(nextSiblingOfBRElement &&
-                                    IsBlockNode(*nextSiblingOfBRElement)),
-                                  IgnoreErrors());
   ErrorResult error;
-  aSelection.Collapse(afterBRElement, error);
+  SelectionRef().SetInterlinePosition(!(nextSiblingOfBRElement &&
+                                        IsBlockNode(*nextSiblingOfBRElement)),
+                                      error);
+  NS_WARNING_ASSERTION(!error.Failed(),
+    "Failed to set or unset interline position");
+  error = NS_OK;
+  SelectionRef().Collapse(afterBRElement, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::DidInsertBreak(Selection* aSelection,
@@ -2092,17 +2117,17 @@ HTMLEditRules::SplitMailCites(Selection*
                               bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aHandled)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  EditorRawDOMPoint pointToSplit(EditorBase::GetStartPoint(aSelection));
+  EditorRawDOMPoint pointToSplit(EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!pointToSplit.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*pointToSplit.GetContainer());
   if (!citeNode) {
     return NS_OK;
@@ -2163,42 +2188,45 @@ HTMLEditRules::SplitMailCites(Selection*
     nsCOMPtr<nsINode> lastChild =
       previousNodeOfSplitPoint->GetLastChild();
     if (lastChild && !lastChild->IsHTMLElement(nsGkAtoms::br)) {
       // We ignore the result here.
       EditorRawDOMPoint endOfPreviousNodeOfSplitPoint;
       endOfPreviousNodeOfSplitPoint.SetToEndOf(previousNodeOfSplitPoint);
       RefPtr<Element> invisibleBrElement =
         HTMLEditorRef().InsertBrElementWithTransaction(
-                          *aSelection,
+                          SelectionRef(),
                           endOfPreviousNodeOfSplitPoint);
       NS_WARNING_ASSERTION(invisibleBrElement,
         "Failed to create an invisible <br> element");
     }
   }
 
   // In most cases, <br> should be inserted after current cite.  However, if
   // left cite hasn't been created because the split point was start of the
   // cite node, <br> should be inserted before the current cite.
   EditorRawDOMPoint pointToInsertBrNode(splitCiteNodeResult.SplitPoint());
   RefPtr<Element> brElement =
-    HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+    HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                    pointToInsertBrNode);
   if (NS_WARN_IF(!brElement)) {
     return NS_ERROR_FAILURE;
   }
   // Now, offset of pointToInsertBrNode is invalid.  Let's clear it.
   pointToInsertBrNode.Clear();
 
   // Want selection before the break, and on same line.
   EditorDOMPoint atBrNode(brElement);
   Unused << atBrNode.Offset(); // Needs offset after collapsing the selection.
-  aSelection->SetInterlinePosition(true, IgnoreErrors());
   ErrorResult error;
-  aSelection->Collapse(atBrNode, error);
+  SelectionRef().SetInterlinePosition(true, error);
+  NS_WARNING_ASSERTION(!error.Failed(),
+    "Failed to set interline position");
+  error = NS_OK;
+  SelectionRef().Collapse(atBrNode, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
   // if citeNode wasn't a block, we might also want another break before it.
   // We need to examine the content both before the br we just added and also
   // just after it.  If we don't have another br or block boundary adjacent,
   // then we will need a 2nd br added to achieve blank line that user expects.
@@ -2223,17 +2251,17 @@ HTMLEditRules::SplitMailCites(Selection*
       wsObjAfterBR.NextVisibleNode(pointAfterNewBrNode,
                                    address_of(visNode), &visOffset, &wsType);
       if (wsType == WSType::normalWS || wsType == WSType::text ||
           wsType == WSType::special ||
           // In case we're at the very end.
           wsType == WSType::thisBlock) {
         brElement =
           HTMLEditorRef().InsertBrElementWithTransaction(
-                            *aSelection, pointToCreateNewBrNode);
+                            SelectionRef(), pointToCreateNewBrNode);
         if (NS_WARN_IF(!brElement)) {
           return NS_ERROR_FAILURE;
         }
         // Now, those points may be invalid.
         pointToCreateNewBrNode.Clear();
         pointAfterNewBrNode.Clear();
       }
     }
@@ -2314,70 +2342,81 @@ HTMLEditRules::WillDeleteSelection(Selec
   cell = nullptr;
 
   // origCollapsed is used later to determine whether we should join blocks. We
   // don't really care about bCollapsed because it will be modified by
   // ExtendSelectionForDelete later. TryToJoinBlocksWithTransaction() should
   // happen if the original selection is collapsed and the cursor is at the end
   // of a block element, in which case ExtendSelectionForDelete would always
   // make the selection not collapsed.
-  bool bCollapsed = aSelection->IsCollapsed();
+  bool bCollapsed = SelectionRef().IsCollapsed();
   bool join = false;
   bool origCollapsed = bCollapsed;
 
   nsCOMPtr<nsINode> selNode;
   int32_t selOffset;
 
-  NS_ENSURE_STATE(aSelection->GetRangeAt(0));
-  nsCOMPtr<nsINode> startNode = aSelection->GetRangeAt(0)->GetStartContainer();
-  int32_t startOffset = aSelection->GetRangeAt(0)->StartOffset();
-  NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  if (NS_WARN_IF(!firstRange)) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsINode> startNode = firstRange->GetStartContainer();
+  if (NS_WARN_IF(!startNode)) {
+    return NS_ERROR_FAILURE;
+  }
+  int32_t startOffset = firstRange->StartOffset();
 
   if (bCollapsed) {
     // If we are inside an empty block, delete it.
     RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
     if (NS_WARN_IF(!host)) {
       return NS_ERROR_FAILURE;
     }
-    rv = CheckForEmptyBlock(startNode, host, aSelection, aAction, aHandled);
+    rv = CheckForEmptyBlock(startNode, host, &SelectionRef(),
+                            aAction, aHandled);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (*aHandled) {
       return NS_OK;
     }
 
     // Test for distance between caret and text that will be deleted
-    rv = CheckBidiLevelForDeletion(aSelection,
+    rv = CheckBidiLevelForDeletion(&SelectionRef(),
                                    EditorRawDOMPoint(startNode, startOffset),
                                    aAction, aCancel);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (*aCancel) {
       return NS_OK;
     }
 
-    rv = HTMLEditorRef().ExtendSelectionForDelete(aSelection, &aAction);
+    rv = HTMLEditorRef().ExtendSelectionForDelete(&SelectionRef(), &aAction);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // We should delete nothing.
     if (aAction == nsIEditor::eNone) {
       return NS_OK;
     }
 
     // ExtendSelectionForDelete() may have changed the selection, update it
-    NS_ENSURE_STATE(aSelection->GetRangeAt(0));
-    startNode = aSelection->GetRangeAt(0)->GetStartContainer();
-    startOffset = aSelection->GetRangeAt(0)->StartOffset();
-    NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-
-    bCollapsed = aSelection->IsCollapsed();
+    firstRange = SelectionRef().GetRangeAt(0);
+    if (NS_WARN_IF(!firstRange)) {
+      return NS_ERROR_FAILURE;
+    }
+    startNode = firstRange->GetStartContainer();
+    if (NS_WARN_IF(!startNode)) {
+      return NS_ERROR_FAILURE;
+    }
+    startOffset = firstRange->StartOffset();
+
+    bCollapsed = SelectionRef().IsCollapsed();
   }
 
   if (bCollapsed) {
     // What's in the direction we are deleting?
     WSRunObject wsObj(&HTMLEditorRef(), startNode, startOffset);
     nsCOMPtr<nsINode> visNode;
     int32_t visOffset;
     WSType wsType;
@@ -2408,17 +2447,21 @@ HTMLEditRules::WillDeleteSelection(Selec
           return rv;
         }
       } else {
         rv = wsObj.DeleteWSBackward();
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
-      return InsertBRIfNeeded(aSelection);
+      rv = InsertBRIfNeeded(&SelectionRef());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
 
     if (wsType == WSType::text) {
       // Found normal text to delete.
       OwningNonNull<Text> nodeAsText = *visNode->GetAsText();
       int32_t so = visOffset;
       int32_t eo = visOffset + 1;
       if (aAction == nsIEditor::ePrevious) {
@@ -2431,18 +2474,20 @@ HTMLEditRules::WillDeleteSelection(Selec
         if (so > 0) {
           const nsTextFragment *text = nodeAsText->GetText();
           if (NS_IS_LOW_SURROGATE(text->CharAt(so)) &&
               NS_IS_HIGH_SURROGATE(text->CharAt(so - 1))) {
             so--;
           }
         }
       } else {
-        RefPtr<nsRange> range = aSelection->GetRangeAt(0);
-        NS_ENSURE_STATE(range);
+        RefPtr<nsRange> range = SelectionRef().GetRangeAt(0);
+        if (NS_WARN_IF(!range)) {
+          return NS_ERROR_FAILURE;
+        }
 
         NS_ASSERTION(range->GetStartContainer() == visNode,
                      "selection start not in visNode");
         NS_ASSERTION(range->GetEndContainer() == visNode,
                      "selection end not in visNode");
 
         so = range->StartOffset();
         eo = range->EndOffset();
@@ -2471,18 +2516,20 @@ HTMLEditRules::WillDeleteSelection(Selec
       //     text nodes when removing the first character of the non-empty
       //     text node.  Chromium removes only selected empty text node and
       //     following empty text nodes and the first character of the
       //     non-empty text node.  For now, we should keep our traditional
       //     behavior same as Chromium for backward compatibility.
 
       DeleteNodeIfCollapsedText(nodeAsText);
 
-      rv = InsertBRIfNeeded(aSelection);
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = InsertBRIfNeeded(&SelectionRef());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
       // Remember that we did a ranged delete for the benefit of
       // AfterEditInner().
       mDidRangedDelete = true;
 
       return NS_OK;
     }
 
@@ -2490,18 +2537,22 @@ HTMLEditRules::WillDeleteSelection(Selec
         visNode->IsHTMLElement(nsGkAtoms::hr)) {
       // Short circuit for invisible breaks.  delete them and recurse.
       if (visNode->IsHTMLElement(nsGkAtoms::br) &&
           !HTMLEditorRef().IsVisibleBRElement(visNode)) {
         rv = HTMLEditorRef().DeleteNodeWithTransaction(*visNode);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
-        return WillDeleteSelection(aSelection, aAction, aStripWrappers,
-                                   aCancel, aHandled);
+        rv = WillDeleteSelection(&SelectionRef(), aAction, aStripWrappers,
+                                 aCancel, aHandled);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        return NS_OK;
       }
 
       // Special handling for backspace when positioned after <hr>
       if (aAction == nsIEditor::ePrevious &&
           visNode->IsHTMLElement(nsGkAtoms::hr)) {
         // Only if the caret is positioned at the end-of-hr-line position, we
         // want to delete the <hr>.
         //
@@ -2520,32 +2571,39 @@ HTMLEditRules::WillDeleteSelection(Selec
         // interlineposition to false, only moving the caret to the
         // end-of-hr-line position.
         bool moveOnly = true;
 
         selNode = visNode->GetParentNode();
         selOffset = selNode ? selNode->ComputeIndexOf(visNode) : -1;
 
         ErrorResult err;
-        bool interLineIsRight = aSelection->GetInterlinePosition(err);
+        bool interLineIsRight = SelectionRef().GetInterlinePosition(err);
         if (NS_WARN_IF(err.Failed())) {
           return err.StealNSResult();
         }
 
         if (startNode == selNode && startOffset - 1 == selOffset &&
             !interLineIsRight) {
           moveOnly = false;
         }
 
         if (moveOnly) {
           // Go to the position after the <hr>, but to the end of the <hr> line
           // by setting the interline position to left.
           ++selOffset;
-          aSelection->Collapse(selNode, selOffset);
-          aSelection->SetInterlinePosition(false, IgnoreErrors());
+          IgnoredErrorResult ignoredError;
+          SelectionRef().Collapse(RawRangeBoundary(selNode, selOffset),
+                                  ignoredError);
+          NS_WARNING_ASSERTION(!ignoredError.Failed(),
+            "Failed to collapse selection at after the <hr>");
+          (ErrorResult&)ignoredError = NS_OK;
+          SelectionRef().SetInterlinePosition(false, ignoredError);
+          NS_WARNING_ASSERTION(!ignoredError.Failed(),
+            "Failed to unset interline position");
           mDidExplicitlySetInterline = true;
           *aHandled = true;
 
           // There is one exception to the move only case.  If the <hr> is
           // followed by a <br> we want to delete the <br>.
 
           WSType otherWSType;
           nsCOMPtr<nsINode> otherNode;
@@ -2607,23 +2665,25 @@ HTMLEditRules::WillDeleteSelection(Selec
         EditorDOMPoint pt =
           JoinNearestEditableNodesWithTransaction(*sibling,
                                                   *startNode->AsContent());
         if (NS_WARN_IF(!pt.IsSet())) {
           return NS_ERROR_FAILURE;
         }
         // Fix up selection
         ErrorResult error;
-        aSelection->Collapse(pt, error);
+        SelectionRef().Collapse(pt, error);
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
       }
-      rv = InsertBRIfNeeded(aSelection);
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = InsertBRIfNeeded(&SelectionRef());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       return NS_OK;
     }
 
     if (wsType == WSType::otherBlock) {
       // Make sure it's not a table element.  If so, cancel the operation
       // (translation: users cannot backspace or delete across table cells)
       if (HTMLEditUtils::IsTableElement(visNode)) {
         *aCancel = true;
@@ -2676,22 +2736,27 @@ HTMLEditRules::WillDeleteSelection(Selec
       // Don't cross table boundaries
       if (leftNode && rightNode &&
           InDifferentTableElements(leftNode, rightNode)) {
         return NS_OK;
       }
 
       if (bDeletedBR) {
         // Put selection at edge of block and we are done.
-        NS_ENSURE_STATE(leafNode);
+        if (NS_WARN_IF(!leafNode)) {
+          return NS_ERROR_FAILURE;
+        }
         EditorDOMPoint newSel = GetGoodSelPointForNode(*leafNode, aAction);
         if (NS_WARN_IF(!newSel.IsSet())) {
           return NS_ERROR_FAILURE;
         }
-        aSelection->Collapse(newSel);
+        IgnoredErrorResult error;
+        SelectionRef().Collapse(newSel, error);
+        NS_WARNING_ASSERTION(!error.Failed(),
+          "Failed to collapse selection at edge of the block");
         return NS_OK;
       }
 
       // Else we are joining content to block
 
       nsCOMPtr<nsINode> selPointNode = startNode;
       int32_t selPointOffset = startOffset;
       {
@@ -2715,23 +2780,31 @@ HTMLEditRules::WillDeleteSelection(Selec
 
       // If TryToJoinBlocksWithTransaction() didn't handle it  and it's not
       // canceled, user may want to modify the start leaf node or the last leaf
       // node of the block.
       if (!*aHandled && !*aCancel && leafNode != startNode) {
         int32_t offset =
           aAction == nsIEditor::ePrevious ?
             static_cast<int32_t>(leafNode->Length()) : 0;
-        aSelection->Collapse(leafNode, offset);
-        return WillDeleteSelection(aSelection, aAction, aStripWrappers,
-                                   aCancel, aHandled);
+        rv = SelectionRef().Collapse(leafNode, offset);
+        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+          "Failed to collapse selection at the leaf node");
+        rv = WillDeleteSelection(&SelectionRef(), aAction, aStripWrappers,
+                                 aCancel, aHandled);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        return NS_OK;
       }
 
       // Otherwise, we must have deleted the selection as user expected.
-      aSelection->Collapse(selPointNode, selPointOffset);
+      rv = SelectionRef().Collapse(selPointNode, selPointOffset);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+        "Failed to selection at deleted point");
       return NS_OK;
     }
 
     if (wsType == WSType::thisBlock) {
       // At edge of our block.  Look beside it and see if we can join to an
       // adjacent block
 
       // Make sure it's not a table element.  If so, cancel the operation
@@ -2779,37 +2852,47 @@ HTMLEditRules::WillDeleteSelection(Selec
         // this handles the action because the caller shouldn't do anything
         // anymore in this case.
         *aHandled = true;
         *aCancel |= ret.Canceled();
         if (NS_WARN_IF(ret.Failed())) {
           return ret.Rv();
         }
       }
-      aSelection->Collapse(selPointNode, selPointOffset);
+      rv = SelectionRef().Collapse(selPointNode, selPointOffset);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
       return NS_OK;
     }
   }
 
 
   // Else we have a non-collapsed selection.  First adjust the selection.
-  rv = ExpandSelectionForDeletion(*aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
+  rv = ExpandSelectionForDeletion(SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // Remember that we did a ranged delete for the benefit of AfterEditInner().
   mDidRangedDelete = true;
 
   // Refresh start and end points
-  NS_ENSURE_STATE(aSelection->GetRangeAt(0));
-  startNode = aSelection->GetRangeAt(0)->GetStartContainer();
-  startOffset = aSelection->GetRangeAt(0)->StartOffset();
-  NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-  nsCOMPtr<nsINode> endNode = aSelection->GetRangeAt(0)->GetEndContainer();
-  int32_t endOffset = aSelection->GetRangeAt(0)->EndOffset();
-  NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
+  firstRange = SelectionRef().GetRangeAt(0);
+  if (NS_WARN_IF(!firstRange)) {
+    return NS_ERROR_FAILURE;
+  }
+  startNode = firstRange->GetStartContainer();
+  if (NS_WARN_IF(!startNode)) {
+    return NS_ERROR_FAILURE;
+  }
+  startOffset = firstRange->StartOffset();
+  nsCOMPtr<nsINode> endNode = firstRange->GetEndContainer();
+  if (NS_WARN_IF(!endNode)) {
+    return NS_ERROR_FAILURE;
+  }
+  int32_t endOffset = firstRange->EndOffset();
 
   // Figure out if the endpoints are in nodes that can be merged.  Adjust
   // surrounding whitespace in preparation to delete selection.
   if (!IsPlaintextEditor()) {
     AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
     rv = WSRunObject::PrepareToDeleteRange(&HTMLEditorRef(),
                                            address_of(startNode), &startOffset,
                                            address_of(endNode), &endOffset);
@@ -2881,28 +2964,28 @@ HTMLEditRules::WillDeleteSelection(Selec
           EditorDOMPoint pt =
             HTMLEditorRef().JoinNodesDeepWithTransaction(*leftParent,
                                                          *rightParent);
           if (NS_WARN_IF(!pt.IsSet())) {
             return NS_ERROR_FAILURE;
           }
           // Fix up selection
           ErrorResult error;
-          aSelection->Collapse(pt, error);
+          SelectionRef().Collapse(pt, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
 
         // Else blocks not same type, or not siblings.  Delete everything
         // except table elements.
         join = true;
 
-        AutoRangeArray arrayOfRanges(aSelection);
+        AutoRangeArray arrayOfRanges(&SelectionRef());
         for (auto& range : arrayOfRanges.mRanges) {
           // Build a list of nodes in the range
           nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
           TrivialFunctor functor;
           DOMSubtreeIterator iter;
           nsresult rv = iter.Init(*range);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
@@ -2991,22 +3074,22 @@ HTMLEditRules::WillDeleteSelection(Selec
   // collapsed to the end of the selection, if deleting backward the selection
   // should be collapsed to the beginning of the selection. But if we're not
   // joining then the selection should collapse to the beginning of the
   // selection if we'redeleting forward, because the end of the selection will
   // still be in the next block. And same thing for deleting backwards
   // (selection should collapse to the end, because the beginning will still be
   // in the first block). See Bug 507936
   if (aAction == (join ? nsIEditor::eNext : nsIEditor::ePrevious)) {
-    rv = aSelection->Collapse(endNode, endOffset);
+    rv = SelectionRef().Collapse(endNode, endOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
-    rv = aSelection->Collapse(startNode, startOffset);
+    rv = SelectionRef().Collapse(startNode, startOffset);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 /**
@@ -3045,17 +3128,18 @@ nsresult
 HTMLEditRules::InsertBRIfNeeded(Selection* aSelection)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aSelection)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  EditorRawDOMPoint atStartOfSelection(EditorBase::GetStartPoint(aSelection));
+  EditorRawDOMPoint atStartOfSelection(
+                      EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // inline elements don't need any br
   if (!IsBlockNode(*atStartOfSelection.GetContainer())) {
     return NS_OK;
   }
@@ -3065,17 +3149,17 @@ HTMLEditRules::InsertBRIfNeeded(Selectio
   if (((wsObj.mStartReason & WSType::block) ||
        (wsObj.mStartReason & WSType::br)) &&
       (wsObj.mEndReason & WSType::block)) {
     // if we are tucked between block boundaries then insert a br
     // first check that we are allowed to
     if (HTMLEditorRef().CanContainTag(*atStartOfSelection.GetContainer(),
                                       *nsGkAtoms::br)) {
       RefPtr<Element> brElement =
-        HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+        HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                        atStartOfSelection,
                                                        nsIEditor::ePrevious);
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
       return NS_OK;
     }
   }
@@ -3604,17 +3688,17 @@ HTMLEditRules::DidDeleteSelection(Select
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aSelection) {
     return NS_ERROR_NULL_POINTER;
   }
 
   // find where we are
-  EditorDOMPoint atStartOfSelection(EditorBase::GetStartPoint(aSelection));
+  EditorDOMPoint atStartOfSelection(EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // find any enclosing mailcite
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*atStartOfSelection.GetContainer());
   if (citeNode) {
@@ -3627,31 +3711,31 @@ HTMLEditRules::DidDeleteSelection(Select
         AutoEditorDOMPointChildInvalidator lockOffset(atCiteNode);
         nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*citeNode);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       if (atCiteNode.IsSet() && seenBR) {
         RefPtr<Element> brElement =
-          HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+          HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                          atCiteNode);
         if (NS_WARN_IF(!brElement)) {
           return NS_ERROR_FAILURE;
         }
         IgnoredErrorResult error;
-        aSelection->Collapse(EditorRawDOMPoint(brElement), error);
+        SelectionRef().Collapse(EditorRawDOMPoint(brElement), error);
         NS_WARNING_ASSERTION(!error.Failed(),
           "Failed to collapse selection at the new <br> element");
       }
     }
   }
 
   // call through to base class
-  return TextEditRules::DidDeleteSelection(aSelection, aDir, aResult);
+  return TextEditRules::DidDeleteSelection(&SelectionRef(), aDir, aResult);
 }
 
 nsresult
 HTMLEditRules::WillMakeList(Selection* aSelection,
                             const nsAString* aListType,
                             bool aEntireList,
                             const nsAString* aBulletType,
                             bool* aCancel,
@@ -3661,50 +3745,53 @@ HTMLEditRules::WillMakeList(Selection* a
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aSelection || !aListType || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
   OwningNonNull<nsAtom> listType = NS_Atomize(*aListType);
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = false;
 
   // deduce what tag to use for list items
   RefPtr<nsAtom> itemType;
   if (aItemType) {
     itemType = NS_Atomize(*aItemType);
-    NS_ENSURE_TRUE(itemType, NS_ERROR_OUT_OF_MEMORY);
   } else if (listType == nsGkAtoms::dl) {
     itemType = nsGkAtoms::dd;
   } else {
     itemType = nsGkAtoms::li;
   }
 
   // convert the selection ranges into "promoted" selection ranges:
   // this basically just expands the range to include the immediate
   // block parent, and then further expands to include any ancestors
   // whose children are all in the range
 
   *aHandled = true;
 
-  nsresult rv = NormalizeSelection(aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetListActionNodes(arrayOfNodes,
                           aEntireList ? EntireList::yes : EntireList::no);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // check if all our nodes are <br>s, or empty inlines
   bool bOnlyBreaks = true;
   for (auto& curNode : arrayOfNodes) {
     // if curNode is not a Break or empty inline, we're done
     if (!TextEditUtils::IsBreak(curNode) &&
         !IsEmptyInline(curNode)) {
       bOnlyBreaks = false;
@@ -3720,17 +3807,17 @@ HTMLEditRules::WillMakeList(Selection* a
       for (auto& node : arrayOfNodes) {
         rv = HTMLEditorRef().DeleteNodeWithTransaction(*node);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
 
-    nsRange* firstRange = aSelection->GetRangeAt(0);
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -3763,17 +3850,17 @@ HTMLEditRules::WillMakeList(Selection* a
       return NS_ERROR_FAILURE;
     }
 
     // remember our new block for postprocessing
     mNewBlock = theListItem;
     // put selection in new list item
     *aHandled = true;
     ErrorResult error;
-    aSelection->Collapse(EditorRawDOMPoint(theListItem, 0), error);
+    SelectionRef().Collapse(EditorRawDOMPoint(theListItem, 0), error);
     // Don't restore the selection
     selectionRestorer.Abort();
     if (NS_WARN_IF(!error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
   }
 
@@ -3786,17 +3873,19 @@ HTMLEditRules::WillMakeList(Selection* a
   // or whatever is approriate.  Wohoo!
 
   uint32_t listCount = arrayOfNodes.Length();
   nsCOMPtr<Element> curList, prevListItem;
 
   for (uint32_t i = 0; i < listCount; i++) {
     // here's where we actually figure out what to do
     RefPtr<Element> newBlock;
-    NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
+    if (NS_WARN_IF(!arrayOfNodes[i]->IsContent())) {
+      return NS_ERROR_FAILURE;
+    }
     OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
 
     // make sure we don't assemble content that is in different table cells
     // into the same list.  respect table cell boundaries when listifying.
     if (curList && InDifferentTableElements(curList, curNode)) {
       curList = nullptr;
     }
 
@@ -4028,25 +4117,25 @@ HTMLEditRules::WillRemoveList(Selection*
 
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
   // initialize out param
   *aCancel = false;
   *aHandled = true;
 
-  nsresult rv = NormalizeSelection(aSelection);
+  nsresult rv = NormalizeSelection(&SelectionRef());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
-  GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::makeList);
+  GetPromotedRanges(SelectionRef(), arrayOfRanges, EditAction::makeList);
 
   // use these ranges to contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetListActionNodes(arrayOfNodes, EntireList::no);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -4081,61 +4170,74 @@ HTMLEditRules::WillRemoveList(Selection*
 
 nsresult
 HTMLEditRules::WillMakeDefListItem(Selection* aSelection,
                                    const nsAString *aItemType,
                                    bool aEntireList,
                                    bool* aCancel,
                                    bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // for now we let WillMakeList handle this
   NS_NAMED_LITERAL_STRING(listType, "dl");
-  return WillMakeList(aSelection, &listType.AsString(), aEntireList, nullptr,
-                      aCancel, aHandled, aItemType);
+  nsresult rv = WillMakeList(&SelectionRef(), &listType.AsString(), aEntireList,
+                             nullptr, aCancel, aHandled, aItemType);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillMakeBasicBlock(Selection& aSelection,
                                   const nsAString& aBlockType,
                                   bool* aCancel,
                                   bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
 
   OwningNonNull<nsAtom> blockType = NS_Atomize(aBlockType);
 
-  WillInsert(aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
   // We want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
-  nsresult rv = MakeBasicBlock(aSelection, blockType);
-  Unused << NS_WARN_IF(NS_FAILED(rv));
-  return rv;
+  nsresult rv = MakeBasicBlock(SelectionRef(), blockType);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::MakeBasicBlock(Selection& aSelection, nsAtom& blockType)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  nsresult rv = NormalizeSelection(&aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
   AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
   // Contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
-  rv = GetNodesFromSelection(aSelection, EditAction::makeBasicBlock,
+  rv = GetNodesFromSelection(SelectionRef(), EditAction::makeBasicBlock,
                              arrayOfNodes);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // If nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
-    nsRange* firstRange = aSelection.GetRangeAt(0);
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint pointToInsertBlock(firstRange->StartRef());
     if (&blockType == nsGkAtoms::normal ||
         &blockType == nsGkAtoms::_empty) {
       // We are removing blocks (going to "body text")
@@ -4166,25 +4268,25 @@ HTMLEditRules::MakeBasicBlock(Selection&
                           *curBlock, pointToInsertBlock,
                           SplitAtEdges::eDoNotCreateEmptyContainer);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       EditorRawDOMPoint pointToInsertBrNode(splitNodeResult.SplitPoint());
       // Put a <br> element at the split point
       brContent =
-        HTMLEditorRef().InsertBrElementWithTransaction(aSelection,
+        HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                        pointToInsertBrNode);
       if (NS_WARN_IF(!brContent)) {
         return NS_ERROR_FAILURE;
       }
       // Put selection at the split point
       EditorRawDOMPoint atBrNode(brContent);
       ErrorResult error;
-      aSelection.Collapse(atBrNode, error);
+      SelectionRef().Collapse(atBrNode, error);
       // Don't restore the selection
       selectionRestorer.Abort();
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
       return NS_OK;
     }
 
@@ -4220,72 +4322,89 @@ HTMLEditRules::MakeBasicBlock(Selection&
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
       rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // Put selection in new block
-    rv = aSelection.Collapse(block, 0);
+    rv = SelectionRef().Collapse(block, 0);
     // Don't restore the selection
     selectionRestorer.Abort();
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     return NS_OK;
   }
   // Okay, now go through all the nodes and make the right kind of blocks, or
   // whatever is approriate.  Woohoo!  Note: blockquote is handled a little
   // differently.
   if (&blockType == nsGkAtoms::blockquote) {
     rv = MakeBlockquote(arrayOfNodes);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   } else if (&blockType == nsGkAtoms::normal ||
              &blockType == nsGkAtoms::_empty) {
     rv = RemoveBlockStyle(arrayOfNodes);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   } else {
     rv = ApplyBlockStyle(arrayOfNodes, blockType);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::DidMakeBasicBlock(Selection* aSelection,
                                  RulesInfo* aInfo,
                                  nsresult aResult)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   // check for empty block.  if so, put a moz br in it.
-  if (!aSelection->IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     return NS_OK;
   }
 
-  NS_ENSURE_STATE(aSelection->GetRangeAt(0) &&
-                  aSelection->GetRangeAt(0)->GetStartContainer());
-  nsresult rv =
-    InsertMozBRIfNeeded(*aSelection->GetRangeAt(0)->GetStartContainer());
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  if (NS_WARN_IF(!firstRange)) {
+    return NS_ERROR_FAILURE;
+  }
+  const RangeBoundary& atStartOfSelection = firstRange->StartRef();
+  if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
+    return NS_ERROR_FAILURE;
+  }
+  nsresult rv = InsertMozBRIfNeeded(*atStartOfSelection.Container());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillIndent(Selection* aSelection,
                           bool* aCancel,
                           bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (HTMLEditorRef().IsCSSEnabled()) {
-    nsresult rv = WillCSSIndent(aSelection, aCancel, aHandled);
+    nsresult rv = WillCSSIndent(&SelectionRef(), aCancel, aHandled);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
-    nsresult rv = WillHTMLIndent(aSelection, aCancel, aHandled);
+    nsresult rv = WillHTMLIndent(&SelectionRef(), aCancel, aHandled);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 nsresult
@@ -4294,36 +4413,38 @@ HTMLEditRules::WillCSSIndent(Selection* 
                              bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
-  nsresult rv = NormalizeSelection(aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
   nsTArray<OwningNonNull<nsRange>> arrayOfRanges;
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
 
   // short circuit: detect case of collapsed selection inside an <li>.
   // just sublist that <li>.  This prevents bug 97797.
 
   nsCOMPtr<Element> liNode;
-  if (aSelection->IsCollapsed()) {
+  if (SelectionRef().IsCollapsed()) {
     EditorRawDOMPoint selectionStartPoint(
-                        EditorBase::GetStartPoint(aSelection));
+                        EditorBase::GetStartPoint(&SelectionRef()));
     if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
     Element* block =
       HTMLEditorRef().GetBlock(*selectionStartPoint.GetContainer());
     if (block && HTMLEditUtils::IsListItem(block)) {
       liNode = block;
     }
@@ -4331,24 +4452,27 @@ HTMLEditRules::WillCSSIndent(Selection* 
 
   if (liNode) {
     arrayOfNodes.AppendElement(*liNode);
   } else {
     // convert the selection ranges into "promoted" selection ranges:
     // this basically just expands the range to include the immediate
     // block parent, and then further expands to include any ancestors
     // whose children are all in the range
-    rv = GetNodesFromSelection(*aSelection, EditAction::indent, arrayOfNodes);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = GetNodesFromSelection(SelectionRef(), EditAction::indent,
+                               arrayOfNodes);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
 
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
     // get selection location
-    nsRange* firstRange = aSelection->GetRangeAt(0);
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -4377,17 +4501,17 @@ HTMLEditRules::WillCSSIndent(Selection* 
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // put selection in new block
     *aHandled = true;
     EditorRawDOMPoint atStartOfTheBlock(theBlock, 0);
     ErrorResult error;
-    aSelection->Collapse(atStartOfTheBlock, error);
+    SelectionRef().Collapse(atStartOfTheBlock, error);
     // Don't restore the selection
     selectionRestorer.Abort();
     if (NS_WARN_IF(!error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
   }
 
@@ -4528,44 +4652,48 @@ HTMLEditRules::WillHTMLIndent(Selection*
                               bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
-  nsresult rv = NormalizeSelection(aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   // convert the selection ranges into "promoted" selection ranges:
   // this basically just expands the range to include the immediate
   // block parent, and then further expands to include any ancestors
   // whose children are all in the range
 
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
-  GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::indent);
+  GetPromotedRanges(SelectionRef(), arrayOfRanges, EditAction::indent);
 
   // use these ranges to contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
-    nsRange* firstRange = aSelection->GetRangeAt(0);
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -4593,17 +4721,17 @@ HTMLEditRules::WillHTMLIndent(Selection*
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // put selection in new block
     *aHandled = true;
     EditorRawDOMPoint atStartOfTheBlock(theBlock, 0);
     ErrorResult error;
-    aSelection->Collapse(atStartOfTheBlock, error);
+    SelectionRef().Collapse(atStartOfTheBlock, error);
     // Don't restore the selection
     selectionRestorer.Abort();
     if (NS_WARN_IF(!error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
   }
 
@@ -4805,30 +4933,35 @@ HTMLEditRules::WillOutdent(Selection& aS
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
   *aCancel = false;
   *aHandled = true;
   nsCOMPtr<nsIContent> rememberedLeftBQ, rememberedRightBQ;
 
   bool useCSS = HTMLEditorRef().IsCSSEnabled();
 
-  nsresult rv = NormalizeSelection(&aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // Some scoping for selection resetting - we may need to tweak it
   {
-    AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
+    AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
     // Convert the selection ranges into "promoted" selection ranges: this
     // basically just expands the range to include the immediate block parent,
     // and then further expands to include any ancestors whose children are all
     // in the range
     nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
-    rv = GetNodesFromSelection(aSelection, EditAction::outdent, arrayOfNodes);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = GetNodesFromSelection(SelectionRef(), EditAction::outdent,
+                               arrayOfNodes);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
 
     // Okay, now go through all the nodes and remove a level of blockquoting,
     // or whatever is appropriate.  Wohoo!
 
     nsCOMPtr<Element> curBlockQuote;
     nsCOMPtr<nsIContent> firstBQChild, lastBQChild;
     bool curBlockQuoteIsIndentedWithCSS = false;
     for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
@@ -5025,46 +5158,67 @@ HTMLEditRules::WillOutdent(Selection& aS
                               curBlockQuoteIsIndentedWithCSS,
                               getter_AddRefs(rememberedLeftBQ),
                               getter_AddRefs(rememberedRightBQ));
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
   // Make sure selection didn't stick to last piece of content in old bq (only
   // a problem for collapsed selections)
-  if (rememberedLeftBQ || rememberedRightBQ) {
-    if (aSelection.IsCollapsed()) {
-      // Push selection past end of rememberedLeftBQ
-      NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_OK);
-      nsCOMPtr<nsINode> startNode =
-        aSelection.GetRangeAt(0)->GetStartContainer();
-      if (rememberedLeftBQ &&
-          (startNode == rememberedLeftBQ ||
-           EditorUtils::IsDescendantOf(*startNode, *rememberedLeftBQ))) {
-        // Selection is inside rememberedLeftBQ - push it past it.
-        EditorRawDOMPoint afterRememberedLeftBQ(rememberedLeftBQ);
-        afterRememberedLeftBQ.AdvanceOffset();
-        aSelection.Collapse(afterRememberedLeftBQ);
-      }
-      // And pull selection before beginning of rememberedRightBQ
-      startNode = aSelection.GetRangeAt(0)->GetStartContainer();
-      if (rememberedRightBQ &&
-          (startNode == rememberedRightBQ ||
-           EditorUtils::IsDescendantOf(*startNode, *rememberedRightBQ))) {
-        // Selection is inside rememberedRightBQ - push it before it.
-        EditorRawDOMPoint atRememberedRightBQ(rememberedRightBQ);
-        aSelection.Collapse(atRememberedRightBQ);
-      }
-    }
+  if (!rememberedLeftBQ && !rememberedRightBQ) {
+    return NS_OK;
+  }
+
+  if (!SelectionRef().IsCollapsed()) {
     return NS_OK;
   }
+
+  // Push selection past end of rememberedLeftBQ
+  if (rememberedLeftBQ) {
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    if (NS_WARN_IF(!firstRange)) {
+      return NS_OK;
+    }
+    const RangeBoundary& atStartOfSelection = firstRange->StartRef();
+    if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
+      return NS_ERROR_FAILURE;
+    }
+    if (atStartOfSelection.Container() == rememberedLeftBQ ||
+        EditorUtils::IsDescendantOf(*atStartOfSelection.Container(),
+                                    *rememberedLeftBQ)) {
+      // Selection is inside rememberedLeftBQ - push it past it.
+      EditorRawDOMPoint afterRememberedLeftBQ(rememberedLeftBQ);
+      afterRememberedLeftBQ.AdvanceOffset();
+      IgnoredErrorResult error;
+      SelectionRef().Collapse(afterRememberedLeftBQ, error);
+      NS_WARNING_ASSERTION(!error.Failed(),
+        "Failed to collapse selection after the left <blockquote>");
+    }
+  }
+  // And pull selection before beginning of rememberedRightBQ
+  if (rememberedRightBQ) {
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    const RangeBoundary& atStartOfSelection = firstRange->StartRef();
+    if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
+      return NS_ERROR_FAILURE;
+    }
+    if (atStartOfSelection.Container() == rememberedRightBQ ||
+        EditorUtils::IsDescendantOf(*atStartOfSelection.Container(),
+                                    *rememberedRightBQ)) {
+      // Selection is inside rememberedRightBQ - push it before it.
+      EditorRawDOMPoint atRememberedRightBQ(rememberedRightBQ);
+      IgnoredErrorResult error;
+      SelectionRef().Collapse(atRememberedRightBQ, error);
+      NS_WARNING_ASSERTION(!error.Failed(),
+        "Failed to collapse selection after the right <blockquote>");
+    }
+  }
   return NS_OK;
 }
 
-
 /**
  * RemovePartOfBlock() splits aBlock and move aStartChild to aEndChild out of
  * aBlock.
  */
 nsresult
 HTMLEditRules::RemovePartOfBlock(Element& aBlock,
                                  nsIContent& aStartChild,
                                  nsIContent& aEndChild)
@@ -5226,22 +5380,27 @@ HTMLEditRules::ConvertListType(Element* 
 nsresult
 HTMLEditRules::CreateStyleForInsertText(Selection& aSelection,
                                         nsIDocument& aDoc)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(HTMLEditorRef().mTypeInState);
 
   bool weDidSomething = false;
-  NS_ENSURE_STATE(aSelection.GetRangeAt(0));
-  nsCOMPtr<nsINode> node = aSelection.GetRangeAt(0)->GetStartContainer();
-  int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  if (NS_WARN_IF(!firstRange)) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsINode> node = firstRange->GetStartContainer();
+  int32_t offset = firstRange->StartOffset();
 
   nsCOMPtr<Element> rootElement = aDoc.GetRootElement();
-  NS_ENSURE_STATE(rootElement);
+  if (NS_WARN_IF(!rootElement)) {
+    return NS_ERROR_FAILURE;
+  }
 
   // process clearing any styles first
   UniquePtr<PropItem> item =
     Move(HTMLEditorRef().mTypeInState->TakeClearProperty());
 
   {
     // Transactions may set selection, but we will set selection if necessary.
     AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
@@ -5312,20 +5471,25 @@ HTMLEditRules::CreateStyleForInsertText(
                                                    *item->tag, item->attr,
                                                    item->value);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       item = HTMLEditorRef().mTypeInState->TakeSetProperty();
     }
   }
-  if (weDidSomething) {
-    return aSelection.Collapse(node, offset);
-  }
-
+
+  if (!weDidSomething) {
+    return NS_OK;
+  }
+
+  nsresult rv = SelectionRef().Collapse(node, offset);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   return NS_OK;
 }
 
 bool
 HTMLEditRules::IsEmptyBlockElement(Element& aElement,
                                    IgnoreSingleBR aIgnoreSingleBR)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
@@ -5347,34 +5511,38 @@ nsresult
 HTMLEditRules::WillAlign(Selection& aSelection,
                          const nsAString& aAlignType,
                          bool* aCancel,
                          bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
 
-  WillInsert(aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // Initialize out param.  We want to ignore result of WillInsert().
   *aCancel = false;
   *aHandled = false;
 
-  nsresult rv = NormalizeSelection(&aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   // Convert the selection ranges into "promoted" selection ranges: This
   // basically just expands the range to include the immediate block parent,
   // and then further expands to include any ancestors whose children are all
   // in the range
   *aHandled = true;
   nsTArray<OwningNonNull<nsINode>> nodeArray;
-  rv = GetNodesFromSelection(aSelection, EditAction::align, nodeArray);
-  NS_ENSURE_SUCCESS(rv, rv);
+  rv = GetNodesFromSelection(SelectionRef(), EditAction::align, nodeArray);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // If we don't have any nodes, or we have only a single br, then we are
   // creating an empty alignment div.  We have to do some different things for
   // these.
   bool emptyDiv = nodeArray.IsEmpty();
   if (nodeArray.Length() == 1) {
     OwningNonNull<nsINode> node = nodeArray[0];
 
@@ -5396,27 +5564,31 @@ HTMLEditRules::WillAlign(Selection& aSel
       // through to the normal case alignment code.
       //
       // XXX: It seems a little error prone for the emptyDiv special case code
       // to assume that the start node of the selection is the parent of the
       // single node in the nodeArray, as the paragraph above points out. Do we
       // rely on the selection start node because of the fact that nodeArray
       // can be empty?  We should probably revisit this issue. - kin
 
-      NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
-                      aSelection.GetRangeAt(0)->GetStartContainer());
-      OwningNonNull<nsINode> parent =
-        *aSelection.GetRangeAt(0)->GetStartContainer();
-
+      nsRange* firstRange = SelectionRef().GetRangeAt(0);
+      if (NS_WARN_IF(!firstRange)) {
+        return NS_ERROR_FAILURE;
+      }
+      const RangeBoundary& atStartOfSelection = firstRange->StartRef();
+      if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
+        return NS_ERROR_FAILURE;
+      }
+      nsINode* parent = atStartOfSelection.Container();
       emptyDiv = !HTMLEditUtils::IsTableElement(parent) ||
-                 HTMLEditUtils::IsTableCellOrCaption(parent);
+                 HTMLEditUtils::IsTableCellOrCaption(*parent);
     }
   }
   if (emptyDiv) {
-    nsRange* firstRange = aSelection.GetRangeAt(0);
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -5465,17 +5637,17 @@ HTMLEditRules::WillAlign(Selection& aSel
     *aHandled = true;
     // Put in a moz-br so that it won't get deleted
     RefPtr<Element> brElement = CreateMozBR(EditorRawDOMPoint(div, 0));
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
     EditorRawDOMPoint atStartOfDiv(div, 0);
     ErrorResult error;
-    aSelection.Collapse(atStartOfDiv, error);
+    SelectionRef().Collapse(atStartOfDiv, error);
     // Don't restore the selection
     selectionRestorer.Abort();
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
   }
 
@@ -5726,24 +5898,24 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
         EditorDOMPoint atBlockParent(blockParent);
         if (NS_WARN_IF(!atBlockParent.IsSet())) {
           return NS_ERROR_FAILURE;
         }
         // If we are a sublist, skip the br creation
         if (!HTMLEditUtils::IsList(atBlockParent.GetContainer())) {
           // Create a br before list
           RefPtr<Element> brElement =
-            HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+            HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                            atBlockParent);
           if (NS_WARN_IF(!brElement)) {
             return NS_ERROR_FAILURE;
           }
           // Adjust selection to be right before it
           ErrorResult error;
-          aSelection->Collapse(EditorRawDOMPoint(brElement), error);
+          SelectionRef().Collapse(EditorRawDOMPoint(brElement), error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
         }
         // Else just let selection percolate up.  We'll adjust it in
         // AfterEdit()
       }
     } else {
@@ -5754,50 +5926,56 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
         DebugOnly<bool> advanced = afterEmptyBlock.AdvanceOffset();
         NS_WARNING_ASSERTION(advanced,
           "Failed to set selection to the after the empty block");
         nsCOMPtr<nsIContent> nextNode =
           HTMLEditorRef().GetNextNode(afterEmptyBlock);
         if (nextNode) {
           EditorDOMPoint pt = GetGoodSelPointForNode(*nextNode, aAction);
           ErrorResult error;
-          aSelection->Collapse(pt, error);
+          SelectionRef().Collapse(pt, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
         } else {
           // Adjust selection to be right after it.
           EditorRawDOMPoint afterEmptyBlock(emptyBlock);
           if (NS_WARN_IF(!afterEmptyBlock.AdvanceOffset())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
-          aSelection->Collapse(afterEmptyBlock, error);
+          SelectionRef().Collapse(afterEmptyBlock, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
         }
       } else if (aAction == nsIEditor::ePrevious ||
                  aAction == nsIEditor::ePreviousWord ||
                  aAction == nsIEditor::eToBeginningOfLine) {
         // Move to the end of the previous node
         EditorRawDOMPoint atEmptyBlock(emptyBlock);
         nsCOMPtr<nsIContent> priorNode =
           HTMLEditorRef().GetPreviousEditableNode(atEmptyBlock);
         if (priorNode) {
           EditorDOMPoint pt = GetGoodSelPointForNode(*priorNode, aAction);
-          nsresult rv = aSelection->Collapse(pt);
-          NS_ENSURE_SUCCESS(rv, rv);
+          ErrorResult error;
+          SelectionRef().Collapse(pt, error);
+          if (NS_WARN_IF(error.Failed())) {
+            return error.StealNSResult();
+          }
         } else {
           EditorRawDOMPoint afterEmptyBlock(emptyBlock);
           if (NS_WARN_IF(!afterEmptyBlock.AdvanceOffset())) {
             return NS_ERROR_FAILURE;
           }
-          nsresult rv = aSelection->Collapse(afterEmptyBlock);
-          NS_ENSURE_SUCCESS(rv, rv);
+          ErrorResult error;
+          SelectionRef().Collapse(afterEmptyBlock, error);
+          if (NS_WARN_IF(error.Failed())) {
+            return error.StealNSResult();
+          }
         }
       } else if (aAction != nsIEditor::eNone) {
         MOZ_CRASH("CheckForEmptyBlock doesn't support this action yet");
       }
     }
     *aHandled = true;
     nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*emptyBlock);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -5885,39 +6063,43 @@ HTMLEditRules::GetInnerContent(
  * Promotes selection to include blocks that have all their children selected.
  */
 nsresult
 HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // Don't need to touch collapsed selections
-  if (aSelection.IsCollapsed()) {
+  if (SelectionRef().IsCollapsed()) {
     return NS_OK;
   }
 
   // We don't need to mess with cell selections, and we assume multirange
   // selections are those.
-  if (aSelection.RangeCount() != 1) {
+  if (SelectionRef().RangeCount() != 1) {
     return NS_OK;
   }
 
   // Find current sel start and end
-  NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_ERROR_NULL_POINTER);
-  OwningNonNull<nsRange> range = *aSelection.GetRangeAt(0);
-
-  nsCOMPtr<nsINode> selStartNode = range->GetStartContainer();
-  int32_t selStartOffset = range->StartOffset();
-  nsCOMPtr<nsINode> selEndNode = range->GetEndContainer();
-  int32_t selEndOffset = range->EndOffset();
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  if (NS_WARN_IF(!firstRange)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsINode> selStartNode = firstRange->GetStartContainer();
+  int32_t selStartOffset = firstRange->StartOffset();
+  nsCOMPtr<nsINode> selEndNode = firstRange->GetEndContainer();
+  int32_t selEndOffset = firstRange->EndOffset();
 
   // Find current selection common block parent
   nsCOMPtr<Element> selCommon =
-    HTMLEditor::GetBlock(*range->GetCommonAncestor());
-  NS_ENSURE_STATE(selCommon);
+    HTMLEditor::GetBlock(*firstRange->GetCommonAncestor());
+  if (NS_WARN_IF(!selCommon)) {
+    return NS_ERROR_FAILURE;
+  }
 
   // Set up for loops and cache our root element
   nsCOMPtr<nsINode> firstBRParent;
   nsCOMPtr<nsINode> unused;
   int32_t visOffset = 0, firstBROffset = 0;
   WSType wsType;
   RefPtr<Element> root = HTMLEditorRef().GetActiveEditingHost();
   if (NS_WARN_IF(!root)) {
@@ -5974,17 +6156,19 @@ HTMLEditRules::ExpandSelectionForDeletio
         selEndNode = wsObj.mEndReasonNode->GetParentNode();
         selEndOffset = 1 + selEndNode->ComputeIndexOf(wsObj.mEndReasonNode);
       } else {
         break;
       }
     }
   }
   // Now set the selection to the new range
-  aSelection.Collapse(selStartNode, selStartOffset);
+  DebugOnly<nsresult> rv =
+    SelectionRef().Collapse(selStartNode, selStartOffset);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
 
   // Expand selection endpoint only if we didn't pass a br, or if we really
   // needed to pass that br (i.e., its block is now totally selected)
   bool doEndExpansion = true;
   if (firstBRParent) {
     // Find block node containing br
     nsCOMPtr<Element> brBlock = HTMLEditor::GetBlock(*firstBRParent);
     bool nodeBefore = false, nodeAfter = false;
@@ -6003,22 +6187,26 @@ HTMLEditRules::ExpandSelectionForDeletio
     }
 
     // If block isn't contained, forgo grabbing the br in expanded selection
     if (nodeBefore || nodeAfter) {
       doEndExpansion = false;
     }
   }
   if (doEndExpansion) {
-    nsresult rv = aSelection.Extend(selEndNode, selEndOffset);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsresult rv = SelectionRef().Extend(selEndNode, selEndOffset);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   } else {
     // Only expand to just before br
-    nsresult rv = aSelection.Extend(firstBRParent, firstBROffset);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsresult rv = SelectionRef().Extend(firstBRParent, firstBROffset);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
 
   return NS_OK;
 }
 
 /**
  * NormalizeSelection() tweaks non-collapsed selections to be more "natural".
  * Idea here is to adjust selection endpoint so that they do not cross breaks
@@ -6029,26 +6217,26 @@ HTMLEditRules::ExpandSelectionForDeletio
 nsresult
 HTMLEditRules::NormalizeSelection(Selection* inSelection)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   NS_ENSURE_TRUE(inSelection, NS_ERROR_NULL_POINTER);
 
   // don't need to touch collapsed selections
-  if (inSelection->IsCollapsed()) {
+  if (SelectionRef().IsCollapsed()) {
     return NS_OK;
   }
 
   // we don't need to mess with cell selections, and we assume multirange selections are those.
-  if (inSelection->RangeCount() != 1) {
+  if (SelectionRef().RangeCount() != 1) {
     return NS_OK;
   }
 
-  RefPtr<nsRange> range = inSelection->GetRangeAt(0);
+  RefPtr<nsRange> range = SelectionRef().GetRangeAt(0);
   if (NS_WARN_IF(!range)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsINode> startNode = range->GetStartContainer();
   if (NS_WARN_IF(!startNode)) {
     return NS_ERROR_FAILURE;
   }
@@ -6172,18 +6360,24 @@ HTMLEditRules::NormalizeSelection(Select
   }
   comp = nsContentUtils::ComparePoints(newStartNode, newStartOffset,
                                        endNode, endOffset);
   if (comp == 1) {
     return NS_OK;  // New start after old end.
   }
 
   // otherwise set selection to new values.
-  inSelection->Collapse(newStartNode, newStartOffset);
-  inSelection->Extend(newEndNode, newEndOffset);
+  // XXX Why don't we use SetBaseAndExtent()?
+  DebugOnly<nsresult> rv =
+    SelectionRef().Collapse(newStartNode, newStartOffset);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+    "Failed to collapse selection");
+  rv = SelectionRef().Extend(newEndNode, newEndOffset);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+    "Failed to extend selection");
   return NS_OK;
 }
 
 /**
  * GetPromotedPoint() figures out where a start or end point for a block
  * operation really is.
  */
 EditorDOMPoint
@@ -6384,20 +6578,21 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
  * GetPromotedRanges() runs all the selection range endpoint through
  * GetPromotedPoint().
  */
 void
 HTMLEditRules::GetPromotedRanges(Selection& aSelection,
                                  nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
                                  EditAction inOperationType)
 {
-  uint32_t rangeCount = aSelection.RangeCount();
-
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  uint32_t rangeCount = SelectionRef().RangeCount();
   for (uint32_t i = 0; i < rangeCount; i++) {
-    RefPtr<nsRange> selectionRange = aSelection.GetRangeAt(i);
+    RefPtr<nsRange> selectionRange = SelectionRef().GetRangeAt(i);
     MOZ_ASSERT(selectionRange);
 
     // Clone range so we don't muck with actual selection ranges
     RefPtr<nsRange> opRange = selectionRange->CloneRange();
 
     // Make a new adjusted range to represent the appropriate block content.
     // The basic idea is to push out the range endpoints to truly enclose the
     // blocks that we will affect.  This call alters opRange.
@@ -6695,25 +6890,22 @@ HTMLEditRules::GetChildNodesForOperation
 nsresult
 HTMLEditRules::GetListActionNodes(
                  nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                  EntireList aEntireList,
                  TouchContent aTouchContent)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
   // Added this in so that ui code can ask to change an entire list, even if
   // selection is only in part of it.  used by list item dialog.
   if (aEntireList == EntireList::yes) {
-    uint32_t rangeCount = selection->RangeCount();
+    uint32_t rangeCount = SelectionRef().RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
-      RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
+      RefPtr<nsRange> range = SelectionRef().GetRangeAt(rangeIdx);
       for (nsCOMPtr<nsINode> parent = range->GetCommonAncestor();
            parent; parent = parent->GetParentNode()) {
         if (HTMLEditUtils::IsList(parent)) {
           aOutArrayOfNodes.AppendElement(*parent);
           break;
         }
       }
     }
@@ -6724,19 +6916,21 @@ HTMLEditRules::GetListActionNodes(
     }
   }
 
   {
     // We don't like other people messing with our selection!
     AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
     // contruct a list of nodes to act on.
-    nsresult rv = GetNodesFromSelection(*selection, EditAction::makeList,
+    nsresult rv = GetNodesFromSelection(SelectionRef(), EditAction::makeList,
                                         aOutArrayOfNodes, aTouchContent);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
 
   // Pre-process our list of nodes
   for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
     OwningNonNull<nsINode> testNode = aOutArrayOfNodes[i];
 
     // Remove all non-editable nodes.  Leave them be.
     if (!HTMLEditorRef().IsEditable(testNode)) {
@@ -6832,23 +7026,23 @@ HTMLEditRules::GetDefinitionListItemType
 
 nsresult
 HTMLEditRules::GetParagraphFormatNodes(
                  nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
                  TouchContent aTouchContent)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-  NS_ENSURE_STATE(selection);
-
   // Contruct a list of nodes to act on.
-  nsresult rv = GetNodesFromSelection(*selection, EditAction::makeBasicBlock,
-                                      outArrayOfNodes, aTouchContent);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult rv =
+   GetNodesFromSelection(SelectionRef(), EditAction::makeBasicBlock,
+                         outArrayOfNodes, aTouchContent);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // Pre-process our list of nodes
   for (int32_t i = outArrayOfNodes.Length() - 1; i >= 0; i--) {
     OwningNonNull<nsINode> testNode = outArrayOfNodes[i];
 
     // Remove all non-editable nodes.  Leave them be.
     if (!HTMLEditorRef().IsEditable(testNode)) {
       outArrayOfNodes.RemoveElementAt(i);
@@ -7060,24 +7254,28 @@ HTMLEditRules::GetNodesFromPoint(
  */
 nsresult
 HTMLEditRules::GetNodesFromSelection(
                  Selection& aSelection,
                  EditAction aOperation,
                  nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
                  TouchContent aTouchContent)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // Promote selection ranges
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
-  GetPromotedRanges(aSelection, arrayOfRanges, aOperation);
+  GetPromotedRanges(SelectionRef(), arrayOfRanges, aOperation);
 
   // Use these ranges to contruct a list of nodes to act on.
   nsresult rv = GetNodesForOperation(arrayOfRanges, outArrayOfNodes,
                                      aOperation, aTouchContent);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   return NS_OK;
 }
 
 /**
  * MakeTransitionList() detects all the transitions in the array, where a
  * transition means that adjacent nodes in the array don't have the same parent.
  */
@@ -7215,51 +7413,57 @@ HTMLEditRules::ReturnInHeader(Selection&
                                                   nextToHeader);
       if (NS_WARN_IF(!pNode)) {
         return NS_ERROR_FAILURE;
       }
 
       // Append a <br> to it
       RefPtr<Element> brElement =
         HTMLEditorRef().InsertBrElementWithTransaction(
-                          aSelection, EditorRawDOMPoint(pNode, 0));
+                          SelectionRef(), EditorRawDOMPoint(pNode, 0));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
 
       // Set selection to before the break
       ErrorResult error;
-      aSelection.Collapse(EditorRawDOMPoint(pNode, 0), error);
+      SelectionRef().Collapse(EditorRawDOMPoint(pNode, 0), error);
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     } else {
       EditorRawDOMPoint afterSibling(sibling);
       if (NS_WARN_IF(!afterSibling.AdvanceOffset())) {
         return NS_ERROR_FAILURE;
       }
       // Put selection after break
-      rv = aSelection.Collapse(afterSibling);
-      NS_ENSURE_SUCCESS(rv, rv);
+      ErrorResult error;
+      SelectionRef().Collapse(afterSibling, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
     }
   } else {
     // Put selection at front of righthand heading
-    rv = aSelection.Collapse(&aHeader, 0);
-    NS_ENSURE_SUCCESS(rv, rv);
+    ErrorResult error;
+    SelectionRef().Collapse(RawRangeBoundary(&aHeader, 0), error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.StealNSResult();
+    }
   }
   return NS_OK;
 }
 
 EditActionResult
 HTMLEditRules::ReturnInParagraph(Selection& aSelection,
                                  Element& aParentDivOrP)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  nsRange* firstRange = aSelection.GetRangeAt(0);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return EditActionResult(NS_ERROR_FAILURE);
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return EditActionResult(NS_ERROR_FAILURE);
   }
@@ -7414,29 +7618,29 @@ HTMLEditRules::ReturnInParagraph(Selecti
     }
 
     // if CR does not create a new P, default to BR creation
     if (NS_WARN_IF(!doesCRCreateNewP)) {
       return EditActionResult(NS_OK);
     }
 
     brContent =
-      HTMLEditorRef().InsertBrElementWithTransaction(aSelection,
+      HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
                                                      pointToInsertBR);
     NS_WARNING_ASSERTION(brContent, "Failed to create a <br> element");
     if (splitAfterNewBR) {
       // We split the parent after the br we've just inserted.
       pointToSplitParentDivOrP.Set(brContent);
       DebugOnly<bool> advanced = pointToSplitParentDivOrP.AdvanceOffset();
       NS_WARNING_ASSERTION(advanced,
         "Failed to advance offset after the new <br>");
     }
   }
   EditActionResult result(
-    SplitParagraph(aSelection, aParentDivOrP, pointToSplitParentDivOrP,
+    SplitParagraph(SelectionRef(), aParentDivOrP, pointToSplitParentDivOrP,
                    brContent));
   result.MarkAsHandled();
   if (NS_WARN_IF(result.Failed())) {
     return result;
   }
   return result;
 }
 
@@ -7495,37 +7699,39 @@ HTMLEditRules::SplitParagraph(
 
   // We need to ensure to both paragraphs visible even if they are empty.
   // However, moz-<br> element isn't useful in this case because moz-<br>
   // elements will be ignored by PlaintextSerializer.  Additionally,
   // moz-<br> will be exposed as <br> with Element.innerHTML.  Therefore,
   // we can use normal <br> elements for placeholder in this case.
   // Note that Chromium also behaves so.
   rv = InsertBRIfNeeded(*splitDivOrPResult.GetPreviousNode());
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   rv = InsertBRIfNeeded(*splitDivOrPResult.GetNextNode());
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // selection to beginning of right hand para;
   // look inside any containers that are up front.
   nsIContent* child = HTMLEditorRef().GetLeftmostChild(&aParentDivOrP, true);
   if (EditorBase::IsTextNode(child) || HTMLEditorRef().IsContainer(child)) {
     EditorRawDOMPoint atStartOfChild(child, 0);
-    ErrorResult error;
-    aSelection.Collapse(atStartOfChild, error);
-    if (NS_WARN_IF(error.Failed())) {
-      error.SuppressException();
-    }
+    IgnoredErrorResult ignoredError;
+    SelectionRef().Collapse(atStartOfChild, ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to collapse selection at the end of the child");
   } else {
     EditorRawDOMPoint atChild(child);
-    ErrorResult error;
-    aSelection.Collapse(atChild, error);
-    if (NS_WARN_IF(error.Failed())) {
-      error.SuppressException();
-    }
+    IgnoredErrorResult ignoredError;
+    SelectionRef().Collapse(atChild, ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to collapse selection at the child");
   }
   return NS_OK;
 }
 
 /**
  * ReturnInListItem: do the right thing for returns pressed in list items
  */
 nsresult
@@ -7568,17 +7774,17 @@ HTMLEditRules::ReturnInListItem(Selectio
       // If so, move item out of this list and into the grandparent list
       nsresult rv =
         HTMLEditorRef().MoveNodeWithTransaction(aListItem,
                                                 atNextSiblingOfLeftList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       ErrorResult error;
-      aSelection.Collapse(RawRangeBoundary(&aListItem, 0), error);
+      SelectionRef().Collapse(RawRangeBoundary(&aListItem, 0), error);
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     } else {
       // Otherwise kill this item
       nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
@@ -7590,32 +7796,27 @@ HTMLEditRules::ReturnInListItem(Selectio
       RefPtr<Element> pNode =
         HTMLEditorRef().CreateNodeWithTransaction(&paraAtom == nsGkAtoms::br ?
                                                     *nsGkAtoms::p : paraAtom,
                                                   atNextSiblingOfLeftList);
       if (NS_WARN_IF(!pNode)) {
         return NS_ERROR_FAILURE;
       }
 
-      RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-      if (NS_WARN_IF(!selection)) {
-        return NS_ERROR_FAILURE;
-      }
-
       // Append a <br> to it
       RefPtr<Element> brElement =
         HTMLEditorRef().InsertBrElementWithTransaction(
-                          *selection, EditorRawDOMPoint(pNode, 0));
+                          SelectionRef(), EditorRawDOMPoint(pNode, 0));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
 
       // Set selection to before the break
       ErrorResult error;
-      aSelection.Collapse(EditorRawDOMPoint(pNode, 0), error);
+      SelectionRef().Collapse(EditorRawDOMPoint(pNode, 0), error);
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     }
     return NS_OK;
   }
 
   // Else we want a new list item at the same list level.  Get ws code to
@@ -7677,17 +7878,17 @@ HTMLEditRules::ReturnInListItem(Selectio
           if (NS_WARN_IF(!newListItem)) {
             return NS_ERROR_FAILURE;
           }
           rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           ErrorResult error;
-          aSelection.Collapse(EditorRawDOMPoint(newListItem, 0), error);
+          SelectionRef().Collapse(EditorRawDOMPoint(newListItem, 0), error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
 
         RefPtr<Element> brElement;
         nsresult rv =
@@ -7698,17 +7899,17 @@ HTMLEditRules::ReturnInListItem(Selectio
           return NS_ERROR_FAILURE;
         }
         if (brElement) {
           EditorRawDOMPoint atBrNode(brElement);
           if (NS_WARN_IF(!atBrNode.IsSetAndValid())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
-          aSelection.Collapse(atBrNode, error);
+          SelectionRef().Collapse(atBrNode, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
       } else {
         WSRunObject wsObj(&HTMLEditorRef(), &aListItem, 0);
         nsCOMPtr<nsINode> visNode;
@@ -7718,32 +7919,34 @@ HTMLEditRules::ReturnInListItem(Selectio
                               address_of(visNode), &visOffset, &wsType);
         if (wsType == WSType::special || wsType == WSType::br ||
             visNode->IsHTMLElement(nsGkAtoms::hr)) {
           EditorRawDOMPoint atVisNode(visNode);
           if (NS_WARN_IF(!atVisNode.IsSetAndValid())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
-          aSelection.Collapse(atVisNode, error);
+          SelectionRef().Collapse(atVisNode, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
 
-        rv = aSelection.Collapse(visNode, visOffset);
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = SelectionRef().Collapse(visNode, visOffset);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         return NS_OK;
       }
     }
   }
 
   ErrorResult error;
-  aSelection.Collapse(EditorRawDOMPoint(&aListItem, 0), error);
+  SelectionRef().Collapse(EditorRawDOMPoint(&aListItem, 0), error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
 /**
  * MakeBlockquote() puts the list of nodes into one or more blockquotes.
@@ -8309,30 +8512,22 @@ HTMLEditRules::ReapplyCachedStyles()
 
   // The idea here is to examine our cached list of styles and see if any have
   // been removed.  If so, add typeinstate for them, so that they will be
   // reinserted when new content is added.
 
   // remember if we are in css mode
   bool useCSS = HTMLEditorRef().IsCSSEnabled();
 
-  // get selection point; if it doesn't exist, we have nothing to do
-  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-  if (!selection) {
-    // If the document is removed from its parent document during executing an
-    // editor operation with DOMMutationEvent or something, there may be no
-    // selection.
-    return NS_OK;
-  }
-  if (!selection->RangeCount()) {
+  if (!SelectionRef().RangeCount()) {
     // Nothing to do
     return NS_OK;
   }
   nsCOMPtr<nsIContent> selNode =
-    do_QueryInterface(selection->GetRangeAt(0)->GetStartContainer());
+    do_QueryInterface(SelectionRef().GetRangeAt(0)->GetStartContainer());
   if (!selNode) {
     // Nothing to do
     return NS_OK;
   }
 
   StyleCache styleAtInsertionPoint[SIZE_STYLE_TABLE];
   InitStyleCacheArray(styleAtInsertionPoint);
   nsresult rv = GetInlineStyles(selNode, styleAtInsertionPoint);
@@ -8418,17 +8613,18 @@ HTMLEditRules::AdjustSpecialBreaks()
   }
 }
 
 nsresult
 HTMLEditRules::AdjustWhitespace(Selection* aSelection)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(aSelection));
+  EditorRawDOMPoint selectionStartPoint(
+                      EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Ask whitespace object to tweak nbsp's
   nsresult rv =
     WSRunObject(&HTMLEditorRef(), selectionStartPoint).AdjustWhitespace();
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -8438,25 +8634,26 @@ HTMLEditRules::AdjustWhitespace(Selectio
 }
 
 nsresult
 HTMLEditRules::PinSelectionToNewBlock(Selection* aSelection)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
-  if (!aSelection->IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     return NS_OK;
   }
 
   if (NS_WARN_IF(!mNewBlock)) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(aSelection));
+  EditorRawDOMPoint selectionStartPoint(
+                      EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Use ranges and nsRange::CompareNodeToRange() to compare selection start
   // to new block.
   // XXX It's too expensive to use nsRange and set it only for comparing a
   //     DOM point with a node.
@@ -8485,107 +8682,126 @@ HTMLEditRules::PinSelectionToNewBlock(Se
         HTMLEditorRef().IsContainer(tmp)) {
       endPoint.SetToEndOf(tmp);
     } else {
       endPoint.Set(tmp);
       if (NS_WARN_IF(!endPoint.AdvanceOffset())) {
         return NS_ERROR_FAILURE;
       }
     }
-    return aSelection->Collapse(endPoint);
+    ErrorResult error;
+    SelectionRef().Collapse(endPoint, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.StealNSResult();
+    }
+    return NS_OK;
   }
 
   // selection is before block.  put at start of block.
   nsCOMPtr<nsINode> tmp = HTMLEditorRef().GetFirstEditableChild(*mNewBlock);
   if (!tmp) {
     tmp = mNewBlock;
   }
   EditorRawDOMPoint atStartOfBlock;
   if (EditorBase::IsTextNode(tmp) ||
       HTMLEditorRef().IsContainer(tmp)) {
     atStartOfBlock.Set(tmp);
   } else {
     atStartOfBlock.Set(tmp, 0);
   }
-  return aSelection->Collapse(atStartOfBlock);
+  ErrorResult error;
+  SelectionRef().Collapse(atStartOfBlock, error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.StealNSResult();
+  }
+  return NS_OK;
 }
 
 void
 HTMLEditRules::CheckInterlinePosition(Selection& aSelection)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // If the selection isn't collapsed, do nothing.
-  if (!aSelection.IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     return;
   }
 
   // Get the (collapsed) selection location
-  nsRange* firstRange = aSelection.GetRangeAt(0);
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return;
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return;
   }
   MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
   // First, let's check to see if we are after a <br>.  We take care of this
   // special-case first so that we don't accidentally fall through into one of
   // the other conditionals.
   nsCOMPtr<nsIContent> node =
     HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(atStartOfSelection);
   if (node && node->IsHTMLElement(nsGkAtoms::br)) {
-    aSelection.SetInterlinePosition(true, IgnoreErrors());
+    IgnoredErrorResult ignoredError;
+    SelectionRef().SetInterlinePosition(true, ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to set interline position");
     return;
   }
 
   // Are we after a block?  If so try set caret to following content
   if (atStartOfSelection.GetChild()) {
     node = HTMLEditorRef().GetPriorHTMLSibling(atStartOfSelection.GetChild());
   } else {
     node = nullptr;
   }
   if (node && IsBlockNode(*node)) {
-    aSelection.SetInterlinePosition(true, IgnoreErrors());
+    IgnoredErrorResult ignoredError;
+    SelectionRef().SetInterlinePosition(true, ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to set interline position");
     return;
   }
 
   // Are we before a block?  If so try set caret to prior content
   if (atStartOfSelection.GetChild()) {
     node = HTMLEditorRef().GetNextHTMLSibling(atStartOfSelection.GetChild());
   } else {
     node = nullptr;
   }
   if (node && IsBlockNode(*node)) {
-    aSelection.SetInterlinePosition(false, IgnoreErrors());
+    IgnoredErrorResult ignoredError;
+    SelectionRef().SetInterlinePosition(false, ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to unset interline position");
   }
 }
 
 nsresult
 HTMLEditRules::AdjustSelection(Selection* aSelection,
                                nsIEditor::EDirection aAction)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aSelection)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // if the selection isn't collapsed, do nothing.
   // moose: one thing to do instead is check for the case of
   // only a single break selected, and collapse it.  Good thing?  Beats me.
-  if (!aSelection->IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     return NS_OK;
   }
 
   // get the (collapsed) selection location
-  EditorDOMPoint point(EditorBase::GetStartPoint(aSelection));
+  EditorDOMPoint point(EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!point.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // are we in an editable node?
   while (!HTMLEditorRef().IsEditable(point.GetContainer())) {
     // scan up the tree until we find an editable place to be
     point.Set(point.GetContainer());
@@ -8651,29 +8867,35 @@ HTMLEditRules::AdjustSelection(Selection
           // the user will see no new line for the break.  Also, things
           // like table cells won't grow in height.
           RefPtr<Element> brElement = CreateMozBR(point);
           if (NS_WARN_IF(!brElement)) {
             return NS_ERROR_FAILURE;
           }
           point.Set(brElement);
           // selection stays *before* moz-br, sticking to it
-          aSelection->SetInterlinePosition(true, IgnoreErrors());
           ErrorResult error;
-          aSelection->Collapse(point, error);
+          SelectionRef().SetInterlinePosition(true, error);
+          NS_WARNING_ASSERTION(!error.Failed(),
+            "Failed to set interline position");
+          error = NS_OK;
+          SelectionRef().Collapse(point, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
         } else {
           nsCOMPtr<nsIContent> nextNode =
             HTMLEditorRef().GetNextEditableHTMLNodeInBlock(*nearNode);
           if (nextNode && TextEditUtils::IsMozBR(nextNode)) {
             // selection between br and mozbr.  make it stick to mozbr
             // so that it will be on blank line.
-            aSelection->SetInterlinePosition(true, IgnoreErrors());
+            IgnoredErrorResult ignoredError;
+            SelectionRef().SetInterlinePosition(true, ignoredError);
+            NS_WARNING_ASSERTION(!ignoredError.Failed(),
+              "Failed to set interline position");
           }
         }
       }
     }
   }
 
   // we aren't in a textnode: are we adjacent to text or a break or an image?
   nearNode = HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
@@ -8696,17 +8918,17 @@ HTMLEditRules::AdjustSelection(Selection
   // prefer the correct direction.
   nearNode = FindNearEditableNode(point, aAction);
   if (!nearNode) {
     return NS_OK;
   }
 
   EditorDOMPoint pt = GetGoodSelPointForNode(*nearNode, aAction);
   ErrorResult error;
-  aSelection->Collapse(pt, error);
+  SelectionRef().Collapse(pt, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
 template<typename PT, typename CT>
 nsIContent*
@@ -8905,25 +9127,21 @@ HTMLEditRules::RemoveEmptyNodes()
   // to pull out any br's and preserve them.
   for (OwningNonNull<nsINode>& delNode : arrayOfEmptyCites) {
     bool bIsEmptyNode;
     rv = HTMLEditorRef().IsEmptyNode(delNode, &bIsEmptyNode, false, true);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (!bIsEmptyNode) {
-      RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-      if (NS_WARN_IF(!selection)) {
-        return NS_ERROR_FAILURE;
-      }
       // We are deleting a cite that has just a br.  We want to delete cite,
       // but preserve br.
       RefPtr<Element> brElement =
         HTMLEditorRef().InsertBrElementWithTransaction(
-                          *selection, EditorRawDOMPoint(delNode));
+                          SelectionRef(), EditorRawDOMPoint(delNode));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
     }
     rv = HTMLEditorRef().DeleteNodeWithTransaction(*delNode);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
@@ -8937,22 +9155,19 @@ HTMLEditRules::SelectionEndpointInNode(n
                                        bool* aResult)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER);
 
   *aResult = false;
 
-  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-  NS_ENSURE_STATE(selection);
-
-  uint32_t rangeCount = selection->RangeCount();
+  uint32_t rangeCount = SelectionRef().RangeCount();
   for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
-    RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
+    RefPtr<nsRange> range = SelectionRef().GetRangeAt(rangeIdx);
     nsINode* startContainer = range->GetStartContainer();
     if (startContainer) {
       if (aNode == startContainer) {
         *aResult = true;
         return NS_OK;
       }
       if (EditorUtils::IsDescendantOf(*startContainer, *aNode)) {
         *aResult = true;
@@ -9150,54 +9365,56 @@ HTMLEditRules::ConfirmSelectionInBody()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   Element* rootElement = HTMLEditorRef().GetRoot();
   if (NS_WARN_IF(!rootElement)) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  Selection* selection = HTMLEditorRef().GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(selection));
+  EditorRawDOMPoint selectionStartPoint(
+                      EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Check that selection start container is inside the <body> element.
   //XXXsmaug this code is insane.
   nsINode* temp = selectionStartPoint.GetContainer();
   while (temp && !temp->IsHTMLElement(nsGkAtoms::body)) {
     temp = temp->GetParentOrHostNode();
   }
 
   // If we aren't in the <body> element, force the issue.
   if (!temp) {
-    selection->Collapse(rootElement, 0);
+    IgnoredErrorResult ignoredError;
+    SelectionRef().Collapse(RawRangeBoundary(rootElement, 0), ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to collapse selection at start of the root element");
     return NS_OK;
   }
 
-  EditorRawDOMPoint selectionEndPoint(EditorBase::GetEndPoint(selection));
+  EditorRawDOMPoint selectionEndPoint(EditorBase::GetEndPoint(&SelectionRef()));
   if (NS_WARN_IF(!selectionEndPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // check that selNode is inside body
   //XXXsmaug this code is insane.
   temp = selectionEndPoint.GetContainer();
   while (temp && !temp->IsHTMLElement(nsGkAtoms::body)) {
     temp = temp->GetParentOrHostNode();
   }
 
   // If we aren't in the <body> element, force the issue.
   if (!temp) {
-    selection->Collapse(rootElement, 0);
+    IgnoredErrorResult ignoredError;
+    SelectionRef().Collapse(RawRangeBoundary(rootElement, 0), ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to collapse selection at start of the root element");
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::UpdateDocChangeRange(nsRange* aRange)
 {
@@ -9305,19 +9522,19 @@ HTMLEditRules::DidCreateNode(Selection& 
 
   if (NS_WARN_IF(!mHTMLEditor)) {
     return;
   }
 
   AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
 
   // assumption that Join keeps the righthand node
-  IgnoredErrorResult error;
-  mUtilRange->SelectNode(aNewElement, error);
-  if (NS_WARN_IF(error.Failed())) {
+  IgnoredErrorResult ignoredError;
+  mUtilRange->SelectNode(aNewElement, ignoredError);
+  if (NS_WARN_IF(ignoredError.Failed())) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
 HTMLEditRules::DidInsertNode(Selection& aSelection,
                              nsIContent& aContent)
@@ -9327,19 +9544,19 @@ HTMLEditRules::DidInsertNode(Selection& 
   }
 
   if (NS_WARN_IF(!mHTMLEditor)) {
     return;
   }
 
   AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
 
-  IgnoredErrorResult error;
-  mUtilRange->SelectNode(aContent, error);
-  if (NS_WARN_IF(error.Failed())) {
+  IgnoredErrorResult ignoredError;
+  mUtilRange->SelectNode(aContent, ignoredError);
+  if (NS_WARN_IF(ignoredError.Failed())) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
 HTMLEditRules::WillDeleteNode(Selection& aSelection,
                               nsINode& aChild)
@@ -9349,19 +9566,19 @@ HTMLEditRules::WillDeleteNode(Selection&
   }
 
   if (NS_WARN_IF(!mHTMLEditor)) {
     return;
   }
 
   AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
 
-  IgnoredErrorResult error;
-  mUtilRange->SelectNode(aChild, error);
-  if (NS_WARN_IF(error.Failed())) {
+  IgnoredErrorResult ignoredError;
+  mUtilRange->SelectNode(aChild, ignoredError);
+  if (NS_WARN_IF(ignoredError.Failed())) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
 HTMLEditRules::DidSplitNode(Selection& aSelection,
                             nsINode& aExistingRightNode,
@@ -9475,21 +9692,21 @@ HTMLEditRules::WillDeleteSelection(Selec
   }
 
   if (NS_WARN_IF(!mHTMLEditor)) {
     return;
   }
 
   AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
 
-  EditorRawDOMPoint startPoint = EditorBase::GetStartPoint(&aSelection);
+  EditorRawDOMPoint startPoint = EditorBase::GetStartPoint(&SelectionRef());
   if (NS_WARN_IF(!startPoint.IsSet())) {
     return;
   }
-  EditorRawDOMPoint endPoint = EditorBase::GetEndPoint(&aSelection);
+  EditorRawDOMPoint endPoint = EditorBase::GetEndPoint(&SelectionRef());
   if (NS_WARN_IF(!endPoint.IsSet())) {
     return;
   }
   nsresult rv = mUtilRange->SetStartAndEnd(startPoint, endPoint);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
@@ -9617,28 +9834,25 @@ HTMLEditRules::MakeSureElemStartsOrEndsO
       if (IsBlockNode(*sibling) || sibling->IsHTMLElement(nsGkAtoms::br)) {
         foundCR = true;
       }
     } else {
       foundCR = true;
     }
   }
   if (!foundCR) {
-    RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
-    if (NS_WARN_IF(!selection)) {
-      return NS_ERROR_FAILURE;
-    }
     EditorRawDOMPoint pointToInsert;
     if (!aStarts) {
       pointToInsert.SetToEndOf(&aNode);
     } else {
       pointToInsert.Set(&aNode, 0);
     }
     RefPtr<Element> brElement =
-      HTMLEditorRef().InsertBrElementWithTransaction(*selection, pointToInsert);
+      HTMLEditorRef().InsertBrElementWithTransaction(SelectionRef(),
+                                                     pointToInsert);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   }
   return NS_OK;
 }
 
 nsresult
@@ -9775,52 +9989,54 @@ HTMLEditRules::ChangeIndentation(Element
 nsresult
 HTMLEditRules::WillAbsolutePosition(Selection& aSelection,
                                     bool* aCancel,
                                     bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
 
-  WillInsert(aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // We want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   RefPtr<Element> focusElement = HTMLEditorRef().GetSelectionContainer();
   if (focusElement && HTMLEditUtils::IsImage(focusElement)) {
     mNewBlock = focusElement;
     return NS_OK;
   }
 
-  nsresult rv = NormalizeSelection(&aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
+  nsresult rv = NormalizeSelection(&SelectionRef());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   // Convert the selection ranges into "promoted" selection ranges: this
   // basically just expands the range to include the immediate block parent,
   // and then further expands to include any ancestors whose children are all
   // in the range.
 
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
-  GetPromotedRanges(aSelection, arrayOfRanges,
+  GetPromotedRanges(SelectionRef(), arrayOfRanges,
                     EditAction::setAbsolutePosition);
 
   // Use these ranges to contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
                             EditAction::setAbsolutePosition);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // If nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
-    nsRange* firstRange = aSelection.GetRangeAt(0);
+    nsRange* firstRange = SelectionRef().GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -9846,20 +10062,23 @@ HTMLEditRules::WillAbsolutePosition(Sele
       rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // Put selection in new block
     *aHandled = true;
-    rv = aSelection.Collapse(positionedDiv, 0);
+    ErrorResult error;
+    SelectionRef().Collapse(RawRangeBoundary(positionedDiv, 0), error);
     // Don't restore the selection
     selectionRestorer.Abort();
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.StealNSResult();
+    }
     return NS_OK;
   }
 
   // Okay, now go through all the nodes and put them in a blockquote, or
   // whatever is appropriate.  Woohoo!
   nsCOMPtr<Element> curList, curPositionedDiv, indentedLI;
   for (OwningNonNull<nsINode>& curNode : arrayOfNodes) {
     // Here's where we actually figure out what to do.
@@ -10038,30 +10257,30 @@ HTMLEditRules::WillRemoveAbsolutePositio
                                           bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // initialize out param
   // we want to ignore aCancel from WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   RefPtr<Element> element =
     HTMLEditorRef().GetAbsolutelyPositionedSelectionContainer();
   if (NS_WARN_IF(!element)) {
     return NS_ERROR_FAILURE;
   }
 
-  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   nsresult rv = HTMLEditorRef().SetPositionToAbsoluteOrStatic(*element, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
@@ -10072,30 +10291,30 @@ HTMLEditRules::WillRelativeChangeZIndex(
                                         bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
 
   // initialize out param
   // we want to ignore aCancel from WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   RefPtr<Element> element =
     HTMLEditorRef().GetAbsolutelyPositionedSelectionContainer();
   if (NS_WARN_IF(!element)) {
     return NS_ERROR_FAILURE;
   }
 
-  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+  AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
 
   int32_t zIndex;
   nsresult rv = HTMLEditorRef().RelativeChangeElementZIndex(*element, aChange,
                                                             &zIndex);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -459,37 +459,39 @@ TextEditRules::WillInsertBreak(Selection
   if (IsSingleLineEditor()) {
     *aCancel = true;
   } else {
     // handle docs with a max length
     // NOTE, this function copies inString into outString for us.
     NS_NAMED_LITERAL_STRING(inString, "\n");
     nsAutoString outString;
     bool didTruncate;
-    nsresult rv = TruncateInsertionIfNeeded(aSelection, &inString.AsString(),
-                                            &outString, aMaxLength,
-                                            &didTruncate);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsresult rv =
+      TruncateInsertionIfNeeded(&SelectionRef(), &inString.AsString(),
+                                &outString, aMaxLength, &didTruncate);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (didTruncate) {
       *aCancel = true;
       return NS_OK;
     }
 
     *aCancel = false;
 
     // if the selection isn't collapsed, delete it.
-    if (!aSelection->IsCollapsed()) {
+    if (!SelectionRef().IsCollapsed()) {
       rv = TextEditorRef().DeleteSelectionAsAction(nsIEditor::eNone,
                                                    nsIEditor::eStrip);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
-    WillInsert(*aSelection, aCancel);
+    WillInsert(SelectionRef(), aCancel);
     // initialize out param
     // we want to ignore result of WillInsert()
     *aCancel = false;
   }
   return NS_OK;
 }
 
 nsresult
@@ -509,27 +511,28 @@ TextEditRules::CollapseSelectionToTraili
   // (because there are a bunch more places you have to worry about it in html)
   if (!IsPlaintextEditor()) {
     return NS_OK;
   }
 
   // If there is no selection ranges, we should set to the end of the editor.
   // This is usually performed in TextEditRules::Init(), however, if the
   // editor is reframed, this may be called by AfterEdit().
-  if (!aSelection->RangeCount()) {
-    TextEditorRef().CollapseSelectionToEnd(aSelection);
+  if (!SelectionRef().RangeCount()) {
+    TextEditorRef().CollapseSelectionToEnd(&SelectionRef());
     if (TextEditorRef().Destroyed()) {
       // The editor has been destroyed.
       return NS_ERROR_FAILURE;
     }
   }
 
   // If we are at the end of the <textarea> element, we need to set the
   // selection to stick to the moz-<br> at the end of the <textarea>.
-  EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(aSelection));
+  EditorRawDOMPoint selectionStartPoint(
+                      EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Nothing to do if we're not at the end of the text node.
   if (!selectionStartPoint.IsInTextNode() ||
       !selectionStartPoint.IsEndOfContainer()) {
     return NS_OK;
@@ -549,17 +552,17 @@ TextEditRules::CollapseSelectionToTraili
     return NS_OK;
   }
 
   EditorRawDOMPoint afterStartContainer(selectionStartPoint.GetContainer());
   if (NS_WARN_IF(!afterStartContainer.AdvanceOffset())) {
     return NS_ERROR_FAILURE;
   }
   ErrorResult error;
-  aSelection->Collapse(afterStartContainer, error);
+  SelectionRef().Collapse(afterStartContainer, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
 static inline already_AddRefed<nsINode>
 GetTextNode(Selection* aSelection)
@@ -696,47 +699,47 @@ TextEditRules::WillInsertText(EditAction
 
   // initialize out param
   *aCancel = false;
   *aHandled = true;
 
   // handle docs with a max length
   // NOTE, this function copies inString into outString for us.
   bool truncated = false;
-  nsresult rv = TruncateInsertionIfNeeded(aSelection, inString, outString,
+  nsresult rv = TruncateInsertionIfNeeded(&SelectionRef(), inString, outString,
                                           aMaxLength, &truncated);
   NS_ENSURE_SUCCESS(rv, rv);
   // If we're exceeding the maxlength when composing IME, we need to clean up
   // the composing text, so we shouldn't return early.
   if (truncated && outString->IsEmpty() &&
       aAction != EditAction::insertIMEText) {
     *aCancel = true;
     return NS_OK;
   }
 
   uint32_t start = 0;
   uint32_t end = 0;
 
   // handle password field docs
   if (IsPasswordEditor()) {
-    nsContentUtils::GetSelectionInTextControl(aSelection,
+    nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
                                               TextEditorRef().GetRoot(),
                                               start, end);
   }
 
   // if the selection isn't collapsed, delete it.
-  if (!aSelection->IsCollapsed()) {
+  if (!SelectionRef().IsCollapsed()) {
     rv = TextEditorRef().DeleteSelectionAsAction(nsIEditor::eNone,
                                                  nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  WillInsert(*aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
 
   // handle password field data
   // this has the side effect of changing all the characters in aOutString
   // to the replacement character
   if (IsPasswordEditor() &&
@@ -777,18 +780,21 @@ TextEditRules::WillInsertText(EditAction
       mTimer->InitWithCallback(this, LookAndFeel::GetPasswordMaskDelay(),
                                nsITimer::TYPE_ONE_SHOT);
     } else {
       FillBufWithPWChars(outString, outString->Length());
     }
   }
 
   // get the (collapsed) selection location
-  NS_ENSURE_STATE(aSelection->GetRangeAt(0));
-  EditorRawDOMPoint atStartOfSelection(aSelection->GetRangeAt(0)->StartRef());
+  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  if (NS_WARN_IF(!firstRange)) {
+    return NS_ERROR_FAILURE;
+  }
+  EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSetAndValid())) {
     return NS_ERROR_FAILURE;
   }
 
   // don't put text in places that can't have it
   if (!atStartOfSelection.IsInTextNode() &&
       !TextEditorRef().CanContainTag(*atStartOfSelection.GetContainer(),
                                      *nsGkAtoms::textTagName)) {
@@ -833,26 +839,28 @@ TextEditRules::WillInsertText(EditAction
       return rv;
     }
 
     if (pointAfterStringInserted.IsSet()) {
       // Make the caret attach to the inserted text, unless this text ends with a LF,
       // in which case make the caret attach to the next line.
       bool endsWithLF =
         !outString->IsEmpty() && outString->Last() == nsCRT::LF;
-      aSelection->SetInterlinePosition(endsWithLF, IgnoreErrors());
+      IgnoredErrorResult error;
+      SelectionRef().SetInterlinePosition(endsWithLF, error);
+      NS_WARNING_ASSERTION(!error.Failed(),
+        "Failed to set or unset interline position");
 
       MOZ_ASSERT(!pointAfterStringInserted.GetChild(),
         "After inserting text into a text node, pointAfterStringInserted."
         "GetChild() should be nullptr");
-      IgnoredErrorResult error;
-      aSelection->Collapse(pointAfterStringInserted, error);
-      if (error.Failed()) {
-        NS_WARNING("Failed to collapse selection after inserting string");
-      }
+      error = IgnoredErrorResult();
+      SelectionRef().Collapse(pointAfterStringInserted, error);
+      NS_WARNING_ASSERTION(!error.Failed(),
+        "Failed to collapse selection after inserting string");
     }
   }
   ASSERT_PASSWORD_LENGTHS_EQUAL()
   return NS_OK;
 }
 
 nsresult
 TextEditRules::DidInsertText(Selection* aSelection,
@@ -885,17 +893,17 @@ TextEditRules::WillSetText(Selection& aS
   }
 
   if (IsPasswordEditor() && LookAndFeel::GetEchoPassword() &&
       !DontEchoPassword()) {
     // Echo password timer will implement on InsertText.
     return NS_OK;
   }
 
-  WillInsert(aSelection, aCancel);
+  WillInsert(SelectionRef(), aCancel);
   // we want to ignore result of WillInsert()
   *aCancel = false;
 
   RefPtr<Element> rootElement = TextEditorRef().GetRoot();
   uint32_t count = rootElement->GetChildCount();
 
   // handles only when there is only one node and it's a text node, or empty.
 
@@ -940,17 +948,17 @@ TextEditRules::WillSetText(Selection& aS
 
   nsINode* curNode = rootElement->GetFirstChild();
   if (NS_WARN_IF(!EditorBase::IsTextNode(curNode))) {
     return NS_OK;
   }
 
   // Even if empty text, we don't remove text node and set empty text
   // for performance
-  nsresult rv = TextEditorRef().SetTextImpl(aSelection, tString,
+  nsresult rv = TextEditorRef().SetTextImpl(SelectionRef(), tString,
                                             *curNode->GetAsText());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   *aHandled = true;
 
   ASSERT_PASSWORD_LENGTHS_EQUAL();
@@ -1035,28 +1043,31 @@ TextEditRules::WillDeleteSelection(Selec
   }
 
   // If the current selection is empty (e.g the user presses backspace with
   // a collapsed selection), then we want to avoid sending the selectstart
   // event to the user, so we hide selection changes. However, we still
   // want to send a single selectionchange event to the document, so we
   // batch the selectionchange events, such that a single event fires after
   // the AutoHideSelectionChanges destructor has been run.
-  SelectionBatcher selectionBatcher(aSelection);
-  AutoHideSelectionChanges hideSelection(aSelection);
+  SelectionBatcher selectionBatcher(&SelectionRef());
+  AutoHideSelectionChanges hideSelection(&SelectionRef());
   nsAutoScriptBlocker scriptBlocker;
 
   if (IsPasswordEditor()) {
     nsresult rv =
-      TextEditorRef().ExtendSelectionForDelete(aSelection, &aCollapsedAction);
-    NS_ENSURE_SUCCESS(rv, rv);
+      TextEditorRef().ExtendSelectionForDelete(&SelectionRef(),
+                                               &aCollapsedAction);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
 
     // manage the password buffer
     uint32_t start, end;
-    nsContentUtils::GetSelectionInTextControl(aSelection,
+    nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
                                               TextEditorRef().GetRoot(),
                                               start, end);
 
     if (LookAndFeel::GetEchoPassword()) {
       HideLastPWInput();
       mLastStart = start;
       mLastLength = 0;
       if (mTimer) {
@@ -1077,36 +1088,37 @@ TextEditRules::WillDeleteSelection(Selec
       // Otherwise nothing to do for this collapsed selection.
     }
     // Extended selection.
     else {
       mPasswordText.Cut(start, end-start);
     }
   } else {
     EditorRawDOMPoint selectionStartPoint(
-                        EditorBase::GetStartPoint(aSelection));
+                        EditorBase::GetStartPoint(&SelectionRef()));
     if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
 
-    if (!aSelection->IsCollapsed()) {
+    if (!SelectionRef().IsCollapsed()) {
       return NS_OK;
     }
 
     // Test for distance between caret and text that will be deleted
-    nsresult rv = CheckBidiLevelForDeletion(aSelection, selectionStartPoint,
-                                            aCollapsedAction, aCancel);
+    nsresult rv =
+      CheckBidiLevelForDeletion(&SelectionRef(), selectionStartPoint,
+                                aCollapsedAction, aCancel);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (*aCancel) {
       return NS_OK;
     }
 
-    rv = TextEditorRef().ExtendSelectionForDelete(aSelection,
+    rv = TextEditorRef().ExtendSelectionForDelete(&SelectionRef(),
                                                   &aCollapsedAction);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   nsresult rv =
     TextEditorRef().DeleteSelectionWithTransaction(aCollapsedAction,
@@ -1122,17 +1134,18 @@ TextEditRules::WillDeleteSelection(Selec
 
 nsresult
 TextEditRules::DidDeleteSelection(Selection* aSelection,
                                   nsIEditor::EDirection aCollapsedAction,
                                   nsresult aResult)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(aSelection));
+  EditorRawDOMPoint selectionStartPoint(
+                      EditorBase::GetStartPoint(&SelectionRef()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Delete empty text nodes at selection.
   if (selectionStartPoint.IsInTextNode() &&
       !selectionStartPoint.GetContainer()->Length()) {
     nsresult rv =
@@ -1144,17 +1157,18 @@ TextEditRules::DidDeleteSelection(Select
   }
 
   if (mDidExplicitlySetInterline) {
     return NS_OK;
   }
   // We prevent the caret from sticking on the left of prior BR
   // (i.e. the end of previous line) after this deletion.  Bug 92124
   ErrorResult err;
-  aSelection->SetInterlinePosition(true, err);
+  SelectionRef().SetInterlinePosition(true, err);
+  NS_WARNING_ASSERTION(!err.Failed(), "Failed to set interline position");
   return err.StealNSResult();
 }
 
 nsresult
 TextEditRules::WillUndo(Selection* aSelection,
                         bool* aCancel,
                         bool* aHandled)
 {
@@ -1529,21 +1543,20 @@ TextEditRules::CreateBogusNodeIfNeeded(S
   nsresult rv =
     TextEditorRef().InsertNodeWithTransaction(
                       *mBogusNode, EditorRawDOMPoint(rootElement, 0));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Set selection.
-  ErrorResult error;
-  aSelection->Collapse(EditorRawDOMPoint(rootElement, 0), error);
-  if (NS_WARN_IF(error.Failed())) {
-    error.SuppressException();
-  }
+  IgnoredErrorResult error;
+  SelectionRef().Collapse(EditorRawDOMPoint(rootElement, 0), error);
+  NS_WARNING_ASSERTION(!error.Failed(),
+    "Failed to collapse selection at start of the root element");
   return NS_OK;
 }
 
 
 nsresult
 TextEditRules::TruncateInsertionIfNeeded(Selection* aSelection,
                                          const nsAString* aInString,
                                          nsAString* aOutString,
@@ -1579,17 +1592,17 @@ TextEditRules::TruncateInsertionIfNeeded
     //    set aOutString to subset of inString so length = max
     int32_t docLength;
     nsresult rv = TextEditorRef().GetTextLength(&docLength);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     uint32_t start, end;
-    nsContentUtils::GetSelectionInTextControl(aSelection,
+    nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
                                               TextEditorRef().GetRoot(),
                                               start, end);
 
     TextComposition* composition = TextEditorRef().GetComposition();
     uint32_t oldCompStrLength = composition ? composition->String().Length() : 0;
 
     const uint32_t selectionLength = end - start;
     const int32_t resultingDocLength = docLength - selectionLength - oldCompStrLength;
@@ -1689,33 +1702,35 @@ TextEditRules::HideLastPWInput()
   if (!mLastLength) {
     // Special case, we're trying to replace a range that no longer exists
     return NS_OK;
   }
 
   nsAutoString hiddenText;
   FillBufWithPWChars(&hiddenText, mLastLength);
 
-  RefPtr<Selection> selection = TextEditorRef().GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
   uint32_t start, end;
-  nsContentUtils::GetSelectionInTextControl(selection,
+  nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
                                             TextEditorRef().GetRoot(),
                                             start, end);
 
-  nsCOMPtr<nsINode> selNode = GetTextNode(selection);
-  NS_ENSURE_TRUE(selNode, NS_OK);
+  nsCOMPtr<nsINode> selNode = GetTextNode(&SelectionRef());
+  if (NS_WARN_IF(!selNode)) {
+    return NS_OK;
+  }
 
   selNode->GetAsText()->ReplaceData(mLastStart, mLastLength, hiddenText,
                                     IgnoreErrors());
   // XXXbz Selection::Collapse/Extend take int32_t, but there are tons of
   // callsites... Converting all that is a battle for another day.
-  selection->Collapse(selNode, start);
+  DebugOnly<nsresult> rv = SelectionRef().Collapse(selNode, start);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
   if (start != end) {
-    selection->Extend(selNode, end);
+    rv = SelectionRef().Extend(selNode, end);
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to extend selection");
   }
   return NS_OK;
 }
 
 // static
 void
 TextEditRules::FillBufWithPWChars(nsAString* aOutString,
                                   int32_t aLength)
@@ -1736,23 +1751,19 @@ TextEditRules::CreateBRInternal(const Ed
                                 bool aCreateMozBR)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aPointToInsert.IsSet())) {
     return nullptr;
   }
 
-  RefPtr<Selection> selection = TextEditorRef().GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return nullptr;
-  }
-
   RefPtr<Element> brElement =
-    TextEditorRef().InsertBrElementWithTransaction(*selection, aPointToInsert);
+    TextEditorRef().InsertBrElementWithTransaction(SelectionRef(),
+                                                   aPointToInsert);
   if (NS_WARN_IF(!brElement)) {
     return nullptr;
   }
 
   // give it special moz attr
   if (aCreateMozBR) {
     // XXX Why do we need to set this attribute with transaction?
     nsresult rv =