Merge mozilla-central to autoland.
authorCosmin Sabou <csabou@mozilla.com>
Wed, 03 Jul 2019 19:21:47 +0300
changeset 540789 7eff60789f10b2766615d486b8e9c1568b7efcbd
parent 540783 0ab7f6c67d4be16e78cdac5b729729646a3375e5 (current diff)
parent 540788 5f0961efaa1c01e5b4bc449ee5d58260393291ef (diff)
child 540790 3fe0f2c3a8754730c5335862f40f84bdea58a081
push id11529
push userarchaeopteryx@coole-files.de
push dateThu, 04 Jul 2019 15:22:33 +0000
treeherdermozilla-beta@ebb510a784b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland.
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -229,17 +229,17 @@ nsresult nsCoreUtils::ScrollSubstringTo(
   nsCOMPtr<nsISelectionController> selCon;
   aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
 
   RefPtr<dom::Selection> selection =
       selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY);
 
   selection->RemoveAllRanges(IgnoreErrors());
-  selection->AddRange(*aRange, IgnoreErrors());
+  selection->AddRangeAndSelectFramesAndNotifyListeners(*aRange, IgnoreErrors());
 
   selection->ScrollIntoView(nsISelectionController::SELECTION_ANCHOR_REGION,
                             aVertical, aHorizontal,
                             Selection::SCROLL_SYNCHRONOUS);
 
   selection->CollapseToStart(IgnoreErrors());
 
   return NS_OK;
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1267,17 +1267,18 @@ nsresult HyperTextAccessible::SetSelecti
   // some input controls
   if (isFocusable) TakeFocus();
 
   dom::Selection* domSel = DOMSelection();
   NS_ENSURE_STATE(domSel);
 
   // Set up the selection.
   for (int32_t idx = domSel->RangeCount() - 1; idx > 0; idx--)
-    domSel->RemoveRange(*domSel->GetRangeAt(idx), IgnoreErrors());
+    domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(
+        *domSel->GetRangeAt(idx), IgnoreErrors());
   SetSelectionBoundsAt(0, aStartPos, aEndPos);
 
   // Make sure it is visible
   domSel->ScrollIntoView(nsISelectionController::SELECTION_FOCUS_REGION,
                          ScrollAxis(), ScrollAxis(),
                          dom::Selection::SCROLL_FOR_CARET_MOVE |
                              dom::Selection::SCROLL_OVERFLOW_HIDDEN);
 
@@ -1566,21 +1567,22 @@ bool HyperTextAccessible::SetSelectionBo
 
   if (!OffsetsToDOMRange(std::min(startOffset, endOffset),
                          std::max(startOffset, endOffset), range))
     return false;
 
   // If this is not a new range, notify selection listeners that the existing
   // selection range has changed. Otherwise, just add the new range.
   if (aSelectionNum != static_cast<int32_t>(rangeCount)) {
-    domSel->RemoveRange(*range, IgnoreErrors());
+    domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(*range,
+                                                           IgnoreErrors());
   }
 
   IgnoredErrorResult err;
-  domSel->AddRange(*range, err);
+  domSel->AddRangeAndSelectFramesAndNotifyListeners(*range, err);
 
   if (!err.Failed()) {
     // Changing the direction of the selection assures that the caret
     // will be at the logical end of the selection.
     domSel->SetDirection(startOffset < endOffset ? eDirNext : eDirPrevious);
     return true;
   }
 
@@ -1590,17 +1592,18 @@ bool HyperTextAccessible::SetSelectionBo
 bool HyperTextAccessible::RemoveFromSelection(int32_t aSelectionNum) {
   dom::Selection* domSel = DOMSelection();
   if (!domSel) return false;
 
   if (aSelectionNum < 0 ||
       aSelectionNum >= static_cast<int32_t>(domSel->RangeCount()))
     return false;
 
-  domSel->RemoveRange(*domSel->GetRangeAt(aSelectionNum), IgnoreErrors());
+  domSel->RemoveRangeAndUnselectFramesAndNotifyListeners(
+      *domSel->GetRangeAt(aSelectionNum), IgnoreErrors());
   return true;
 }
 
 void HyperTextAccessible::ScrollSubstringTo(int32_t aStartOffset,
                                             int32_t aEndOffset,
                                             uint32_t aScrollType) {
   RefPtr<nsRange> range = new nsRange(mContent);
   if (OffsetsToDOMRange(aStartOffset, aEndOffset, range))
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -933,17 +933,17 @@ nsresult Selection::AddItem(nsRange* aIt
   if (!aItem->IsPositioned()) return NS_ERROR_UNEXPECTED;
 
   NS_ASSERTION(aOutIndex, "aOutIndex can't be null");
 
   if (mUserInitiated) {
     AutoTArray<RefPtr<nsRange>, 4> rangesToAdd;
     *aOutIndex = int32_t(mRanges.Length()) - 1;
 
-    Document* doc = GetParentObject();
+    Document* doc = GetDocument();
     bool selectEventsEnabled =
         StaticPrefs::dom_select_events_enabled() ||
         (doc && nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()));
 
     if (!aNoStartSelect && mSelectionType == SelectionType::eNormal &&
         selectEventsEnabled && IsCollapsed() &&
         !IsBlockingSelectionChangeEvents()) {
       // First, we generate the ranges to add with a scratch range, which is a
@@ -979,17 +979,17 @@ nsresult Selection::AddItem(nsRange* aIt
             // This is a selection under a text control, so don't dispatch the
             // event.
             dispatchEvent = false;
           }
         }
 
         if (dispatchEvent) {
           nsContentUtils::DispatchTrustedEvent(
-              GetParentObject(), target, NS_LITERAL_STRING("selectstart"),
+              GetDocument(), target, NS_LITERAL_STRING("selectstart"),
               CanBubble::eYes, Cancelable::eYes, &defaultAction);
 
           if (!defaultAction) {
             return NS_OK;
           }
 
           // As we just dispatched an event to the DOM, something could have
           // changed under our feet. Re-generate the rangesToAdd array, and
@@ -1973,26 +1973,28 @@ nsresult Selection::RemoveAllRangesTempo
     mCachedRange->ResetTemporarily();
   }
   return result.StealNSResult();
 }
 
 void Selection::AddRangeJS(nsRange& aRange, ErrorResult& aRv) {
   AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
   mCalledByJS = true;
-  AddRange(aRange, aRv);
+  AddRangeAndSelectFramesAndNotifyListeners(aRange, aRv);
 }
 
-void Selection::AddRange(nsRange& aRange, ErrorResult& aRv) {
-  RefPtr<Document> document(GetParentObject());
-  return AddRangeInternal(aRange, document, aRv);
+void Selection::AddRangeAndSelectFramesAndNotifyListeners(nsRange& aRange,
+                                                          ErrorResult& aRv) {
+  RefPtr<Document> document(GetDocument());
+  return AddRangeAndSelectFramesAndNotifyListeners(aRange, document, aRv);
 }
 
-void Selection::AddRangeInternal(nsRange& aRange, Document* aDocument,
-                                 ErrorResult& aRv) {
+void Selection::AddRangeAndSelectFramesAndNotifyListeners(nsRange& aRange,
+                                                          Document* aDocument,
+                                                          ErrorResult& aRv) {
   // If the given range is part of another Selection, we need to clone the
   // range first.
   RefPtr<nsRange> range;
   if (aRange.IsInSelection() && aRange.GetSelection() != this) {
     // Because of performance reason, when there is a cached range, let's use
     // it.  Otherwise, clone the range.
     if (mCachedRange) {
       range = std::move(mCachedRange);
@@ -2062,29 +2064,30 @@ void Selection::AddRangeInternal(nsRange
   // XXX Why doesn't this call Selection::NotifySelectionListener() directly?
   RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
   result = frameSelection->NotifySelectionListeners(GetType());
   if (NS_FAILED(result)) {
     aRv.Throw(result);
   }
 }
 
-// Selection::RemoveRange
+// Selection::RemoveRangeAndUnselectFramesAndNotifyListeners
 //
 //    Removes the given range from the selection. The tricky part is updating
 //    the flags on the frames that indicate whether they have a selection or
 //    not. There could be several selection ranges on the frame, and clearing
 //    the bit would cause the selection to not be drawn, even when there is
 //    another range on the frame (bug 346185).
 //
 //    We therefore find any ranges that intersect the same nodes as the range
 //    being removed, and cause them to set the selected bits back on their
 //    selected frames after we've cleared the bit from ours.
 
-void Selection::RemoveRange(nsRange& aRange, ErrorResult& aRv) {
+void Selection::RemoveRangeAndUnselectFramesAndNotifyListeners(
+    nsRange& aRange, ErrorResult& aRv) {
   nsresult rv = RemoveItem(&aRange);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   nsINode* beginNode = aRange.GetStartContainer();
   nsINode* endNode = aRange.GetEndContainer();
@@ -3482,17 +3485,17 @@ void Selection::SetStartAndEndInternal(I
     }
   }
 
   RemoveAllRanges(aRv);
   if (aRv.Failed()) {
     return;
   }
 
-  AddRange(*newRange, aRv);
+  AddRangeAndSelectFramesAndNotifyListeners(*newRange, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   // Adding a range may set 2 or more ranges if there are non-selectable
   // contents only when this change is caused by a user operation.  Therefore,
   // we need to select frames with the result in such case.
   if (mUserInitiated) {
@@ -3667,11 +3670,11 @@ JSObject* Selection::WrapObject(JSContex
 // AutoHideSelectionChanges
 AutoHideSelectionChanges::AutoHideSelectionChanges(
     const nsFrameSelection* aFrame)
     : AutoHideSelectionChanges(
           aFrame ? aFrame->GetSelection(SelectionType::eNormal) : nullptr) {}
 
 bool Selection::HasSameRootOrSameComposedDoc(const nsINode& aNode) {
   nsINode* root = aNode.SubtreeRoot();
-  Document* doc = GetParentObject();
+  Document* doc = GetDocument();
   return doc == root || (root && doc == root->GetComposedDoc());
 }
--- a/dom/base/Selection.h
+++ b/dom/base/Selection.h
@@ -112,17 +112,20 @@ class Selection final : public nsSupport
    * selectionchange event at every selection change.
    */
   void EnableSelectionChangeEvent() {
     if (!mSelectionChangeEventDispatcher) {
       mSelectionChangeEventDispatcher = new SelectionChangeEventDispatcher();
     }
   }
 
+  // Required for WebIDL bindings, see
+  // https://developer.mozilla.org/en-US/docs/Mozilla/WebIDL_bindings#Adding_WebIDL_bindings_to_a_class.
   Document* GetParentObject() const;
+
   DocGroup* GetDocGroup() const;
 
   // utility methods for scrolling the selection into view
   nsPresContext* GetPresContext() const;
   PresShell* GetPresShell() const;
   nsFrameSelection* GetFrameSelection() const { return mFrameSelection; }
   // Returns a rect containing the selection region, and frame that that
   // position is relative to. For SELECTION_ANCHOR_REGION or
@@ -287,17 +290,18 @@ class Selection final : public nsSupport
   uint32_t RangeCount() const { return mRanges.Length(); }
 
   void GetType(nsAString& aOutType) const;
 
   nsRange* GetRangeAt(uint32_t aIndex, mozilla::ErrorResult& aRv);
   void AddRangeJS(nsRange& aRange, mozilla::ErrorResult& aRv);
 
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
-  void RemoveRange(nsRange& aRange, mozilla::ErrorResult& aRv);
+  void RemoveRangeAndUnselectFramesAndNotifyListeners(
+      nsRange& aRange, mozilla::ErrorResult& aRv);
 
   MOZ_CAN_RUN_SCRIPT_BOUNDARY void RemoveAllRanges(mozilla::ErrorResult& aRv);
 
   /**
    * RemoveAllRangesTemporarily() is useful if the caller will add one or more
    * ranges later.  This tries to cache a removing range if it's possible.
    * If a range is not referred by anything else this selection, the range
    * can be reused later.  Otherwise, this works as same as RemoveAllRanges().
@@ -433,17 +437,18 @@ class Selection final : public nsSupport
    * @param aContainer The node where the selection will be extended to
    * @param aOffset    Where in aContainer to place the offset of the new
    *                   selection end.
    */
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   void Extend(nsINode& aContainer, uint32_t aOffset, ErrorResult& aRv);
 
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
-  void AddRange(nsRange& aRange, mozilla::ErrorResult& aRv);
+  void AddRangeAndSelectFramesAndNotifyListeners(nsRange& aRange,
+                                                 mozilla::ErrorResult& aRv);
 
   /**
    * 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);
 
@@ -592,17 +597,19 @@ class Selection final : public nsSupport
 
   bool HasSameRootOrSameComposedDoc(const nsINode& aNode);
 
   // XXX Please don't add additional uses of this method, it's only for
   // XXX supporting broken code (bug 1245883) in the following classes:
   friend class ::nsCopySupport;
   friend class ::nsHTMLCopyEncoder;
   MOZ_CAN_RUN_SCRIPT
-  void AddRangeInternal(nsRange& aRange, Document* aDocument, ErrorResult&);
+  void AddRangeAndSelectFramesAndNotifyListeners(nsRange& aRange,
+                                                 Document* aDocument,
+                                                 ErrorResult&);
 
   // This is helper method for GetPrimaryFrameForFocusNode.
   // If aVisual is true, this returns caret frame.
   // If false, this returns primary frame.
   nsresult GetPrimaryOrCaretFrameForNodeOffset(nsIContent* aContent,
                                                uint32_t aOffset,
                                                nsIFrame** aReturnFrame,
                                                int32_t* aOffsetUsed,
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -420,17 +420,17 @@ nsresult nsCopySupport::GetTransferableF
   // XXX bug 1245883
   RefPtr<Selection> selection = new Selection();
   RefPtr<nsRange> range = new nsRange(aNode);
   ErrorResult result;
   range->SelectNode(*aNode, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
   }
-  selection->AddRangeInternal(*range, aDoc, result);
+  selection->AddRangeAndSelectFramesAndNotifyListeners(*range, aDoc, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
   }
   // It's not the primary selection - so don't skip invisible content.
   uint32_t additionalFlags = 0;
   return EncodeDocumentWithContextAndCreateTransferable(
       *aDoc, selection, additionalFlags, aTransferable);
 }
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -1371,17 +1371,18 @@ nsHTMLCopyEncoder::SetSelection(Selectio
     // adjust range to include any ancestors who's children are entirely
     // selected
     nsresult rv = PromoteRange(myRange);
     NS_ENSURE_SUCCESS(rv, rv);
 
     ErrorResult result;
     RefPtr<Selection> selection(mEncodingScope.mSelection);
     RefPtr<Document> document(mDocument);
-    selection->AddRangeInternal(*myRange, document, result);
+    selection->AddRangeAndSelectFramesAndNotifyListeners(*myRange, document,
+                                                         result);
     rv = result.StealNSResult();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2308,17 +2308,18 @@ void nsFocusManager::MoveCaretToFocus(Pr
         if (!aContent->GetFirstChild() ||
             aContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
           // If current focus node is a leaf, set range to before the
           // node by using the parent as a container.
           // This prevents it from appearing as selected.
           newRange->SetStartBefore(*aContent, IgnoreErrors());
           newRange->SetEndBefore(*aContent, IgnoreErrors());
         }
-        domSelection->AddRange(*newRange, IgnoreErrors());
+        domSelection->AddRangeAndSelectFramesAndNotifyListeners(*newRange,
+                                                                IgnoreErrors());
         domSelection->CollapseToStart(IgnoreErrors());
       }
     }
   }
 }
 
 nsresult nsFocusManager::SetCaretVisible(PresShell* aPresShell, bool aVisible,
                                          nsIContent* aContent) {
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -969,17 +969,18 @@ void nsRange::SetSelection(mozilla::dom:
   // aSelection will be null when we are removing from a selection
   // and a range can't be in more than one selection at a time,
   // thus mSelection must be null too.
   MOZ_ASSERT(!aSelection || !mSelection);
 
   // Extra step in case our parent failed to ensure the above
   // invariant.
   if (aSelection && mSelection) {
-    mSelection->RemoveRange(*this, IgnoreErrors());
+    mSelection->RemoveRangeAndUnselectFramesAndNotifyListeners(*this,
+                                                               IgnoreErrors());
   }
 
   mSelection = aSelection;
   if (mSelection) {
     nsINode* commonAncestor = GetCommonAncestor();
     NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
     RegisterCommonAncestor(commonAncestor);
   } else if (mRegisteredCommonAncestor) {
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -94,18 +94,20 @@ class RestoreSelectionState : public Run
     if (!mTextEditorState) {
       return NS_OK;
     }
 
     AutoHideSelectionChanges hideSelectionChanges(
         mFrame->GetConstFrameSelection());
 
     if (mFrame) {
-      // SetSelectionRange leads to Selection::AddRange which flushes Layout -
-      // need to block script to avoid nested PrepareEditor calls (bug 642800).
+      // SetSelectionRange leads to
+      // Selection::AddRangeAndSelectFramesAndNotifyListeners which flushes
+      // Layout - need to block script to avoid nested PrepareEditor calls (bug
+      // 642800).
       nsAutoScriptBlocker scriptBlocker;
       nsTextEditorState::SelectionProperties& properties =
           mTextEditorState->GetSelectionProperties();
       if (properties.IsDirty()) {
         mFrame->SetSelectionRange(properties.GetStart(), properties.GetEnd(),
                                   properties.GetDirection());
       }
       if (!mTextEditorState->mSelectionRestoreEagerInit) {
--- a/dom/webidl/Selection.webidl
+++ b/dom/webidl/Selection.webidl
@@ -30,17 +30,17 @@ interface Selection {
   /**
    * Adds a range to the current selection.
    */
   [Throws, BinaryName="addRangeJS"]
   void      addRange(Range range);
   /**
    * Removes a range from the current selection.
    */
-  [Throws]
+  [Throws, BinaryName="removeRangeAndUnselectFramesAndNotifyListeners"]
   void      removeRange(Range range);
   /**
    * Removes all ranges from the current selection.
    */
   [Throws]
   void      removeAllRanges();
   [Throws, BinaryName="RemoveAllRanges"]
   void      empty();
--- a/editor/libeditor/CompositionTransaction.cpp
+++ b/editor/libeditor/CompositionTransaction.cpp
@@ -292,17 +292,18 @@ nsresult CompositionTransaction::SetIMES
     RefPtr<Selection> selectionOfIME =
         selCon->GetSelection(ToRawSelectionType(textRange.mRangeType));
     if (!selectionOfIME) {
       NS_WARNING("Failed to get IME selection");
       break;
     }
 
     IgnoredErrorResult err;
-    selectionOfIME->AddRange(*clauseRange, err);
+    selectionOfIME->AddRangeAndSelectFramesAndNotifyListeners(*clauseRange,
+                                                              err);
     if (err.Failed()) {
       NS_WARNING("Failed to add selection range for a clause of composition");
       break;
     }
 
     // Set the style of the clause.
     rv = selectionOfIME->SetTextRangeStyle(clauseRange, textRange.mRangeStyle);
     if (NS_FAILED(rv)) {
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2994,17 +2994,18 @@ void EditorBase::DoSplitNode(const Edito
     }
 
     RefPtr<nsRange> newRange =
         nsRange::Create(range.mStartContainer, range.mStartOffset,
                         range.mEndContainer, range.mEndOffset, aError);
     if (NS_WARN_IF(aError.Failed())) {
       return;
     }
-    range.mSelection->AddRange(*newRange, aError);
+    range.mSelection->AddRangeAndSelectFramesAndNotifyListeners(*newRange,
+                                                                aError);
     if (NS_WARN_IF(aError.Failed())) {
       return;
     }
   }
 
   // We don't need to set selection here because the caller should do that
   // in any case.
 
@@ -3160,17 +3161,17 @@ nsresult EditorBase::DoJoinNodes(nsINode
     RefPtr<nsRange> newRange =
         nsRange::Create(range.mStartContainer, range.mStartOffset,
                         range.mEndContainer, range.mEndOffset, IgnoreErrors());
     if (NS_WARN_IF(!newRange)) {
       return NS_ERROR_FAILURE;
     }
 
     ErrorResult err;
-    range.mSelection->AddRange(*newRange, err);
+    range.mSelection->AddRangeAndSelectFramesAndNotifyListeners(*newRange, err);
     if (NS_WARN_IF(err.Failed())) {
       return err.StealNSResult();
     }
   }
 
   if (allowedTransactionsToChangeSelection) {
     // Editor wants us to set selection at join point.
     DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(
@@ -4214,17 +4215,17 @@ nsresult EditorBase::AppendNodeToSelecti
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (NS_WARN_IF(!range)) {
     return NS_ERROR_FAILURE;
   }
 
   ErrorResult err;
-  SelectionRefPtr()->AddRange(*range, err);
+  SelectionRefPtr()->AddRangeAndSelectFramesAndNotifyListeners(*range, err);
   NS_WARNING_ASSERTION(!err.Failed(), "Failed to add range to Selection");
   return err.StealNSResult();
 }
 
 nsresult EditorBase::ClearSelection() {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   ErrorResult rv;
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -799,17 +799,17 @@ nsresult HTMLEditor::DeleteTableElementA
     }
 
     RefPtr<nsRange> range = new nsRange(&aTableElement);
     ErrorResult error;
     range->SelectNode(aTableElement, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
-    SelectionRefPtr()->AddRange(*range, error);
+    SelectionRefPtr()->AddRangeAndSelectFramesAndNotifyListeners(*range, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
 
 #ifdef DEBUG
     range = SelectionRefPtr()->GetRangeAt(0);
     MOZ_ASSERT(range);
     MOZ_ASSERT(range->GetStartContainer() == aTableElement.GetParent());
@@ -1788,17 +1788,18 @@ HTMLEditor::SelectBlockOfCells(Element* 
   while (cell) {
     CellIndexes currentCellIndexes(*cell, error);
     if (NS_WARN_IF(error.Failed())) {
       return EditorBase::ToGenericNSResult(error.StealNSResult());
     }
     if (currentCellIndexes.mRow < maxRow || currentCellIndexes.mRow > maxRow ||
         currentCellIndexes.mColumn < maxColumn ||
         currentCellIndexes.mColumn > maxColumn) {
-      SelectionRefPtr()->RemoveRange(*range, IgnoreErrors());
+      SelectionRefPtr()->RemoveRangeAndUnselectFramesAndNotifyListeners(
+          *range, IgnoreErrors());
       // Since we've removed the range, decrement pointer to next range
       MOZ_ASSERT(mSelectedCellIndex > 0);
       mSelectedCellIndex--;
     }
     cell = GetNextSelectedTableCellElement(error);
     if (NS_WARN_IF(error.Failed())) {
       return EditorBase::ToGenericNSResult(error.StealNSResult());
     }
@@ -2644,17 +2645,18 @@ HTMLEditor::JoinTableCells(bool aMergeNo
       range = SelectionRefPtr()->GetRangeAt(i);
       if (NS_WARN_IF(!range)) {
         return NS_ERROR_FAILURE;
       }
 
       RefPtr<Element> deletedCell;
       HTMLEditor::GetCellFromRange(range, getter_AddRefs(deletedCell));
       if (!deletedCell) {
-        SelectionRefPtr()->RemoveRange(*range, IgnoreErrors());
+        SelectionRefPtr()->RemoveRangeAndUnselectFramesAndNotifyListeners(
+            *range, IgnoreErrors());
         rangeCount--;
         i--;
       }
     }
 
     // Set spans for the cell everything merged into
     rv = SetRowSpan(MOZ_KnownLive(firstSelectedCell.mElement),
                     lastRowIndex - firstSelectedCell.mIndexes.mRow + 1);
--- a/editor/libeditor/SelectionState.cpp
+++ b/editor/libeditor/SelectionState.cpp
@@ -76,17 +76,17 @@ nsresult SelectionState::RestoreSelectio
 
   // set the selection ranges anew
   size_t arrayCount = mArray.Length();
   for (size_t i = 0; i < arrayCount; i++) {
     RefPtr<nsRange> range = mArray[i]->GetRange();
     NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
 
     ErrorResult rv;
-    aSel->AddRange(*range, rv);
+    aSel->AddRangeAndSelectFramesAndNotifyListeners(*range, rv);
     if (rv.Failed()) {
       return rv.StealNSResult();
     }
   }
   return NS_OK;
 }
 
 bool SelectionState::IsCollapsed() {
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -1148,17 +1148,18 @@ nsresult TextEditor::ReplaceTextAsAction
 
   // Select the range but as far as possible, we should not create new range
   // even if it's part of special Selection.
   nsresult rv = SelectionRefPtr()->RemoveAllRangesTemporarily();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   ErrorResult error;
-  SelectionRefPtr()->AddRange(*aReplaceRange, error);
+  SelectionRefPtr()->AddRangeAndSelectFramesAndNotifyListeners(*aReplaceRange,
+                                                               error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
   rv = ReplaceSelectionAsSubAction(aString);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditorBase::ToGenericNSResult(rv);
   }
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1599,17 +1599,18 @@ nsresult mozInlineSpellChecker::CleanupR
 //    selection, we need to decrement mNumWordsInSpellSelection
 
 nsresult mozInlineSpellChecker::RemoveRange(Selection* aSpellCheckSelection,
                                             nsRange* aRange) {
   NS_ENSURE_ARG_POINTER(aSpellCheckSelection);
   NS_ENSURE_ARG_POINTER(aRange);
 
   ErrorResult rv;
-  aSpellCheckSelection->RemoveRange(*aRange, rv);
+  aSpellCheckSelection->RemoveRangeAndUnselectFramesAndNotifyListeners(*aRange,
+                                                                       rv);
   if (!rv.Failed() && mNumWordsInSpellSelection) mNumWordsInSpellSelection--;
 
   return rv.StealNSResult();
 }
 
 // mozInlineSpellChecker::AddRange
 //
 //    For performance reasons, we have an upper bound on the number of word
@@ -1620,17 +1621,18 @@ nsresult mozInlineSpellChecker::AddRange
                                          nsRange* aRange) {
   NS_ENSURE_ARG_POINTER(aSpellCheckSelection);
   NS_ENSURE_ARG_POINTER(aRange);
 
   nsresult rv = NS_OK;
 
   if (!SpellCheckSelectionIsFull()) {
     IgnoredErrorResult err;
-    aSpellCheckSelection->AddRange(*aRange, err);
+    aSpellCheckSelection->AddRangeAndSelectFramesAndNotifyListeners(*aRange,
+        err);
     if (err.Failed()) {
       rv = err.StealNSResult();
     } else {
       mNumWordsInSpellSelection++;
     }
   }
 
   return rv;
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -3121,17 +3121,18 @@ nsresult PresShell::GoToAnchor(const nsA
     while (content && content->GetFirstChild()) {
       content = content->GetFirstChild();
     }
     jumpToRange->SelectNodeContents(*content, IgnoreErrors());
     // Select the anchor
     RefPtr<Selection> sel = mSelection->GetSelection(SelectionType::eNormal);
     if (sel) {
       sel->RemoveAllRanges(IgnoreErrors());
-      sel->AddRange(*jumpToRange, IgnoreErrors());
+      sel->AddRangeAndSelectFramesAndNotifyListeners(*jumpToRange,
+                                                     IgnoreErrors());
       if (!selectAnchor) {
         // Use a caret (collapsed selection) at the start of the anchor
         sel->CollapseToStart(IgnoreErrors());
       }
     }
     // Selection is at anchor.
     // Now focus the document itself if focus is on an element within it.
     nsPIDOMWindowOuter* win = mDocument->GetWindow();
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -833,17 +833,18 @@ nsresult nsTextControlFrame::SetSelectio
   }
 
   ErrorResult err;
   selection->RemoveAllRanges(err);
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
   }
 
-  selection->AddRange(*range, err);  // NOTE: can destroy the world
+  selection->AddRangeAndSelectFramesAndNotifyListeners(
+      *range, err);  // NOTE: can destroy the world
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
   }
 
   selection->SetDirection(direction);
   return rv;
 }
 
--- a/layout/generic/nsFrameSelection.cpp
+++ b/layout/generic/nsFrameSelection.cpp
@@ -1240,17 +1240,18 @@ nsresult nsFrameSelection::TakeFocus(nsI
     if (aMultipleSelection) {
       // Remove existing collapsed ranges as there's no point in having
       // non-anchor/focus collapsed ranges.
       mDomSelections[index]->RemoveCollapsedRanges();
 
       RefPtr<nsRange> newRange = new nsRange(aNewFocus);
 
       newRange->CollapseTo(aNewFocus, aContentOffset);
-      mDomSelections[index]->AddRange(*newRange, IgnoreErrors());
+      mDomSelections[index]->AddRangeAndSelectFramesAndNotifyListeners(
+          *newRange, IgnoreErrors());
       mBatching = batching;
       mChangesDuringBatching = changes;
     } else {
       bool oldDesiredPosSet = mDesiredPosSet;  // need to keep old desired
                                                // position if it was set.
       mDomSelections[index]->Collapse(aNewFocus, aContentOffset);
       mDesiredPosSet = oldDesiredPosSet;  // now reset desired pos back.
       mBatching = batching;
@@ -2238,17 +2239,18 @@ nsresult nsFrameSelection::HandleTableSe
 #endif
             // Unselecting the start of previous block
             // XXX What do we use now!
             if (childContent == mAppendStartSelectedCell)
               mAppendStartSelectedCell = nullptr;
 
             // Deselect cell by removing its range from selection
             ErrorResult err;
-            mDomSelections[index]->RemoveRange(*range, err);
+            mDomSelections[index]
+                ->RemoveRangeAndUnselectFramesAndNotifyListeners(*range, err);
             return err.StealNSResult();
           }
         }
         mUnselectCellOnMouseUp = nullptr;
       }
     }
   }
   return result;
@@ -2318,17 +2320,18 @@ nsresult nsFrameSelection::UnselectCells
 #ifdef DEBUG_TABLE_SELECTION
     if (!range) printf("RemoveCellsToSelection -- range is null\n");
 #endif
 
     if (range) {
       if (aRemoveOutsideOfCellRange) {
         if (curRowIndex < minRowIndex || curRowIndex > maxRowIndex ||
             curColIndex < minColIndex || curColIndex > maxColIndex) {
-          mDomSelections[index]->RemoveRange(*range, IgnoreErrors());
+          mDomSelections[index]->RemoveRangeAndUnselectFramesAndNotifyListeners(
+              *range, IgnoreErrors());
           // Since we've removed the range, decrement pointer to next range
           mSelectedCellIndex--;
         }
 
       } else {
         // Remove cell from selection if it belongs to the given cells range or
         // it is spanned onto the cells range.
         nsTableCellFrame* cellFrame =
@@ -2343,17 +2346,18 @@ nsresult nsFrameSelection::UnselectCells
         if (origRowIndex <= static_cast<uint32_t>(maxRowIndex) &&
             maxRowIndex >= 0 &&
             origRowIndex + actualRowSpan - 1 >=
                 static_cast<uint32_t>(minRowIndex) &&
             origColIndex <= static_cast<uint32_t>(maxColIndex) &&
             maxColIndex >= 0 &&
             origColIndex + actualColSpan - 1 >=
                 static_cast<uint32_t>(minColIndex)) {
-          mDomSelections[index]->RemoveRange(*range, IgnoreErrors());
+          mDomSelections[index]->RemoveRangeAndUnselectFramesAndNotifyListeners(
+              *range, IgnoreErrors());
           // Since we've removed the range, decrement pointer to next range
           mSelectedCellIndex--;
         }
       }
     }
 
     range = GetNextCellRange();
     cellNode = GetFirstSelectedContent(range);
@@ -2633,17 +2637,17 @@ nsresult nsFrameSelection::CreateAndAddR
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   int8_t index = GetIndexFromSelectionType(SelectionType::eNormal);
   if (!mDomSelections[index]) return NS_ERROR_NULL_POINTER;
 
   ErrorResult err;
-  mDomSelections[index]->AddRange(*range, err);
+  mDomSelections[index]->AddRangeAndSelectFramesAndNotifyListeners(*range, err);
   return err.StealNSResult();
 }
 
 // End of Table Selection
 
 void nsFrameSelection::SetAncestorLimiter(nsIContent* aLimiter) {
   if (mAncestorLimiter != aLimiter) {
     mAncestorLimiter = aLimiter;
--- a/layout/printing/nsPrintJob.cpp
+++ b/layout/printing/nsPrintJob.cpp
@@ -1904,17 +1904,18 @@ nsresult nsPrintJob::UpdateSelectionAndS
   // this function before.
   if (selectionPS) {
     selectionPS->RemoveAllRanges(IgnoreErrors());
   }
   if (selection && selectionPS) {
     int32_t cnt = selection->RangeCount();
     int32_t inx;
     for (inx = 0; inx < cnt; ++inx) {
-      selectionPS->AddRange(*selection->GetRangeAt(inx), IgnoreErrors());
+      selectionPS->AddRangeAndSelectFramesAndNotifyListeners(
+          *selection->GetRangeAt(inx), IgnoreErrors());
     }
   }
 
   // If we are trying to shrink the contents to fit on the page
   // we must first locate the "pageContent" frame
   // Then we walk the frame tree and look for the "xmost" frame
   // this is the frame where the right-hand side of the frame extends
   // the furthest
@@ -2293,17 +2294,18 @@ static nsresult DeleteUnselectedNodes(Do
 
     // Create the range that we want to remove. Note that if startNode or
     // endNode are null nsRange::Create() will fail and we won't remove
     // that section.
     RefPtr<nsRange> range = nsRange::Create(startNode, startOffset, endNode,
                                             endOffset, IgnoreErrors());
 
     if (range && !range->Collapsed()) {
-      selection->AddRange(*range, IgnoreErrors());
+      selection->AddRangeAndSelectFramesAndNotifyListeners(*range,
+                                                           IgnoreErrors());
 
       // Unless we've already added an ellipsis at the start, if we ended mid
       // text node then add ellipsis.
       Text* text = endNode->GetAsText();
       if (!ellipsisOffset && text && endOffset && endOffset < text->Length()) {
         text->InsertData(endOffset, kEllipsis, IgnoreErrors());
         ellipsisOffset += kEllipsis.Length();
       }
@@ -2328,17 +2330,18 @@ static nsresult DeleteUnselectedNodes(Do
     }
   }
 
   // Add in the last range to the end of the body.
   RefPtr<nsRange> lastRange =
       nsRange::Create(startNode, startOffset, bodyNode,
                       bodyNode->GetChildCount(), IgnoreErrors());
   if (lastRange && !lastRange->Collapsed()) {
-    selection->AddRange(*lastRange, IgnoreErrors());
+    selection->AddRangeAndSelectFramesAndNotifyListeners(*lastRange,
+                                                         IgnoreErrors());
   }
 
   selection->DeleteFromDocument(IgnoreErrors());
   return NS_OK;
 }
 
 //-------------------------------------------------------
 nsresult nsPrintJob::DoPrint(const UniquePtr<nsPrintObject>& aPO) {
--- a/toolkit/components/find/nsWebBrowserFind.cpp
+++ b/toolkit/components/find/nsWebBrowserFind.cpp
@@ -353,17 +353,18 @@ void nsWebBrowserFind::SetSelectionAndSc
     }
   }
 
   selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
   RefPtr<Selection> selection =
       selCon->GetSelection(nsISelectionController::SELECTION_NORMAL);
   if (selection) {
     selection->RemoveAllRanges(IgnoreErrors());
-    selection->AddRange(*aRange, IgnoreErrors());
+    selection->AddRangeAndSelectFramesAndNotifyListeners(*aRange,
+                                                         IgnoreErrors());
 
     nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
     if (fm) {
       if (tcFrame) {
         RefPtr<Element> newFocusedElement = Element::FromNode(content);
         fm->SetFocus(newFocusedElement, nsIFocusManager::FLAG_NOSCROLL);
       } else {
         RefPtr<Element> result;
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -593,17 +593,18 @@ nsresult nsTypeAheadFind::FindItNow(bool
         GetSelection(presShell, getter_AddRefs(selectionController),
                      getter_AddRefs(selection));
       }
       mSelectionController = do_GetWeakReference(selectionController);
 
       // Select the found text
       if (selection) {
         selection->RemoveAllRanges(IgnoreErrors());
-        selection->AddRange(*returnRange, IgnoreErrors());
+        selection->AddRangeAndSelectFramesAndNotifyListeners(*returnRange,
+                                                             IgnoreErrors());
       }
 
       if (!mFoundEditable && fm) {
         fm->MoveFocus(window->GetOuterWindow(), nullptr,
                       nsIFocusManager::MOVEFOCUS_CARET,
                       nsIFocusManager::FLAG_NOSCROLL |
                           nsIFocusManager::FLAG_NOSWITCHFRAME,
                       getter_AddRefs(mFoundLink));
--- a/toolkit/modules/subprocess/subprocess_unix.jsm
+++ b/toolkit/modules/subprocess/subprocess_unix.jsm
@@ -107,17 +107,17 @@ var SubprocessUnix = {
     function decode(array) {
       try {
         return decoder.decode(array);
       } catch (e) {
         return array;
       }
     }
 
-    for (let envp = environ; !envp.contents.isNull(); envp = envp.increment()) {
+    for (let envp = environ; !envp.isNull() && !envp.contents.isNull(); envp = envp.increment()) {
       let buf = ptrToUint8Array(envp.contents);
 
       for (let i = 0; i < buf.length; i++) {
         if (buf[i] == EQUAL) {
           yield [decode(buf.subarray(0, i)),
                  decode(buf.subarray(i + 1))];
           break;
         }