Backed out 3 changesets (bug 1533293) for causing Bug 1536595 a=backout
authorNoemi Erli <nerli@mozilla.com>
Wed, 20 Mar 2019 13:29:17 +0200
changeset 465170 25398e555020fef80c7b2a06a0d4c667e861cd6f
parent 465169 708979f9c3f33c77fb2e9106054b215c77044a04
child 465171 235af3330b73446fe4349f2b04828c71848430da
push id35733
push usernerli@mozilla.com
push dateWed, 20 Mar 2019 11:29:39 +0000
treeherdermozilla-central@25398e555020 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1533293, 1536595
milestone68.0a1
backs outd011dfe8368374923cb69a0ab510d6814cbf3ab1
e536f6e123d8f54d5bf165e5e78da13c71a901af
19cff61f4fed314bb596c9b82483d1bc88a246fd
first release with
nightly linux32
25398e555020 / 68.0a1 / 20190320112939 / files
nightly linux64
25398e555020 / 68.0a1 / 20190320112939 / files
nightly mac
25398e555020 / 68.0a1 / 20190320112939 / files
nightly win32
25398e555020 / 68.0a1 / 20190320112939 / files
nightly win64
25398e555020 / 68.0a1 / 20190320112939 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1533293) for causing Bug 1536595 a=backout Backed out changeset d011dfe83683 (bug 1533293) Backed out changeset e536f6e123d8 (bug 1533293) Backed out changeset 19cff61f4fed (bug 1533293)
dom/base/Selection.cpp
dom/base/Selection.h
dom/events/ContentEventHandler.cpp
dom/events/ContentEventHandler.h
dom/events/EventStateManager.cpp
dom/events/IMEStateManager.h
dom/events/TextComposition.h
dom/html/nsTextEditorState.cpp
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/EditorCommands.cpp
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLEditorEventListener.cpp
editor/libeditor/HTMLTableEditor.cpp
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditor.cpp
editor/libeditor/TextEditor.h
editor/libeditor/tests/test_bug430392.html
editor/nsIEditor.idl
editor/nsIEditorMailSupport.idl
editor/nsIEditorSpellCheck.idl
editor/nsIHTMLEditor.idl
editor/nsITableEditor.idl
editor/spellchecker/EditorSpellCheck.cpp
editor/spellchecker/TextServicesDocument.cpp
editor/spellchecker/TextServicesDocument.h
editor/spellchecker/nsIInlineSpellChecker.idl
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozSpellChecker.cpp
extensions/spellcheck/src/mozSpellChecker.h
testing/web-platform/mozilla/meta/focus/Selection_selectAllChildren.html.ini
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -2758,22 +2758,24 @@ void Selection::SelectAllChildren(nsINod
   if (!HasSameRoot(aNode)) {
     // Return with no error
     return;
   }
 
   if (mFrameSelection) {
     mFrameSelection->PostReason(nsISelectionListener::SELECTALL_REASON);
   }
-
-  // Chrome moves focus when aNode is outside of active editing host.
-  // So, we don't need to respect the limiter with this method.
-  SetStartAndEndInternal(InLimiter::eNo, RawRangeBoundary(&aNode, 0),
-                         RawRangeBoundary(&aNode, aNode.GetChildCount()),
-                         eDirNext, aRv);
+  SelectionBatcher batch(this);
+
+  Collapse(aNode, 0, aRv);
+  if (aRv.Failed()) {
+    return;
+  }
+
+  Extend(aNode, aNode.GetChildCount(), aRv);
 }
 
 bool Selection::ContainsNode(nsINode& aNode, bool aAllowPartial,
                              ErrorResult& aRv) {
   nsresult rv;
   if (mRanges.Length() == 0) {
     return false;
   }
@@ -3383,96 +3385,53 @@ void Selection::Modify(const nsAString& 
 void Selection::SetBaseAndExtentJS(nsINode& aAnchorNode, uint32_t aAnchorOffset,
                                    nsINode& aFocusNode, uint32_t aFocusOffset,
                                    ErrorResult& aRv) {
   AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
   mCalledByJS = true;
   SetBaseAndExtent(aAnchorNode, aAnchorOffset, aFocusNode, aFocusOffset, aRv);
 }
 
-void Selection::SetBaseAndExtentInternal(InLimiter aInLimiter,
-                                         const RawRangeBoundary& aAnchorRef,
-                                         const RawRangeBoundary& aFocusRef,
-                                         ErrorResult& aRv) {
+void Selection::SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset,
+                                 nsINode& aFocusNode, uint32_t aFocusOffset,
+                                 ErrorResult& aRv) {
   if (!mFrameSelection) {
     return;
   }
 
-  if (NS_WARN_IF(!aAnchorRef.IsSet()) || NS_WARN_IF(!aFocusRef.IsSet())) {
-    aRv.Throw(NS_ERROR_INVALID_ARG);
-    return;
-  }
-
-  if (!HasSameRoot(*aAnchorRef.Container()) ||
-      !HasSameRoot(*aFocusRef.Container())) {
+  if (!HasSameRoot(aAnchorNode) || !HasSameRoot(aFocusNode)) {
     // Return with no error
     return;
   }
 
-  // Prevent "selectionchange" event temporarily because it should be fired
-  // after we set the direction.
-  // XXX If they are disconnected, shouldn't we return error before allocating
-  //     new nsRange instance?
   SelectionBatcher batch(this);
-  if (nsContentUtils::ComparePoints(aAnchorRef, aFocusRef) <= 0) {
-    SetStartAndEndInternal(aInLimiter, aAnchorRef, aFocusRef, eDirNext, aRv);
-    return;
-  }
-
-  SetStartAndEndInternal(aInLimiter, aFocusRef, aAnchorRef, eDirPrevious, aRv);
-}
-
-void Selection::SetStartAndEndInternal(InLimiter aInLimiter,
-                                       const RawRangeBoundary& aStartRef,
-                                       const RawRangeBoundary& aEndRef,
-                                       nsDirection aDirection,
-                                       ErrorResult& aRv) {
-  if (NS_WARN_IF(!aStartRef.IsSet()) || NS_WARN_IF(!aEndRef.IsSet())) {
-    aRv.Throw(NS_ERROR_INVALID_ARG);
-    return;
-  }
-
-  // Don't fire "selectionchange" event until everything done.
-  SelectionBatcher batch(this);
-
-  if (aInLimiter == InLimiter::eYes) {
-    if (!IsValidSelectionPoint(mFrameSelection, aStartRef.Container())) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-    if (aStartRef.Container() != aEndRef.Container() &&
-        !IsValidSelectionPoint(mFrameSelection, aEndRef.Container())) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-  }
-
-  // If we're not called by JS, we can remove all ranges first.  Then, we
-  // may be able to reuse one of current ranges for reducing the cost of
-  // nsRange allocation.  Note that if this is called by
-  // SetBaseAndExtentJS(), when we fail to initialize new range, we
-  // shouldn't remove current ranges.  Therefore, we need to check whether
-  // we're called by JS or internally.
-  if (!mCalledByJS && !mCachedRange) {
-    nsresult rv = RemoveAllRangesTemporarily();
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      aRv.Throw(rv);
-      return;
-    }
+
+  int32_t relativePosition = nsContentUtils::ComparePoints(
+      &aAnchorNode, aAnchorOffset, &aFocusNode, aFocusOffset);
+  nsINode* start = &aAnchorNode;
+  nsINode* end = &aFocusNode;
+  uint32_t startOffset = aAnchorOffset;
+  uint32_t endOffset = aFocusOffset;
+  if (relativePosition > 0) {
+    start = &aFocusNode;
+    end = &aAnchorNode;
+    startOffset = aFocusOffset;
+    endOffset = aAnchorOffset;
   }
 
   // If there is cached range, we should reuse it for saving the allocation
-  // const (and some other cost in nsRange::DoSetRange()).
+  // const (and some other cost in nsRange::DoSetRange().
   RefPtr<nsRange> newRange = std::move(mCachedRange);
 
   nsresult rv = NS_OK;
   if (newRange) {
-    rv = newRange->SetStartAndEnd(aStartRef, aEndRef);
+    rv = newRange->SetStartAndEnd(start, startOffset, end, endOffset);
   } else {
-    rv = nsRange::CreateRange(aStartRef, aEndRef, getter_AddRefs(newRange));
+    rv = nsRange::CreateRange(start, startOffset, end, endOffset,
+                              getter_AddRefs(newRange));
   }
 
   // nsRange::SetStartAndEnd() and nsRange::CreateRange() returns
   // IndexSizeError if any offset is out of bounds.
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
@@ -3482,17 +3441,17 @@ void Selection::SetStartAndEndInternal(I
     return;
   }
 
   AddRange(*newRange, aRv);
   if (aRv.Failed()) {
     return;
   }
 
-  SetDirection(aDirection);
+  SetDirection(relativePosition > 0 ? eDirPrevious : eDirNext);
 }
 
 /** SelectionLanguageChange modifies the cursor Bidi level after a change in
  * keyboard direction
  *  @param aLangRTL is true if the new language is right-to-left or false if the
  * new language is left-to-right
  */
 nsresult Selection::SelectionLanguageChange(bool aLangRTL) {
--- a/dom/base/Selection.h
+++ b/dom/base/Selection.h
@@ -344,17 +344,16 @@ class Selection final : public nsSupport
    * @throws NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
    * "sentenceboundary", "paragraph", "paragraphboundary", or
    * "documentboundary".  Throws NS_ERROR_INVALID_ARG if alter, direction,
    * or granularity has an unrecognized value.
    */
   void Modify(const nsAString& aAlter, const nsAString& aDirection,
               const nsAString& aGranularity, mozilla::ErrorResult& aRv);
 
-  MOZ_CAN_RUN_SCRIPT
   void SetBaseAndExtentJS(nsINode& aAnchorNode, uint32_t aAnchorOffset,
                           nsINode& aFocusNode, uint32_t aFocusOffset,
                           mozilla::ErrorResult& aRv);
 
   bool GetInterlinePosition(mozilla::ErrorResult& aRv);
   void SetInterlinePosition(bool aValue, mozilla::ErrorResult& aRv);
 
   Nullable<int16_t> GetCaretBidiLevel(mozilla::ErrorResult& aRv) const;
@@ -440,94 +439,19 @@ class Selection final : public nsSupport
 
   /**
    * Adds all children of the specified node to the selection.
    * @param aNode the parent of the children to be added to the selection.
    */
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   void SelectAllChildren(nsINode& aNode, mozilla::ErrorResult& aRv);
 
-  /**
-   * SetStartAndEnd() removes all ranges and sets new range as given range.
-   * Different from SetBaseAndExtent(), this won't compare the DOM points of
-   * aStartRef and aEndRef for performance nor set direction to eDirPrevious.
-   * Note that this may reset the limiter and move focus.  If you don't want
-   * that, use SetStartAndEndInLimiter() instead.
-   */
-  MOZ_CAN_RUN_SCRIPT
-  void SetStartAndEnd(const RawRangeBoundary& aStartRef,
-                      const RawRangeBoundary& aEndRef, ErrorResult& aRv) {
-    SetStartAndEndInternal(InLimiter::eNo, aStartRef, aEndRef, eDirNext, aRv);
-  }
-  MOZ_CAN_RUN_SCRIPT
-  void SetStartAndEnd(nsINode& aStartContainer, uint32_t aStartOffset,
-                      nsINode& aEndContainer, uint32_t aEndOffset,
-                      ErrorResult& aRv) {
-    SetStartAndEnd(RawRangeBoundary(&aStartContainer, aStartOffset),
-                   RawRangeBoundary(&aEndContainer, aEndOffset), aRv);
-  }
-
-  /**
-   * SetStartAndEndInLimiter() is similar to SetStartAndEnd(), but this respects
-   * the selection limiter.  If all or part of given range is not in the
-   * limiter, this returns error.
-   */
-  MOZ_CAN_RUN_SCRIPT
-  void SetStartAndEndInLimiter(const RawRangeBoundary& aStartRef,
-                               const RawRangeBoundary& aEndRef,
-                               ErrorResult& aRv) {
-    SetStartAndEndInternal(InLimiter::eYes, aStartRef, aEndRef, eDirNext, aRv);
-  }
-  MOZ_CAN_RUN_SCRIPT
-  void SetStartAndEndInLimiter(nsINode& aStartContainer, uint32_t aStartOffset,
-                               nsINode& aEndContainer, uint32_t aEndOffset,
-                               ErrorResult& aRv) {
-    SetStartAndEndInLimiter(RawRangeBoundary(&aStartContainer, aStartOffset),
-                            RawRangeBoundary(&aEndContainer, aEndOffset), aRv);
-  }
-
-  /**
-   * SetBaseAndExtent() is alternative of the JS API for internal use.
-   * Different from SetStartAndEnd(), this sets anchor and focus points as
-   * specified, then if anchor point is after focus node, this sets the
-   * direction to eDirPrevious.
-   * Note that this may reset the limiter and move focus.  If you don't want
-   * that, use SetBaseAndExtentInLimier() instead.
-   */
-  MOZ_CAN_RUN_SCRIPT
   void SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset,
                         nsINode& aFocusNode, uint32_t aFocusOffset,
-                        ErrorResult& aRv) {
-    SetBaseAndExtent(RawRangeBoundary(&aAnchorNode, aAnchorOffset),
-                     RawRangeBoundary(&aFocusNode, aFocusOffset), aRv);
-  }
-  MOZ_CAN_RUN_SCRIPT
-  void SetBaseAndExtent(const RawRangeBoundary& aAnchorRef,
-                        const RawRangeBoundary& aFocusRef, ErrorResult& aRv) {
-    SetBaseAndExtentInternal(InLimiter::eNo, aAnchorRef, aFocusRef, aRv);
-  }
-
-  /**
-   * SetBaseAndExtentInLimier() is similar to SetBaseAndExtent(), but this
-   * respects the selection limiter.  If all or part of given range is not in
-   * the limiter, this returns error.
-   */
-  MOZ_CAN_RUN_SCRIPT
-  void SetBaseAndExtentInLimiter(nsINode& aAnchorNode, uint32_t aAnchorOffset,
-                                 nsINode& aFocusNode, uint32_t aFocusOffset,
-                                 ErrorResult& aRv) {
-    SetBaseAndExtentInLimiter(RawRangeBoundary(&aAnchorNode, aAnchorOffset),
-                              RawRangeBoundary(&aFocusNode, aFocusOffset), aRv);
-  }
-  MOZ_CAN_RUN_SCRIPT
-  void SetBaseAndExtentInLimiter(const RawRangeBoundary& aAnchorRef,
-                                 const RawRangeBoundary& aFocusRef,
-                                 ErrorResult& aRv) {
-    SetBaseAndExtentInternal(InLimiter::eYes, aAnchorRef, aFocusRef, aRv);
-  }
+                        mozilla::ErrorResult& aRv);
 
   void AddSelectionChangeBlocker();
   void RemoveSelectionChangeBlocker();
   bool IsBlockingSelectionChangeEvents() const;
 
   // Whether this selection is focused in an editable element.
   bool IsEditorSelection() const;
 
@@ -607,35 +531,16 @@ class Selection final : public nsSupport
                                                nsIFrame** aReturnFrame,
                                                int32_t* aOffsetUsed,
                                                bool aVisual) const;
 
   // Get the cached value for nsTextFrame::GetPointFromOffset.
   nsresult GetCachedFrameOffset(nsIFrame* aFrame, int32_t inOffset,
                                 nsPoint& aPoint);
 
-  enum class InLimiter {
-    // If eYes, the method may reset selection limiter and move focus if the
-    // given range is out of the limiter.
-    eYes,
-    // If eNo, the method won't reset selection limiter.  So, if given range
-    // is out of bounds, the method may return error.
-    eNo,
-  };
-  MOZ_CAN_RUN_SCRIPT
-  void SetStartAndEndInternal(InLimiter aInLimiter,
-                              const RawRangeBoundary& aStartRef,
-                              const RawRangeBoundary& aEndRef,
-                              nsDirection aDirection, ErrorResult& aRv);
-  MOZ_CAN_RUN_SCRIPT
-  void SetBaseAndExtentInternal(InLimiter aInLimiter,
-                                const RawRangeBoundary& aAnchorRef,
-                                const RawRangeBoundary& aFocusRef,
-                                ErrorResult& aRv);
-
  public:
   SelectionType GetType() const { return mSelectionType; }
   void SetType(SelectionType aSelectionType) {
     mSelectionType = aSelectionType;
   }
 
   SelectionCustomColors* GetCustomColors() const { return mCustomColors.get(); }
 
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -2976,38 +2976,42 @@ nsresult ContentEventHandler::OnSelectio
   int32_t endNodeOffset = rawRange.EndOffset();
   AdjustRangeForSelection(mRootContent, &startNode, &startNodeOffset);
   AdjustRangeForSelection(mRootContent, &endNode, &endNodeOffset);
   if (NS_WARN_IF(!startNode) || NS_WARN_IF(!endNode) ||
       NS_WARN_IF(startNodeOffset < 0) || NS_WARN_IF(endNodeOffset < 0)) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  if (aEvent->mReversed) {
-    nsCOMPtr<nsINode> startNodeStrong(startNode);
-    nsCOMPtr<nsINode> endNodeStrong(endNode);
-    ErrorResult error;
-    MOZ_KnownLive(mSelection)
-        ->SetBaseAndExtentInLimiter(*endNodeStrong, endNodeOffset,
-                                    *startNodeStrong, startNodeOffset, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
+  mSelection->StartBatchChanges();
+
+  // Clear selection first before setting
+  rv = mSelection->RemoveAllRangesTemporarily();
+  // Need to call EndBatchChanges at the end even if call failed
+  if (NS_SUCCEEDED(rv)) {
+    if (aEvent->mReversed) {
+      rv = mSelection->Collapse(endNode, endNodeOffset);
+    } else {
+      rv = mSelection->Collapse(startNode, startNodeOffset);
     }
-  } else {
-    nsCOMPtr<nsINode> startNodeStrong(startNode);
-    nsCOMPtr<nsINode> endNodeStrong(endNode);
-    ErrorResult error;
-    MOZ_KnownLive(mSelection)
-        ->SetBaseAndExtentInLimiter(*startNodeStrong, startNodeOffset,
-                                    *endNodeStrong, endNodeOffset, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
+    if (NS_SUCCEEDED(rv) &&
+        (startNode != endNode || startNodeOffset != endNodeOffset)) {
+      if (aEvent->mReversed) {
+        rv = mSelection->Extend(startNode, startNodeOffset);
+      } else {
+        rv = mSelection->Extend(endNode, endNodeOffset);
+      }
     }
   }
 
+  // Pass the eSetSelection events reason along with the BatchChange-end
+  // selection change notifications.
+  mSelection->EndBatchChanges(aEvent->mReason);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   mSelection->ScrollIntoView(nsISelectionController::SELECTION_FOCUS_REGION,
                              nsIPresShell::ScrollAxis(),
                              nsIPresShell::ScrollAxis(), 0);
   aEvent->mSucceeded = true;
   return NS_OK;
 }
 
 nsRect ContentEventHandler::FrameRelativeRect::RectRelativeTo(
--- a/dom/events/ContentEventHandler.h
+++ b/dom/events/ContentEventHandler.h
@@ -118,17 +118,16 @@ class MOZ_STACK_CLASS ContentEventHandle
   // eQuerySelectionAsTransferable event handler
   nsresult OnQuerySelectionAsTransferable(WidgetQueryContentEvent* aEvent);
   // eQueryCharacterAtPoint event handler
   nsresult OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent);
   // eQueryDOMWidgetHittest event handler
   nsresult OnQueryDOMWidgetHittest(WidgetQueryContentEvent* aEvent);
 
   // NS_SELECTION_* event
-  MOZ_CAN_RUN_SCRIPT
   nsresult OnSelectionEvent(WidgetSelectionEvent* aEvent);
 
  protected:
   RefPtr<dom::Document> mDocument;
   // mSelection is typically normal selection but if OnQuerySelectedText()
   // is called, i.e., handling eQuerySelectedText, it's the specified selection
   // by WidgetQueryContentEvent::mInput::mSelectionType.
   RefPtr<Selection> mSelection;
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -745,22 +745,20 @@ nsresult EventStateManager::PreHandleEve
 
       // Init lineOrPageDelta values for line scroll events for some devices
       // on some platforms which might dispatch wheel events which don't have
       // lineOrPageDelta values.  And also, if delta values are customized by
       // prefs, this recomputes them.
       DeltaAccumulator::GetInstance()->InitLineOrPageDelta(aTargetFrame, this,
                                                            wheelEvent);
     } break;
-    case eSetSelection: {
-      nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
-      IMEStateManager::HandleSelectionEvent(aPresContext, focusedContent,
+    case eSetSelection:
+      IMEStateManager::HandleSelectionEvent(aPresContext, GetFocusedContent(),
                                             aEvent->AsSelectionEvent());
       break;
-    }
     case eContentCommandCut:
     case eContentCommandCopy:
     case eContentCommandPaste:
     case eContentCommandDelete:
     case eContentCommandUndo:
     case eContentCommandRedo:
     case eContentCommandPasteTransferable:
     case eContentCommandLookUpDictionary:
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -207,17 +207,16 @@ class IMEStateManager {
       nsEventStatus* aStatus, EventDispatchingCallback* aCallBack,
       bool aIsSynthesized = false);
 
   /**
    * All selection events must be handled via HandleSelectionEvent()
    * because they must be handled by same target as composition events when
    * there is a composition.
    */
-  MOZ_CAN_RUN_SCRIPT
   static void HandleSelectionEvent(nsPresContext* aPresContext,
                                    nsIContent* aEventTargetContent,
                                    WidgetSelectionEvent* aSelectionEvent);
 
   /**
    * This is called when PresShell ignores a composition event due to not safe
    * to dispatch events.
    */
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -451,23 +451,19 @@ class TextComposition final {
                      nsEventStatus* aStatus,
                      EventDispatchingCallback* aCallback,
                      const WidgetCompositionEvent* aOriginalEvent = nullptr);
 
   /**
    * HandleSelectionEvent() sends the selection event to ContentEventHandler
    * or dispatches it to the focused child process.
    */
-  MOZ_CAN_RUN_SCRIPT
   void HandleSelectionEvent(WidgetSelectionEvent* aSelectionEvent) {
-    RefPtr<nsPresContext> presContext(mPresContext);
-    RefPtr<TabParent> tabParent(mTabParent);
-    HandleSelectionEvent(presContext, tabParent, aSelectionEvent);
+    HandleSelectionEvent(mPresContext, mTabParent, aSelectionEvent);
   }
-  MOZ_CAN_RUN_SCRIPT
   static void HandleSelectionEvent(nsPresContext* aPresContext,
                                    TabParent* aTabParent,
                                    WidgetSelectionEvent* aSelectionEvent);
 
   /**
    * MaybeDispatchCompositionUpdate() may dispatch a compositionupdate event
    * if aCompositionEvent changes composition string.
    * @return Returns false if dispatching the compositionupdate event caused
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -2296,19 +2296,17 @@ bool nsTextEditorState::SetValue(const n
 
           if (aFlags & eSetValue_BySetUserInput) {
             // If the caller inserts text as part of user input, for example,
             // autocomplete, we need to replace the text as "insert string"
             // because undo should cancel only this operation (i.e., previous
             // transactions typed by user shouldn't be merged with this).
             // In this case, we need to dispatch "input" event because
             // web apps may need to know the user's operation.
-            RefPtr<nsRange> range;  // See bug 1506439
-            DebugOnly<nsresult> rv =
-                textEditor->ReplaceTextAsAction(newValue, range);
+            DebugOnly<nsresult> rv = textEditor->ReplaceTextAsAction(newValue);
             NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                                  "Failed to set the new value");
           } else if (aFlags & eSetValue_ForXUL) {
             // When setting value of XUL <textbox>, we shouldn't dispatch
             // "input" event.
             suppressInputEventDispatching.Init();
 
             // On XUL <textbox> element, we need to preserve existing undo
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2655,16 +2655,29 @@ nsresult EditorBase::InsertTextIntoTextN
       mComposition->OnTextNodeRemoved();
       static_cast<CompositionTransaction*>(transaction.get())->MarkFixed();
     }
   }
 
   return rv;
 }
 
+nsresult EditorBase::SelectEntireDocument() {
+  MOZ_ASSERT(IsEditActionDataAvailable());
+
+  Element* rootElement = GetRoot();
+  if (!rootElement) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  ErrorResult errorResult;
+  SelectionRefPtr()->SelectAllChildren(*rootElement, errorResult);
+  return errorResult.StealNSResult();
+}
+
 nsINode* EditorBase::GetFirstEditableNode(nsINode* aRoot) {
   MOZ_ASSERT(aRoot);
 
   nsIContent* node = GetLeftmostChild(aRoot);
   if (node && !IsEditable(node)) {
     node = GetNextEditableNode(*node);
   }
 
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -384,17 +384,16 @@ class EditorBase : public nsIEditor,
   }
   bool RemoveTransactionListener(nsITransactionListener& aListener) {
     if (!mTransactionManager) {
       return false;
     }
     return mTransactionManager->RemoveTransactionListener(aListener);
   }
 
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent);
 
   virtual dom::EventTarget* GetDOMEventTarget() = 0;
 
   /**
    * Accessor methods to flags.
    */
   uint32_t Flags() const { return mFlags; }
@@ -1812,17 +1811,16 @@ class EditorBase : public nsIEditor,
    */
   nsresult GetDocumentCharsetInternal(nsACString& aCharset) const;
 
   /**
    * SelectAllInternal() should be used instead of SelectAll() in editor
    * because SelectAll() creates AutoEditActionSetter but we should avoid
    * to create it as far as possible.
    */
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult SelectAllInternal();
 
   nsresult DetermineCurrentDirection();
 
   /**
    * FireInputEvent() dispatches an "input" event synchronously or
    * asynchronously if it's not safe to dispatch.
    */
@@ -1857,18 +1855,17 @@ class EditorBase : public nsIEditor,
     eDocumentStateChanged
   };
   nsresult NotifyDocumentListeners(
       TDocumentListenerNotification aNotificationType);
 
   /**
    * Make the given selection span the entire document.
    */
-  MOZ_CAN_RUN_SCRIPT
-  virtual nsresult SelectEntireDocument() = 0;
+  virtual nsresult SelectEntireDocument();
 
   /**
    * Helper method for scrolling the selection into view after
    * an edit operation. aScrollToAnchor should be true if you
    * want to scroll to the point where the selection was started.
    * If false, it attempts to scroll the end of the selection into view.
    *
    * Editor methods *should* call this method instead of the versions
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -690,17 +690,17 @@ NS_IMETHODIMP
 SelectAllCommand::DoCommand(const char* aCommandName,
                             nsISupports* aCommandRefCon) {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (!editor) {
     return NS_ERROR_FAILURE;
   }
   TextEditor* textEditor = editor->AsTextEditor();
   MOZ_ASSERT(textEditor);
-  return MOZ_KnownLive(textEditor)->SelectAll();
+  return textEditor->SelectAll();
 }
 
 NS_IMETHODIMP
 SelectAllCommand::DoCommandParams(const char* aCommandName,
                                   nsICommandParams* aParams,
                                   nsISupports* aCommandRefCon) {
   return DoCommand(aCommandName, aCommandRefCon);
 }
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -1726,18 +1726,17 @@ EditActionResult HTMLEditRules::WillInse
 
   if (host == blockParent && separator != ParagraphSeparator::br) {
     // Insert a new block first
     MOZ_ASSERT(separator == ParagraphSeparator::div ||
                separator == ParagraphSeparator::p);
     // MakeBasicBlock() creates AutoSelectionRestorer.
     // Therefore, even if it returns NS_OK, editor might have been destroyed
     // at restoring Selection.
-    OwningNonNull<nsAtom> separatorTag = ParagraphSeparatorElement(separator);
-    nsresult rv = MakeBasicBlock(separatorTag);
+    nsresult rv = MakeBasicBlock(ParagraphSeparatorElement(separator));
     if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED) ||
         NS_WARN_IF(!CanHandleEditAction())) {
       return EditActionIgnored(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");
@@ -2217,18 +2216,17 @@ nsresult HTMLEditRules::WillDeleteSelect
   }
 
   // First check for table selection mode.  If so, hand off to table editor.
   ErrorResult error;
   RefPtr<Element> cellElement =
       HTMLEditorRef().GetFirstSelectedTableCellElement(error);
   if (cellElement) {
     error.SuppressException();
-    nsresult rv =
-        MOZ_KnownLive(HTMLEditorRef()).DeleteTableCellContentsWithTransaction();
+    nsresult rv = HTMLEditorRef().DeleteTableCellContentsWithTransaction();
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     *aHandled = true;
     return rv;
   }
   nsresult rv = error.StealNSResult();
   cellElement = nullptr;
@@ -6505,16 +6503,23 @@ nsresult HTMLEditRules::ExpandSelectionF
         }
         selEndNode = wsObj.mEndReasonNode->GetParentNode();
         selEndOffset = 1 + selEndNode->ComputeIndexOf(wsObj.mEndReasonNode);
       } else {
         break;
       }
     }
   }
+  // Now set the selection to the new range
+  DebugOnly<nsresult> rv =
+      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;
   if (firstBRParent) {
     // Find block node containing <br>.
     nsCOMPtr<Element> brBlock = HTMLEditor::GetBlock(*firstBRParent);
     bool nodeBefore = false, nodeAfter = false;
@@ -6532,30 +6537,36 @@ nsresult HTMLEditRules::ExpandSelectionF
       nsRange::CompareNodeToRange(brBlock, range, &nodeBefore, &nodeAfter);
     }
 
     // If block isn't contained, forgo grabbing the <br> in expanded selection.
     if (nodeBefore || nodeAfter) {
       doEndExpansion = false;
     }
   }
-
-  EditorRawDOMPoint newSelectionStart(selStartNode, selStartOffset);
-  EditorRawDOMPoint newSelectionEnd(
-      doEndExpansion ? selEndNode : firstBRParent,
-      doEndExpansion ? selEndOffset : firstBROffset);
-  ErrorResult error;
-  MOZ_KnownLive(SelectionRefPtr())
-      ->SetStartAndEndInLimiter(newSelectionStart, newSelectionEnd, error);
-  if (NS_WARN_IF(!CanHandleEditAction())) {
-    error.SuppressException();
-    return NS_ERROR_EDITOR_DESTROYED;
-  }
-  NS_WARNING_ASSERTION(!error.Failed(), "Failed to set selection for deletion");
-  return error.StealNSResult();
+  if (doEndExpansion) {
+    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 = SelectionRefPtr()->Extend(firstBRParent, firstBROffset);
+    if (NS_WARN_IF(!CanHandleEditAction())) {
+      return NS_ERROR_EDITOR_DESTROYED;
+    }
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
 }
 
 nsresult HTMLEditRules::NormalizeSelection() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // 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
@@ -6698,28 +6709,30 @@ nsresult HTMLEditRules::NormalizeSelecti
     return NS_OK;  // New end before old start.
   }
   comp = nsContentUtils::ComparePoints(newStartNode, newStartOffset, endNode,
                                        endOffset);
   if (comp == 1) {
     return NS_OK;  // New start after old end.
   }
 
-  // Otherwise set selection to new values.  Note that end point may be prior
-  // to start point.  So, we cannot use Selection::SetStartAndEndInLimit() here.
-  ErrorResult error;
-  MOZ_KnownLive(SelectionRefPtr())
-      ->SetBaseAndExtentInLimiter(*newStartNode, newStartOffset, *newEndNode,
-                                  newEndOffset, error);
+  // otherwise set selection to new values.
+  // XXX Why don't we use SetBaseAndExtent()?
+  DebugOnly<nsresult> rv =
+      SelectionRefPtr()->Collapse(newStartNode, newStartOffset);
   if (NS_WARN_IF(!CanHandleEditAction())) {
-    error.SuppressException();
     return NS_ERROR_EDITOR_DESTROYED;
   }
-  NS_WARNING_ASSERTION(!error.Failed(), "Failed to set selection");
-  return error.StealNSResult();
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
+  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;
 }
 
 EditorDOMPoint HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere,
                                                nsINode& aNode, int32_t aOffset,
                                                EditSubAction aEditSubAction) {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // we do one thing for text actions, something else entirely for other
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -225,17 +225,16 @@ class HTMLEditRules : public TextEditRul
    * Called before deleting selected contents.  This method actually removes
    * selected contents.
    *
    * @param aAction             Direction of the deletion.
    * @param aStripWrappers      Must be eStrip or eNoStrip.
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillDeleteSelection(
       nsIEditor::EDirection aAction, nsIEditor::EStripWrappers aStripWrappers,
       bool* aCancel, bool* aHandled);
 
   /**
    * Called after deleting selected content.
    * This method removes unnecessary empty nodes and/or inserts <br> if
    * necessary.
@@ -370,84 +369,77 @@ class HTMLEditRules : public TextEditRul
    *
    */
   MOZ_MUST_USE nsresult
   DeleteElementsExceptTableRelatedElements(nsINode& aNode);
 
   /**
    * XXX Should document what this does.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillMakeList(const nsAString* aListType,
                                      bool aEntireList,
                                      const nsAString* aBulletType,
                                      bool* aCancel, bool* aHandled,
                                      const nsAString* aItemType = nullptr);
 
   /**
    * Called before removing a list element.  This method actually removes
    * list elements and list item elements at Selection.  And move contents
    * in them where the removed list was.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillRemoveList(bool* aCancel, bool* aHandled);
 
   /**
    * Called before indenting around Selection.  This method actually tries to
    * indent the contents.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillIndent(bool* aCancel, bool* aHandled);
 
   /**
    * Called before indenting around Selection and it's in CSS mode.
    * This method actually tries to indent the contents.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillCSSIndent(bool* aCancel, bool* aHandled);
 
   /**
    * Called before indenting around Selection and it's not in CSS mode.
    * This method actually tries to indent the contents.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillHTMLIndent(bool* aCancel, bool* aHandled);
 
   /**
    * Called before outdenting around Selection.  This method actually tries
    * to indent the contents.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillOutdent(bool* aCancel, bool* aHandled);
 
   /**
    * Called before aligning contents around Selection.  This method actually
    * sets align attributes to align contents.
    *
    * @param aAlignType          New align attribute value where the contents
    *                            should be aligned to.
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult WillAlign(const nsAString& aAlignType, bool* aCancel,
                      bool* aHandled);
 
   /**
    * Called before changing absolute positioned element to static positioned.
    * This method actually changes the position property of nearest absolute
    * positioned element.  Therefore, this might cause destroying the HTML
    * editor.
@@ -476,47 +468,44 @@ class HTMLEditRules : public TextEditRul
    * method just calls WillMakeList() with "dl" as aListType and
    * aDefinitionListItemTag as aItemType.
    *
    * @param aDefinitionListItemTag  Should be "dt" or "dd".
    * @param aEntireList             XXX not sure
    * @param aCancel                 Returns true if the operation is canceled.
    * @param aHandled                Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillMakeDefListItem(const nsAString* aBlockType,
                                             bool aEntireList, bool* aCancel,
                                             bool* aHandled);
 
   /**
    * WillMakeBasicBlock() called before changing block style around Selection.
    * This method actually does something with calling MakeBasicBlock().
    *
    * @param aBlockType          Necessary block style as string.
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillMakeBasicBlock(const nsAString& aBlockType,
                                            bool* aCancel, bool* aHandled);
 
   /**
    * MakeBasicBlock() applies or clears block style around Selection.
    * This method creates AutoSelectionRestorer.  Therefore, each caller
    * need to check if the editor is still available even if this returns
    * NS_OK.
    *
    * @param aBlockType          New block tag name.
    *                            If nsGkAtoms::normal or nsGkAtoms::_empty,
    *                            RemoveBlockStyle() will be called.
    *                            If nsGkAtoms::blockquote, MakeBlockquote()
    *                            will be called.
    *                            Otherwise, ApplyBlockStyle() will be called.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult MakeBasicBlock(nsAtom& aBlockType);
 
   /**
    * Called after creating a basic block, indenting, outdenting or aligning
    * contents.  This method inserts moz-<br> element if start container of
    * Selection needs it.
    */
   MOZ_MUST_USE nsresult DidMakeBasicBlock();
@@ -525,17 +514,16 @@ class HTMLEditRules : public TextEditRul
    * Called before changing an element to absolute positioned.
    * This method only prepares the operation since DidAbsolutePosition() will
    * change it actually later.  mNewBlock is set to the target element and
    * if necessary, some ancestor nodes of selection may be split.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult WillAbsolutePosition(bool* aCancel, bool* aHandled);
 
   /**
    * PrepareToMakeElementAbsolutePosition() is helper method of
    * WillAbsolutePosition() since in some cases, needs to restore selection
    * with AutoSelectionRestorer.  So, all callers have to check if
    * CanHandleEditAction() still returns true after a call of this method.
    * XXX Should be documented outline of this method.
@@ -855,26 +843,24 @@ class HTMLEditRules : public TextEditRul
                                int32_t aOffset = 0);
 
   /**
    * ExpandSelectionForDeletion() may expand Selection range if it's not
    * collapsed and there is only one range.  This may expand to include
    * invisible <br> element for preventing delete action handler to keep
    * unexpected nodes.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult ExpandSelectionForDeletion();
 
   /**
    * NormalizeSelection() adjust Selection if it's not collapsed and there is
    * only one range.  If range start and/or end point is <br> node or something
    * non-editable point, they should be moved to nearest text node or something
    * where the other methods easier to handle edit action.
    */
-  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult NormalizeSelection();
 
   /**
    * GetPromotedPoint() figures out where a start or end point for a block
    * operation really is.
    */
   EditorDOMPoint GetPromotedPoint(RulesEndpoint aWhere, nsINode& aNode,
                                   int32_t aOffset,
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -1722,43 +1722,53 @@ HTMLEditor::SelectElement(Element* aElem
     return NS_ERROR_INVALID_ARG;
   }
 
   AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  nsresult rv = SelectContentInternal(MOZ_KnownLive(*aElement));
+  nsresult rv = SelectContentInternal(*aElement);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult HTMLEditor::SelectContentInternal(nsIContent& aContentToSelect) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   // Must be sure that element is contained in the document body
   if (!IsDescendantOfEditorRoot(&aContentToSelect)) {
     return NS_ERROR_FAILURE;
   }
 
-  EditorRawDOMPoint newSelectionStart(&aContentToSelect);
-  if (NS_WARN_IF(!newSelectionStart.IsSet())) {
+  nsINode* parent = aContentToSelect.GetParentNode();
+  if (NS_WARN_IF(!parent)) {
     return NS_ERROR_FAILURE;
   }
-  EditorRawDOMPoint newSelectionEnd(&aContentToSelect);
-  MOZ_ASSERT(newSelectionEnd.IsSet());
-  DebugOnly<bool> advanced = newSelectionEnd.AdvanceOffset();
-  ErrorResult error;
-  MOZ_KnownLive(SelectionRefPtr())
-      ->SetStartAndEndInLimiter(newSelectionStart, newSelectionEnd, error);
-  NS_WARNING_ASSERTION(!error.Failed(), "Failed to select the given content");
-  return error.StealNSResult();
+
+  // Don't notify selection change at collapse.
+  AutoUpdateViewBatch notifySelectionChangeOnce(*this);
+
+  // XXX Perhaps, Selection should have SelectNode(nsIContent&).
+  int32_t offsetInParent = parent->ComputeIndexOf(&aContentToSelect);
+
+  // Collapse selection to just before desired element,
+  nsresult rv = SelectionRefPtr()->Collapse(parent, offsetInParent);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  // then extend it to just after
+  rv = SelectionRefPtr()->Extend(parent, offsetInParent + 1);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetCaretAfterElement(Element* aElement) {
   if (NS_WARN_IF(!aElement)) {
     return NS_ERROR_INVALID_ARG;
   }
 
@@ -3588,41 +3598,33 @@ bool HTMLEditor::IsContainer(nsINode* aN
 
 nsresult HTMLEditor::SelectEntireDocument() {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (!mRules) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  RefPtr<Element> rootElement = GetRoot();
-  if (NS_WARN_IF(!rootElement)) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
-  // If we're empty, don't select all children because that would select the
-  // bogus node.
+  // is doc empty?
   if (rules->DocumentIsEmpty()) {
+    // get editor root node
+    Element* rootElement = GetRoot();
+
+    // if its empty dont select entire doc - that would select the bogus node
     nsresult rv = SelectionRefPtr()->Collapse(rootElement, 0);
-    NS_WARNING_ASSERTION(
-        NS_SUCCEEDED(rv),
-        "Failed to move caret to start of the editor root element");
-    return rv;
-  }
-
-  // Otherwise, select all children.
-  ErrorResult error;
-  SelectionRefPtr()->SelectAllChildren(*rootElement, error);
-  NS_WARNING_ASSERTION(
-      !error.Failed(),
-      "Failed to select all children of the editor root element");
-  return error.StealNSResult();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  return EditorBase::SelectEntireDocument();
 }
 
 nsresult HTMLEditor::SelectAllInternal() {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   CommitComposition();
   if (NS_WARN_IF(Destroyed())) {
     return NS_ERROR_EDITOR_DESTROYED;
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -136,17 +136,16 @@ class HTMLEditor final : public TextEdit
 
   MOZ_CAN_RUN_SCRIPT
   NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
 
   NS_IMETHOD DeleteNode(nsINode* aNode) override;
 
   NS_IMETHOD InsertLineBreak() override;
 
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult HandleKeyPressEvent(
       WidgetKeyboardEvent* aKeyboardEvent) override;
   virtual nsIContent* GetFocusedContent() override;
   virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
   virtual bool IsActiveInDOMWindow() override;
   virtual dom::EventTarget* GetDOMEventTarget() override;
   virtual Element* FindSelectionRoot(nsINode* aNode) const override;
   virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
@@ -419,17 +418,16 @@ class HTMLEditor final : public TextEdit
     mDefaultParagraphSeparator = aSep;
   }
 
   /**
    * Modifies the table containing the selection according to the
    * activation of an inline table editing UI element
    * @param aUIAnonymousElement [IN] the inline table editing UI element
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement);
 
   /**
    * GetElementOrParentByTagName() looks for an element node whose name matches
    * aTagName from aNode or anchor node of Selection to <body> element.
    *
    * @param aTagName        The tag name which you want to look for.
    *                        Must not be nsGkAtoms::_empty.
@@ -638,17 +636,16 @@ class HTMLEditor final : public TextEdit
 
   /**
    * DeleteTableCellContentsWithTransaction() removes any contents in cell
    * elements.  If two or more cell elements are selected, this removes
    * all selected cells' contents.  Otherwise, this removes contents of
    * a cell which contains first selection range.  This does not return
    * error even if selection is not in cell element, just does nothing.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteTableCellContentsWithTransaction();
 
   void IsNextCharInNodeWhitespace(nsIContent* aContent, int32_t aOffset,
                                   bool* outIsSpace, bool* outIsNBSP,
                                   nsIContent** outNode = nullptr,
                                   int32_t* outOffset = 0);
   void IsPrevCharInNodeWhitespace(nsIContent* aContent, int32_t aOffset,
                                   bool* outIsSpace, bool* outIsNBSP,
@@ -953,26 +950,24 @@ class HTMLEditor final : public TextEdit
   virtual ~HTMLEditor();
 
   /**
    * InsertParagraphSeparatorAsSubAction() inserts a line break if it's
    * HTMLEditor and it's possible.
    */
   nsresult InsertParagraphSeparatorAsSubAction();
 
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult SelectAllInternal() override;
 
   /**
    * SelectContentInternal() sets Selection to aContentToSelect to
    * aContentToSelect + 1 in parent of aContentToSelect.
    *
    * @param aContentToSelect    The content which should be selected.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult SelectContentInternal(nsIContent& aContentToSelect);
 
   /**
    * CollapseSelectionAfter() collapses Selection after aElement.
    * If aElement is an orphan node or not in editing host, returns error.
    */
   nsresult CollapseSelectionAfter(Element& aElement);
 
@@ -1521,17 +1516,16 @@ class HTMLEditor final : public TextEdit
   nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
 
   virtual void InitializeSelectionAncestorLimit(
       nsIContent& aAncestorLimit) override;
 
   /**
    * Make the given selection span the entire document.
    */
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult SelectEntireDocument() override;
 
   /**
    * Use this to assure that selection is set after attribute nodes when
    * trying to collapse selection at begining of a block node
    * e.g., when setting at beginning of a table cell
    * This will stop at a table, however, since we don't want to
    * "drill down" into nested tables.
@@ -1664,17 +1658,16 @@ class HTMLEditor final : public TextEdit
 
   virtual already_AddRefed<Element> GetInputEventTargetElement() override;
 
   /**
    * Return TRUE if aElement is a table-related elemet and caret was set.
    */
   bool SetCaretInTableCell(dom::Element* aElement);
 
-  MOZ_CAN_RUN_SCRIPT
   nsresult TabInTable(bool inIsShift, bool* outHandled);
 
   /**
    * InsertPosition is an enum to indicate where the method should insert to.
    */
   enum class InsertPosition {
     // Before selected cell or a cell containing first selection range.
     eBeforeSelectedCell,
@@ -1696,49 +1689,46 @@ class HTMLEditor final : public TextEdit
    * for keeping table rectangle.
    * If first selection range is not in table cell element, this does nothing
    * but does not return error.
    *
    * @param aNumberOfCellssToInsert     Number of cells to insert.
    * @param aInsertPosition             Before or after the target cell which
    *                                    contains first selection range.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult InsertTableCellsWithTransaction(int32_t aNumberOfCellsToInsert,
                                            InsertPosition aInsertPosition);
 
   /**
    * InsertTableColumnsWithTransaction() inserts columns before or after
    * a cell element containing first selection range.  I.e., if the cell
    * spans columns and aInsertPosition is eAfterSelectedCell, new columns
    * will be inserted after the right-most row which contains the cell.
    * If first selection range is not in table cell element, this does nothing
    * but does not return error.
    *
    * @param aNumberOfColumnsToInsert    Number of columns to insert.
    * @param aInsertPosition             Before or after the target cell which
    *                                    contains first selection range.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult InsertTableColumnsWithTransaction(int32_t aNumberOfColumnsToInsert,
                                              InsertPosition aInsertPosition);
 
   /**
    * InsertTableRowsWithTransaction() inserts <tr> elements before or after
    * a cell element containing first selection range.  I.e., if the cell
    * spans rows and aInsertPosition is eAfterSelectedCell, new rows will be
    * inserted after the most-bottom row which contains the cell.  If first
    * selection range is not in table cell element, this does nothing but
    * does not return error.
    *
    * @param aNumberOfRowsToInsert       Number of rows to insert.
    * @param aInsertPosition             Before or after the target cell which
    *                                    contains first selection range.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult InsertTableRowsWithTransaction(int32_t aNumberOfRowsToInsert,
                                           InsertPosition aInsertPosition);
 
   /**
    * Insert a new cell after or before supplied aCell.
    * Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
    * of course)
    * This doesn't change or use the current selection.
@@ -1758,33 +1748,31 @@ class HTMLEditor final : public TextEdit
    * If selection is not in a cell element, this does not return error,
    * just does nothing.
    * WARNING: This does not remove <col> nor <colgroup> elements.
    *
    * @param aNumberOfColumnsToDelete    Number of columns to remove.  This is
    *                                    ignored if 2 ore more cells are
    *                                    selected.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteSelectedTableColumnsWithTransaction(
       int32_t aNumberOfColumnsToDelete);
 
   /**
    * DeleteTableColumnWithTransaction() removes cell elements which belong
    * to the specified column.
    * This method adjusts colspan attribute value if cells spanning the
    * column to delete.
    * WARNING: This does not remove <col> nor <colgroup> elements.
    *
    * @param aTableElement       The <table> element which contains the
    *                            column which you want to remove.
    * @param aRowIndex           Index of the column which you want to remove.
    *                            0 is the first column.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteTableColumnWithTransaction(Element& aTableElement,
                                             int32_t aColumnIndex);
 
   /**
    * DeleteSelectedTableRowsWithTransaction() removes <tr> elements.
    * If only one cell element is selected or first selection range is
    * in a cell, removes <tr> elements starting from a <tr> element
    * containing the selected cell or first selection range.
@@ -1793,32 +1781,30 @@ class HTMLEditor final : public TextEdit
    * is ignored.
    * If there is no selection ranges, returns error.
    * If selection is not in a cell element, this does not return error,
    * just does nothing.
    *
    * @param aNumberOfRowsToDelete   Number of rows to remove.  This is ignored
    *                                if 2 or more cells are selected.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteSelectedTableRowsWithTransaction(
       int32_t aNumberOfRowsToDelete);
 
   /**
    * DeleteTableRowWithTransaction() removes a <tr> element whose index in
    * the <table> is aRowIndex.
    * This method adjusts rowspan attribute value if the <tr> element contains
    * cells which spans rows.
    *
    * @param aTableElement       The <table> element which contains the
    *                            <tr> element which you want to remove.
    * @param aRowIndex           Index of the <tr> element which you want to
    *                            remove.  0 is the first row.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteTableRowWithTransaction(Element& aTableElement,
                                          int32_t aRowIndex);
 
   /**
    * DeleteTableCellWithTransaction() removes table cell elements.  If two or
    * more cell elements are selected, this removes all selected cell elements.
    * Otherwise, this removes some cell elements starting from selected cell
    * element or a cell containing first selection range.  When this removes
@@ -1826,17 +1812,16 @@ class HTMLEditor final : public TextEdit
    * <table> too.  Note that when removing a cell causes number of its row
    * becomes less than the others, this method does NOT fill the place with
    * rowspan nor colspan.  This does not return error even if selection is not
    * in cell element, just does nothing.
    *
    * @param aNumberOfCellsToDelete  Number of cells to remove.  This is ignored
    *                                if 2 or more cells are selected.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteTableCellWithTransaction(int32_t aNumberOfCellsToDelete);
 
   /**
    * DeleteAllChildrenWithTransaction() removes all children of aElement from
    * the tree.
    *
    * @param aElement        The element whose children you want to remove.
    */
@@ -2130,17 +2115,16 @@ class HTMLEditor final : public TextEdit
    *                    row (ePreviousRow) or don't search for another cell
    *                    (aNoSearch).  If no cell is found, caret is place just
    *                    before table; and if that fails, at beginning of
    *                    document.  Thus we generally don't worry about the
    *                    return value and can use the
    *                    AutoSelectionSetterAfterTableEdit stack-based object to
    *                    insure we reset the caret in a table-editing method.
    */
-  MOZ_CAN_RUN_SCRIPT
   void SetSelectionAfterTableEdit(Element* aTable, int32_t aRow, int32_t aCol,
                                   int32_t aDirection, bool aSelected);
 
   void RemoveListenerAndDeleteRef(const nsAString& aEvent,
                                   nsIDOMEventListener* aListener,
                                   bool aUseCapture, ManualNACPtr aElement,
                                   PresShell* aPresShell);
   void DeleteRefToAnonymousNode(ManualNACPtr aContent, PresShell* aPresShell);
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ b/editor/libeditor/HTMLEditorEventListener.cpp
@@ -253,17 +253,17 @@ nsresult HTMLEditorEventListener::MouseD
   // point.  Then, we won't be able to commit the composition.
   if (!EnsureCommitComposition()) {
     return NS_OK;
   }
 
   WidgetMouseEvent* mousedownEvent =
       aMouseEvent->WidgetEventPtr()->AsMouseEvent();
 
-  RefPtr<HTMLEditor> htmlEditor = mEditorBase->AsHTMLEditor();
+  HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
   MOZ_ASSERT(htmlEditor);
 
   // Contenteditable should disregard mousedowns outside it.
   // IsAcceptableInputEvent() checks it for a mouse event.
   if (!htmlEditor->IsAcceptableInputEvent(mousedownEvent)) {
     return EditorEventListener::MouseDown(aMouseEvent);
   }
 
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -58,22 +58,20 @@ class MOZ_STACK_CLASS AutoSelectionSette
                                     int32_t aDirection, bool aSelected)
       : mHTMLEditor(&aHTMLEditor),
         mTable(aTable),
         mCol(aCol),
         mRow(aRow),
         mDirection(aDirection),
         mSelected(aSelected) {}
 
-  MOZ_CAN_RUN_SCRIPT
   ~AutoSelectionSetterAfterTableEdit() {
     if (mHTMLEditor) {
-      MOZ_KnownLive(mHTMLEditor)
-          ->SetSelectionAfterTableEdit(MOZ_KnownLive(mTable), mRow, mCol,
-                                       mDirection, mSelected);
+      mHTMLEditor->SetSelectionAfterTableEdit(mTable, mRow, mCol, mDirection,
+                                              mSelected);
     }
   }
 
   // This is needed to abort the caret reset in the destructor
   // when one method yields control to another
   void CancelSetCaret() {
     mHTMLEditor = nullptr;
     mTable = nullptr;
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -1700,24 +1700,30 @@ nsresult TextEditRules::HideLastPassword
     return NS_OK;
   }
 
   selNode->GetAsText()->ReplaceData(mLastStart, mLastLength, hiddenText,
                                     IgnoreErrors());
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
-  IgnoredErrorResult ignoredError;
-  MOZ_KnownLive(SelectionRefPtr())
-      ->SetStartAndEndInLimiter(RawRangeBoundary(selNode, start),
-                                RawRangeBoundary(selNode, end), ignoredError);
+  // 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 = SelectionRefPtr()->Collapse(selNode, start);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
-  NS_WARNING_ASSERTION(!ignoredError.Failed(), "Failed to set selection");
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
+  if (start != 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;
 }
 
 // static
 void TextEditRules::FillBufWithPWChars(nsAString* aOutString, int32_t aLength) {
   MOZ_ASSERT(aOutString);
 
   // change the output to the platform password character
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -1193,35 +1193,28 @@ nsresult TextEditor::SetTextAsSubAction(
     return NS_OK;
   }
   if (!handled) {
     // Note that do not notify selectionchange caused by selecting all text
     // because it's preparation of our delete implementation so web apps
     // shouldn't receive such selectionchange before the first mutation.
     AutoUpdateViewBatch preventSelectionChangeEvent(*this);
 
-    Element* rootElement = GetRoot();
-    if (NS_WARN_IF(!rootElement)) {
-      return NS_ERROR_FAILURE;
-    }
-
     // We want to select trailing BR node to remove all nodes to replace all,
     // 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 = SelectionRefPtr()->Collapse(rootElement, 0);
-      NS_WARNING_ASSERTION(
-          NS_SUCCEEDED(rv),
-          "Failed to move caret to start of the editor root element");
     } else {
-      ErrorResult error;
-      SelectionRefPtr()->SelectAllChildren(*rootElement, error);
-      NS_WARNING_ASSERTION(
-          !error.Failed(),
-          "Failed to select all children of the editor root element");
-      rv = error.StealNSResult();
+      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
@@ -2145,62 +2138,56 @@ void TextEditor::OnEndHandlingTopLevelEd
 
 nsresult TextEditor::SelectEntireDocument() {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (!mRules) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  Element* rootElement = GetRoot();
-  if (NS_WARN_IF(!rootElement)) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
-  // If we're empty, don't select all children because that would select the
-  // bogus node.
+  // is doc empty?
   if (rules->DocumentIsEmpty()) {
-    nsresult rv = SelectionRefPtr()->Collapse(rootElement, 0);
-    NS_WARNING_ASSERTION(
-        NS_SUCCEEDED(rv),
-        "Failed to move caret to start of the editor root element");
+    // get root node
+    Element* rootElement = GetRoot();
+    if (NS_WARN_IF(!rootElement)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // if it's empty don't select entire doc - that would select the bogus node
+    return SelectionRefPtr()->Collapse(rootElement, 0);
+  }
+
+  SelectionBatcher selectionBatcher(SelectionRefPtr());
+  nsresult rv = EditorBase::SelectEntireDocument();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Don't select the trailing BR node if we have one
   nsCOMPtr<nsIContent> childNode;
-  nsresult rv = EditorBase::GetEndChildNode(*SelectionRefPtr(),
-                                            getter_AddRefs(childNode));
+  rv = EditorBase::GetEndChildNode(*SelectionRefPtr(),
+                                   getter_AddRefs(childNode));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (childNode) {
     childNode = childNode->GetPreviousSibling();
   }
 
   if (childNode && TextEditUtils::IsMozBR(childNode)) {
-    ErrorResult error;
-    MOZ_KnownLive(SelectionRefPtr())
-        ->SetStartAndEndInLimiter(RawRangeBoundary(rootElement, 0),
-                                  EditorRawDOMPoint(childNode), error);
-    NS_WARNING_ASSERTION(!error.Failed(),
-                         "Failed to select all children of the editor root "
-                         "element except the moz-<br> element");
-    return error.StealNSResult();
+    int32_t parentOffset;
+    nsINode* parentNode = GetNodeLocation(childNode, &parentOffset);
+
+    return SelectionRefPtr()->Extend(parentNode, parentOffset);
   }
 
-  ErrorResult error;
-  SelectionRefPtr()->SelectAllChildren(*rootElement, error);
-  NS_WARNING_ASSERTION(
-      !error.Failed(),
-      "Failed to select all children of the editor root element");
-  return error.StealNSResult();
+  return NS_OK;
 }
 
 EventTarget* TextEditor::GetDOMEventTarget() { return mEventTarget; }
 
 nsresult TextEditor::SetAttributeOrEquivalent(Element* aElement,
                                               nsAtom* aAttribute,
                                               const nsAString& aValue,
                                               bool aSuppressTransaction) {
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -100,17 +100,16 @@ class TextEditor : public EditorBase, pu
   bool IsEmpty() const {
     bool isEmpty = false;
     nsresult rv = IsEmpty(&isEmpty);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                          "Checking whether the editor is empty failed");
     return NS_SUCCEEDED(rv) && isEmpty;
   }
 
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult HandleKeyPressEvent(
       WidgetKeyboardEvent* aKeyboardEvent) override;
 
   virtual dom::EventTarget* GetDOMEventTarget() override;
 
   /**
    * PasteAsAction() pastes clipboard content to Selection.  This method
    * may dispatch ePaste event first.  If its defaultPrevent() is called,
@@ -169,28 +168,26 @@ class TextEditor : public EditorBase, pu
   void SetMaxTextLength(int32_t aLength) { mMaxTextLength = aLength; }
 
   /**
    * Replace existed string with a string.
    * This is fast path to replace all string when using single line control.
    *
    * @ param aString   the string to be set
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult SetText(const nsAString& aString);
 
   /**
    * Replace text in aReplaceRange or all text in this editor with aString and
    * treat the change as inserting the string.
    *
    * @param aString             The string to set.
    * @param aReplaceRange       The range to be replaced.
    *                            If nullptr, all contents will be replaced.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult ReplaceTextAsAction(const nsAString& aString,
                                nsRange* aReplaceRange = nullptr);
 
   /**
    * InsertLineBreakAsAction() is called when user inputs a line break with
    * Enter or something.
    */
   virtual nsresult InsertLineBreakAsAction();
@@ -363,17 +360,16 @@ class TextEditor : public EditorBase, pu
  protected:  // Shouldn't be used by friend classes
   virtual ~TextEditor();
 
   int32_t WrapWidth() const { return mWrapColumn; }
 
   /**
    * Make the given selection span the entire document.
    */
-  MOZ_CAN_RUN_SCRIPT
   virtual nsresult SelectEntireDocument() override;
 
   /**
    * OnInputText() is called when user inputs text with keyboard or something.
    *
    * @param aStringToInsert     The string to insert.
    */
   nsresult OnInputText(const nsAString& aStringToInsert);
--- a/editor/libeditor/tests/test_bug430392.html
+++ b/editor/libeditor/tests/test_bug430392.html
@@ -33,17 +33,19 @@ function test() {
   // it's neither the original value nor expectedValue.
   var tests = [["adding returns", () => {
     getSelection().collapse(edit.firstChild, 0);
     synthesizeKey("KEY_ArrowRight");
     synthesizeKey("KEY_Enter");
     synthesizeKey("KEY_Enter");
     synthesizeKey("KEY_Backspace");
     synthesizeKey("KEY_Backspace");
-  }],
+  // For some reason this test fails if the separator is not "br"
+  }, () => document.queryCommandValue("defaultParagraphSeparator") == "br"
+           ? undefined : " A; B ; C "],
   ["adding shift-returns", () => {
     getSelection().collapse(edit.firstChild, 0);
     synthesizeKey("KEY_ArrowRight");
     synthesizeKey("KEY_Enter", {shiftKey: true});
     synthesizeKey("KEY_Enter", {shiftKey: true});
     synthesizeKey("KEY_Backspace");
     synthesizeKey("KEY_Backspace");
   }]];
--- a/editor/nsIEditor.idl
+++ b/editor/nsIEditor.idl
@@ -300,17 +300,16 @@ interface nsIEditor  : nsISupports
   /** Can we paste? True if the doc is modifiable, and we have
     * pasteable data in the clipboard.
     */
   boolean canPaste(in long aSelectionType);
 
   /* ------------ Selection methods -------------- */
 
   /** sets the document selection to the entire contents of the document */
-  [can_run_script]
   void selectAll();
 
   /**
    * Collapses selection at start of the document.  If it's an HTML editor,
    * collapses selection at start of current editing host (<body> element if
    * it's in designMode) instead.  If there is a non-editable node before any
    * editable text nodes or inline elements which can have text nodes as their
    * children, collapses selection at start of the editing host.  If there is
--- a/editor/nsIEditorMailSupport.idl
+++ b/editor/nsIEditorMailSupport.idl
@@ -25,12 +25,11 @@ interface nsIEditorMailSupport : nsISupp
   Node insertAsCitedQuotation(in AString aQuotedText,
                               in AString aCitation,
                               in boolean aInsertHTML);
 
   /**
    * Rewrap the selected part of the document, re-quoting if necessary.
    * @param aRespectNewlines  Try to maintain newlines in the original?
    */
-  [can_run_script]
   void rewrap(in boolean aRespectNewlines);
 };
 
--- a/editor/nsIEditorSpellCheck.idl
+++ b/editor/nsIEditorSpellCheck.idl
@@ -31,17 +31,16 @@ interface nsIEditorSpellCheck : nsISuppo
 
   /**
    * When interactively spell checking the document, this will return the
    * value of the next word that is misspelled. This also computes the
    * suggestions which you can get by calling GetSuggestedWord.
    *
    * @see mozSpellChecker::GetNextMisspelledWord
    */
-  [can_run_script]
   AString       GetNextMisspelledWord();
 
   /**
    * Used to get suggestions for the last word that was checked and found to
    * be misspelled. The first call will give you the first (best) suggestion.
    * Subsequent calls will iterate through all the suggestions, allowing you
    * to build a list. When there are no more suggestions, an empty string
    * (not a null pointer) will be returned.
@@ -60,17 +59,16 @@ interface nsIEditorSpellCheck : nsISuppo
    */
   boolean       CheckCurrentWord(in AString suggestedWord);
 
   /**
    * Use when modally checking the document to replace a word.
    *
    * @see mozSpellChecker::CheckCurrentWord
    */
-  [can_run_script]
   void          ReplaceWord(in AString misspelledWord, in AString replaceWord, in boolean allOccurrences);
 
   /**
    * @see mozSpellChecker::IgnoreAll
    */
   void          IgnoreWordAllOccurrences(in AString word);
 
   /**
--- a/editor/nsIHTMLEditor.idl
+++ b/editor/nsIHTMLEditor.idl
@@ -142,17 +142,16 @@ interface nsIHTMLEditor : nsISupports
   void pasteNoFormatting(in long aSelectionType);
 
   /**
    *  Rebuild the entire document from source HTML
    *  Needed to be able to edit HEAD and other outside-of-BODY content
    *
    *  @param aSourceString   HTML source string of the entire new document
    */
-  [can_run_script]
   void rebuildDocumentFromSource(in AString aSourceString);
 
   /**
     * Insert an element, which may have child nodes, at the selection
     * Used primarily to insert a new element for various insert element dialogs,
     *   but it enforces the HTML 4.0 DTD "CanContain" rules, so it should
     *   be useful for other elements.
     *
@@ -178,17 +177,16 @@ interface nsIHTMLEditor : nsISupports
   /* ------------ Selection manipulation -------------- */
   /* Should these be moved to Selection? */
 
   /**
     * Set the selection at the suppled element
     *
     * @param aElement   An element in the document
     */
-  [can_run_script]
   void selectElement(in Element aElement);
 
   /**
     * Create a collapsed selection just after aElement
     *
     * XXX could we parameterize SelectElement(before/select/after>?
     *
     * The selection is set to parent-of-aElement with an
--- a/editor/nsITableEditor.idl
+++ b/editor/nsITableEditor.idl
@@ -32,90 +32,84 @@ interface nsITableEditor : nsISupports
    * If first selection range is not in table cell element, this does nothing
    * without exception.
    *
    * @param aNumberOfCellssToInsert     Number of cells to insert.
    * @param aInsertAfterSelectedCell    true if new cells should be inserted
    *                                    before current cell.  Otherwise, will
    *                                    be inserted after the cell.
    */
-  [can_run_script]
   void insertTableCell(in long aNumberOfColumnsToInsert,
                        in boolean aInsertAfterSelectedCell);
 
   /**
    * insertTableColumn() inserts columns before or after a cell element
    * containing first selection range.  I.e., if the cell spans columns and
    * aInsertAfterSelectedCell is tre, new columns will be inserted after the
    * right-most column which contains the cell.  If first selection range is
    * not in table cell element, this does nothing without exception.
    *
    * @param aNumberOfColumnsToInsert    Number of columns to insert.
    * @param aInsertAfterSelectedCell    true if new columns will be inserted
    *                                    before current cell.  Otherwise, will
    *                                    be inserted after the cell.
    */
-  [can_run_script]
   void insertTableColumn(in long aNumberOfColumnsToInsert,
                          in boolean aInsertAfterSelectedCell);
 
   /*
    * insertTableRow() inserts <tr> elements before or after a <td> element
    * containing first selection range.  I.e., if the cell spans rows and
    * aInsertAfterSelectedCell is true, new rows will be inserted after the
    * bottom-most row which contains the cell.  If first selection range is
    * not in table cell element, this does nothing without exception.
    *
    * @param aNumberOfRowsToInsert       Number of rows to insert.
    * @param aInsertAfterSelectedCell    true if new rows will be inserted
    *                                    before current cell.  Otherwise, will
    *                                    be inserted after the cell.
    */
-  [can_run_script]
   void insertTableRow(in long aNumberOfRowsToInsert,
                       in boolean aInsertAfterSelectedCell);
 
   /** Delete table methods
     * Delete starting at the selected cell or the
     *  cell (or table) enclosing the selection anchor
     * The selection is collapsed and is left in the
     *  cell at the same row,col location as
     *  the previous selection anchor, if possible,
     *  else in the closest neigboring cell
     *
     * @param aNumber    Number of items to insert/delete
     */
-  [can_run_script]
   void deleteTable();
 
   /**
    * deleteTableCellContents() removes any contents in cell elements.  If two
    * or more cell elements are selected, this removes all selected cells'
    * contents.  Otherwise, this removes contents of a cell which contains
    * first selection range.  This does nothing without exception if selection
    * is not in cell element.
    */
-  [can_run_script]
   void deleteTableCellContents();
 
   /**
    * deleteTableCell() removes table cell elements.  If two or more cell
    * elements are selected, this removes all selected cell elements.
    * Otherwise, this removes some cell elements starting from selected cell
    * element or a cell containing first selection range.  When this removes
    * last cell element in <tr> or <table>, this removes the <tr> or the
    * <table> too.  Note that when removing a cell causes number of its row
    * becomes less than the others, this method does NOT fill the place with
    * rowspan nor colspan.  This does nothing without exception if selection is
    * not in cell element.
    *
    * @param aNumberOfCellsToDelete  Number of cells to remove.  This is ignored
    *                                if 2 or more cells are selected.
    */
-  [can_run_script]
   void deleteTableCell(in long aNumberOfCellsToDelete);
 
   /**
    * deleteTableColumn() removes cell elements which belong to same columns
    * of selected cell elements.
    * If only one cell element is selected or first selection range is
    * in a cell, removes cell elements which belong to same column.
    * If 2 or more cell elements are selected, removes cell elements which
@@ -125,17 +119,16 @@ interface nsITableEditor : nsISupports
    * If selection is not in a cell element, just does nothing without
    * throwing exception.
    * WARNING: This does not remove <col> nor <colgroup> elements.
    *
    * @param aNumberOfColumnsToDelete    Number of columns to remove.  This is
    *                                    ignored if 2 ore more cells are
    *                                    selected.
    */
-  [can_run_script]
   void deleteTableColumn(in long aNumberOfColumnsToDelete);
 
   /**
    * deleteTableRow() removes <tr> elements.
    * If only one cell element is selected or first selection range is
    * in a cell, removes <tr> elements starting from a <tr> element
    * containing the selected cell or first selection range.
    * If 2 or more cell elements are selected, all <tr> elements
@@ -143,56 +136,48 @@ interface nsITableEditor : nsISupports
    * is ignored.
    * If there is no selection ranges, throws exception.
    * If selection is not in a cell element, just does nothing without
    * throwing exception.
    *
    * @param aNumberOfRowsToDelete   Number of rows to remove.  This is ignored
    *                                if 2 or more cells are selected.
    */
-  [can_run_script]
   void deleteTableRow(in long aNumberOfRowsToDelete);
 
   /** Table Selection methods
     * Selecting a row or column actually
     * selects all cells (not TR in the case of rows)
     */
-  [can_run_script]
   void selectTableCell();
 
   /** Select a rectangular block of cells:
     *  all cells falling within the row/column index of aStartCell
     *  to through the row/column index of the aEndCell
     *  aStartCell can be any location relative to aEndCell,
     *   as long as they are in the same table
     *  @param aStartCell  starting cell in block
     *  @param aEndCell    ending cell in block
     */
-  [can_run_script]
   void selectBlockOfCells(in Element aStartCell,
                           in Element aEndCell);
 
-  [can_run_script]
   void selectTableRow();
-  [can_run_script]
   void selectTableColumn();
-  [can_run_script]
   void selectTable();
-  [can_run_script]
   void selectAllTableCells();
 
   /** Create a new TD or TH element, the opposite type of the supplied aSourceCell
     *   1. Copy all attributes from aSourceCell to the new cell
     *   2. Move all contents of aSourceCell to the new cell
     *   3. Replace aSourceCell in the table with the new cell
     *
     *  @param aSourceCell   The cell to be replaced
     *  @return              The new cell that replaces aSourceCell
     */
-  [can_run_script]
   Element switchTableCellHeaderType(in Element aSourceCell);
 
   /** Merges contents of all selected cells
     * for selected cells that are adjacent,
     * this will result in a larger cell with appropriate
     * rowspan and colspan, and original cells are deleted
     * The resulting cell is in the location of the
     *   cell at the upper-left corner of the adjacent
@@ -205,39 +190,36 @@ interface nsITableEditor : nsISupports
     *         to the upper-left cell
     *       If false: contiguous cells are ignored
     *
     * If there are no selected cells,
     *   and selection or caret is in a cell,
     *   that cell and the one to the right
     *   are merged
     */
-  [can_run_script]
   void joinTableCells(in boolean aMergeNonContiguousContents);
 
   /** Split a cell that has rowspan and/or colspan > 0
     *   into cells such that all new cells have
     *   rowspan = 1 and colspan = 1
     *  All of the contents are not touched --
     *   they will appear to be in the upper-left cell
     */
-  [can_run_script]
   void splitTableCell();
 
   /** Scan through all rows and add cells as needed so
     *   all locations in the cellmap are occupied.
     *   Used after inserting single cells or pasting
     *   a collection of cells that extend past the
     *   previous size of the table
     * If aTable is null, it uses table enclosing the selection anchor
     * This doesn't doesn't change the selection,
     *   thus it can be used to fixup all tables
     *   in a page independent of the selection
     */
-  [can_run_script]
   void normalizeTable(in Element aTable);
 
   /**
    * getCellIndexes() computes row index and column index of a table cell.
    * Note that this depends on layout information.  Therefore, all pending
    * layout should've been flushed before calling this.
    *
    * @param aCellElement        If not null, this computes indexes of the cell.
--- a/editor/spellchecker/EditorSpellCheck.cpp
+++ b/editor/spellchecker/EditorSpellCheck.cpp
@@ -402,19 +402,18 @@ EditorSpellCheck::InitSpellChecker(nsIEd
 
 NS_IMETHODIMP
 EditorSpellCheck::GetNextMisspelledWord(nsAString& aNextMisspelledWord) {
   NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
 
   DeleteSuggestedWordList();
   // Beware! This may flush notifications via synchronous
   // ScrollSelectionIntoView.
-  RefPtr<mozSpellChecker> spellChecker(mSpellChecker);
-  return spellChecker->NextMisspelledWord(aNextMisspelledWord,
-                                          &mSuggestedWordList);
+  return mSpellChecker->NextMisspelledWord(aNextMisspelledWord,
+                                           &mSuggestedWordList);
 }
 
 NS_IMETHODIMP
 EditorSpellCheck::GetSuggestedWord(nsAString& aSuggestedWord) {
   // XXX This is buggy if mSuggestedWordList.Length() is over INT32_MAX.
   if (mSuggestedWordIndex < static_cast<int32_t>(mSuggestedWordList.Length())) {
     aSuggestedWord = mSuggestedWordList[mSuggestedWordIndex];
     mSuggestedWordIndex++;
@@ -446,18 +445,17 @@ RefPtr<CheckWordPromise> EditorSpellChec
 }
 
 NS_IMETHODIMP
 EditorSpellCheck::ReplaceWord(const nsAString& aMisspelledWord,
                               const nsAString& aReplaceWord,
                               bool aAllOccurrences) {
   NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
 
-  RefPtr<mozSpellChecker> spellChecker(mSpellChecker);
-  return spellChecker->Replace(aMisspelledWord, aReplaceWord, aAllOccurrences);
+  return mSpellChecker->Replace(aMisspelledWord, aReplaceWord, aAllOccurrences);
 }
 
 NS_IMETHODIMP
 EditorSpellCheck::IgnoreWordAllOccurrences(const nsAString& aWord) {
   NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
 
   return mSpellChecker->IgnoreAll(aWord);
 }
--- a/editor/spellchecker/TextServicesDocument.cpp
+++ b/editor/spellchecker/TextServicesDocument.cpp
@@ -1661,20 +1661,17 @@ bool TextServicesDocument::HasSameBlockN
 bool TextServicesDocument::IsTextNode(nsIContent* aContent) {
   NS_ENSURE_TRUE(aContent, false);
   return nsINode::TEXT_NODE == aContent->NodeType();
 }
 
 nsresult TextServicesDocument::SetSelectionInternal(int32_t aOffset,
                                                     int32_t aLength,
                                                     bool aDoUpdate) {
-  if (NS_WARN_IF(!mSelCon) || NS_WARN_IF(aOffset < 0) ||
-      NS_WARN_IF(aLength < 0)) {
-    return NS_ERROR_INVALID_ARG;
-  }
+  NS_ENSURE_TRUE(mSelCon && aOffset >= 0 && aLength >= 0, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsINode> startNode;
   int32_t startNodeOffset = 0;
   OffsetEntry* entry;
 
   // Find start of selection in node offset terms:
 
   for (size_t i = 0; !startNode && i < mOffsetTable.Length(); i++) {
@@ -1726,32 +1723,36 @@ nsresult TextServicesDocument::SetSelect
   }
 
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
 
   // XXX: If we ever get a SetSelection() method in nsIEditor, we should
   //      use it.
 
   RefPtr<Selection> selection;
+
   if (aDoUpdate) {
     selection = mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL);
-    if (NS_WARN_IF(!selection)) {
-      return NS_ERROR_FAILURE;
-    }
+    NS_ENSURE_STATE(selection);
+
+    nsresult rv = selection->Collapse(startNode, startNodeOffset);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if (!aLength) {
-    if (aDoUpdate) {
-      nsresult rv = selection->Collapse(startNode, startNodeOffset);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
-    }
+  if (aLength <= 0) {
+    // We have a collapsed selection. (Caret)
+
     mSelEndIndex = mSelStartIndex;
     mSelEndOffset = mSelStartOffset;
+
+    //**** KDEBUG ****
+    // printf("\n* Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex,
+    //        mSelStartOffset, mSelEndIndex, mSelEndOffset);
+    //**** KDEBUG ****
+
     return NS_OK;
   }
 
   // Find the end of the selection in node offset terms:
   nsCOMPtr<nsINode> endNode;
   int32_t endNodeOffset = 0;
   int32_t endOffset = aOffset + aLength;
   for (int32_t i = mOffsetTable.Length() - 1; !endNode && i >= 0; i--) {
@@ -1774,32 +1775,28 @@ nsresult TextServicesDocument::SetSelect
 
       if (endNode) {
         mSelEndIndex = i;
         mSelEndOffset = endOffset;
       }
     }
   }
 
-  if (!aDoUpdate) {
-    return NS_OK;
+  if (aDoUpdate && endNode) {
+    nsresult rv = selection->Extend(endNode, endNodeOffset);
+
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if (!endNode) {
-    nsresult rv = selection->Collapse(startNode, startNodeOffset);
-    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to collapse selection");
-    return rv;
-  }
-
-  ErrorResult error;
-  selection->SetStartAndEndInLimiter(
-      RawRangeBoundary(startNode, startNodeOffset),
-      RawRangeBoundary(endNode, endNodeOffset), error);
-  NS_WARNING_ASSERTION(!error.Failed(), "Failed to set selection");
-  return error.StealNSResult();
+  //**** KDEBUG ****
+  // printf("\n * Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex,
+  //        mSelStartOffset, mSelEndIndex, mSelEndOffset);
+  //**** KDEBUG ****
+
+  return NS_OK;
 }
 
 nsresult TextServicesDocument::GetSelection(BlockSelectionStatus* aSelStatus,
                                             int32_t* aSelOffset,
                                             int32_t* aSelLength) {
   NS_ENSURE_TRUE(aSelStatus && aSelOffset && aSelLength, NS_ERROR_NULL_POINTER);
 
   *aSelStatus = BlockSelectionStatus::eBlockNotFound;
--- a/editor/spellchecker/TextServicesDocument.h
+++ b/editor/spellchecker/TextServicesDocument.h
@@ -145,17 +145,16 @@ class TextServicesDocument final : publi
    * @param aSelectionStatus    [OUT] This will contain the text block
    *                            selection status.
    * @param aSelectionOffset    [OUT] This will contain the offset into the
    *                            string returned by GetCurrentTextBlock() where
    *                            the selection begins.
    * @param aLength             [OUT] This will contain the number of
    *                            characters that are selected in the string.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult LastSelectedBlock(BlockSelectionStatus* aSelStatus,
                              int32_t* aSelOffset, int32_t* aSelLength);
 
   /**
    * Tells the document to point to the text block before the current one.
    * This method will return NS_OK, even if there is no previous block.
    * Callers should call IsDone() to check if we have gone beyond the first
    * text block in the document.
@@ -185,37 +184,34 @@ class TextServicesDocument final : publi
    * into the string returned by GetCurrentTextBlock().  A length of zero
    * places the cursor at that offset. A positive non-zero length "n" selects
    * n characters in the string.
    *
    * @param aOffset             Offset into string returned by
    *                            GetCurrentTextBlock().
    * @param aLength             Number of characters selected.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult SetSelection(int32_t aOffset, int32_t aLength);
 
   /**
    * Scrolls the document so that the current selection is visible.
    */
   nsresult ScrollSelectionIntoView();
 
   /**
    * Deletes the text selected by SetSelection(). Calling DeleteSelection()
    * with nothing selected, or with a collapsed selection (cursor) does
    * nothing and returns NS_OK.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteSelection();
 
   /**
    * Inserts the given text at the current cursor position.  If there is a
    * selection, it will be deleted before the text is inserted.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult InsertText(const nsString* aText);
 
   /**
    * nsIEditActionListener method implementations.
    */
   NS_DECL_NSIEDITACTIONLISTENER
 
   /**
@@ -266,23 +262,20 @@ class TextServicesDocument final : publi
   static bool IsTextNode(nsIContent* aContent);
 
   static bool DidSkip(FilteredContentIterator* aFilteredIter);
   static void ClearDidSkip(FilteredContentIterator* aFilteredIter);
 
   static bool HasSameBlockNodeParent(nsIContent* aContent1,
                                      nsIContent* aContent2);
 
-  MOZ_CAN_RUN_SCRIPT
   nsresult SetSelectionInternal(int32_t aOffset, int32_t aLength,
                                 bool aDoUpdate);
-  MOZ_CAN_RUN_SCRIPT
   nsresult GetSelection(BlockSelectionStatus* aSelStatus, int32_t* aSelOffset,
                         int32_t* aSelLength);
-  MOZ_CAN_RUN_SCRIPT
   nsresult GetCollapsedSelection(BlockSelectionStatus* aSelStatus,
                                  int32_t* aSelOffset, int32_t* aSelLength);
   nsresult GetUncollapsedSelection(BlockSelectionStatus* aSelStatus,
                                    int32_t* aSelOffset, int32_t* aSelLength);
 
   bool SelectionIsCollapsed();
   bool SelectionIsValid();
 
--- a/editor/spellchecker/nsIInlineSpellChecker.idl
+++ b/editor/spellchecker/nsIInlineSpellChecker.idl
@@ -20,17 +20,16 @@ interface nsIInlineSpellChecker : nsISup
   void init(in nsIEditor aEditor);
   void cleanup(in boolean aDestroyingFrames);
 
   attribute boolean enableRealTimeSpell;
 
   void spellCheckRange(in Range aSelection);
 
   Range getMisspelledWord(in Node aNode, in long aOffset);
-  [can_run_script]
   void replaceWord(in Node aNode, in long aOffset, in AString aNewword);
   void addWordToDictionary(in AString aWord);
   void removeWordFromDictionary(in AString aWord);
 
   void ignoreWord(in AString aWord);
   void ignoreWords([array, size_is(aCount)] in wstring aWordsToIgnore, in unsigned long aCount);
   void updateCurrentDictionary();
 
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -864,18 +864,17 @@ mozInlineSpellChecker::ReplaceWord(nsINo
   RefPtr<nsRange> range;
   nsresult res = GetMisspelledWord(aNode, aOffset, getter_AddRefs(range));
   NS_ENSURE_SUCCESS(res, res);
 
   if (!range) {
     return NS_OK;
   }
 
-  RefPtr<TextEditor> textEditor(mTextEditor);
-  DebugOnly<nsresult> rv = textEditor->ReplaceTextAsAction(newword, range);
+  DebugOnly<nsresult> rv = mTextEditor->ReplaceTextAsAction(newword, range);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the new word");
   return NS_OK;
 }
 
 // mozInlineSpellChecker::AddWordToDictionary
 
 NS_IMETHODIMP
 mozInlineSpellChecker::AddWordToDictionary(const nsAString& word) {
--- a/extensions/spellcheck/src/mozSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozSpellChecker.cpp
@@ -95,18 +95,17 @@ nsresult mozSpellChecker::NextMisspelled
     do {
       result = mConverter->FindNextWord(str.get(), str.Length(), selOffset,
                                         &begin, &end);
       if (NS_SUCCEEDED(result) && begin != -1) {
         const nsAString &currWord = Substring(str, begin, end - begin);
         result = CheckWord(currWord, &isMisspelled, aSuggestions);
         if (isMisspelled) {
           aWord = currWord;
-          MOZ_KnownLive(mTextServicesDocument)
-              ->SetSelection(begin, end - begin);
+          mTextServicesDocument->SetSelection(begin, end - begin);
           // After ScrollSelectionIntoView(), the pending notifications might
           // be flushed and PresShell/PresContext/Frames may be dead.
           // See bug 418470.
           mTextServicesDocument->ScrollSelectionIntoView();
           return NS_OK;
         }
       }
       selOffset = end;
@@ -220,19 +219,18 @@ nsresult mozSpellChecker::Replace(const 
             // block move the selection point forwards
             if (currentBlock == startBlock && begin < selOffset) {
               selOffset +=
                   int32_t(aNewWord.Length()) - int32_t(aOldWord.Length());
               if (selOffset < begin) {
                 selOffset = begin;
               }
             }
-            MOZ_KnownLive(mTextServicesDocument)
-                ->SetSelection(begin, end - begin);
-            MOZ_KnownLive(mTextServicesDocument)->InsertText(&newWord);
+            mTextServicesDocument->SetSelection(begin, end - begin);
+            mTextServicesDocument->InsertText(&newWord);
             mTextServicesDocument->GetCurrentTextBlock(&str);
             end += (aNewWord.Length() -
                     aOldWord.Length());  // recursion was cute in GEB, not here.
           }
         }
         currOffset = end;
       } while (currOffset != -1);
       mTextServicesDocument->NextBlock();
@@ -264,23 +262,23 @@ nsresult mozSpellChecker::Replace(const 
       result = mConverter->FindNextWord(str.get(), str.Length(), selOffset,
                                         &begin, &end);
       if (end == -1) {
         mTextServicesDocument->NextBlock();
         selOffset = 0;
         result = mTextServicesDocument->GetCurrentTextBlock(&str);
         result = mConverter->FindNextWord(str.get(), str.Length(), selOffset,
                                           &begin, &end);
-        MOZ_KnownLive(mTextServicesDocument)->SetSelection(begin, 0);
+        mTextServicesDocument->SetSelection(begin, 0);
       } else {
-        MOZ_KnownLive(mTextServicesDocument)->SetSelection(begin, 0);
+        mTextServicesDocument->SetSelection(begin, 0);
       }
     }
   } else {
-    MOZ_KnownLive(mTextServicesDocument)->InsertText(&newWord);
+    mTextServicesDocument->InsertText(&newWord);
   }
   return NS_OK;
 }
 
 nsresult mozSpellChecker::IgnoreAll(const nsAString &aWord) {
   if (mPersonalDictionary) {
     mPersonalDictionary->IgnoreWord(aWord);
   }
@@ -458,18 +456,18 @@ nsresult mozSpellChecker::SetupDoc(int32
   nsresult rv;
 
   TextServicesDocument::BlockSelectionStatus blockStatus;
   int32_t selOffset;
   int32_t selLength;
   *outBlockOffset = 0;
 
   if (!mFromStart) {
-    rv = MOZ_KnownLive(mTextServicesDocument)
-             ->LastSelectedBlock(&blockStatus, &selOffset, &selLength);
+    rv = mTextServicesDocument->LastSelectedBlock(&blockStatus, &selOffset,
+                                                  &selLength);
     if (NS_SUCCEEDED(rv) &&
         blockStatus !=
             TextServicesDocument::BlockSelectionStatus::eBlockNotFound) {
       switch (blockStatus) {
         // No TB in S, but found one before/after S.
         case TextServicesDocument::BlockSelectionStatus::eBlockOutside:
         // S begins or ends in TB but extends outside of TB.
         case TextServicesDocument::BlockSelectionStatus::eBlockPartial:
--- a/extensions/spellcheck/src/mozSpellChecker.h
+++ b/extensions/spellcheck/src/mozSpellChecker.h
@@ -46,17 +46,16 @@ class mozSpellChecker final {
                        bool aFromStartofDoc);
 
   /**
    * Selects (hilites) the next misspelled word in the document.
    * @param aWord will contain the misspelled word.
    * @param aSuggestions is an array of nsStrings, that represent the
    * suggested replacements for the misspelled word.
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult NextMisspelledWord(nsAString& aWord,
                               nsTArray<nsString>* aSuggestions);
 
   /**
    * Checks if a word is misspelled. No document is required to use this method.
    * @param aWord is the word to check.
    * @param aIsMisspelled will be set to true if the word is misspelled.
    * @param aSuggestions is an array of nsStrings which represent the
@@ -77,17 +76,16 @@ class mozSpellChecker final {
   /**
    * Replaces the old word with the specified new word.
    * @param aOldWord is the word to be replaced.
    * @param aNewWord is the word that is to replace old word.
    * @param aAllOccurrences will replace all occurrences of old
    * word, in the document, with new word when it is true. If
    * false, it will replace the 1st occurrence only!
    */
-  MOZ_CAN_RUN_SCRIPT
   nsresult Replace(const nsAString& aOldWord, const nsAString& aNewWord,
                    bool aAllOccurrences);
 
   /**
    * Ignores all occurrences of the specified word in the document.
    * @param aWord is the word to ignore.
    */
   nsresult IgnoreAll(const nsAString& aWord);
@@ -159,17 +157,16 @@ class mozSpellChecker final {
   RefPtr<mozilla::TextServicesDocument> mTextServicesDocument;
   nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
 
   nsCOMPtr<mozISpellCheckingEngine> mSpellCheckingEngine;
   bool mFromStart;
 
   nsString mCurrentDictionary;
 
-  MOZ_CAN_RUN_SCRIPT
   nsresult SetupDoc(int32_t* outBlockOffset);
 
   nsresult GetCurrentBlockIndex(
       mozilla::TextServicesDocument* aTextServicesDocument,
       int32_t* aOutBlockIndex);
 
   nsresult GetEngineList(nsCOMArray<mozISpellCheckingEngine>* aDictionaryList);
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/focus/Selection_selectAllChildren.html.ini
@@ -0,0 +1,41 @@
+[Selection_selectAllChildren.html]
+  type: testharness
+  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'editor']
+    expected: FAIL
+
+  [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'editor']
+    expected: FAIL
+
+  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'editor']
+    expected: FAIL
+
+  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'editor']
+    expected: FAIL
+
+  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'editor']
+    expected: FAIL
+
+  [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'outerEditor']
+    expected: FAIL
+
+  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'outerEditor']
+    expected: FAIL
+
+  [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'outerEditor']
+    expected: FAIL
+
+  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'innerEditor']
+    expected: FAIL
+
+  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'innerEditor']
+    expected: FAIL
+
+  [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'innerEditor']
+    expected: FAIL
+
+  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'innerEditor']
+    expected: FAIL
+
+  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'innerEditor']
+    expected: FAIL
+