Bug 1465702 - part 6: Remove unnecessary Selection argument from TextEditRules and HTMLEditRules and rename/reimplement TextEditRules::SelectionRef() as TextEditRules::SelectionRefPtr() r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 30 Oct 2018 10:02:58 +0000
changeset 502709 258672244b3e879b464788d7e054e9f72bd67655
parent 502708 1945bfc27c6d9bbd6797df4aa2117b787907a525
child 502710 bda6c79cf03c921d16e4944fc200a424b4af78b0
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1465702
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1465702 - part 6: Remove unnecessary Selection argument from TextEditRules and HTMLEditRules and rename/reimplement TextEditRules::SelectionRef() as TextEditRules::SelectionRefPtr() r=m_kato When each method of TextEditRules and HTMLEditRules should be called only by EditorBase/TextEditor/HTMLEditor while the editor instance has AutoEditActionDataSetter instance. Therefore, we can get rid of all pointers/references of Selection from each method's argument. Additionally, this reimplements TextEditRules::SelectionRef() with EditorBase::SelectionRefPtr() and make it return |const RefPtr<Selection>&| rather than |Selection&| since RefPtr reference is required when we call methods which are marked as MOZ_CAN_RUN_SCRIPT. Differential Revision: https://phabricator.services.mozilla.com/D10010
editor/libeditor/EditorBase.cpp
editor/libeditor/HTMLAbsPositionEditor.cpp
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditorDataTransfer.cpp
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
editor/libeditor/TextEditRulesBidi.cpp
editor/libeditor/TextEditor.cpp
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1410,16 +1410,18 @@ EditorBase::SetSpellcheckUserOverride(bo
 }
 
 template<typename PT, typename CT>
 already_AddRefed<Element>
 EditorBase::CreateNodeWithTransaction(
               nsAtom& aTagName,
               const EditorDOMPointBase<PT, CT>& aPointToInsert)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   MOZ_ASSERT(aPointToInsert.IsSetAndValid());
 
   // XXX We need offset at new node for mRangeUpdater.  Therefore, we need
   //     to compute the offset now but this is expensive.  So, if it's possible,
   //     we need to redesign mRangeUpdater as avoiding using indices.
   Unused << aPointToInsert.Offset();
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
@@ -1445,23 +1447,18 @@ EditorBase::CreateNodeWithTransaction(
     // be inserted before the old child.  Although, mutation observer can do
     // anything, but currently, we don't check it.
     mRangeUpdater.SelAdjCreateNode(
                     EditorRawDOMPoint(aPointToInsert.GetContainer(),
                                       aPointToInsert.Offset()));
   }
 
   if (mRules && mRules->AsHTMLEditRules() && newElement) {
-    Selection* selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->DidCreateNode(*selection, *newElement);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->DidCreateNode(*newElement);
   }
 
   if (!mActionListeners.IsEmpty()) {
     AutoActionListenerArray listeners(mActionListeners);
     for (auto& listener : listeners) {
       listener->DidCreateNode(nsDependentAtomString(&aTagName),
                               newElement, rv);
     }
@@ -1496,39 +1493,36 @@ EditorBase::InsertNode(nsINode* aNodeToI
 }
 
 template<typename PT, typename CT>
 nsresult
 EditorBase::InsertNodeWithTransaction(
               nsIContent& aContentToInsert,
               const EditorDOMPointBase<PT, CT>& aPointToInsert)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (NS_WARN_IF(!aPointToInsert.IsSet())) {
     return NS_ERROR_INVALID_ARG;
   }
   MOZ_ASSERT(aPointToInsert.IsSetAndValid());
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertNode,
                                       nsIEditor::eNext);
 
   RefPtr<InsertNodeTransaction> transaction =
     InsertNodeTransaction::Create(*this, aContentToInsert, aPointToInsert);
   nsresult rv = DoTransactionInternal(transaction);
 
   mRangeUpdater.SelAdjInsertNode(aPointToInsert);
 
   if (mRules && mRules->AsHTMLEditRules()) {
-    Selection* selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->DidInsertNode(*selection, aContentToInsert);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->DidInsertNode(aContentToInsert);
   }
 
   if (!mActionListeners.IsEmpty()) {
     AutoActionListenerArray listeners(mActionListeners);
     for (auto& listener : listeners) {
       listener->DidInsertNode(&aContentToInsert, rv);
     }
   }
@@ -1563,16 +1557,18 @@ EditorBase::SplitNode(nsINode* aNode,
 }
 
 template<typename PT, typename CT>
 already_AddRefed<nsIContent>
 EditorBase::SplitNodeWithTransaction(
               const EditorDOMPointBase<PT, CT>& aStartOfRightNode,
               ErrorResult& aError)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (NS_WARN_IF(!aStartOfRightNode.IsSet()) ||
       NS_WARN_IF(!aStartOfRightNode.GetContainerAsContent())) {
     aError.Throw(NS_ERROR_INVALID_ARG);
     return nullptr;
   }
   MOZ_ASSERT(aStartOfRightNode.IsSetAndValid());
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
@@ -1592,24 +1588,18 @@ EditorBase::SplitNodeWithTransaction(
   NS_WARNING_ASSERTION(newNode, "Failed to create a new left node");
 
   // XXX Some other transactions manage range updater by themselves.
   //     Why doesn't SplitNodeTransaction do it?
   mRangeUpdater.SelAdjSplitNode(*aStartOfRightNode.GetContainerAsContent(),
                                 newNode);
 
   if (mRules && mRules->AsHTMLEditRules() && newNode) {
-    Selection* selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->DidSplitNode(*selection,
-                                  *aStartOfRightNode.GetContainer(), *newNode);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->DidSplitNode(*aStartOfRightNode.GetContainer(), *newNode);
   }
 
   if (mInlineSpellChecker) {
     RefPtr<mozInlineSpellChecker> spellChecker = mInlineSpellChecker;
     spellChecker->DidSplitNode(aStartOfRightNode.GetContainer(), newNode);
   }
 
   if (!mActionListeners.IsEmpty()) {
@@ -1644,16 +1634,18 @@ EditorBase::JoinNodes(nsINode* aLeftNode
 
   return JoinNodesWithTransaction(*aLeftNode, *aRightNode);
 }
 
 nsresult
 EditorBase::JoinNodesWithTransaction(nsINode& aLeftNode,
                                      nsINode& aRightNode)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   nsCOMPtr<nsINode> parent = aLeftNode.GetParentNode();
   MOZ_ASSERT(parent);
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eJoinNodes,
                                       nsIEditor::ePrevious);
 
   // Remember some values; later used for saved selection updating.
@@ -1675,23 +1667,18 @@ EditorBase::JoinNodesWithTransaction(nsI
   }
 
   // XXX Some other transactions manage range updater by themselves.
   //     Why doesn't JoinNodeTransaction do it?
   mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset,
                                 (int32_t)oldLeftNodeLen);
 
   if (mRules && mRules->AsHTMLEditRules()) {
-    Selection* selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->DidJoinNodes(*selection, aLeftNode, aRightNode);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->DidJoinNodes(aLeftNode, aRightNode);
   }
 
   if (mInlineSpellChecker) {
     RefPtr<mozInlineSpellChecker> spellChecker = mInlineSpellChecker;
     spellChecker->DidJoinNodes(aLeftNode, aRightNode);
   }
 
   if (mTextServicesDocument && NS_SUCCEEDED(rv)) {
@@ -1722,28 +1709,25 @@ EditorBase::DeleteNode(nsINode* aNode)
   }
 
   return DeleteNodeWithTransaction(*aNode);
 }
 
 nsresult
 EditorBase::DeleteNodeWithTransaction(nsINode& aNode)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eCreateNode,
                                       nsIEditor::ePrevious);
 
   if (mRules && mRules->AsHTMLEditRules()) {
-    Selection* selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->WillDeleteNode(*selection, aNode);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->WillDeleteNode(aNode);
   }
 
   // FYI: DeleteNodeTransaction grabs aNode while it's alive.  So, it's safe
   //      to refer aNode even after calling DoTransaction().
   RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
     DeleteNodeTransaction::MaybeCreate(*this, aNode);
   nsresult rv =
     deleteNodeTransaction ? DoTransactionInternal(deleteNodeTransaction) :
@@ -2815,16 +2799,18 @@ EditorBase::InsertTextWithTransaction(
 
 nsresult
 EditorBase::InsertTextIntoTextNodeWithTransaction(
               const nsAString& aStringToInsert,
               Text& aTextNode,
               int32_t aOffset,
               bool aSuppressIME)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   RefPtr<EditTransactionBase> transaction;
   bool isIMETransaction = false;
   RefPtr<Text> insertedTextNode = &aTextNode;
   int32_t insertedOffset = aOffset;
   // aSuppressIME is used when editor must insert text, yet this text is not
   // part of the current IME operation. Example: adjusting whitespace around an
   // IME insertion.
   if (ShouldHandleIMEComposition() && !aSuppressIME) {
@@ -2846,24 +2832,19 @@ EditorBase::InsertTextIntoTextNodeWithTr
 
   // XXX We may not need these view batches anymore.  This is handled at a
   // higher level now I believe.
   BeginUpdateViewBatch();
   nsresult rv = DoTransactionInternal(transaction);
   EndUpdateViewBatch();
 
   if (mRules && mRules->AsHTMLEditRules() && insertedTextNode) {
-    Selection* selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->DidInsertText(*selection, *insertedTextNode,
-                                   insertedOffset, aStringToInsert);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->DidInsertText(*insertedTextNode,
+                                 insertedOffset, aStringToInsert);
   }
 
   // let listeners know what happened
   if (!mActionListeners.IsEmpty()) {
     AutoActionListenerArray listeners(mActionListeners);
     for (auto& listener : listeners) {
       listener->DidInsertText(insertedTextNode, insertedOffset,
                               aStringToInsert, rv);
@@ -3016,20 +2997,20 @@ EditorBase::SetTextImpl(const nsAString&
   }
 
   mRangeUpdater.SelAdjDeleteText(&aCharData, 0, length);
   mRangeUpdater.SelAdjInsertText(aCharData, 0, aString);
 
   if (mRules && mRules->AsHTMLEditRules()) {
     RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
     if (length) {
-      htmlEditRules->DidDeleteText(*SelectionRefPtr(), aCharData, 0, length);
+      htmlEditRules->DidDeleteText(aCharData, 0, length);
     }
     if (!aString.IsEmpty()) {
-      htmlEditRules->DidInsertText(*SelectionRefPtr(), aCharData, 0, aString);
+      htmlEditRules->DidInsertText(aCharData, 0, aString);
     }
   }
 
   // Let listeners know what happened
   if (!mActionListeners.IsEmpty()) {
     AutoActionListenerArray listeners(mActionListeners);
     for (auto& listener : listeners) {
       if (length) {
@@ -3044,16 +3025,18 @@ EditorBase::SetTextImpl(const nsAString&
   return rv;
 }
 
 nsresult
 EditorBase::DeleteTextWithTransaction(CharacterData& aCharData,
                                       uint32_t aOffset,
                                       uint32_t aLength)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   RefPtr<DeleteTextTransaction> transaction =
     DeleteTextTransaction::MaybeCreate(*this, aCharData, aOffset, aLength);
   if (NS_WARN_IF(!transaction)) {
     return NS_ERROR_FAILURE;
   }
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eDeleteText,
@@ -3065,23 +3048,18 @@ EditorBase::DeleteTextWithTransaction(Ch
     for (auto& listener : listeners) {
       listener->WillDeleteText(&aCharData, aOffset, aLength);
     }
   }
 
   nsresult rv = DoTransactionInternal(transaction);
 
   if (mRules && mRules->AsHTMLEditRules()) {
-    RefPtr<Selection> selection = GetSelection();
-    if (selection) {
-      RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->DidDeleteText(*selection, aCharData, aOffset, aLength);
-    } else {
-      NS_WARNING("Selection has gone");
-    }
+    RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
+    htmlEditRules->DidDeleteText(aCharData, aOffset, aLength);
   }
 
   // Let listeners know what happened
   if (!mActionListeners.IsEmpty()) {
     AutoActionListenerArray listeners(mActionListeners);
     for (auto& listener : listeners) {
       listener->DidDeleteText(&aCharData, aOffset, aLength, rv);
     }
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -42,16 +42,18 @@
 
 namespace mozilla {
 
 using namespace dom;
 
 nsresult
 HTMLEditor::SetSelectionToAbsoluteOrStatic(bool aEnabled)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   AutoEditActionDataSetter editActionData(
                              *this,
                              EditAction::eSetPositionToAbsoluteOrStatic);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
@@ -59,32 +61,34 @@ HTMLEditor::SetSelectionToAbsoluteOrStat
                                       *this,
                                       aEnabled ?
                                         EditSubAction::eSetPositionToAbsolute :
                                         EditSubAction::eSetPositionToStatic,
                                       nsIEditor::eNext);
 
   // the line below does not match the code; should it be removed?
   // Find out if the selection is collapsed:
-  RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   EditSubActionInfo subActionInfo(
                       aEnabled ? EditSubAction::eSetPositionToAbsolute :
                                  EditSubAction::eSetPositionToStatic);
   bool cancel, handled;
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
   nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+    rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_FAILED(rv) || cancel) {
     return rv;
   }
 
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 already_AddRefed<Element>
 HTMLEditor::GetAbsolutelyPositionedSelectionContainer()
 {
   AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return nullptr;
@@ -150,16 +154,18 @@ HTMLEditor::SetZIndex(Element& aElement,
   zIndexStr.AppendInt(aZindex);
 
   mCSSEditUtils->SetCSSProperty(aElement, *nsGkAtoms::z_index, zIndexStr);
 }
 
 nsresult
 HTMLEditor::AddZIndex(int32_t aChange)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   AutoEditActionDataSetter editActionData(
                              *this,
                              EditAction::eIncreaseOrDecreaseZIndex);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
@@ -167,30 +173,31 @@ HTMLEditor::AddZIndex(int32_t aChange)
                                       *this,
                                       aChange < 0 ?
                                         EditSubAction::eDecreaseZIndex :
                                         EditSubAction::eIncreaseZIndex,
                                       nsIEditor::eNext);
 
   // brade: can we get rid of this comment?
   // Find out if the selection is collapsed:
-  RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
   EditSubActionInfo subActionInfo(aChange < 0 ? EditSubAction::eDecreaseZIndex :
                                                 EditSubAction::eIncreaseZIndex);
   bool cancel, handled;
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 int32_t
 HTMLEditor::GetZIndex(Element& aElement)
 {
   AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return 0;
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -274,22 +274,18 @@ HTMLEditRules::Init(TextEditor* aTextEdi
   }
 
   InitFields();
 
   mHTMLEditor = aTextEditor->AsHTMLEditor();
   if (NS_WARN_IF(!mHTMLEditor)) {
     return NS_ERROR_FAILURE;
   }
-  Selection* selection = aTextEditor->GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   nsresult rv = TextEditRules::Init(aTextEditor);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (NS_WARN_IF(!mHTMLEditor)) {
     return NS_ERROR_FAILURE;
@@ -366,30 +362,25 @@ HTMLEditRules::BeforeEdit(EditSubAction 
   mDidExplicitlySetInterline = false;
 
   if (!mActionNesting) {
     mActionNesting++;
 
     // Clear our flag about if just deleted a range
     mDidRangedDelete = false;
 
-    Selection* selection = mHTMLEditor->GetSelection();
-    if (NS_WARN_IF(!selection)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+    AutoSafeEditorData setData(*this, *mHTMLEditor);
 
     // Remember where our selection was before edit action took place:
 
     // Get the selection location
-    if (!SelectionRef().RangeCount()) {
+    if (!SelectionRefPtr()->RangeCount()) {
       return NS_ERROR_UNEXPECTED;
     }
-    mRangeItem->StoreRange(SelectionRef().GetRangeAt(0));
+    mRangeItem->StoreRange(SelectionRefPtr()->GetRangeAt(0));
     nsCOMPtr<nsINode> selStartNode = mRangeItem->mStartContainer;
     nsCOMPtr<nsINode> selEndNode = mRangeItem->mEndContainer;
 
     // Register with range updater to track this as we perturb the doc
     HTMLEditorRef().mRangeUpdater.RegisterRangeItem(mRangeItem);
 
     // Clear deletion state bool
     mDidDeleteSelection = false;
@@ -452,22 +443,17 @@ HTMLEditRules::AfterEdit(EditSubAction a
   }
 
   AutoLockRulesSniffing lockIt(this);
 
   MOZ_ASSERT(mActionNesting > 0);
   nsresult rv = NS_OK;
   mActionNesting--;
   if (!mActionNesting) {
-    Selection* selection = mHTMLEditor->GetSelection();
-    if (NS_WARN_IF(!selection)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+    AutoSafeEditorData setData(*this, *mHTMLEditor);
 
     // Do all the tricky stuff
     rv = AfterEditInner(aEditSubAction, aDirection);
     // Perhaps, we need to do the following jobs even if the editor has been
     // destroyed since they adjust some states of HTML document but don't
     // modify the DOM tree nor Selection.
 
     // Free up selectionState range item
@@ -620,17 +606,17 @@ HTMLEditRules::AfterEditInner(EditSubAct
       }
     }
 
     // check for any styles which were removed inappropriately
     if (aEditSubAction == EditSubAction::eInsertText ||
         aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
         aEditSubAction == EditSubAction::eDeleteSelectedContent ||
         IsStyleCachePreservingSubAction(aEditSubAction)) {
-      HTMLEditorRef().mTypeInState->UpdateSelState(&SelectionRef());
+      HTMLEditorRef().mTypeInState->UpdateSelState(SelectionRefPtr());
       rv = ReapplyCachedStyles();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       ClearCachedStyles();
     }
   }
 
@@ -655,50 +641,46 @@ HTMLEditRules::AfterEditInner(EditSubAct
   if (!mDidExplicitlySetInterline) {
     CheckInterlinePosition();
   }
 
   return NS_OK;
 }
 
 nsresult
-HTMLEditRules::WillDoAction(Selection* aSelection,
-                            EditSubActionInfo& aInfo,
+HTMLEditRules::WillDoAction(EditSubActionInfo& aInfo,
                             bool* aCancel,
                             bool* aHandled)
 {
-  if (NS_WARN_IF(!aSelection)) {
-    return NS_ERROR_INVALID_ARG;
-  }
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
   MOZ_ASSERT(aCancel);
   MOZ_ASSERT(aHandled);
 
   *aCancel = false;
   *aHandled = false;
 
   // Deal with actions for which we don't need to check whether the selection is
   // editable.
   if (aInfo.mEditSubAction == EditSubAction::eComputeTextToOutput ||
       aInfo.mEditSubAction == EditSubAction::eUndo ||
       aInfo.mEditSubAction == EditSubAction::eRedo) {
-    return TextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *aSelection);
+    return TextEditRules::WillDoAction(aInfo, aCancel, aHandled);
+  }
+
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // Nothing to do if there's no selection to act on
-  if (NS_WARN_IF(!SelectionRef().RangeCount())) {
+  if (NS_WARN_IF(!SelectionRefPtr()->RangeCount())) {
     return NS_OK;
   }
 
-  RefPtr<nsRange> range = SelectionRef().GetRangeAt(0);
+  RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(0);
   nsCOMPtr<nsINode> selStartNode = range->GetStartContainer();
   if (NS_WARN_IF(!selStartNode)) {
     return NS_ERROR_FAILURE;
   }
 
   if (!HTMLEditorRef().IsModifiableNode(*selStartNode)) {
     *aCancel = true;
     return NS_OK;
@@ -777,34 +759,29 @@ HTMLEditRules::WillDoAction(Selection* a
       NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WillInsert() failed");
       return NS_OK;
     }
     case EditSubAction::eDecreaseZIndex:
       return WillRelativeChangeZIndex(-1, aCancel, aHandled);
     case EditSubAction::eIncreaseZIndex:
       return WillRelativeChangeZIndex(1, aCancel, aHandled);
     default:
-      return TextEditRules::WillDoAction(&SelectionRef(), aInfo,
-                                         aCancel, aHandled);
+      return TextEditRules::WillDoAction(aInfo, aCancel, aHandled);
   }
 }
 
 nsresult
-HTMLEditRules::DidDoAction(Selection* aSelection,
-                           EditSubActionInfo& aInfo,
+HTMLEditRules::DidDoAction(EditSubActionInfo& aInfo,
                            nsresult aResult)
 {
-  if (NS_WARN_IF(!aSelection)) {
-    return NS_ERROR_INVALID_ARG;
-  }
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   switch (aInfo.mEditSubAction) {
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertParagraphSeparator:
     case EditSubAction::eInsertTextComingFromIME:
       return NS_OK;
     case EditSubAction::eDeleteSelectedContent:
       return DidDeleteSelection();
@@ -816,17 +793,17 @@ HTMLEditRules::DidDoAction(Selection* aS
     case EditSubAction::eSetPositionToAbsolute: {
       nsresult rv = DidMakeBasicBlock();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return DidAbsolutePosition();
     }
     default:
-      return TextEditRules::DidDoAction(aSelection, aInfo, aResult);
+      return TextEditRules::DidDoAction(aInfo, aResult);
   }
 }
 
 bool
 HTMLEditRules::DocumentIsEmpty()
 {
   return !!mBogusNode;
 }
@@ -843,22 +820,17 @@ HTMLEditRules::GetListState(bool* aMixed
   *aUL = false;
   *aDL = false;
   bool bNonList = false;
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
-  Selection* selection = mHTMLEditor->GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   nsresult rv = GetListActionNodes(arrayOfNodes, EntireList::no,
                                    TouchContent::no);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -907,22 +879,17 @@ HTMLEditRules::GetListItemState(bool* aM
   *aDT = false;
   *aDD = false;
   bool bNonList = false;
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
-  Selection* selection = mHTMLEditor->GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   nsresult rv = GetListActionNodes(arrayOfNodes, EntireList::no,
                                    TouchContent::no);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -962,22 +929,17 @@ HTMLEditRules::GetAlignment(bool* aMixed
                             nsIHTMLEditor::EAlignment* aAlign)
 {
   MOZ_ASSERT(aMixed && aAlign);
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
-  Selection* selection = mHTMLEditor->GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // For now, just return first alignment.  We'll lie about if it's mixed.
   // This is for efficiency given that our current ui doesn't care if it's
   // mixed.
   // cmanske: NOT TRUE! We would like to pay attention to mixed state in Format
   // | Align submenu!
 
   // This routine assumes that alignment is done ONLY via divs
@@ -990,29 +952,30 @@ HTMLEditRules::GetAlignment(bool* aMixed
   if (NS_WARN_IF(!HTMLEditorRef().GetRoot())) {
     return NS_ERROR_FAILURE;
   }
   OwningNonNull<Element> root = *HTMLEditorRef().GetRoot();
 
   int32_t rootOffset = root->GetParentNode() ?
                        root->GetParentNode()->ComputeIndexOf(root) : -1;
 
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return NS_ERROR_FAILURE;
   }
   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 (SelectionRef().IsCollapsed() || atStartOfSelection.GetContainerAsText()) {
+  if (SelectionRefPtr()->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) &&
@@ -1157,22 +1120,17 @@ HTMLEditRules::GetParagraphState(bool* a
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
   // This routine is *heavily* tied to our ui choices in the paragraph
   // style popup.  I can't see a way around that.
   *aMixed = true;
   outFormat.Truncate(0);
 
-  Selection* selection = mHTMLEditor->GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   bool bMixed = false;
   // using "x" as an uninitialized value, since "" is meaningful
   nsAutoString formatStr(NS_LITERAL_STRING("x"));
 
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   nsresult rv = GetParagraphFormatNodes(arrayOfNodes);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1194,17 +1152,17 @@ HTMLEditRules::GetParagraphState(bool* a
       }
     }
   }
 
   // we might have an empty node list.  if so, find selection parent
   // and put that on the list
   if (arrayOfNodes.IsEmpty()) {
     EditorRawDOMPoint selectionStartPoint(
-                        EditorBase::GetStartPoint(SelectionRef()));
+                        EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
     arrayOfNodes.AppendElement(*selectionStartPoint.GetContainer());
   }
 
   // remember root node
   Element* rootElement = HTMLEditorRef().GetRoot();
@@ -1308,23 +1266,23 @@ HTMLEditRules::WillInsert(bool* aCancel)
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // 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 (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
   // If we are after a mozBR in the same block, then move selection to be
   // before it
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return NS_ERROR_FAILURE;
   }
 
   EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
@@ -1339,17 +1297,17 @@ HTMLEditRules::WillInsert(bool* aCancel)
     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);
       ErrorResult error;
-      SelectionRef().Collapse(point, error);
+      SelectionRefPtr()->Collapse(point, error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     }
@@ -1387,17 +1345,17 @@ HTMLEditRules::WillInsertText(EditSubAct
     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 (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     nsresult rv =
       HTMLEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
                                                  nsIEditor::eNoStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -1419,17 +1377,17 @@ HTMLEditRules::WillInsertText(EditSubAct
 
   // for every property that is set, insert a new inline style node
   rv = CreateStyleForInsertText(*doc);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // get the (collapsed) selection location
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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());
@@ -1605,17 +1563,18 @@ HTMLEditRules::WillInsertText(EditSubAct
           }
           pos++;
           currentPoint = pointAfterInsertedSpaces;
           pointToInsert = pointAfterInsertedSpaces;
         }
         // is it a return?
         else if (subStr.Equals(newlineStr)) {
           RefPtr<Element> newBRElement =
-            wsObj.InsertBreak(SelectionRef(), currentPoint, nsIEditor::eNone);
+            wsObj.InsertBreak(*SelectionRefPtr(), currentPoint,
+                              nsIEditor::eNone);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(!newBRElement)) {
             return NS_ERROR_FAILURE;
           }
           pos++;
           if (newBRElement->GetNextSibling()) {
@@ -1648,23 +1607,23 @@ HTMLEditRules::WillInsertText(EditSubAct
         }
       }
     }
 
     // After this block, pointToInsert is updated by AutoTrackDOMPoint.
   }
 
   IgnoredErrorResult ignoredError;
-  SelectionRef().SetInterlinePosition(false, ignoredError);
+  SelectionRefPtr()->SetInterlinePosition(false, ignoredError);
   NS_WARNING_ASSERTION(!ignoredError.Failed(),
     "Failed to unset interline position");
 
   if (currentPoint.IsSet()) {
     IgnoredErrorResult ignoredError;
-    SelectionRef().Collapse(currentPoint, ignoredError);
+    SelectionRefPtr()->Collapse(currentPoint, ignoredError);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
       "Failed to collapse at current point");
   }
 
   // manually update the doc changed range so that AfterEdit will clean up
@@ -1743,17 +1702,17 @@ HTMLEditRules::WillInsertBreak(bool* aCa
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   MOZ_ASSERT(aCancel && aHandled);
   *aCancel = false;
   *aHandled = false;
 
   // If the selection isn't collapsed, delete it.
-  if (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     nsresult rv =
       HTMLEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
                                                  nsIEditor::eStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -1775,17 +1734,17 @@ HTMLEditRules::WillInsertBreak(bool* aCa
       return rv;
     }
     if (*aHandled) {
       return NS_OK;
     }
   }
 
   // Smart splitting rules
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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;
   }
@@ -1866,17 +1825,17 @@ HTMLEditRules::WillInsertBreak(bool* aCa
         NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     // 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 = SelectionRef().GetRangeAt(0);
+    firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -2042,17 +2001,17 @@ HTMLEditRules::InsertBRElement(const Edi
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(splitLinkNodeResult.Failed())) {
         return splitLinkNodeResult.Rv();
       }
       pointToBreak = splitLinkNodeResult.SplitPoint();
     }
     brElement =
-      wsObj.InsertBreak(SelectionRef(), pointToBreak, nsIEditor::eNone);
+      wsObj.InsertBreak(*SelectionRefPtr(), pointToBreak, nsIEditor::eNone);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   }
 
@@ -2065,21 +2024,21 @@ HTMLEditRules::InsertBRElement(const Edi
   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.
     ErrorResult error;
-    SelectionRef().SetInterlinePosition(true, error);
+    SelectionRefPtr()->SetInterlinePosition(true, error);
     NS_WARNING_ASSERTION(!error.Failed(), "Failed to set interline position");
     EditorRawDOMPoint point(brElement);
     error = NS_OK;
-    SelectionRef().Collapse(point, error);
+    SelectionRefPtr()->Collapse(point, error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -2119,23 +2078,24 @@ HTMLEditRules::InsertBRElement(const Edi
   // 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();
   ErrorResult error;
-  SelectionRef().SetInterlinePosition(!(nextSiblingOfBRElement &&
-                                        IsBlockNode(*nextSiblingOfBRElement)),
-                                      error);
+  SelectionRefPtr()->SetInterlinePosition(
+                       !(nextSiblingOfBRElement &&
+                         IsBlockNode(*nextSiblingOfBRElement)),
+                       error);
   NS_WARNING_ASSERTION(!error.Failed(),
     "Failed to set or unset interline position");
   error = NS_OK;
-  SelectionRef().Collapse(afterBRElement, error);
+  SelectionRefPtr()->Collapse(afterBRElement, error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
@@ -2145,17 +2105,17 @@ nsresult
 HTMLEditRules::SplitMailCites(bool* aHandled)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aHandled)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  EditorRawDOMPoint pointToSplit(EditorBase::GetStartPoint(SelectionRef()));
+  EditorRawDOMPoint pointToSplit(EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!pointToSplit.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*pointToSplit.GetContainer());
   if (!citeNode) {
     return NS_OK;
@@ -2247,21 +2207,21 @@ HTMLEditRules::SplitMailCites(bool* aHan
   }
   // 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.
   ErrorResult error;
-  SelectionRef().SetInterlinePosition(true, error);
+  SelectionRefPtr()->SetInterlinePosition(true, error);
   NS_WARNING_ASSERTION(!error.Failed(),
     "Failed to set interline position");
   error = NS_OK;
-  SelectionRef().Collapse(atBrNode, error);
+  SelectionRefPtr()->Collapse(atBrNode, error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
@@ -2393,20 +2353,20 @@ HTMLEditRules::WillDeleteSelection(nsIEd
 
   // 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 join = false;
-  bool origCollapsed = SelectionRef().IsCollapsed();
+  bool origCollapsed = SelectionRefPtr()->IsCollapsed();
 
   if (origCollapsed) {
-    EditorDOMPoint startPoint(EditorBase::GetStartPoint(SelectionRef()));
+    EditorDOMPoint startPoint(EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!startPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
 
     // If we are inside an empty block, delete it.
     RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
     if (NS_WARN_IF(!host)) {
       return NS_ERROR_FAILURE;
@@ -2433,34 +2393,35 @@ HTMLEditRules::WillDeleteSelection(nsIEd
     if (*aCancel) {
       return NS_OK;
     }
 
     // ExtendSelectionForDelete will use selection controller to set
     // selection for delete.  But if focus event doesn't receive yet,
     // ancestor isn't set.  So we must set root eleement of editor to
     // ancestor.
-    AutoSetTemporaryAncestorLimiter autoSetter(HTMLEditorRef(), SelectionRef(),
+    AutoSetTemporaryAncestorLimiter autoSetter(HTMLEditorRef(),
+                                               *SelectionRefPtr(),
                                                *startPoint.GetContainer());
 
     rv = HTMLEditorRef().ExtendSelectionForDelete(&aAction);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // We should delete nothing.
     if (aAction == nsIEditor::eNone) {
       return NS_OK;
     }
   }
 
-  if (SelectionRef().IsCollapsed()) {
+  if (SelectionRefPtr()->IsCollapsed()) {
     // ExtendSelectionForDelete() won't change the selection.
 
-    EditorDOMPoint startPoint(EditorBase::GetStartPoint(SelectionRef()));
+    EditorDOMPoint startPoint(EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!startPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
 
     // What's in the direction we are deleting?
     WSRunObject wsObj(&HTMLEditorRef(), startPoint);
     nsCOMPtr<nsINode> visNode;
     int32_t visOffset;
@@ -2526,17 +2487,17 @@ HTMLEditRules::WillDeleteSelection(nsIEd
         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 = SelectionRef().GetRangeAt(0);
+        RefPtr<nsRange> range = SelectionRefPtr()->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");
@@ -2634,17 +2595,17 @@ HTMLEditRules::WillDeleteSelection(nsIEd
         // In any other case we set the position to startPoint's container -1
         // and interlineposition to false, only moving the caret to the
         // end-of-hr-line position.
         bool moveOnly = true;
 
         EditorDOMPoint selPoint(visNode);
 
         ErrorResult err;
-        bool interLineIsRight = SelectionRef().GetInterlinePosition(err);
+        bool interLineIsRight = SelectionRefPtr()->GetInterlinePosition(err);
         if (NS_WARN_IF(err.Failed())) {
           return err.StealNSResult();
         }
 
         if (startPoint.GetContainer() == selPoint.GetContainer() &&
             startPoint.Offset() - 1 == selPoint.Offset() &&
             !interLineIsRight) {
           moveOnly = false;
@@ -2656,26 +2617,26 @@ HTMLEditRules::WillDeleteSelection(nsIEd
           DebugOnly<bool> advanced = selPoint.AdvanceOffset();
           NS_WARNING_ASSERTION(advanced,
             "Failed to advance offset after <hr> element");
 
           {
             AutoEditorDOMPointChildInvalidator lockOffset(selPoint);
 
             IgnoredErrorResult ignoredError;
-            SelectionRef().Collapse(selPoint, ignoredError);
+            SelectionRefPtr()->Collapse(selPoint, ignoredError);
             if (NS_WARN_IF(!CanHandleEditAction())) {
               return NS_ERROR_EDITOR_DESTROYED;
             }
             NS_WARNING_ASSERTION(!ignoredError.Failed(),
               "Failed to collapse selection at after the <hr>");
           }
 
           IgnoredErrorResult ignoredError;
-          SelectionRef().SetInterlinePosition(false, ignoredError);
+          SelectionRefPtr()->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>.
 
@@ -2755,17 +2716,17 @@ HTMLEditRules::WillDeleteSelection(nsIEd
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         if (NS_WARN_IF(!pt.IsSet())) {
           return NS_ERROR_FAILURE;
         }
         // Fix up selection
         ErrorResult error;
-        SelectionRef().Collapse(pt, error);
+        SelectionRefPtr()->Collapse(pt, error);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           error.SuppressException();
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
       }
@@ -2840,17 +2801,17 @@ HTMLEditRules::WillDeleteSelection(nsIEd
         if (NS_WARN_IF(!leafNode)) {
           return NS_ERROR_FAILURE;
         }
         EditorDOMPoint newSel = GetGoodSelPointForNode(*leafNode, aAction);
         if (NS_WARN_IF(!newSel.IsSet())) {
           return NS_ERROR_FAILURE;
         }
         IgnoredErrorResult error;
-        SelectionRef().Collapse(newSel, error);
+        SelectionRefPtr()->Collapse(newSel, error);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         NS_WARNING_ASSERTION(!error.Failed(),
           "Failed to collapse selection at edge of the block");
         return NS_OK;
       }
 
@@ -2877,32 +2838,32 @@ HTMLEditRules::WillDeleteSelection(nsIEd
 
       // 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 != startPoint.GetContainer()) {
         int32_t offset =
           aAction == nsIEditor::ePrevious ?
             static_cast<int32_t>(leafNode->Length()) : 0;
-        rv = SelectionRef().Collapse(leafNode, offset);
+        rv = SelectionRefPtr()->Collapse(leafNode, offset);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
           "Failed to collapse selection at the leaf node");
         rv = WillDeleteSelection(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.
       IgnoredErrorResult ignored;
-      SelectionRef().Collapse(selPoint, ignored);
+      SelectionRefPtr()->Collapse(selPoint, ignored);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(!ignored.Failed(),
         "Failed to selection at deleted point");
       return NS_OK;
     }
 
@@ -2954,17 +2915,17 @@ HTMLEditRules::WillDeleteSelection(nsIEd
         // anymore in this case.
         *aHandled = true;
         *aCancel |= ret.Canceled();
         if (NS_WARN_IF(ret.Failed())) {
           return ret.Rv();
         }
       }
       IgnoredErrorResult ignored;
-      SelectionRef().Collapse(selPoint, ignored);
+      SelectionRefPtr()->Collapse(selPoint, ignored);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(!ignored.Failed(), "Failed to collapse selection");
       return NS_OK;
     }
   }
 
@@ -2974,17 +2935,17 @@ HTMLEditRules::WillDeleteSelection(nsIEd
   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
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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();
@@ -3084,32 +3045,32 @@ HTMLEditRules::WillDeleteSelection(nsIEd
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(!pt.IsSet())) {
             return NS_ERROR_FAILURE;
           }
           // Fix up selection
           ErrorResult error;
-          SelectionRef().Collapse(pt, error);
+          SelectionRefPtr()->Collapse(pt, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           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(&SelectionRef());
+        AutoRangeArray arrayOfRanges(SelectionRefPtr());
         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;
@@ -3216,25 +3177,25 @@ HTMLEditRules::WillDeleteSelection(nsIEd
   // 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 = SelectionRef().Collapse(endNode, endOffset);
+    rv = SelectionRefPtr()->Collapse(endNode, endOffset);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
-    rv = SelectionRef().Collapse(startNode, startOffset);
+    rv = SelectionRefPtr()->Collapse(startNode, startOffset);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
@@ -3265,17 +3226,17 @@ HTMLEditRules::DeleteNodeIfCollapsedText
 }
 
 nsresult
 HTMLEditRules::InsertBRIfNeeded()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   EditorRawDOMPoint atStartOfSelection(
-                      EditorBase::GetStartPoint(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // inline elements don't need any br
   if (!IsBlockNode(*atStartOfSelection.GetContainer())) {
     return NS_OK;
   }
@@ -3888,17 +3849,18 @@ HTMLEditRules::DeleteElementsExceptTable
 }
 
 nsresult
 HTMLEditRules::DidDeleteSelection()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // find where we are
-  EditorDOMPoint atStartOfSelection(EditorBase::GetStartPoint(SelectionRef()));
+  EditorDOMPoint atStartOfSelection(
+                   EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // find any enclosing mailcite
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*atStartOfSelection.GetContainer());
   if (citeNode) {
@@ -3922,17 +3884,17 @@ HTMLEditRules::DidDeleteSelection()
           HTMLEditorRef().InsertBrElementWithTransaction(atCiteNode);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(!brElement)) {
           return NS_ERROR_FAILURE;
         }
         IgnoredErrorResult error;
-        SelectionRef().Collapse(EditorRawDOMPoint(brElement), error);
+        SelectionRefPtr()->Collapse(EditorRawDOMPoint(brElement), error);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         NS_WARNING_ASSERTION(!error.Failed(),
           "Failed to collapse selection at the new <br> element");
       }
     }
   }
@@ -4047,17 +4009,17 @@ HTMLEditRules::MakeList(nsAtom& aListTyp
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
 
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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;
     }
@@ -4096,17 +4058,17 @@ HTMLEditRules::MakeList(nsAtom& aListTyp
       return NS_ERROR_FAILURE;
     }
 
     // remember our new block for postprocessing
     mNewBlock = theListItem;
     // Put selection in new list item and don't restore the Selection.
     restoreSelectionLater.Abort();
     ErrorResult error;
-    SelectionRef().Collapse(EditorRawDOMPoint(theListItem, 0), error);
+    SelectionRefPtr()->Collapse(EditorRawDOMPoint(theListItem, 0), error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(!error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -4541,17 +4503,17 @@ HTMLEditRules::MakeBasicBlock(nsAtom& bl
   rv = GetNodesFromSelection(EditSubAction::eCreateOrRemoveBlock, arrayOfNodes,
                              TouchContent::yes);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // If nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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")
@@ -4600,17 +4562,17 @@ HTMLEditRules::MakeBasicBlock(nsAtom& bl
       if (NS_WARN_IF(!brContent)) {
         return NS_ERROR_FAILURE;
       }
       // Put selection at the split point
       EditorRawDOMPoint atBrNode(brContent);
       // Don't restore the selection
       restoreSelectionLater.Abort();
       ErrorResult error;
-      SelectionRef().Collapse(atBrNode, error);
+      SelectionRefPtr()->Collapse(atBrNode, error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
       return NS_OK;
@@ -4659,17 +4621,17 @@ HTMLEditRules::MakeBasicBlock(nsAtom& bl
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // Don't restore the selection
     restoreSelectionLater.Abort();
     // Put selection in new block
-    rv = SelectionRef().Collapse(block, 0);
+    rv = SelectionRefPtr()->Collapse(block, 0);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
@@ -4697,21 +4659,21 @@ HTMLEditRules::MakeBasicBlock(nsAtom& bl
 }
 
 nsresult
 HTMLEditRules::DidMakeBasicBlock()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // check for empty block.  if so, put a moz br in it.
-  if (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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());
@@ -4787,19 +4749,19 @@ HTMLEditRules::IndentAroundSelectionWith
   AutoSelectionRestorer restoreSelectionLater(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 (SelectionRef().IsCollapsed()) {
+  if (SelectionRefPtr()->IsCollapsed()) {
     EditorRawDOMPoint selectionStartPoint(
-                        EditorBase::GetStartPoint(SelectionRef()));
+                        EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
     Element* block =
       HTMLEditorRef().GetBlock(*selectionStartPoint.GetContainer());
     if (block && HTMLEditUtils::IsListItem(block)) {
       liNode = block;
     }
@@ -4818,17 +4780,17 @@ HTMLEditRules::IndentAroundSelectionWith
     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 = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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;
     }
@@ -4868,17 +4830,17 @@ HTMLEditRules::IndentAroundSelectionWith
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // put selection in new block
     EditorRawDOMPoint atStartOfTheBlock(theBlock, 0);
     // Don't restore the selection
     restoreSelectionLater.Abort();
     ErrorResult error;
-    SelectionRef().Collapse(atStartOfTheBlock, error);
+    SelectionRefPtr()->Collapse(atStartOfTheBlock, error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(!error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -5104,17 +5066,17 @@ HTMLEditRules::IndentAroundSelectionWith
     GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditSubAction::eIndent,
                          TouchContent::yes);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // if nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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;
     }
@@ -5148,17 +5110,17 @@ HTMLEditRules::IndentAroundSelectionWith
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     EditorRawDOMPoint atStartOfTheBlock(theBlock, 0);
     // Don't restore the selection
     restoreSelectionLater.Abort();
     ErrorResult error;
-    SelectionRef().Collapse(atStartOfTheBlock, error);
+    SelectionRefPtr()->Collapse(atStartOfTheBlock, error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(!error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -5404,60 +5366,60 @@ HTMLEditRules::WillOutdent(bool* aCancel
   }
 
   // Make sure selection didn't stick to last piece of content in old bq (only
   // a problem for collapsed selections)
   if (!outdentResult.GetLeftContent() && !outdentResult.GetRightContent()) {
     return NS_OK;
   }
 
-  if (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
   // Push selection past end of left element of last split indented element.
   if (outdentResult.GetLeftContent()) {
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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() == outdentResult.GetLeftContent() ||
         EditorUtils::IsDescendantOf(*atStartOfSelection.Container(),
                                     *outdentResult.GetLeftContent())) {
       // Selection is inside the left node - push it past it.
       EditorRawDOMPoint afterRememberedLeftBQ(outdentResult.GetLeftContent());
       afterRememberedLeftBQ.AdvanceOffset();
       IgnoredErrorResult error;
-      SelectionRef().Collapse(afterRememberedLeftBQ, error);
+      SelectionRefPtr()->Collapse(afterRememberedLeftBQ, error);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(!error.Failed(),
         "Failed to collapse selection after the left <blockquote>");
     }
   }
   // And pull selection before beginning of right element of last split
   // indented element.
   if (outdentResult.GetRightContent()) {
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
     const RangeBoundary& atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
     if (atStartOfSelection.Container() == outdentResult.GetRightContent() ||
         EditorUtils::IsDescendantOf(*atStartOfSelection.Container(),
                                     *outdentResult.GetRightContent())) {
       // Selection is inside the right element - push it before it.
       EditorRawDOMPoint atRememberedRightBQ(outdentResult.GetRightContent());
       IgnoredErrorResult error;
-      SelectionRef().Collapse(atRememberedRightBQ, error);
+      SelectionRefPtr()->Collapse(atRememberedRightBQ, error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(!error.Failed(),
         "Failed to collapse selection after the right <blockquote>");
     }
   }
   return NS_OK;
@@ -5926,17 +5888,17 @@ HTMLEditRules::ConvertListType(Element& 
 
 nsresult
 HTMLEditRules::CreateStyleForInsertText(nsIDocument& aDocument)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(HTMLEditorRef().mTypeInState);
 
   bool weDidSomething = false;
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<nsINode> node = firstRange->GetStartContainer();
   int32_t offset = firstRange->StartOffset();
 
   RefPtr<Element> rootElement = aDocument.GetRootElement();
   if (NS_WARN_IF(!rootElement)) {
@@ -6036,17 +5998,17 @@ HTMLEditRules::CreateStyleForInsertText(
       item = HTMLEditorRef().mTypeInState->TakeSetProperty();
     }
   }
 
   if (!weDidSomething) {
     return NS_OK;
   }
 
-  nsresult rv = SelectionRef().Collapse(node, offset);
+  nsresult rv = SelectionRefPtr()->Collapse(node, offset);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
@@ -6150,31 +6112,31 @@ HTMLEditRules::AlignContentsAtSelection(
       // 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
 
-      nsRange* firstRange = SelectionRef().GetRangeAt(0);
+      nsRange* firstRange = SelectionRefPtr()->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);
     }
   }
   if (emptyDiv) {
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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;
     }
@@ -6233,17 +6195,17 @@ HTMLEditRules::AlignContentsAtSelection(
       CreateMozBR(EditorRawDOMPoint(div, 0));
     if (NS_WARN_IF(createMozBrResult.Failed())) {
       return createMozBrResult.Rv();
     }
     EditorRawDOMPoint atStartOfDiv(div, 0);
     // Don't restore the selection
     restoreSelectionLater.Abort();
     ErrorResult error;
-    SelectionRef().Collapse(atStartOfDiv, error);
+    SelectionRefPtr()->Collapse(atStartOfDiv, error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -6541,17 +6503,17 @@ HTMLEditRules::MaybeDeleteTopMostEmptyAn
           HTMLEditorRef().InsertBrElementWithTransaction(atBlockParent);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(!brElement)) {
           return NS_ERROR_FAILURE;
         }
         ErrorResult error;
-        SelectionRef().Collapse(EditorRawDOMPoint(brElement), error);
+        SelectionRefPtr()->Collapse(EditorRawDOMPoint(brElement), error);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           error.SuppressException();
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
       }
@@ -6567,31 +6529,31 @@ HTMLEditRules::MaybeDeleteTopMostEmptyAn
         bool advancedFromEmptyBlock = afterEmptyBlock.AdvanceOffset();
         NS_WARNING_ASSERTION(advancedFromEmptyBlock,
           "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;
-          SelectionRef().Collapse(pt, error);
+          SelectionRefPtr()->Collapse(pt, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           break;
         }
         if (NS_WARN_IF(!advancedFromEmptyBlock)) {
           return NS_ERROR_FAILURE;
         }
         ErrorResult error;
-        SelectionRef().Collapse(afterEmptyBlock, error);
+        SelectionRefPtr()->Collapse(afterEmptyBlock, error);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           error.SuppressException();
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
         break;
@@ -6602,32 +6564,32 @@ HTMLEditRules::MaybeDeleteTopMostEmptyAn
         // Collapse Selection to previous editable node of the empty block
         // if there is.  Otherwise, to after the empty block.
         EditorRawDOMPoint atEmptyBlock(emptyBlock);
         nsCOMPtr<nsIContent> priorNode =
           HTMLEditorRef().GetPreviousEditableNode(atEmptyBlock);
         if (priorNode) {
           EditorDOMPoint pt = GetGoodSelPointForNode(*priorNode, aAction);
           ErrorResult error;
-          SelectionRef().Collapse(pt, error);
+          SelectionRefPtr()->Collapse(pt, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           break;
         }
         EditorRawDOMPoint afterEmptyBlock(emptyBlock);
         if (NS_WARN_IF(!afterEmptyBlock.AdvanceOffset())) {
           return NS_ERROR_FAILURE;
         }
         ErrorResult error;
-        SelectionRef().Collapse(afterEmptyBlock, error);
+        SelectionRefPtr()->Collapse(afterEmptyBlock, error);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           error.SuppressException();
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
         break;
@@ -6717,28 +6679,28 @@ HTMLEditRules::GetInnerContent(
 }
 
 nsresult
 HTMLEditRules::ExpandSelectionForDeletion()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // Don't need to touch collapsed selections
-  if (SelectionRef().IsCollapsed()) {
+  if (SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
   // We don't need to mess with cell selections, and we assume multirange
   // selections are those.
-  if (SelectionRef().RangeCount() != 1) {
+  if (SelectionRefPtr()->RangeCount() != 1) {
     return NS_OK;
   }
 
   // Find current sel start and end
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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();
@@ -6810,17 +6772,17 @@ HTMLEditRules::ExpandSelectionForDeletio
         selEndOffset = 1 + selEndNode->ComputeIndexOf(wsObj.mEndReasonNode);
       } else {
         break;
       }
     }
   }
   // Now set the selection to the new range
   DebugOnly<nsresult> rv =
-    SelectionRef().Collapse(selStartNode, selStartOffset);
+    SelectionRefPtr()->Collapse(selStartNode, selStartOffset);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   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;
@@ -6843,26 +6805,26 @@ HTMLEditRules::ExpandSelectionForDeletio
     }
 
     // If block isn't contained, forgo grabbing the <br> in expanded selection.
     if (nodeBefore || nodeAfter) {
       doEndExpansion = false;
     }
   }
   if (doEndExpansion) {
-    nsresult rv = SelectionRef().Extend(selEndNode, selEndOffset);
+    nsresult rv = SelectionRefPtr()->Extend(selEndNode, selEndOffset);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
     // Only expand to just before <br>.
-    nsresult rv = SelectionRef().Extend(firstBRParent, firstBROffset);
+    nsresult rv = SelectionRefPtr()->Extend(firstBRParent, firstBROffset);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
@@ -6876,28 +6838,28 @@ HTMLEditRules::NormalizeSelection()
 
   // NormalizeSelection() tweaks non-collapsed selections to be more "natural".
   // Idea here is to adjust selection endpoint so that they do not cross breaks
   // or block boundaries unless something editable beyond that boundary is also
   // selected.  This adjustment makes it much easier for the various block
   // operations to determine what nodes to act on.
 
   // don't need to touch collapsed selections
-  if (SelectionRef().IsCollapsed()) {
+  if (SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
   // We don't need to mess with cell selections, and we assume multirange
   // selections are those.
   // XXX Why?  Even in <input>, user can select 2 or more ranges.
-  if (SelectionRef().RangeCount() != 1) {
+  if (SelectionRefPtr()->RangeCount() != 1) {
     return NS_OK;
   }
 
-  RefPtr<nsRange> range = SelectionRef().GetRangeAt(0);
+  RefPtr<nsRange> range = SelectionRefPtr()->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;
   }
@@ -7021,23 +6983,23 @@ HTMLEditRules::NormalizeSelection()
                                        endNode, endOffset);
   if (comp == 1) {
     return NS_OK;  // New start after old end.
   }
 
   // otherwise set selection to new values.
   // XXX Why don't we use SetBaseAndExtent()?
   DebugOnly<nsresult> rv =
-    SelectionRef().Collapse(newStartNode, newStartOffset);
+    SelectionRefPtr()->Collapse(newStartNode, newStartOffset);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
     "Failed to collapse selection");
-  rv = SelectionRef().Extend(newEndNode, newEndOffset);
+  rv = SelectionRefPtr()->Extend(newEndNode, newEndOffset);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
     "Failed to extend selection");
   return NS_OK;
 }
 
@@ -7237,19 +7199,19 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
 }
 
 void
 HTMLEditRules::GetPromotedRanges(nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
                                  EditSubAction aEditSubAction)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  uint32_t rangeCount = SelectionRef().RangeCount();
+  uint32_t rangeCount = SelectionRefPtr()->RangeCount();
   for (uint32_t i = 0; i < rangeCount; i++) {
-    RefPtr<nsRange> selectionRange = SelectionRef().GetRangeAt(i);
+    RefPtr<nsRange> selectionRange = SelectionRefPtr()->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.
@@ -7545,19 +7507,19 @@ HTMLEditRules::GetListActionNodes(
                  EntireList aEntireList,
                  TouchContent aTouchContent)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // 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 = SelectionRef().RangeCount();
+    uint32_t rangeCount = SelectionRefPtr()->RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
-      RefPtr<nsRange> range = SelectionRef().GetRangeAt(rangeIdx);
+      RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(rangeIdx);
       for (nsCOMPtr<nsINode> parent = range->GetCommonAncestor();
            parent; parent = parent->GetParentNode()) {
         if (HTMLEditUtils::IsList(parent)) {
           aOutArrayOfNodes.AppendElement(*parent);
           break;
         }
       }
     }
@@ -8087,61 +8049,61 @@ HTMLEditRules::ReturnInHeader(Element& a
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
 
       // Set selection to before the break
       ErrorResult error;
-      SelectionRef().Collapse(EditorRawDOMPoint(pNode, 0), error);
+      SelectionRefPtr()->Collapse(EditorRawDOMPoint(pNode, 0), error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       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
       ErrorResult error;
-      SelectionRef().Collapse(afterSibling, error);
+      SelectionRefPtr()->Collapse(afterSibling, error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     }
   } else {
     // Put selection at front of righthand heading
     ErrorResult error;
-    SelectionRef().Collapse(RawRangeBoundary(&aHeader, 0), error);
+    SelectionRefPtr()->Collapse(RawRangeBoundary(&aHeader, 0), error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
   }
   return NS_OK;
 }
 
 EditActionResult
 HTMLEditRules::ReturnInParagraph(Element& aParentDivOrP)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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);
   }
@@ -8402,26 +8364,26 @@ HTMLEditRules::SplitParagraph(
   }
 
   // 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);
     IgnoredErrorResult ignoredError;
-    SelectionRef().Collapse(atStartOfChild, ignoredError);
+    SelectionRefPtr()->Collapse(atStartOfChild, ignoredError);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
       "Failed to collapse selection at the end of the child");
   } else {
     EditorRawDOMPoint atChild(child);
     IgnoredErrorResult ignoredError;
-    SelectionRef().Collapse(atChild, ignoredError);
+    SelectionRefPtr()->Collapse(atChild, ignoredError);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
       "Failed to collapse selection at the child");
   }
   return NS_OK;
 }
@@ -8472,17 +8434,17 @@ HTMLEditRules::ReturnInListItem(Element&
                                                 atNextSiblingOfLeftList);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       ErrorResult error;
-      SelectionRef().Collapse(RawRangeBoundary(&aListItem, 0), error);
+      SelectionRefPtr()->Collapse(RawRangeBoundary(&aListItem, 0), error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     } else {
@@ -8517,17 +8479,17 @@ HTMLEditRules::ReturnInListItem(Element&
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
 
       // Set selection to before the break
       ErrorResult error;
-      SelectionRef().Collapse(EditorRawDOMPoint(pNode, 0), error);
+      SelectionRefPtr()->Collapse(EditorRawDOMPoint(pNode, 0), error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     }
@@ -8606,17 +8568,17 @@ HTMLEditRules::ReturnInListItem(Element&
           rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           ErrorResult error;
-          SelectionRef().Collapse(EditorRawDOMPoint(newListItem, 0), error);
+          SelectionRefPtr()->Collapse(EditorRawDOMPoint(newListItem, 0), error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
@@ -8634,17 +8596,17 @@ HTMLEditRules::ReturnInListItem(Element&
           return NS_ERROR_FAILURE;
         }
         if (brElement) {
           EditorRawDOMPoint atBrNode(brElement);
           if (NS_WARN_IF(!atBrNode.IsSetAndValid())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
-          SelectionRef().Collapse(atBrNode, error);
+          SelectionRefPtr()->Collapse(atBrNode, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
@@ -8658,41 +8620,41 @@ HTMLEditRules::ReturnInListItem(Element&
                               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;
-          SelectionRef().Collapse(atVisNode, error);
+          SelectionRefPtr()->Collapse(atVisNode, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
 
-        rv = SelectionRef().Collapse(visNode, visOffset);
+        rv = SelectionRefPtr()->Collapse(visNode, visOffset);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         return NS_OK;
       }
     }
   }
 
   ErrorResult error;
-  SelectionRef().Collapse(EditorRawDOMPoint(&aListItem, 0), error);
+  SelectionRefPtr()->Collapse(EditorRawDOMPoint(&aListItem, 0), error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
@@ -9333,22 +9295,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();
 
-  if (!SelectionRef().RangeCount()) {
+  if (!SelectionRefPtr()->RangeCount()) {
     // Nothing to do
     return NS_OK;
   }
   const RangeBoundary& atStartOfSelection =
-    SelectionRef().GetRangeAt(0)->StartRef();
+    SelectionRefPtr()->GetRangeAt(0)->StartRef();
   nsCOMPtr<nsIContent> selNode =
     atStartOfSelection.Container() &&
     atStartOfSelection.Container()->IsContent() ?
       atStartOfSelection.Container()->AsContent() : nullptr;
   if (!selNode) {
     // Nothing to do
     return NS_OK;
   }
@@ -9448,17 +9410,17 @@ HTMLEditRules::InsertBRElementToEmptyLis
 }
 
 nsresult
 HTMLEditRules::AdjustWhitespace()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   EditorRawDOMPoint selectionStartPoint(
-                      EditorBase::GetStartPoint(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   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(!CanHandleEditAction())) {
@@ -9470,26 +9432,26 @@ HTMLEditRules::AdjustWhitespace()
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::PinSelectionToNewBlock()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  if (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
   if (NS_WARN_IF(!mNewBlock)) {
     return NS_ERROR_NULL_POINTER;
   }
 
   EditorRawDOMPoint selectionStartPoint(
-                      EditorBase::GetStartPoint(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   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.
@@ -9521,17 +9483,17 @@ HTMLEditRules::PinSelectionToNewBlock()
       endPoint.SetToEndOf(tmp);
     } else {
       endPoint.Set(tmp);
       if (NS_WARN_IF(!endPoint.AdvanceOffset())) {
         return NS_ERROR_FAILURE;
       }
     }
     ErrorResult error;
-    SelectionRef().Collapse(endPoint, error);
+    SelectionRefPtr()->Collapse(endPoint, error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -9545,39 +9507,39 @@ HTMLEditRules::PinSelectionToNewBlock()
   EditorRawDOMPoint atStartOfBlock;
   if (EditorBase::IsTextNode(tmp) ||
       HTMLEditorRef().IsContainer(tmp)) {
     atStartOfBlock.Set(tmp);
   } else {
     atStartOfBlock.Set(tmp, 0);
   }
   ErrorResult error;
-  SelectionRef().Collapse(atStartOfBlock, error);
+  SelectionRefPtr()->Collapse(atStartOfBlock, error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
 void
 HTMLEditRules::CheckInterlinePosition()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // If the selection isn't collapsed, do nothing.
-  if (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     return;
   }
 
   // Get the (collapsed) selection location
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return;
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return;
   }
@@ -9585,64 +9547,64 @@ HTMLEditRules::CheckInterlinePosition()
 
   // 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)) {
     IgnoredErrorResult ignoredError;
-    SelectionRef().SetInterlinePosition(true, ignoredError);
+    SelectionRefPtr()->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)) {
     IgnoredErrorResult ignoredError;
-    SelectionRef().SetInterlinePosition(true, ignoredError);
+    SelectionRefPtr()->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)) {
     IgnoredErrorResult ignoredError;
-    SelectionRef().SetInterlinePosition(false, ignoredError);
+    SelectionRefPtr()->SetInterlinePosition(false, ignoredError);
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
       "Failed to unset interline position");
   }
 }
 
 nsresult
 HTMLEditRules::AdjustSelection(nsIEditor::EDirection aAction)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // 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 (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     return NS_OK;
   }
 
   // get the (collapsed) selection location
-  EditorDOMPoint point(EditorBase::GetStartPoint(SelectionRef()));
+  EditorDOMPoint point(EditorBase::GetStartPoint(*SelectionRefPtr()));
   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());
@@ -9709,40 +9671,40 @@ HTMLEditRules::AdjustSelection(nsIEditor
           // like table cells won't grow in height.
           CreateElementResult createMozBrResult = CreateMozBR(point);
           if (NS_WARN_IF(createMozBrResult.Failed())) {
             return createMozBrResult.Rv();
           }
           point.Set(createMozBrResult.GetNewNode());
           // selection stays *before* moz-br, sticking to it
           ErrorResult error;
-          SelectionRef().SetInterlinePosition(true, error);
+          SelectionRefPtr()->SetInterlinePosition(true, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           NS_WARNING_ASSERTION(!error.Failed(),
             "Failed to set interline position");
           error = NS_OK;
-          SelectionRef().Collapse(point, error);
+          SelectionRefPtr()->Collapse(point, error);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             error.SuppressException();
             return NS_ERROR_EDITOR_DESTROYED;
           }
           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.
             IgnoredErrorResult ignoredError;
-            SelectionRef().SetInterlinePosition(true, ignoredError);
+            SelectionRefPtr()->SetInterlinePosition(true, ignoredError);
             NS_WARNING_ASSERTION(!ignoredError.Failed(),
               "Failed to set interline position");
           }
         }
       }
     }
   }
 
@@ -9767,17 +9729,17 @@ HTMLEditRules::AdjustSelection(nsIEditor
   // prefer the correct direction.
   nearNode = FindNearEditableNode(point, aAction);
   if (!nearNode) {
     return NS_OK;
   }
 
   EditorDOMPoint pt = GetGoodSelPointForNode(*nearNode, aAction);
   ErrorResult error;
-  SelectionRef().Collapse(pt, error);
+  SelectionRefPtr()->Collapse(pt, error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
@@ -10021,19 +9983,19 @@ HTMLEditRules::SelectionEndpointInNode(n
                                        bool* aResult)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER);
 
   *aResult = false;
 
-  uint32_t rangeCount = SelectionRef().RangeCount();
+  uint32_t rangeCount = SelectionRefPtr()->RangeCount();
   for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
-    RefPtr<nsRange> range = SelectionRef().GetRangeAt(rangeIdx);
+    RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(rangeIdx);
     nsINode* startContainer = range->GetStartContainer();
     if (startContainer) {
       if (aNode == startContainer) {
         *aResult = true;
         return NS_OK;
       }
       if (EditorUtils::IsDescendantOf(*startContainer, *aNode)) {
         *aResult = true;
@@ -10267,56 +10229,57 @@ HTMLEditRules::ConfirmSelectionInBody()
   MOZ_ASSERT(IsEditorDataAvailable());
 
   Element* rootElement = HTMLEditorRef().GetRoot();
   if (NS_WARN_IF(!rootElement)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   EditorRawDOMPoint selectionStartPoint(
-                      EditorBase::GetStartPoint(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   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) {
     IgnoredErrorResult ignoredError;
-    SelectionRef().Collapse(RawRangeBoundary(rootElement, 0), ignoredError);
+    SelectionRefPtr()->Collapse(RawRangeBoundary(rootElement, 0), ignoredError);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
       "Failed to collapse selection at start of the root element");
     return NS_OK;
   }
 
-  EditorRawDOMPoint selectionEndPoint(EditorBase::GetEndPoint(SelectionRef()));
+  EditorRawDOMPoint selectionEndPoint(
+                      EditorBase::GetEndPoint(*SelectionRefPtr()));
   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) {
     IgnoredErrorResult ignoredError;
-    SelectionRef().Collapse(RawRangeBoundary(rootElement, 0), ignoredError);
+    SelectionRefPtr()->Collapse(RawRangeBoundary(rootElement, 0), ignoredError);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
       "Failed to collapse selection at start of the root element");
   }
 
   return NS_OK;
@@ -10416,96 +10379,92 @@ HTMLEditRules::InsertBRIfNeededInternal(
                     CreateMozBR(EditorRawDOMPoint(&aNode, 0));
   if (NS_WARN_IF(createBrResult.Failed())) {
     return createBrResult.Rv();
   }
   return NS_OK;
 }
 
 void
-HTMLEditRules::DidCreateNode(Selection& aSelection,
-                             Element& aNewElement)
+HTMLEditRules::DidCreateNode(Element& aNewElement)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // assumption that Join keeps the righthand node
   IgnoredErrorResult ignoredError;
   mUtilRange->SelectNode(aNewElement, ignoredError);
   if (NS_WARN_IF(ignoredError.Failed())) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
-HTMLEditRules::DidInsertNode(Selection& aSelection,
-                             nsIContent& aContent)
+HTMLEditRules::DidInsertNode(nsIContent& aContent)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   IgnoredErrorResult ignoredError;
   mUtilRange->SelectNode(aContent, ignoredError);
   if (NS_WARN_IF(ignoredError.Failed())) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
-HTMLEditRules::WillDeleteNode(Selection& aSelection,
-                              nsINode& aChild)
+HTMLEditRules::WillDeleteNode(nsINode& aChild)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   IgnoredErrorResult ignoredError;
   mUtilRange->SelectNode(aChild, ignoredError);
   if (NS_WARN_IF(ignoredError.Failed())) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
-HTMLEditRules::DidSplitNode(Selection& aSelection,
-                            nsINode& aExistingRightNode,
+HTMLEditRules::DidSplitNode(nsINode& aExistingRightNode,
                             nsINode& aNewLeftNode)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   nsresult rv = mUtilRange->SetStartAndEnd(&aNewLeftNode, 0,
                                            &aExistingRightNode, 0);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
@@ -10522,104 +10481,101 @@ HTMLEditRules::WillJoinNodes(nsINode& aL
     return;
   }
 
   // remember split point
   mJoinOffset = aLeftNode.Length();
 }
 
 void
-HTMLEditRules::DidJoinNodes(Selection& aSelection,
-                            nsINode& aLeftNode,
+HTMLEditRules::DidJoinNodes(nsINode& aLeftNode,
                             nsINode& aRightNode)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // assumption that Join keeps the righthand node
   nsresult rv = mUtilRange->CollapseTo(&aRightNode, mJoinOffset);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
-HTMLEditRules::DidInsertText(Selection& aSelection,
-                             nsINode& aTextNode,
+HTMLEditRules::DidInsertText(nsINode& aTextNode,
                              int32_t aOffset,
                              const nsAString& aString)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   int32_t length = aString.Length();
   nsresult rv = mUtilRange->SetStartAndEnd(&aTextNode, aOffset,
                                            &aTextNode, aOffset + length);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
-HTMLEditRules::DidDeleteText(Selection& aSelection,
-                             nsINode& aTextNode,
+HTMLEditRules::DidDeleteText(nsINode& aTextNode,
                              int32_t aOffset,
                              int32_t aLength)
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   nsresult rv = mUtilRange->CollapseTo(&aTextNode, aOffset);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
 }
 
 void
-HTMLEditRules::WillDeleteSelection(Selection& aSelection)
+HTMLEditRules::WillDeleteSelection()
 {
   if (!mListenerEnabled) {
     return;
   }
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return;
   }
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
-
-  EditorRawDOMPoint startPoint = EditorBase::GetStartPoint(SelectionRef());
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
+
+  EditorRawDOMPoint startPoint = EditorBase::GetStartPoint(*SelectionRefPtr());
   if (NS_WARN_IF(!startPoint.IsSet())) {
     return;
   }
-  EditorRawDOMPoint endPoint = EditorBase::GetEndPoint(SelectionRef());
+  EditorRawDOMPoint endPoint = EditorBase::GetEndPoint(*SelectionRefPtr());
   if (NS_WARN_IF(!endPoint.IsSet())) {
     return;
   }
   nsresult rv = mUtilRange->SetStartAndEnd(startPoint, endPoint);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
   UpdateDocChangeRange(mUtilRange);
@@ -10784,22 +10740,17 @@ nsresult
 HTMLEditRules::MakeSureElemStartsAndEndsOnCR(nsINode& aNode)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
-  Selection* selection = mHTMLEditor->GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   nsresult rv = MakeSureElemStartsOrEndsOnCR(aNode, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   rv = MakeSureElemStartsOrEndsOnCR(aNode, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -11001,17 +10952,17 @@ HTMLEditRules::PrepareToMakeElementAbsol
                                      EditSubAction::eSetPositionToAbsolute,
                                      TouchContent::yes);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // If nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
-    nsRange* firstRange = SelectionRef().GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->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;
     }
@@ -11046,17 +10997,17 @@ HTMLEditRules::PrepareToMakeElementAbsol
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // Put selection in new block
     *aHandled = true;
     // Don't restore the selection
     restoreSelectionLater.Abort();
     ErrorResult error;
-    SelectionRef().Collapse(RawRangeBoundary(positionedDiv, 0), error);
+    SelectionRefPtr()->Collapse(RawRangeBoundary(positionedDiv, 0), error);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       error.SuppressException();
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     return NS_OK;
@@ -11375,21 +11326,21 @@ HTMLEditRules::DocumentModifiedWorker()
     return;
   }
 
   RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
   htmlEditor->OnModifyDocument();
 }
 
 void
-HTMLEditRules::OnModifyDocument(Selection& aSelection)
+HTMLEditRules::OnModifyDocument()
 {
   MOZ_ASSERT(mHTMLEditor);
 
-  AutoSafeEditorData setData(*this, *mHTMLEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   // DeleteNodeWithTransaction() below may cause a flush, which could destroy
   // the editor
   nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
 
   // Delete our bogus node, if we have one, since the document might not be
   // empty any more.
   if (mBogusNode) {
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -95,22 +95,20 @@ public:
 
   // TextEditRules methods
   virtual nsresult Init(TextEditor* aTextEditor) override;
   virtual nsresult DetachEditor() override;
   virtual nsresult BeforeEdit(EditSubAction aEditSubAction,
                               nsIEditor::EDirection aDirection) override;
   virtual nsresult AfterEdit(EditSubAction aEditSubAction,
                              nsIEditor::EDirection aDirection) override;
-  virtual nsresult WillDoAction(Selection* aSelection,
-                                EditSubActionInfo& aInfo,
+  virtual nsresult WillDoAction(EditSubActionInfo& aInfo,
                                 bool* aCancel,
                                 bool* aHandled) override;
-  virtual nsresult DidDoAction(Selection* aSelection,
-                               EditSubActionInfo& aInfo,
+  virtual nsresult DidDoAction(EditSubActionInfo& aInfo,
                                nsresult aResult) override;
   virtual bool DocumentIsEmpty() override;
 
   /**
    * DocumentModified() is called when editor content is changed.
    */
   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult DocumentModified();
 
@@ -125,40 +123,37 @@ public:
    * - first (last) editable child of aNode is a block or a <br>,
    * - previous (next) sibling of aNode is block or a <br>
    * - nor no previous (next) sibling of aNode.
    *
    * @param aNode               The node which may be inserted <br> elements.
    */
   MOZ_MUST_USE nsresult MakeSureElemStartsAndEndsOnCR(nsINode& aNode);
 
-  void DidCreateNode(Selection& aSelection, Element& aNewElement);
-  void DidInsertNode(Selection& aSelection, nsIContent& aNode);
-  void WillDeleteNode(Selection& aSelection, nsINode& aChild);
-  void DidSplitNode(Selection& aSelection,
-                    nsINode& aExistingRightNode,
+  void DidCreateNode(Element& aNewElement);
+  void DidInsertNode(nsIContent& aNode);
+  void WillDeleteNode(nsINode& aChild);
+  void DidSplitNode(nsINode& aExistingRightNode,
                     nsINode& aNewLeftNode);
   void WillJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
-  void DidJoinNodes(Selection& aSelection,
-                    nsINode& aLeftNode, nsINode& aRightNode);
-  void DidInsertText(Selection& aSelection,
-                     nsINode& aTextNode, int32_t aOffset,
+  void DidJoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
+  void DidInsertText(nsINode& aTextNode, int32_t aOffset,
                      const nsAString& aString);
-  void DidDeleteText(Selection& aSelection,
-                     nsINode& aTextNode, int32_t aOffset, int32_t aLength);
-  void WillDeleteSelection(Selection& aSelection);
+  void DidDeleteText(nsINode& aTextNode, int32_t aOffset, int32_t aLength);
+  void WillDeleteSelection();
 
   void StartToListenToEditSubActions() { mListenerEnabled = true; }
   void EndListeningToEditSubActions() { mListenerEnabled = false; }
 
   /**
    * OnModifyDocument() is called when DocumentModifiedWorker() calls
-   * HTMLEditor::OnModifyDocument().
+   * HTMLEditor::OnModifyDocument().  The caller guarantees that there
+   * is AutoEditActionDataSetter instance in the editor.
    */
-  MOZ_CAN_RUN_SCRIPT void OnModifyDocument(Selection& aSelection);
+  MOZ_CAN_RUN_SCRIPT void OnModifyDocument();
 
 protected:
   virtual ~HTMLEditRules();
 
   HTMLEditor& HTMLEditorRef() const
   {
     MOZ_ASSERT(mData);
     return mData->HTMLEditorRef();
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -587,16 +587,18 @@ HTMLEditor::SetFlags(uint32_t aFlags)
   mCSSAware = !NoCSS() && !IsMailEditor();
 
   return NS_OK;
 }
 
 nsresult
 HTMLEditor::InitRules()
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (!mRules) {
     // instantiate the rules for the html editor
     mRules = new HTMLEditRules();
   }
   return mRules->Init(this);
 }
 
 NS_IMETHODIMP
@@ -1662,18 +1664,17 @@ HTMLEditor::InsertElementAtSelection(Ele
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertElement,
                                       nsIEditor::eNext);
 
   // hand off to the rules system, see if it has anything to say about this
   bool cancel, handled;
   EditSubActionInfo subActionInfo(EditSubAction::eInsertElement);
-  nsresult rv =
-    rules->WillDoAction(SelectionRefPtr(), subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
   if (!handled) {
     if (aDeleteSelection) {
       if (!IsBlockNode(aElement)) {
         // E.g., inserting an image.  In this case we don't need to delete any
@@ -1737,18 +1738,21 @@ HTMLEditor::InsertElementAtSelection(Ele
         RefPtr<Element> newBrElement =
           InsertBrElementWithTransaction(insertedPoint, ePrevious);
         if (NS_WARN_IF(!newBrElement)) {
           return NS_ERROR_FAILURE;
         }
       }
     }
   }
-  rv = rules->DidDoAction(SelectionRefPtr(), subActionInfo, rv);
-  return rv;
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 template<typename PT, typename CT>
 EditorDOMPoint
 HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
               nsIContent& aNode,
               const EditorDOMPointBase<PT, CT>& aPointToInsert,
               SplitAtEdges aSplitAtEdges)
@@ -2233,18 +2237,17 @@ HTMLEditor::MakeOrChangeList(const nsASt
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eCreateOrChangeList,
                                       nsIEditor::eNext);
 
   EditSubActionInfo subActionInfo(EditSubAction::eCreateOrChangeList);
   subActionInfo.blockType = &aListType;
   subActionInfo.entireList = entireList;
   subActionInfo.bulletType = &aBulletType;
-  nsresult rv =
-    rules->WillDoAction(SelectionRefPtr(), subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
   if (!handled && SelectionRefPtr()->IsCollapsed()) {
     nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
@@ -2299,17 +2302,17 @@ HTMLEditor::MakeOrChangeList(const nsASt
     }
     ErrorResult error;
     SelectionRefPtr()->Collapse(RawRangeBoundary(newItem, 0), error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
   }
 
-  rv = rules->DidDoAction(SelectionRefPtr(), subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::RemoveList(const nsAString&)
@@ -2329,34 +2332,35 @@ HTMLEditor::RemoveList(const nsAString&)
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eRemoveList,
                                       nsIEditor::eNext);
 
   EditSubActionInfo subActionInfo(EditSubAction::eRemoveList);
   bool cancel, handled;
-  nsresult rv =
-    rules->WillDoAction(SelectionRefPtr(), subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
   // no default behavior for this yet.  what would it mean?
 
-  rv = rules->DidDoAction(SelectionRefPtr(), subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditor::MakeDefinitionListItemWithTransaction(nsAtom& aTagName)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (!mRules) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   MOZ_ASSERT(&aTagName == nsGkAtoms::dt ||
              &aTagName == nsGkAtoms::dd);
 
   // Protect the edit rules object from dying
@@ -2365,40 +2369,40 @@ HTMLEditor::MakeDefinitionListItemWithTr
   bool cancel, handled;
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier
     maybeTopLevelEditSubAction(*this,
                                EditSubAction::eCreateOrChangeDefinitionList,
                                nsIEditor::eNext);
 
-  // pre-process
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
   nsDependentAtomString tagName(&aTagName);
   EditSubActionInfo subActionInfo(EditSubAction::eCreateOrChangeDefinitionList);
   subActionInfo.blockType = &tagName;
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
   if (!handled) {
     // todo: no default for now.  we count on rules to handle it.
   }
 
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditor::InsertBasicBlockWithTransaction(nsAtom& aTagName)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (!mRules) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   MOZ_ASSERT(&aTagName != nsGkAtoms::dd &&
              &aTagName != nsGkAtoms::dt);
 
   // Protect the edit rules object from dying
@@ -2407,30 +2411,26 @@ HTMLEditor::InsertBasicBlockWithTransact
   bool cancel, handled;
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this,
                                       EditSubAction::eCreateOrRemoveBlock,
                                       nsIEditor::eNext);
 
-  // pre-process
-  RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
   nsDependentAtomString tagName(&aTagName);
   EditSubActionInfo subActionInfo(EditSubAction::eCreateOrRemoveBlock);
   subActionInfo.blockType = &tagName;
-  nsresult rv =
-   rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
-  if (!handled && selection->IsCollapsed()) {
-    nsRange* firstRange = selection->GetRangeAt(0);
+  if (!handled && SelectionRefPtr()->IsCollapsed()) {
+    nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet()) ||
         NS_WARN_IF(!atStartOfSelection.GetContainerAsContent())) {
       return NS_ERROR_FAILURE;
@@ -2469,23 +2469,27 @@ HTMLEditor::InsertBasicBlockWithTransact
     RefPtr<Element> newBlock =
       CreateNodeWithTransaction(aTagName, pointToInsertBlock);
     if (NS_WARN_IF(!newBlock)) {
       return NS_ERROR_FAILURE;
     }
 
     // reposition selection to inside the block
     ErrorResult error;
-    selection->Collapse(RawRangeBoundary(newBlock, 0), error);
+    SelectionRefPtr()->Collapse(RawRangeBoundary(newBlock, 0), error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
   }
 
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::Indent(const nsAString& aIndent)
 {
   if (aIndent.LowerCaseEqualsLiteral("indent")) {
     nsresult rv = IndentAsAction();
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -2541,44 +2545,40 @@ HTMLEditor::OutdentAsAction()
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditor::IndentOrOutdentAsSubAction(EditSubAction aIndentOrOutdent)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(mRules);
   MOZ_ASSERT(mPlaceholderBatch);
+
   MOZ_ASSERT(aIndentOrOutdent == EditSubAction::eIndent ||
              aIndentOrOutdent == EditSubAction::eOutdent);
 
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
   bool cancel, handled;
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, aIndentOrOutdent,
                                       nsIEditor::eNext);
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   EditSubActionInfo subActionInfo(aIndentOrOutdent);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
-  if (!handled && selection->IsCollapsed() &&
+  if (!handled && SelectionRefPtr()->IsCollapsed() &&
       aIndentOrOutdent == EditSubAction::eIndent) {
-    nsRange* firstRange = selection->GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet()) ||
         NS_WARN_IF(!atStartOfSelection.GetContainerAsContent())) {
       return NS_ERROR_FAILURE;
@@ -2618,36 +2618,37 @@ HTMLEditor::IndentOrOutdentAsSubAction(E
     RefPtr<Element> newBQ =
       CreateNodeWithTransaction(*nsGkAtoms::blockquote,
                                 pointToInsertBlockquote);
     if (NS_WARN_IF(!newBQ)) {
       return NS_ERROR_FAILURE;
     }
     // put a space in it so layout will draw the list item
     ErrorResult error;
-    selection->Collapse(RawRangeBoundary(newBQ, 0), error);
+    SelectionRefPtr()->Collapse(RawRangeBoundary(newBQ, 0), error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     rv = InsertTextAsSubAction(NS_LITERAL_STRING(" "));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     // Reposition selection to before the space character.
-    firstRange = selection->GetRangeAt(0);
+    firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
-    selection->Collapse(RawRangeBoundary(firstRange->GetStartContainer(), 0),
-                        error);
+    SelectionRefPtr()->Collapse(
+                         RawRangeBoundary(firstRange->GetStartContainer(), 0),
+                         error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
   }
-  rv = rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 //TODO: IMPLEMENT ALIGNMENT!
 
@@ -2669,23 +2670,22 @@ HTMLEditor::Align(const nsAString& aAlig
                                       EditSubAction::eSetOrClearAlignment,
                                       nsIEditor::eNext);
 
   bool cancel, handled;
 
   // Find out if the selection is collapsed:
   EditSubActionInfo subActionInfo(EditSubAction::eSetOrClearAlignment);
   subActionInfo.alignType = &aAlignType;
-  nsresult rv =
-   rules->WillDoAction(SelectionRefPtr(), subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
 
-  rv = rules->DidDoAction(SelectionRefPtr(), subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 Element*
 HTMLEditor::GetElementOrParentByTagName(const nsAtom& aTagName,
@@ -4630,48 +4630,51 @@ HTMLEditor::SetIsCSSEnabled(bool aIsCSSP
 
   return SetFlags(flags);
 }
 
 // Set the block background color
 nsresult
 HTMLEditor::SetCSSBackgroundColorWithTransaction(const nsAString& aColor)
 {
-  NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
+  if (NS_WARN_IF(!mRules)) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
   CommitComposition();
 
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
-  RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_STATE(selection);
-
-  bool isCollapsed = selection->IsCollapsed();
+  bool isCollapsed = SelectionRefPtr()->IsCollapsed();
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertElement,
                                       nsIEditor::eNext);
   AutoSelectionRestorer restoreSelectionLater(*this);
   AutoTransactionsConserveSelection dontChangeMySelection(*this);
 
   // XXX Although, this method may set background color of ancestor block
   //     element, using EditSubAction::eSetTextProperty.
   bool cancel, handled;
   EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!cancel && !handled) {
     // Loop through the ranges in the selection
-    for (uint32_t i = 0; i < selection->RangeCount(); i++) {
-      RefPtr<nsRange> range = selection->GetRangeAt(i);
-      NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
+    for (uint32_t i = 0; i < SelectionRefPtr()->RangeCount(); i++) {
+      RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(i);
+      if (NS_WARN_IF(!range)) {
+        return NS_ERROR_FAILURE;
+      }
 
       nsCOMPtr<Element> cachedBlockParent;
 
       // Check for easy case: both range endpoints in same text node
       nsCOMPtr<nsINode> startNode = range->GetStartContainer();
       int32_t startOffset = range->StartOffset();
       nsCOMPtr<nsINode> endNode = range->GetEndContainer();
       int32_t endOffset = range->EndOffset();
@@ -4777,18 +4780,20 @@ HTMLEditor::SetCSSBackgroundColorWithTra
                                                        false);
           }
         }
       }
     }
   }
   if (!cancel) {
     // Post-process
-    rv = rules->DidDoAction(selection, subActionInfo, rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = rules->DidDoAction(subActionInfo, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetBackgroundColor(const nsAString& aColor)
 {
   AutoEditActionDataSetter editActionData(*this,
@@ -5410,21 +5415,21 @@ HTMLEditor::GetHTMLDocument() const
 
 void
 HTMLEditor::OnModifyDocument()
 {
   MOZ_ASSERT(mRules);
 
   RefPtr<HTMLEditRules> htmlRules = mRules->AsHTMLEditRules();
   if (IsEditActionDataAvailable()) {
-    htmlRules->OnModifyDocument(*SelectionRefPtr());
+    htmlRules->OnModifyDocument();
     return;
   }
 
   AutoEditActionDataSetter editActionData(*this, EditAction::eCreateBogusNode);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return;
   }
 
-  htmlRules->OnModifyDocument(*SelectionRefPtr());
+  htmlRules->OnModifyDocument();
 }
 
 } // namespace mozilla
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -87,55 +87,56 @@ static bool FindIntegerAfterString(const
 static nsresult RemoveFragComments(nsCString& theStr);
 static void RemoveBodyAndHead(nsINode& aNode);
 static nsresult FindTargetNode(nsINode* aStart,
                                nsCOMPtr<nsINode>& aResult);
 
 nsresult
 HTMLEditor::LoadHTML(const nsAString& aInputString)
 {
-  NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
+  if (NS_WARN_IF(!mRules)) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
 
   // force IME commit; set up rules sniffing and batching
   CommitComposition();
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this,
                                       EditSubAction::eInsertHTMLSource,
                                       nsIEditor::eNext);
 
-  // Get selection
-  RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_STATE(selection);
-
   EditSubActionInfo subActionInfo(EditSubAction::eInsertHTMLSource);
   bool cancel, handled;
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (cancel) {
     return NS_OK; // rules canceled the operation
   }
 
   if (!handled) {
     // Delete Selection, but only if it isn't collapsed, see bug #106269
-    if (!selection->IsCollapsed()) {
+    if (!SelectionRefPtr()->IsCollapsed()) {
       rv = DeleteSelectionAsSubAction(eNone, eStrip);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // Get the first range in the selection, for context:
-    RefPtr<nsRange> range = selection->GetRangeAt(0);
-    NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
+    RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(0);
+    if (NS_WARN_IF(!range)) {
+      return NS_ERROR_FAILURE;
+    }
 
     // Create fragment for pasted HTML.
     ErrorResult error;
     RefPtr<DocumentFragment> documentFragment =
       range->CreateContextualFragment(aInputString, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
@@ -164,17 +165,21 @@ HTMLEditor::LoadHTML(const nsAString& aI
       if (NS_WARN_IF(!pointToInsert.Offset())) {
         // Append the remaining children to the container if offset is
         // overflown.
         pointToInsert.SetToEndOf(pointToInsert.GetContainer());
       }
     }
   }
 
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::InsertHTML(const nsAString& aInString)
 {
   AutoEditActionDataSetter editActionData(*this, EditAction::eInsertHTML);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
@@ -192,34 +197,32 @@ HTMLEditor::DoInsertHTMLWithContext(cons
                                     const nsAString& aFlavor,
                                     nsIDocument* aSourceDoc,
                                     nsINode* aDestNode,
                                     int32_t aDestOffset,
                                     bool aDeleteSelection,
                                     bool aTrustedInput,
                                     bool aClearStyle)
 {
-  NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
+  if (NS_WARN_IF(!mRules)) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
 
   // Prevent the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
   // force IME commit; set up rules sniffing and batching
   CommitComposition();
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::ePasteHTMLContent,
                                       nsIEditor::eNext);
 
-  // Get selection
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   // create a dom document fragment that represents the structure to paste
   nsCOMPtr<nsINode> fragmentAsNode, streamStartParent, streamEndParent;
   int32_t streamStartOffset = 0, streamEndOffset = 0;
 
   nsresult rv = CreateDOMFragmentFromPaste(aInputString, aContextStr, aInfoStr,
                                            address_of(fragmentAsNode),
                                            address_of(streamStartParent),
                                            address_of(streamEndParent),
@@ -227,17 +230,17 @@ HTMLEditor::DoInsertHTMLWithContext(cons
                                            &streamEndOffset,
                                            aTrustedInput);
   NS_ENSURE_SUCCESS(rv, rv);
 
   EditorDOMPoint targetPoint;
   if (!aDestNode) {
     // if caller didn't provide the destination/target node,
     // fetch the paste insertion point from our selection
-    targetPoint = EditorBase::GetStartPoint(*selection);
+    targetPoint = EditorBase::GetStartPoint(*SelectionRefPtr());
     if (NS_WARN_IF(!targetPoint.IsSet()) ||
         !IsEditable(targetPoint.GetContainer())) {
       return NS_ERROR_FAILURE;
     }
   } else {
     targetPoint.Set(aDestNode, aDestOffset);
   }
 
@@ -254,17 +257,17 @@ HTMLEditor::DoInsertHTMLWithContext(cons
       AutoTrackDOMPoint tracker(mRangeUpdater, &targetPoint);
       rv = DeleteSelectionAsSubAction(eNone, eStrip);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     ErrorResult error;
-    selection->Collapse(targetPoint, error);
+    SelectionRefPtr()->Collapse(targetPoint, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
   }
 
   // we need to recalculate various things based on potentially new offsets
   // this is work to be completed at a later date (probably by jfrancis)
 
@@ -310,18 +313,19 @@ HTMLEditor::DoInsertHTMLWithContext(cons
   }
 
   if (!cellSelectionMode) {
     rv = DeleteSelectionAndPrepareToCreateNode();
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aClearStyle) {
       // pasting does not inherit local inline styles
-      nsCOMPtr<nsINode> tmpNode = selection->GetAnchorNode();
-      int32_t tmpOffset = static_cast<int32_t>(selection->AnchorOffset());
+      nsCOMPtr<nsINode> tmpNode = SelectionRefPtr()->GetAnchorNode();
+      int32_t tmpOffset =
+        static_cast<int32_t>(SelectionRefPtr()->AnchorOffset());
       rv = ClearStyle(address_of(tmpNode), &tmpOffset, nullptr, nullptr);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   } else {
     // Delete whole cells: we will replace with new table content.
 
     // Braces for artificial block to scope AutoSelectionRestorer.
     // Save current selection since DeleteTableCellWithTransaction() perturbs
@@ -329,34 +333,39 @@ HTMLEditor::DoInsertHTMLWithContext(cons
     {
       AutoSelectionRestorer restoreSelectionLater(*this);
       rv = DeleteTableCellWithTransaction(1);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
     // collapse selection to beginning of deleted table content
-    selection->CollapseToStart(IgnoreErrors());
+    IgnoredErrorResult ignoredError;
+    SelectionRefPtr()->CollapseToStart(ignoredError);
+    NS_WARNING_ASSERTION(!ignoredError.Failed(),
+      "Failed to collapse Selection to start");
   }
 
   // give rules a chance to handle or cancel
   EditSubActionInfo subActionInfo(EditSubAction::eInsertElement);
   bool cancel, handled;
-  rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
-  NS_ENSURE_SUCCESS(rv, rv);
+  rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   if (cancel) {
     return NS_OK; // rules canceled the operation
   }
 
   if (!handled) {
     // Adjust position based on the first node we are going to insert.
     // FYI: WillDoAction() above might have changed the selection.
     EditorDOMPoint pointToInsert =
       GetBetterInsertionPointFor(nodeList[0],
-                                 EditorBase::GetStartPoint(*selection));
+                                 EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!pointToInsert.IsSet())) {
       return NS_ERROR_FAILURE;
     }
 
     // if there are any invisible br's after our insertion point, remove them.
     // this is because if there is a br at end of what we paste, it will make
     // the invisible br visible.
     WSRunObject wsObj(this, pointToInsert);
@@ -662,17 +671,18 @@ HTMLEditor::DoInsertHTMLWithContext(cons
             // prior visible thing is an image or some other non-text thingy.
             // We want to be right after it.
             atStartReasonNode.Set(wsRunObj.mStartReasonNode);
             selNode = atStartReasonNode.GetContainer();
             selOffset = atStartReasonNode.Offset() + 1;
           }
         }
       }
-      selection->Collapse(selNode, selOffset);
+      DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(selNode, selOffset);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse Selection");
 
       // if we just pasted a link, discontinue link style
       nsCOMPtr<nsIContent> linkContent;
       if (!bStartedInLink &&
           (linkContent = GetLinkElement(selNode))) {
         // so, if we just pasted a link, I split it.  Why do that instead of just
         // nudging selection point beyond it?  Because it might have ended in a BR
         // that is not visible.  If so, the code above just placed selection
@@ -681,24 +691,30 @@ HTMLEditor::DoInsertHTMLWithContext(cons
           SplitNodeDeepWithTransaction(
             *linkContent, EditorRawDOMPoint(selNode, selOffset),
             SplitAtEdges::eDoNotCreateEmptyContainer);
         NS_WARNING_ASSERTION(splitLinkResult.Succeeded(),
           "Failed to split the link");
         if (splitLinkResult.GetPreviousNode()) {
           EditorRawDOMPoint afterLeftLink(splitLinkResult.GetPreviousNode());
           if (afterLeftLink.AdvanceOffset()) {
-            selection->Collapse(afterLeftLink);
+            DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(afterLeftLink);
+            NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+              "Failed to collapse Selection after the left link");
           }
         }
       }
     }
   }
 
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 // static
 Element*
 HTMLEditor::GetLinkElement(nsINode* aNode)
 {
   if (NS_WARN_IF(!aNode)) {
     return nullptr;
@@ -1724,27 +1740,21 @@ HTMLEditor::PasteAsQuotationAsAction(int
   // If it's not in plain text edit mode, paste text into new
   // <blockquote type="cite"> element after removing selection.
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertQuotation,
                                       nsIEditor::eNext);
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Adjust Selection and clear cached style before inserting <blockquote>.
   EditSubActionInfo subActionInfo(EditSubAction::eInsertElement);
   bool cancel, handled;
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (cancel || handled) {
     return NS_OK;
   }
 
   // Then, remove Selection and create <blockquote type="cite"> now.
@@ -1754,17 +1764,17 @@ HTMLEditor::PasteAsQuotationAsAction(int
     DeleteSelectionAndCreateElement(*nsGkAtoms::blockquote);
   if (NS_WARN_IF(!newNode)) {
     return NS_ERROR_FAILURE;
   }
   newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                    NS_LITERAL_STRING("cite"), true);
 
   // Collapse Selection in the new <blockquote> element.
-  rv = selection->Collapse(newNode, 0);
+  rv = SelectionRefPtr()->Collapse(newNode, 0);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // XXX Why don't we call HTMLEditRules::DidDoAction() after Paste()?
   // XXX If ePaste event has not been dispatched yet but selected content
   //     has already been removed and created a <blockquote> element.
   //     So, web apps cannot prevent the default of ePaste event which
@@ -1973,36 +1983,32 @@ HTMLEditor::InsertAsQuotation(const nsAS
 // This differs from its corresponding method in TextEditor
 // in that here, quoted material is enclosed in a <pre> tag
 // in order to preserve the original line wrapping.
 nsresult
 HTMLEditor::InsertAsPlaintextQuotation(const nsAString& aQuotedText,
                                        bool aAddCites,
                                        nsINode** aNodeInserted)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (aNodeInserted) {
     *aNodeInserted = nullptr;
   }
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertQuotation,
                                       nsIEditor::eNext);
 
   // give rules a chance to handle or cancel
   EditSubActionInfo subActionInfo(EditSubAction::eInsertElement);
   bool cancel, handled;
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (cancel || handled) {
     return NS_OK; // rules canceled the operation
   }
 
   // Wrap the inserted quote in a <span> so we can distinguish it. If we're
@@ -2029,17 +2035,17 @@ HTMLEditor::InsertAsPlaintextQuotation(c
         NS_LITERAL_STRING("white-space: pre-wrap; display: block; width: 98vw;"),
         true);
     } else {
       newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
         NS_LITERAL_STRING("white-space: pre-wrap;"), true);
     }
 
     // and set the selection inside it:
-    DebugOnly<nsresult> rv = selection->Collapse(newNode, 0);
+    DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(newNode, 0);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
       "Failed to collapse selection into the new node");
   }
 
   if (aAddCites) {
     rv = InsertWithQuotationsAsSubAction(aQuotedText);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -2056,17 +2062,17 @@ HTMLEditor::InsertAsPlaintextQuotation(c
   }
 
   // Set the selection to just after the inserted node:
   EditorRawDOMPoint afterNewNode(newNode);
   bool advanced = afterNewNode.AdvanceOffset();
   NS_WARNING_ASSERTION(advanced,
     "Failed to advance offset to after the new <span> element");
   if (advanced) {
-    DebugOnly<nsresult> rvIgnored = selection->Collapse(afterNewNode);
+    DebugOnly<nsresult> rvIgnored = SelectionRefPtr()->Collapse(afterNewNode);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
       "Failed to collapse after the new node");
   }
 
   // Note that if !aAddCites, aNodeInserted isn't set.
   // That's okay because the routines that use aAddCites
   // don't need to know the inserted node.
   if (aNodeInserted) {
@@ -2166,34 +2172,29 @@ HTMLEditor::InsertAsCitedQuotation(const
 }
 
 nsresult
 HTMLEditor::InsertAsCitedQuotationInternal(const nsAString& aQuotedText,
                                            const nsAString& aCitation,
                                            bool aInsertHTML,
                                            nsINode** aNodeInserted)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(!IsPlaintextEditor());
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertQuotation,
                                       nsIEditor::eNext);
 
   // give rules a chance to handle or cancel
   EditSubActionInfo subActionInfo(EditSubAction::eInsertElement);
   bool cancel, handled;
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (cancel || handled) {
     return NS_OK; // rules canceled the operation
   }
 
   RefPtr<Element> newNode =
@@ -2206,17 +2207,19 @@ HTMLEditor::InsertAsCitedQuotationIntern
   newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                    NS_LITERAL_STRING("cite"), true);
 
   if (!aCitation.IsEmpty()) {
     newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::cite, aCitation, true);
   }
 
   // Set the selection inside the blockquote so aQuotedText will go there:
-  selection->Collapse(newNode, 0);
+  DebugOnly<nsresult> rvIgnored = SelectionRefPtr()->Collapse(newNode, 0);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
+    "Failed to collapse Selection in the new <blockquote> element");
 
   if (aInsertHTML) {
     rv = LoadHTML(aQuotedText);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
     rv = InsertTextAsSubAction(aQuotedText);  // XXX ignore charset
@@ -2230,17 +2233,17 @@ HTMLEditor::InsertAsCitedQuotationIntern
   }
 
   // Set the selection to just after the inserted node:
   EditorRawDOMPoint afterNewNode(newNode);
   bool advanced = afterNewNode.AdvanceOffset();
   NS_WARNING_ASSERTION(advanced,
     "Failed advance offset to after the new <blockquote> element");
   if (advanced) {
-    DebugOnly<nsresult> rvIgnored = selection->Collapse(afterNewNode);
+    DebugOnly<nsresult> rvIgnored = SelectionRefPtr()->Collapse(afterNewNode);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
       "Failed to collapse after the new node");
   }
 
   if (aNodeInserted) {
     newNode.forget(aNodeInserted);
   }
 
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -107,53 +107,49 @@ HTMLEditor::SetInlineProperty(const nsAS
   return SetInlinePropertyInternal(*property, attribute, aValue);
 }
 
 nsresult
 HTMLEditor::SetInlinePropertyInternal(nsAtom& aProperty,
                                       nsAtom* aAttribute,
                                       const nsAString& aValue)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (NS_WARN_IF(!mRules)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   RefPtr<TextEditRules> rules(mRules);
   CommitComposition();
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (selection->IsCollapsed()) {
+  if (SelectionRefPtr()->IsCollapsed()) {
     // Manipulating text attributes on a collapsed selection only sets state
     // for the next text insertion
     mTypeInState->SetProp(&aProperty, aAttribute, aValue);
     return NS_OK;
   }
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertElement,
                                       nsIEditor::eNext);
   AutoSelectionRestorer restoreSelectionLater(*this);
   AutoTransactionsConserveSelection dontChangeMySelection(*this);
 
   bool cancel, handled;
   EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
   // Protect the edit rules object from dying
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!cancel && !handled) {
     // Loop through the ranges in the selection
-    AutoRangeArray arrayOfRanges(selection);
+    AutoRangeArray arrayOfRanges(SelectionRefPtr());
     for (auto& range : arrayOfRanges.mRanges) {
       // Adjust range to include any ancestors whose children are entirely
       // selected
       rv = PromoteInlineRange(*range);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
@@ -233,17 +229,17 @@ HTMLEditor::SetInlinePropertyInternal(ns
         }
       }
     }
   }
   if (cancel) {
     return NS_OK;
   }
 
-  rv = rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 // Helper function for SetInlinePropertyOn*: is aNode a simple old <b>, <font>,
 // <span style="">, etc. that we can reuse instead of creating a new one?
@@ -1329,28 +1325,25 @@ HTMLEditor::RemoveInlineProperty(const n
 
   return RemoveInlinePropertyInternal(property, attribute);
 }
 
 nsresult
 HTMLEditor::RemoveInlinePropertyInternal(nsAtom* aProperty,
                                          nsAtom* aAttribute)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (NS_WARN_IF(!mRules)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   CommitComposition();
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (selection->IsCollapsed()) {
+  if (SelectionRefPtr()->IsCollapsed()) {
     // Manipulating text attributes on a collapsed selection only sets state
     // for the next text insertion
 
     // For links, aProperty uses "href", use "a" instead
     if (aProperty == nsGkAtoms::href || aProperty == nsGkAtoms::name) {
       aProperty = nsGkAtoms::a;
     }
 
@@ -1368,26 +1361,25 @@ HTMLEditor::RemoveInlinePropertyInternal
                                       nsIEditor::eNext);
   AutoSelectionRestorer restoreSelectionLater(*this);
   AutoTransactionsConserveSelection dontChangeMySelection(*this);
 
   bool cancel, handled;
   EditSubActionInfo subActionInfo(EditSubAction::eRemoveTextProperty);
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!cancel && !handled) {
     // Loop through the ranges in the selection
     // Since ranges might be modified by SplitStyleAboveRange, we need hold
     // current ranges
-    AutoRangeArray arrayOfRanges(selection);
+    AutoRangeArray arrayOfRanges(SelectionRefPtr());
     for (auto& range : arrayOfRanges.mRanges) {
       if (aProperty == nsGkAtoms::name) {
         // Promote range if it starts or end in a named anchor and we want to
         // remove named anchors
         rv = PromoteRangeIfStartsOrEndsInNamedAnchor(*range);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
@@ -1475,17 +1467,17 @@ HTMLEditor::RemoveInlinePropertyInternal
       }
     }
   }
 
   if (cancel) {
     return NS_OK;
   }
 
-  rv = rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::IncreaseFontSize()
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -143,28 +143,28 @@ TextEditRules::Init(TextEditor* aTextEdi
   if (NS_WARN_IF(!selection)) {
     return NS_ERROR_FAILURE;
   }
 
   InitFields();
 
   // We hold a non-refcounted reference back to our editor.
   mTextEditor = aTextEditor;
-  AutoSafeEditorData setData(*this, *mTextEditor, *selection);
+  AutoSafeEditorData setData(*this, *mTextEditor);
 
   // Put in a magic <br> if needed. This method handles null selection,
   // which should never happen anyway
   nsresult rv = CreateBogusNodeIfNeeded();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // If the selection hasn't been set up yet, set it up collapsed to the end of
   // our editable content.
-  if (!SelectionRef().RangeCount()) {
+  if (!SelectionRefPtr()->RangeCount()) {
     rv = TextEditorRef().CollapseSelectionToEnd();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   if (IsPlaintextEditor()) {
     // ensure trailing br node
@@ -250,22 +250,17 @@ TextEditRules::AfterEdit(EditSubAction a
   if (mLockRulesSniffing) {
     return NS_OK;
   }
 
   AutoLockRulesSniffing lockIt(this);
 
   MOZ_ASSERT(mActionNesting>0, "bad action nesting!");
   if (!--mActionNesting) {
-    Selection* selection = mTextEditor->GetSelection();
-    if (NS_WARN_IF(!selection)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    AutoSafeEditorData setData(*this, *mTextEditor, *selection);
+    AutoSafeEditorData setData(*this, *mTextEditor);
 
     nsresult rv =
       TextEditorRef().HandleInlineSpellCheck(aEditSubAction,
                                              mCachedSelectionNode,
                                              mCachedSelectionOffset,
                                              nullptr, 0, nullptr, 0);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -300,35 +295,31 @@ TextEditRules::AfterEdit(EditSubAction a
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
       "Failed to selection to after the text node in TextEditor");
   }
   return NS_OK;
 }
 
 nsresult
-TextEditRules::WillDoAction(Selection* aSelection,
-                            EditSubActionInfo& aInfo,
+TextEditRules::WillDoAction(EditSubActionInfo& aInfo,
                             bool* aCancel,
                             bool* aHandled)
 {
-  if (NS_WARN_IF(!aSelection)) {
-    return NS_ERROR_INVALID_ARG;
-  }
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
   MOZ_ASSERT(aCancel);
   MOZ_ASSERT(aHandled);
 
   *aCancel = false;
   *aHandled = false;
 
-  AutoSafeEditorData setData(*this, *mTextEditor, *aSelection);
+  AutoSafeEditorData setData(*this, *mTextEditor);
 
   // my kingdom for dynamic cast
   switch (aInfo.mEditSubAction) {
     case EditSubAction::eInsertParagraphSeparator:
       UndefineCaretBidiLevel();
       return WillInsertBreak(aCancel, aHandled, aInfo.maxLength);
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertTextComingFromIME:
@@ -358,28 +349,24 @@ TextEditRules::WillDoAction(Selection* a
       // into plaintext mail when doing quoting for reply!  doh!
       return WillInsert(aCancel);
     default:
       return NS_ERROR_FAILURE;
   }
 }
 
 nsresult
-TextEditRules::DidDoAction(Selection* aSelection,
-                           EditSubActionInfo& aInfo,
+TextEditRules::DidDoAction(EditSubActionInfo& aInfo,
                            nsresult aResult)
 {
-  if (NS_WARN_IF(!aSelection)) {
-    return NS_ERROR_INVALID_ARG;
-  }
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
-  AutoSafeEditorData setData(*this, *mTextEditor, *aSelection);
+  AutoSafeEditorData setData(*this, *mTextEditor);
 
   // don't let any txns in here move the selection around behind our back.
   // Note that this won't prevent explicit selection setting from working.
   AutoTransactionsConserveSelection dontChangeMySelection(TextEditorRef());
 
   switch (aInfo.mEditSubAction) {
     case EditSubAction::eDeleteSelectedContent:
       return DidDeleteSelection();
@@ -465,17 +452,17 @@ TextEditRules::WillInsertBreak(bool* aCa
     if (didTruncate) {
       *aCancel = true;
       return NS_OK;
     }
 
     *aCancel = false;
 
     // if the selection isn't collapsed, delete it.
-    if (!SelectionRef().IsCollapsed()) {
+    if (!SelectionRefPtr()->IsCollapsed()) {
       rv = TextEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
                                                       nsIEditor::eStrip);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
@@ -499,27 +486,27 @@ 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 (!SelectionRef().RangeCount()) {
+  if (!SelectionRefPtr()->RangeCount()) {
     TextEditorRef().CollapseSelectionToEnd();
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
   }
 
   // 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(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   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;
@@ -539,34 +526,34 @@ TextEditRules::CollapseSelectionToTraili
     return NS_OK;
   }
 
   EditorRawDOMPoint afterStartContainer(selectionStartPoint.GetContainer());
   if (NS_WARN_IF(!afterStartContainer.AdvanceOffset())) {
     return NS_ERROR_FAILURE;
   }
   ErrorResult error;
-  SelectionRef().Collapse(afterStartContainer, error);
+  SelectionRefPtr()->Collapse(afterStartContainer, error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
 already_AddRefed<nsINode>
 TextEditRules::GetTextNodeAroundSelectionStartContainer()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   EditorRawDOMPoint selectionStartPoint(
-                      EditorBase::GetStartPoint(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return nullptr;
   }
   if (selectionStartPoint.IsInTextNode()) {
     nsCOMPtr<nsINode> node = selectionStartPoint.GetContainer();
     return node.forget();
   }
   // This should be the root node, walk the tree looking for text nodes.
@@ -718,23 +705,23 @@ TextEditRules::WillInsertText(EditSubAct
     return NS_OK;
   }
 
   uint32_t start = 0;
   uint32_t end = 0;
 
   // handle password field docs
   if (IsPasswordEditor()) {
-    nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
+    nsContentUtils::GetSelectionInTextControl(SelectionRefPtr(),
                                               TextEditorRef().GetRoot(),
                                               start, end);
   }
 
   // if the selection isn't collapsed, delete it.
-  if (!SelectionRef().IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     rv = TextEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
                                                     nsIEditor::eStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
@@ -797,17 +784,17 @@ TextEditRules::WillInsertText(EditSubAct
       mTimer->InitWithCallback(this, LookAndFeel::GetPasswordMaskDelay(),
                                nsITimer::TYPE_ONE_SHOT);
     } else {
       FillBufWithPWChars(outString, outString->Length());
     }
   }
 
   // get the (collapsed) selection location
-  nsRange* firstRange = SelectionRef().GetRangeAt(0);
+  nsRange* firstRange = SelectionRefPtr()->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;
   }
 
@@ -863,25 +850,25 @@ TextEditRules::WillInsertText(EditSubAct
     }
 
     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;
       IgnoredErrorResult error;
-      SelectionRef().SetInterlinePosition(endsWithLF, error);
+      SelectionRefPtr()->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");
       error = IgnoredErrorResult();
-      SelectionRef().Collapse(pointAfterStringInserted, error);
+      SelectionRefPtr()->Collapse(pointAfterStringInserted, error);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(!error.Failed(),
         "Failed to collapse selection after inserting string");
     }
   }
   ASSERT_PASSWORD_LENGTHS_EQUAL()
@@ -1069,29 +1056,29 @@ TextEditRules::DeleteSelectionWithTransa
   MOZ_ASSERT(aHandled);
 
   // 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(&SelectionRef());
-  AutoHideSelectionChanges hideSelection(&SelectionRef());
+  SelectionBatcher selectionBatcher(SelectionRefPtr());
+  AutoHideSelectionChanges hideSelection(SelectionRefPtr());
   nsAutoScriptBlocker scriptBlocker;
 
   if (IsPasswordEditor()) {
     nsresult rv = TextEditorRef().ExtendSelectionForDelete(&aCollapsedAction);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // manage the password buffer
     uint32_t start, end;
-    nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
+    nsContentUtils::GetSelectionInTextControl(SelectionRefPtr(),
                                               TextEditorRef().GetRoot(),
                                               start, end);
 
     if (LookAndFeel::GetEchoPassword()) {
       rv = HideLastPasswordInputInternal();
       mLastStart = start;
       mLastLength = 0;
       if (mTimer) {
@@ -1115,22 +1102,22 @@ TextEditRules::DeleteSelectionWithTransa
       // Otherwise nothing to do for this collapsed selection.
     }
     // Extended selection.
     else {
       mPasswordText.Cut(start, end-start);
     }
   } else {
     EditorRawDOMPoint selectionStartPoint(
-                        EditorBase::GetStartPoint(SelectionRef()));
+                        EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
 
-    if (!SelectionRef().IsCollapsed()) {
+    if (!SelectionRefPtr()->IsCollapsed()) {
       return NS_OK;
     }
 
     // Test for distance between caret and text that will be deleted
     nsresult rv =
       CheckBidiLevelForDeletion(selectionStartPoint, aCollapsedAction, aCancel);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -1161,17 +1148,17 @@ TextEditRules::DeleteSelectionWithTransa
 }
 
 nsresult
 TextEditRules::DidDeleteSelection()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   EditorRawDOMPoint selectionStartPoint(
-                      EditorBase::GetStartPoint(SelectionRef()));
+                      EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Delete empty text nodes at selection.
   if (selectionStartPoint.IsInTextNode() &&
       !selectionStartPoint.GetContainer()->Length()) {
     nsresult rv =
@@ -1186,17 +1173,17 @@ TextEditRules::DidDeleteSelection()
   }
 
   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;
-  SelectionRef().SetInterlinePosition(true, err);
+  SelectionRefPtr()->SetInterlinePosition(true, err);
   NS_WARNING_ASSERTION(!err.Failed(), "Failed to set interline position");
   return err.StealNSResult();
 }
 
 nsresult
 TextEditRules::WillUndo(bool* aCancel,
                         bool* aHandled)
 {
@@ -1570,17 +1557,17 @@ TextEditRules::CreateBogusNodeIfNeeded()
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Set selection.
   IgnoredErrorResult error;
-  SelectionRef().Collapse(EditorRawDOMPoint(rootElement, 0), error);
+  SelectionRefPtr()->Collapse(EditorRawDOMPoint(rootElement, 0), error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(!error.Failed(),
     "Failed to collapse selection at start of the root element");
   return NS_OK;
 }
 
@@ -1620,17 +1607,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(&SelectionRef(),
+    nsContentUtils::GetSelectionInTextControl(SelectionRefPtr(),
                                               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;
@@ -1710,24 +1697,23 @@ TextEditRules::Notify(nsITimer* aTimer)
   nsresult rv = textEditor->HideLastPasswordInput();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
-TextEditRules::HideLastPasswordInput(Selection& aSelection)
+TextEditRules::HideLastPasswordInput()
 {
+  MOZ_ASSERT(mTextEditor);
   MOZ_ASSERT(IsPasswordEditor());
 
-  AutoSafeEditorData setData(*this, *mTextEditor, aSelection);
+  AutoSafeEditorData setData(*this, *mTextEditor);
 
-  // Check whether our text editor's password flag was changed before this
-  // "hide password character" timer actually fires.
   nsresult rv = HideLastPasswordInputInternal();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   ASSERT_PASSWORD_LENGTHS_EQUAL();
   mLastLength = 0;
   return NS_OK;
 }
@@ -1748,39 +1734,39 @@ TextEditRules::HideLastPasswordInputInte
     // Special case, we're trying to replace a range that no longer exists
     return NS_OK;
   }
 
   nsAutoString hiddenText;
   FillBufWithPWChars(&hiddenText, mLastLength);
 
   uint32_t start, end;
-  nsContentUtils::GetSelectionInTextControl(&SelectionRef(),
+  nsContentUtils::GetSelectionInTextControl(SelectionRefPtr(),
                                             TextEditorRef().GetRoot(),
                                             start, end);
 
   nsCOMPtr<nsINode> selNode = GetTextNodeAroundSelectionStartContainer();
   if (NS_WARN_IF(!selNode)) {
     return NS_OK;
   }
 
   selNode->GetAsText()->ReplaceData(mLastStart, mLastLength, hiddenText,
                                     IgnoreErrors());
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   // XXXbz Selection::Collapse/Extend take int32_t, but there are tons of
   // callsites... Converting all that is a battle for another day.
-  DebugOnly<nsresult> rv = SelectionRef().Collapse(selNode, start);
+  DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(selNode, start);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
   if (start != end) {
-    rv = SelectionRef().Extend(selNode, end);
+    rv = SelectionRefPtr()->Extend(selNode, end);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to extend selection");
   }
   return NS_OK;
 }
 
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -84,22 +84,20 @@ public:
   virtual nsresult Init(TextEditor* aTextEditor);
   virtual nsresult SetInitialValue(const nsAString& aValue);
   virtual nsresult DetachEditor();
   virtual nsresult BeforeEdit(EditSubAction aEditSubAction,
                               nsIEditor::EDirection aDirection);
   virtual nsresult AfterEdit(EditSubAction aEditSubAction,
                              nsIEditor::EDirection aDirection);
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
-  virtual nsresult WillDoAction(Selection* aSelection,
-                                EditSubActionInfo& aInfo,
+  virtual nsresult WillDoAction(EditSubActionInfo& aInfo,
                                 bool* aCancel,
                                 bool* aHandled);
-  virtual nsresult DidDoAction(Selection* aSelection,
-                               EditSubActionInfo& aInfo,
+  virtual nsresult DidDoAction(EditSubActionInfo& aInfo,
                                nsresult aResult);
 
   /**
    * Return false if the editor has non-empty text nodes or non-text
    * nodes.  Otherwise, i.e., there is no meaningful content,
    * return true.
    */
   virtual bool DocumentIsEmpty();
@@ -145,21 +143,21 @@ public:
   static void FillBufWithPWChars(nsAString* aOutString, int32_t aLength);
 
   bool HasBogusNode()
   {
     return !!mBogusNode;
   }
 
   /**
-   * HideLastPasswordInput() is called while Nodify() is calling
+   * HideLastPasswordInput() is called when Nodify() calls
    * TextEditor::HideLastPasswordInput().  It guarantees that there is a
    * AutoEditActionDataSetter instance in the editor.
    */
-  MOZ_CAN_RUN_SCRIPT nsresult HideLastPasswordInput(Selection& aSelection);
+  MOZ_CAN_RUN_SCRIPT nsresult HideLastPasswordInput();
 
 protected:
 
   void InitFields();
 
   // TextEditRules implementation methods
 
   /**
@@ -411,31 +409,29 @@ protected:
    * handling an edit action.  When this is created, its pointer is set to
    * the mSafeData, and this guarantees the lifetime of grabbing objects
    * until it's destroyed.
    */
   class MOZ_STACK_CLASS AutoSafeEditorData
   {
   public:
     AutoSafeEditorData(TextEditRules& aTextEditRules,
-                       TextEditor& aTextEditor,
-                       Selection& aSelection)
+                       TextEditor& aTextEditor)
       : mTextEditRules(aTextEditRules)
       , mHTMLEditor(nullptr)
     {
       // mTextEditRules may have AutoSafeEditorData instance since in some
       // cases. E.g., while public methods of *EditRules are called, it
       // calls attaching editor's method, then, editor will call public
       // methods of *EditRules again.
       if (mTextEditRules.mData) {
         return;
       }
       mTextEditor = &aTextEditor;
       mHTMLEditor = aTextEditor.AsHTMLEditor();
-      mSelection = &aSelection;
       mTextEditRules.mData = this;
     }
 
     ~AutoSafeEditorData()
     {
       if (mTextEditRules.mData != this) {
         return;
       }
@@ -443,39 +439,40 @@ protected:
     }
 
     TextEditor& TextEditorRef() const { return *mTextEditor; }
     HTMLEditor& HTMLEditorRef() const
     {
       MOZ_ASSERT(mHTMLEditor);
       return *mHTMLEditor;
     }
-    Selection& SelectionRef() const { return *mSelection; }
 
   private:
     // This class should be created by public methods TextEditRules and
     // HTMLEditRules and in the stack.  So, the lifetime of this should
     // be guaranteed the callers of the public methods.
     TextEditRules& MOZ_NON_OWNING_REF mTextEditRules;
     RefPtr<TextEditor> mTextEditor;
     // Shortcut for HTMLEditorRef().  So, not necessary to use RefPtr.
     HTMLEditor* MOZ_NON_OWNING_REF mHTMLEditor;
-    RefPtr<Selection> mSelection;
   };
   AutoSafeEditorData* mData;
 
   TextEditor& TextEditorRef() const
   {
     MOZ_ASSERT(mData);
     return mData->TextEditorRef();
   }
-  Selection& SelectionRef() const
+  // SelectionRefPtr() won't return nullptr unless editor instance accidentally
+  // ignored result of AutoEditActionDataSetter::CanHandle() and keep handling
+  // edit action.
+  const RefPtr<Selection>& SelectionRefPtr() const
   {
     MOZ_ASSERT(mData);
-    return mData->SelectionRef();
+    return TextEditorRef().SelectionRefPtr();
   }
   bool CanHandleEditAction() const
   {
     if (!mTextEditor) {
       return false;
     }
     if (mTextEditor->Destroyed()) {
       return false;
--- a/editor/libeditor/TextEditRulesBidi.cpp
+++ b/editor/libeditor/TextEditRulesBidi.cpp
@@ -45,17 +45,18 @@ TextEditRules::CheckBidiLevelForDeletion
   if (!presContext->BidiEnabled()) {
     return NS_OK;
   }
 
   if (!aSelectionPoint.GetContainerAsContent()) {
     return NS_ERROR_FAILURE;
   }
 
-  RefPtr<nsFrameSelection> frameSelection = SelectionRef().GetFrameSelection();
+  RefPtr<nsFrameSelection> frameSelection =
+    SelectionRefPtr()->GetFrameSelection();
   if (NS_WARN_IF(!frameSelection)) {
     return NS_ERROR_FAILURE;
   }
 
   nsPrevNextBidiLevels levels = frameSelection->
     GetPrevNextBidiLevels(aSelectionPoint.GetContainerAsContent(),
                           aSelectionPoint.Offset(), true);
 
@@ -91,15 +92,16 @@ TextEditRules::UndefineCaretBidiLevel()
   /**
    * After inserting text the caret Bidi level must be set to the level of the
    * inserted text.This is difficult, because we cannot know what the level is
    * until after the Bidi algorithm is applied to the whole paragraph.
    *
    * So we set the caret Bidi level to UNDEFINED here, and the caret code will
    * set it correctly later
    */
-  RefPtr<nsFrameSelection> frameSelection = SelectionRef().GetFrameSelection();
+  RefPtr<nsFrameSelection> frameSelection =
+    SelectionRefPtr()->GetFrameSelection();
   if (frameSelection) {
     frameSelection->UndefineCaretBidiLevel();
   }
 }
 
 } // namespace mozilla
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -331,16 +331,18 @@ TextEditor::UpdateMetaCharset(nsIDocumen
     return NS_SUCCEEDED(rv);
   }
   return false;
 }
 
 nsresult
 TextEditor::InitRules()
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (!mRules) {
     // instantiate the rules for this text editor
     mRules = new TextEditRules();
   }
   return mRules->Init(this);
 }
 
 nsresult
@@ -718,49 +720,45 @@ TextEditor::DeleteSelectionAsAction(EDir
   }
   return NS_OK;
 }
 
 nsresult
 TextEditor::DeleteSelectionAsSubAction(EDirection aDirection,
                                        EStripWrappers aStripWrappers)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+  MOZ_ASSERT(mPlaceholderBatch);
+
   MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
-  MOZ_ASSERT(mPlaceholderBatch);
 
   if (!mRules) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
-  // pre-process
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   // If there is an existing selection when an extended delete is requested,
   //  platforms that use "caret-style" caret positioning collapse the
   //  selection to the  start and then create a new selection.
   //  Platforms that use "selection-style" caret positioning just delete the
   //  existing selection without extending it.
-  if (!selection->IsCollapsed()) {
+  if (!SelectionRefPtr()->IsCollapsed()) {
     switch (aDirection) {
       case eNextWord:
       case ePreviousWord:
       case eToBeginningOfLine:
       case eToEndOfLine: {
         if (mCaretStyle != 1) {
           aDirection = eNone;
           break;
         }
         ErrorResult error;
-        selection->CollapseToStart(error);
+        SelectionRefPtr()->CollapseToStart(error);
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
         break;
       }
       default:
         break;
     }
@@ -769,46 +767,44 @@ TextEditor::DeleteSelectionAsSubAction(E
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this,
                                       EditSubAction::eDeleteSelectedContent,
                                       aDirection);
   EditSubActionInfo subActionInfo(EditSubAction::eDeleteSelectedContent);
   subActionInfo.collapsedAction = aDirection;
   subActionInfo.stripWrappers = aStripWrappers;
   bool cancel, handled;
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!cancel && !handled) {
     rv = DeleteSelectionWithTransaction(aDirection, aStripWrappers);
   }
   if (!cancel) {
     // post-process
-    rv = rules->DidDoAction(selection, subActionInfo, rv);
+    rv = rules->DidDoAction(subActionInfo, rv);
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "TextEditRules::DidDoAction() failed");
   }
   return rv;
 }
 
 nsresult
 TextEditor::DeleteSelectionWithTransaction(EDirection aDirection,
                                            EStripWrappers aStripWrappers)
 {
-  MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
+  MOZ_ASSERT(IsEditActionDataAvailable());
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
+  MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
 
   RefPtr<EditAggregateTransaction> deleteSelectionTransaction;
   nsCOMPtr<nsINode> deleteNode;
   int32_t deleteCharOffset = 0, deleteCharLength = 0;
-  if (!selection->IsCollapsed() || aDirection != eNone) {
+  if (!SelectionRefPtr()->IsCollapsed() || aDirection != eNone) {
     deleteSelectionTransaction =
       CreateTxnForDeleteSelection(aDirection,
                                   getter_AddRefs(deleteNode),
                                   &deleteCharOffset,
                                   &deleteCharLength);
     if (NS_WARN_IF(!deleteSelectionTransaction)) {
       return NS_ERROR_FAILURE;
     }
@@ -819,59 +815,59 @@ TextEditor::DeleteSelectionWithTransacti
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this,
                                       EditSubAction::eDeleteSelectedContent,
                                       aDirection);
 
   if (mRules && mRules->AsHTMLEditRules()) {
     if (!deleteNode) {
       RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->WillDeleteSelection(*selection);
+      htmlEditRules->WillDeleteSelection();
     } else if (!deleteCharData) {
       RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-      htmlEditRules->WillDeleteNode(*selection, *deleteNode);
+      htmlEditRules->WillDeleteNode(*deleteNode);
     }
   }
 
   // Notify nsIEditActionListener::WillDelete[Selection|Text]
   if (!mActionListeners.IsEmpty()) {
     if (!deleteNode) {
       AutoActionListenerArray listeners(mActionListeners);
       for (auto& listener : listeners) {
-        listener->WillDeleteSelection(selection);
+        listener->WillDeleteSelection(SelectionRefPtr());
       }
     } else if (deleteCharData) {
       AutoActionListenerArray listeners(mActionListeners);
       for (auto& listener : listeners) {
         listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
       }
     }
   }
 
   // Delete the specified amount
   nsresult rv = DoTransactionInternal(deleteSelectionTransaction);
 
   if (mRules && mRules->AsHTMLEditRules() && deleteCharData) {
     MOZ_ASSERT(deleteNode);
     RefPtr<HTMLEditRules> htmlEditRules = mRules->AsHTMLEditRules();
-    htmlEditRules->DidDeleteText(*selection, *deleteNode, deleteCharOffset, 1);
+    htmlEditRules->DidDeleteText(*deleteNode, deleteCharOffset, 1);
   }
 
   if (mTextServicesDocument && NS_SUCCEEDED(rv) &&
       deleteNode && !deleteCharData) {
     RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
     textServicesDocument->DidDeleteNode(deleteNode);
   }
 
   // Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
   {
     AutoActionListenerArray listeners(mActionListeners);
     if (!deleteNode) {
       for (auto& listener : mActionListeners) {
-        listener->DidDeleteSelection(selection);
+        listener->DidDeleteSelection(SelectionRefPtr());
       }
     } else if (deleteCharData) {
       for (auto& listener : mActionListeners) {
         listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
       }
     } else {
       for (auto& listener : mActionListeners) {
         listener->DidDeleteNode(deleteNode, rv);
@@ -1027,60 +1023,55 @@ TextEditor::InsertTextAsAction(const nsA
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
 TextEditor::InsertTextAsSubAction(const nsAString& aStringToInsert)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(mPlaceholderBatch);
 
   if (!mRules) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // Protect the edit rules object from dying.
   RefPtr<TextEditRules> rules(mRules);
 
   EditSubAction editSubAction =
     ShouldHandleIMEComposition() ?
       EditSubAction::eInsertTextComingFromIME : EditSubAction::eInsertText;
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, editSubAction, nsIEditor::eNext);
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   nsAutoString resultString;
   // XXX can we trust instring to outlive subActionInfo,
   // XXX and subActionInfo not to refer to instring in its dtor?
   //nsAutoString instring(aStringToInsert);
   EditSubActionInfo subActionInfo(editSubAction);
   subActionInfo.inString = &aStringToInsert;
   subActionInfo.outString = &resultString;
   subActionInfo.maxLength = mMaxTextLength;
 
   bool cancel, handled;
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!cancel && !handled) {
     // we rely on rules code for now - no default implementation
   }
   if (cancel) {
     return NS_OK;
   }
   // post-process
-  rv = rules->DidDoAction(selection, subActionInfo, NS_OK);
+  rv = rules->DidDoAction(subActionInfo, NS_OK);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextEditor::InsertLineBreak()
@@ -1093,49 +1084,46 @@ TextEditor::InsertLineBreak()
   }
 
   return InsertParagraphSeparatorAsAction();
 }
 
 nsresult
 TextEditor::InsertParagraphSeparatorAsAction()
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   if (!mRules) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this,
                                       EditSubAction::eInsertParagraphSeparator,
                                       nsIEditor::eNext);
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   EditSubActionInfo subActionInfo(EditSubAction::eInsertParagraphSeparator);
   subActionInfo.maxLength = mMaxTextLength;
   bool cancel, handled;
-  nsresult rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     // XXX DidDoAction() won't be called when WillDoAction() returns error.
     //     Perhaps, we should move the code between WillDoAction() and
     //     DidDoAction() to a new method and guarantee that DidDoAction() is
     //     always called after WillDoAction().
     return rv;
   }
 
   if (!cancel && !handled) {
     // get the (collapsed) selection location
-    nsRange* firstRange = selection->GetRangeAt(0);
+    nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorRawDOMPoint pointToInsert(firstRange->StartRef());
     if (NS_WARN_IF(!pointToInsert.IsSet())) {
       return NS_ERROR_FAILURE;
     }
@@ -1164,34 +1152,36 @@ TextEditor::InsertParagraphSeparatorAsAc
     if (NS_WARN_IF(!pointAfterInsertedLineBreak.IsSet())) {
       rv = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called
     }
     if (NS_SUCCEEDED(rv)) {
       // set the selection to the correct location
       MOZ_ASSERT(!pointAfterInsertedLineBreak.GetChild(),
         "After inserting text into a text node, pointAfterInsertedLineBreak."
         "GetChild() should be nullptr");
-      rv = selection->Collapse(pointAfterInsertedLineBreak);
+      rv = SelectionRefPtr()->Collapse(pointAfterInsertedLineBreak);
       if (NS_SUCCEEDED(rv)) {
         // see if we're at the end of the editor range
-        EditorRawDOMPoint endPoint = EditorBase::GetEndPoint(*selection);
+        EditorRawDOMPoint endPoint(EditorBase::GetEndPoint(*SelectionRefPtr()));
         if (endPoint == pointAfterInsertedLineBreak) {
           // 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.
-          selection->SetInterlinePosition(true, IgnoreErrors());
+          SelectionRefPtr()->SetInterlinePosition(true, IgnoreErrors());
         }
       }
     }
   }
 
   if (!cancel) {
     // post-process, always called if WillInsertBreak didn't return cancel==true
-    rv = rules->DidDoAction(selection, subActionInfo, rv);
+    rv = rules->DidDoAction(subActionInfo, rv);
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "TextEditRules::DidDoAction() failed");
   }
   return rv;
 }
 
 nsresult
 TextEditor::SetText(const nsAString& aString)
 {
   MOZ_ASSERT(aString.FindChar(static_cast<char16_t>('\r')) == kNotFound);
@@ -1259,42 +1249,37 @@ TextEditor::ReplaceTextAsAction(const ns
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
 TextEditor::SetTextAsSubAction(const nsAString& aString)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(mPlaceholderBatch);
 
   if (NS_WARN_IF(!mRules)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eSetText,
                                       nsIEditor::eNext);
 
-  // pre-process
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_NULL_POINTER;
-  }
   EditSubActionInfo subActionInfo(EditSubAction::eSetText);
   subActionInfo.inString = &aString;
   subActionInfo.maxLength = mMaxTextLength;
 
   bool cancel;
   bool handled;
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (cancel) {
     return NS_OK;
   }
   if (!handled) {
     // Note that do not notify selectionchange caused by selecting all text
@@ -1306,28 +1291,32 @@ TextEditor::SetTextAsSubAction(const nsA
     // but TextEditor::SelectEntireDocument doesn't select that BR node.
     if (rules->DocumentIsEmpty()) {
       // if it's empty, don't select entire doc - that would select
       // the bogus node
       Element* rootElement = GetRoot();
       if (NS_WARN_IF(!rootElement)) {
         return NS_ERROR_FAILURE;
       }
-      rv = selection->Collapse(rootElement, 0);
+      rv = SelectionRefPtr()->Collapse(rootElement, 0);
     } else {
       rv = EditorBase::SelectEntireDocument();
     }
     if (NS_SUCCEEDED(rv)) {
       rv = ReplaceSelectionAsSubAction(aString);
       NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
         "Failed to replace selection with new string");
     }
   }
   // post-process
-  return rules->DidDoAction(selection, subActionInfo, rv);
+  rv = rules->DidDoAction(subActionInfo, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 TextEditor::ReplaceSelectionAsSubAction(const nsAString& aString)
 {
   if (aString.IsEmpty()) {
     nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1725,28 +1714,29 @@ TextEditor::Undo(uint32_t aCount)
   nsresult rv;
   {
     AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                         *this, EditSubAction::eUndo,
                                         nsIEditor::eNone);
 
     EditSubActionInfo subActionInfo(EditSubAction::eUndo);
     bool cancel, handled;
-    rv = rules->WillDoAction(SelectionRefPtr(), subActionInfo,
-                             &cancel, &handled);
+    rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
     if (!cancel && NS_SUCCEEDED(rv)) {
       RefPtr<TransactionManager> transactionManager(mTransactionManager);
       for (uint32_t i = 0; i < aCount; ++i) {
         rv = transactionManager->Undo();
         if (NS_WARN_IF(NS_FAILED(rv))) {
           break;
         }
         DoAfterUndoTransaction();
       }
-      rv = rules->DidDoAction(SelectionRefPtr(), subActionInfo, rv);
+      rv = rules->DidDoAction(subActionInfo, rv);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                           "TextEditRules::DidDoAction() failed");
     }
   }
 
   NotifyEditorObservers(eNotifyEditorObserversOfEnd);
   return rv;
 }
 
 NS_IMETHODIMP
@@ -1785,28 +1775,29 @@ TextEditor::Redo(uint32_t aCount)
   nsresult rv;
   {
     AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                         *this, EditSubAction::eRedo,
                                         nsIEditor::eNone);
 
     EditSubActionInfo subActionInfo(EditSubAction::eRedo);
     bool cancel, handled;
-    rv = rules->WillDoAction(SelectionRefPtr(), subActionInfo,
-                             &cancel, &handled);
+    rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
     if (!cancel && NS_SUCCEEDED(rv)) {
       RefPtr<TransactionManager> transactionManager(mTransactionManager);
       for (uint32_t i = 0; i < aCount; ++i) {
         nsresult rv = transactionManager->Redo();
         if (NS_WARN_IF(NS_FAILED(rv))) {
           break;
         }
         DoAfterRedoTransaction();
       }
-      rv = rules->DidDoAction(SelectionRefPtr(), subActionInfo, rv);
+      rv = rules->DidDoAction(subActionInfo, rv);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                           "TextEditRules::DidDoAction() failed");
     }
   }
 
   NotifyEditorObservers(eNotifyEditorObserversOfEnd);
   return rv;
 }
 
 bool
@@ -2025,30 +2016,28 @@ TextEditor::OutputToString(const nsAStri
                               aOutputString);
 }
 
 nsresult
 TextEditor::ComputeValueInternal(const nsAString& aFormatType,
                                  uint32_t aDocumentEncoderFlags,
                                  nsAString& aOutputString) const
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
   EditSubActionInfo subActionInfo(EditSubAction::eComputeTextToOutput);
   subActionInfo.outString = &aOutputString;
   subActionInfo.flags = aDocumentEncoderFlags;
   subActionInfo.outputFormat = &aFormatType;
-  Selection* selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
+
   bool cancel, handled;
-  nsresult rv =
-    rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (cancel || NS_FAILED(rv)) {
     return rv;
   }
   if (handled) {
     // This case will get triggered by password fields or single text node only.
     return rv;
   }
 
@@ -2060,17 +2049,21 @@ TextEditor::ComputeValueInternal(const n
 
   nsCOMPtr<nsIDocumentEncoder> encoder =
     GetAndInitDocEncoder(aFormatType, aDocumentEncoderFlags, charset);
   if (NS_WARN_IF(!encoder)) {
     return NS_ERROR_FAILURE;
   }
 
   // XXX Why don't we call TextEditRules::DidDoAction() here?
-  return encoder->EncodeToString(aOutputString);
+  rv = encoder->EncodeToString(aOutputString);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 TextEditor::PasteAsQuotationAsAction(int32_t aClipboardType,
                                      bool aDispatchPasteEvent)
 {
   MOZ_ASSERT(aClipboardType == nsIClipboard::kGlobalClipboard ||
              aClipboardType == nsIClipboard::kSelectionClipboard);
@@ -2131,47 +2124,44 @@ TextEditor::PasteAsQuotationAsAction(int
     }
   }
   return NS_OK;
 }
 
 nsresult
 TextEditor::InsertWithQuotationsAsSubAction(const nsAString& aQuotedText)
 {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
   // Let the citer quote it for us:
   nsString quotedStuff;
   nsresult rv = InternetCiter::GetCiteString(aQuotedText, quotedStuff);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // It's best to put a blank line after the quoted text so that mails
   // written without thinking won't be so ugly.
   if (!aQuotedText.IsEmpty() && (aQuotedText.Last() != char16_t('\n'))) {
     quotedStuff.Append(char16_t('\n'));
   }
 
-  RefPtr<Selection> selection = GetSelection();
-  if (NS_WARN_IF(!selection)) {
-    return NS_ERROR_FAILURE;
-  }
-
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertText,
                                       nsIEditor::eNext);
 
   // XXX This WillDoAction() usage is hacky.  If it returns as handled,
   //     this method cannot work as expected.  So, this should have specific
   //     sub-action rather than using eInsertElement.
   EditSubActionInfo subActionInfo(EditSubAction::eInsertElement);
   bool cancel, handled;
-  rv = rules->WillDoAction(selection, subActionInfo, &cancel, &handled);
+  rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (cancel) {
     return NS_OK; // Rules canceled the operation.
   }
   MOZ_ASSERT(!handled, "WillDoAction() shouldn't handle in this case");
   if (!handled) {
@@ -2340,16 +2330,16 @@ TextEditor::HideLastPasswordInput()
   MOZ_ASSERT(!IsEditActionDataAvailable());
 
   AutoEditActionDataSetter editActionData(*this, EditAction::eHidePassword);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   RefPtr<TextEditRules> rules(mRules);
-  nsresult rv = rules->HideLastPasswordInput(*SelectionRefPtr());
+  nsresult rv = rules->HideLastPasswordInput();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 } // namespace mozilla