Bug 1549155 - Mark EditorBase::DeleteNodeWithTransaction() as MOZ_CAN_RUN_SCRIPT r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 07 May 2019 22:27:29 +0000
changeset 531809 36ab55f6cd91191eb913d95049996094789297d7
parent 531808 b1d829e6fe2f40052c6bbeb18f5fb3d996f66871
child 531810 93efde688b8c6869c30e2e50c9b755989d4e6e57
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1549155
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1549155 - Mark EditorBase::DeleteNodeWithTransaction() as MOZ_CAN_RUN_SCRIPT r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D30038
accessible/generic/HyperTextAccessible.h
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/EditorCommands.cpp
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLEditorDataTransfer.cpp
editor/libeditor/HTMLTableEditor.cpp
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
editor/libeditor/TextEditor.h
editor/libeditor/WSRunObject.h
editor/nsIEditor.idl
--- a/accessible/generic/HyperTextAccessible.h
+++ b/accessible/generic/HyperTextAccessible.h
@@ -399,18 +399,19 @@ class HyperTextAccessible : public Acces
   void RangeAtPoint(int32_t aX, int32_t aY, TextRange& aRange) const;
 
   //////////////////////////////////////////////////////////////////////////////
   // EditableTextAccessible
 
   void ReplaceText(const nsAString& aText);
   void InsertText(const nsAString& aText, int32_t aPosition);
   void CopyText(int32_t aStartPos, int32_t aEndPos);
-  void CutText(int32_t aStartPos, int32_t aEndPos);
-  void DeleteText(int32_t aStartPos, int32_t aEndPos);
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY void CutText(int32_t aStartPos, int32_t aEndPos);
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY void DeleteText(int32_t aStartPos,
+                                              int32_t aEndPos);
   MOZ_CAN_RUN_SCRIPT
   void PasteText(int32_t aPosition);
 
   /**
    * Return the editor associated with the accessible.
    * The result may be either TextEditor or HTMLEditor.
    */
   virtual already_AddRefed<TextEditor> GetEditor() const;
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2668,17 +2668,17 @@ nsresult EditorBase::InsertTextIntoTextN
   // means that furure IME txns won't merge with it.  This is because we don't
   // want future IME txns trying to put their text into a node that is no
   // longer in the document.  This does not break undo/redo, because all these
   // txns are wrapped in a parent PlaceHolder txn, and placeholder txns are
   // already savvy to having multiple ime txns inside them.
 
   // Delete empty IME text node if there is one
   if (isIMETransaction && mComposition) {
-    Text* textNode = mComposition->GetContainerTextNode();
+    RefPtr<Text> textNode = mComposition->GetContainerTextNode();
     if (textNode && !textNode->Length()) {
       DeleteNodeWithTransaction(*textNode);
       mComposition->OnTextNodeRemoved();
       static_cast<CompositionTransaction*>(transaction.get())->MarkFixed();
     }
   }
 
   return rv;
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -918,17 +918,17 @@ class EditorBase : public nsIEditor,
 
   nsresult SetTextImpl(const nsAString& aString, Text& aTextNode);
 
   /**
    * DeleteNodeWithTransaction() removes aNode from the DOM tree.
    *
    * @param aNode       The node which will be removed form the DOM tree.
    */
-  nsresult DeleteNodeWithTransaction(nsINode& aNode);
+  MOZ_CAN_RUN_SCRIPT nsresult DeleteNodeWithTransaction(nsINode& aNode);
 
   /**
    * InsertNodeWithTransaction() inserts aContentToInsert before the child
    * specified by aPointToInsert.
    *
    * @param aContentToInsert    The node to be inserted.
    * @param aPointToInsert      The insertion point of aContentToInsert.
    *                            If this refers end of the container, the
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -817,17 +817,17 @@ bool InsertLineBreakCommand::IsCommandEn
 }
 
 nsresult InsertLineBreakCommand::DoCommand(Command aCommand,
                                            TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_ERROR_FAILURE;
   }
-  return htmlEditor->InsertLineBreakAsAction();
+  return MOZ_KnownLive(htmlEditor)->InsertLineBreakAsAction();
 }
 
 nsresult InsertLineBreakCommand::DoCommandParams(
     Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
   return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult InsertLineBreakCommand::GetCommandStateParams(
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -1302,18 +1302,19 @@ nsresult HTMLEditRules::WillInsertText(E
   }
 
   // initialize out param
   *aCancel = false;
   *aHandled = true;
   // If the selection isn't collapsed, delete it.  Don't delete existing inline
   // tags, because we're hopefully going to insert text (bug 787432).
   if (!SelectionRefPtr()->IsCollapsed()) {
-    nsresult rv = HTMLEditorRef().DeleteSelectionAsSubAction(
-        nsIEditor::eNone, nsIEditor::eNoStrip);
+    nsresult rv =
+        MOZ_KnownLive(HTMLEditorRef())
+            .DeleteSelectionAsSubAction(nsIEditor::eNone, nsIEditor::eNoStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
@@ -1625,23 +1626,25 @@ nsresult HTMLEditRules::WillInsertText(E
 
 nsresult HTMLEditRules::WillLoadHTML() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // Delete mBogusNode if it exists. If we really need one,
   // it will be added during post-processing in AfterEditInner().
 
   if (mBogusNode) {
+    // A mutation event listener may recreate bogus node again during the
+    // call of DeleteNodeWithTransaction().  So, move it first.
+    nsCOMPtr<nsINode> bogusNode(std::move(mBogusNode));
     DebugOnly<nsresult> rv =
-        HTMLEditorRef().DeleteNodeWithTransaction(*mBogusNode);
+        MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*bogusNode);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove the bogus node");
-    mBogusNode = nullptr;
   }
 
   return NS_OK;
 }
 
 bool HTMLEditRules::CanContainParagraph(Element& aElement) const {
   MOZ_ASSERT(IsEditorDataAvailable());
 
@@ -1663,18 +1666,19 @@ bool HTMLEditRules::CanContainParagraph(
   return false;
 }
 
 EditActionResult HTMLEditRules::WillInsertParagraphSeparator() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // If the selection isn't collapsed, delete it.
   if (!SelectionRefPtr()->IsCollapsed()) {
-    nsresult rv = HTMLEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
-                                                             nsIEditor::eStrip);
+    nsresult rv =
+        MOZ_KnownLive(HTMLEditorRef())
+            .DeleteSelectionAsSubAction(nsIEditor::eNone, nsIEditor::eStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
   }
 
@@ -2204,34 +2208,36 @@ EditActionResult HTMLEditRules::SplitMai
   bool bEmptyCite = false;
   if (previousNodeOfSplitPoint) {
     nsresult rv = HTMLEditorRef().IsEmptyNode(previousNodeOfSplitPoint,
                                               &bEmptyCite, true, false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
     if (bEmptyCite) {
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*previousNodeOfSplitPoint);
+      rv = MOZ_KnownLive(HTMLEditorRef())
+               .DeleteNodeWithTransaction(
+                   MOZ_KnownLive(*previousNodeOfSplitPoint));
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
     }
   }
 
   if (citeNode) {
     nsresult rv =
         HTMLEditorRef().IsEmptyNode(citeNode, &bEmptyCite, true, false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
     if (bEmptyCite) {
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*citeNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*citeNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
     }
   }
@@ -2299,18 +2305,18 @@ nsresult HTMLEditRules::WillDeleteSelect
     RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
     if (NS_WARN_IF(!host)) {
       return NS_ERROR_FAILURE;
     }
 
     {
       AutoEditorDOMPointChildInvalidator lockOffset(startPoint);
 
-      rv = MaybeDeleteTopMostEmptyAncestor(*startPoint.GetContainer(), *host,
-                                           aAction, aHandled);
+      rv = MaybeDeleteTopMostEmptyAncestor(
+          MOZ_KnownLive(*startPoint.GetContainer()), *host, aAction, aHandled);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       if (*aHandled) {
         return NS_OK;
       }
     }
 
@@ -2483,17 +2489,17 @@ nsresult HTMLEditRules::WillDeleteSelect
       return NS_OK;
     }
 
     if (wsType == WSType::special || wsType == WSType::br ||
         visNode->IsHTMLElement(nsGkAtoms::hr)) {
       // Short circuit for invisible breaks.  delete them and recurse.
       if (visNode->IsHTMLElement(nsGkAtoms::br) &&
           !HTMLEditorRef().IsVisibleBRElement(visNode)) {
-        rv = HTMLEditorRef().DeleteNodeWithTransaction(*visNode);
+        rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*visNode);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         rv = WillDeleteSelection(aAction, aStripWrappers, aCancel, aHandled);
         if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -2582,17 +2588,18 @@ nsresult HTMLEditRules::WillDeleteSelect
             rv = WSRunObject::PrepareToDeleteNode(
                 MOZ_KnownLive(&HTMLEditorRef()), MOZ_KnownLive(otherContent));
             if (NS_WARN_IF(!CanHandleEditAction())) {
               return NS_ERROR_EDITOR_DESTROYED;
             }
             if (NS_WARN_IF(NS_FAILED(rv))) {
               return rv;
             }
-            rv = HTMLEditorRef().DeleteNodeWithTransaction(*otherContent);
+            rv = MOZ_KnownLive(HTMLEditorRef())
+                     .DeleteNodeWithTransaction(MOZ_KnownLive(*otherContent));
             if (NS_WARN_IF(!CanHandleEditAction())) {
               return NS_ERROR_EDITOR_DESTROYED;
             }
             if (NS_WARN_IF(NS_FAILED(rv))) {
               return rv;
             }
           }
 
@@ -2612,17 +2619,17 @@ nsresult HTMLEditRules::WillDeleteSelect
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // Remember sibling to visnode, if any
       nsCOMPtr<nsIContent> sibling =
           HTMLEditorRef().GetPriorHTMLSibling(visNode);
       // Delete the node, and join like nodes if appropriate
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*visNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*visNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // We did something, so let's say so.
       *aHandled = true;
@@ -2694,17 +2701,18 @@ nsresult HTMLEditRules::WillDeleteSelect
         rightNode = startPoint.GetContainer();
       } else {
         leafNode = HTMLEditorRef().GetFirstEditableLeaf(*visNode);
         leftNode = startPoint.GetContainer();
         rightNode = leafNode;
       }
 
       if (otherNode->IsHTMLElement(nsGkAtoms::br)) {
-        rv = HTMLEditorRef().DeleteNodeWithTransaction(*otherNode);
+        rv = MOZ_KnownLive(HTMLEditorRef())
+                 .DeleteNodeWithTransaction(*otherNode);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         // XXX Only in this case, setting "handled" to true only when it
         //     succeeds?
@@ -2895,18 +2903,18 @@ nsresult HTMLEditRules::WillDeleteSelect
     AutoTrackDOMPoint startTracker(HTMLEditorRef().RangeUpdaterRef(),
                                    address_of(startNode), &startOffset);
     AutoTrackDOMPoint endTracker(HTMLEditorRef().RangeUpdaterRef(),
                                  address_of(endNode), &endOffset);
     // We are handling all ranged deletions directly now.
     *aHandled = true;
 
     if (endNode == startNode) {
-      rv = HTMLEditorRef().DeleteSelectionWithTransaction(aAction,
-                                                          aStripWrappers);
+      rv = MOZ_KnownLive(HTMLEditorRef())
+               .DeleteSelectionWithTransaction(aAction, aStripWrappers);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     } else {
       // Figure out mailcite ancestors
@@ -2923,17 +2931,18 @@ nsresult HTMLEditRules::WillDeleteSelect
       }
 
       // Figure out block parents
       nsCOMPtr<Element> leftParent = HTMLEditor::GetBlock(*startNode);
       nsCOMPtr<Element> rightParent = HTMLEditor::GetBlock(*endNode);
 
       // Are endpoint block parents the same?  Use default deletion
       if (leftParent && leftParent == rightParent) {
-        HTMLEditorRef().DeleteSelectionWithTransaction(aAction, aStripWrappers);
+        MOZ_KnownLive(HTMLEditorRef())
+            .DeleteSelectionWithTransaction(aAction, aStripWrappers);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
       } else {
         // Deleting across blocks.  Are the blocks of same type?
         if (NS_WARN_IF(!leftParent) || NS_WARN_IF(!rightParent)) {
           return NS_ERROR_FAILURE;
         }
@@ -2945,18 +2954,18 @@ nsresult HTMLEditRules::WillDeleteSelect
         // MOOSE: this could conceivably screw up a table.. fix me.
         if (leftBlockParent == rightBlockParent &&
             HTMLEditorRef().AreNodesSameType(*leftParent, *rightParent) &&
             // XXX What's special about these three types of block?
             (leftParent->IsHTMLElement(nsGkAtoms::p) ||
              HTMLEditUtils::IsListItem(leftParent) ||
              HTMLEditUtils::IsHeader(*leftParent))) {
           // First delete the selection
-          rv = HTMLEditorRef().DeleteSelectionWithTransaction(aAction,
-                                                              aStripWrappers);
+          rv = MOZ_KnownLive(HTMLEditorRef())
+                   .DeleteSelectionWithTransaction(aAction, aStripWrappers);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           // Join blocks
           EditorDOMPoint pt = HTMLEditorRef().JoinNodesDeepWithTransaction(
@@ -3129,17 +3138,17 @@ nsresult HTMLEditRules::DeleteNodeIfColl
   if (!text) {
     return NS_OK;
   }
 
   if (HTMLEditorRef().IsVisibleTextNode(*text)) {
     return NS_OK;
   }
 
-  nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aNode);
+  nsresult rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(aNode);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
@@ -3296,31 +3305,32 @@ EditActionResult HTMLEditRules::TryToJoi
     // Tricky case.  Left block is inside right block.  Do ws adjustment.  This
     // just destroys non-visible ws at boundaries we will be joining.
     DebugOnly<bool> advanced = atRightBlockChild.AdvanceOffset();
     NS_WARNING_ASSERTION(
         advanced,
         "Failed to advance offset to after child of rightBlock, "
         "leftBlock is a descendant of the child");
     nsresult rv = WSRunObject::ScrubBlockBoundary(
-        &HTMLEditorRef(), WSRunObject::kBlockEnd, leftBlock);
+        MOZ_KnownLive(&HTMLEditorRef()), WSRunObject::kBlockEnd, leftBlock);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
 
     {
       // We can't just track rightBlock because it's an Element.
       AutoTrackDOMPoint tracker(HTMLEditorRef().RangeUpdaterRef(),
                                 &atRightBlockChild);
       rv = WSRunObject::ScrubBlockBoundary(
-          &HTMLEditorRef(), WSRunObject::kAfterBlock,
-          atRightBlockChild.GetContainer(), atRightBlockChild.Offset());
+          MOZ_KnownLive(&HTMLEditorRef()), WSRunObject::kAfterBlock,
+          MOZ_KnownLive(atRightBlockChild.GetContainer()),
+          atRightBlockChild.Offset());
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
 
       // XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
@@ -3370,17 +3380,18 @@ EditActionResult HTMLEditRules::TryToJoi
       if (retMoveBlock.Handled()) {
         ret.MarkAsHandled();
       }
       // Now, all children of rightBlock were moved to leftBlock.  So,
       // atRightBlockChild is now invalid.
       atRightBlockChild.Clear();
     }
     if (brNode) {
-      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+      nsresult rv =
+          MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*brNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_SUCCEEDED(rv)) {
         ret.MarkAsHandled();
       } else {
         NS_WARNING("Failed to remove the <br> element");
       }
@@ -3392,30 +3403,30 @@ EditActionResult HTMLEditRules::TryToJoi
 
   // Offset below is where you find yourself in leftBlock when you traverse
   // upwards from rightBlock
   EditorDOMPoint leftBlockChild;
   if (EditorUtils::IsDescendantOf(*rightBlock, *leftBlock, &leftBlockChild)) {
     // Tricky case.  Right block is inside left block.  Do ws adjustment.  This
     // just destroys non-visible ws at boundaries we will be joining.
     nsresult rv = WSRunObject::ScrubBlockBoundary(
-        &HTMLEditorRef(), WSRunObject::kBlockStart, rightBlock);
+        MOZ_KnownLive(&HTMLEditorRef()), WSRunObject::kBlockStart, rightBlock);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
 
     {
       // We can't just track leftBlock because it's an Element, so track
       // something else.
       AutoTrackDOMPoint tracker(HTMLEditorRef().RangeUpdaterRef(),
                                 &leftBlockChild);
-      rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
+      rv = WSRunObject::ScrubBlockBoundary(MOZ_KnownLive(&HTMLEditorRef()),
                                            WSRunObject::kBeforeBlock, leftBlock,
                                            leftBlockChild.Offset());
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
@@ -3510,17 +3521,18 @@ EditActionResult HTMLEditRules::TryToJoi
 
       ret |= MoveBlock(MOZ_KnownLive(*previousContent.GetContainerAsElement()),
                        *rightBlock, previousContent.Offset(), 0);
       if (NS_WARN_IF(ret.Failed())) {
         return ret;
       }
     }
     if (brNode) {
-      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+      nsresult rv =
+          MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*brNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
       }
       if (NS_SUCCEEDED(rv)) {
         ret.MarkAsHandled();
       } else {
         NS_WARNING("Failed to remove the <br> element");
       }
@@ -3541,17 +3553,17 @@ EditActionResult HTMLEditRules::TryToJoi
       MOZ_KnownLive(&HTMLEditorRef()), leftBlock, rightBlock);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditActionIgnored(rv);
   }
   // Do br adjustment.
-  nsCOMPtr<Element> brNode =
+  RefPtr<Element> brNode =
       CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
   EditActionResult ret(NS_OK);
   if (mergeLists ||
       leftBlock->NodeInfo()->NameAtom() == rightBlock->NodeInfo()->NameAtom()) {
     // Nodes are same type.  merge them.
     EditorDOMPoint pt;
     nsresult rv =
         JoinNearestEditableNodesWithTransaction(*leftBlock, *rightBlock, &pt);
@@ -3569,17 +3581,17 @@ EditActionResult HTMLEditRules::TryToJoi
   } else {
     // Nodes are dissimilar types.
     ret |= MoveBlock(*leftBlock, *rightBlock, -1, 0);
     if (NS_WARN_IF(ret.Failed())) {
       return ret;
     }
   }
   if (brNode) {
-    rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+    rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*brNode);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
     }
     // XXX In other top level if blocks, the result of
     //     DeleteNodeWithTransaction() is ignored.  Why does only this result
     //     is respected?
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return ret.SetResult(rv);
@@ -3609,17 +3621,18 @@ EditActionResult HTMLEditRules::MoveBloc
     // get the node to act on
     if (IsBlockNode(arrayOfNodes[i])) {
       // For block nodes, move their contents only, then delete block.
       ret |= MoveContents(MOZ_KnownLive(*arrayOfNodes[i]->AsElement()),
                           aLeftBlock, &aLeftOffset);
       if (NS_WARN_IF(ret.Failed())) {
         return ret;
       }
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*arrayOfNodes[i]);
+      rv = MOZ_KnownLive(HTMLEditorRef())
+               .DeleteNodeWithTransaction(MOZ_KnownLive(*arrayOfNodes[i]));
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
       }
       NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove a block node");
       ret.MarkAsHandled();
     } else {
       // Otherwise move the content as is, checking against the DTD.
       ret |= MoveNodeSmart(MOZ_KnownLive(*arrayOfNodes[i]->AsContent()),
@@ -3681,17 +3694,17 @@ EditActionResult HTMLEditRules::MoveNode
   if (aNode.IsElement()) {
     ret = MoveContents(MOZ_KnownLive(*aNode.AsElement()), aDestElement,
                        aInOutDestOffset);
     if (NS_WARN_IF(ret.Failed())) {
       return ret;
     }
   }
 
-  nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aNode);
+  nsresult rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(aNode);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return ret.SetResult(rv);
   }
   return ret.MarkAsHandled();
 }
@@ -3716,17 +3729,18 @@ EditActionResult HTMLEditRules::MoveCont
   return ret;
 }
 
 nsresult HTMLEditRules::DeleteElementsExceptTableRelatedElements(
     nsINode& aNode) {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!HTMLEditUtils::IsTableElementButNotTable(&aNode)) {
-    nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aNode);
+    nsresult rv =
+        MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(aNode);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
@@ -3767,17 +3781,18 @@ nsresult HTMLEditRules::DidDeleteSelecti
   if (citeNode) {
     bool isEmpty = true, seenBR = false;
     HTMLEditorRef().IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false,
                                     &seenBR);
     if (isEmpty) {
       EditorDOMPoint atCiteNode(citeNode);
       {
         AutoEditorDOMPointChildInvalidator lockOffset(atCiteNode);
-        nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*citeNode);
+        nsresult rv =
+            MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*citeNode);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       if (atCiteNode.IsSet() && seenBR) {
@@ -3892,17 +3907,17 @@ nsresult HTMLEditRules::MakeList(nsAtom&
   }
 
   // if no nodes, we make empty list.  Ditto if the user tried to make a list
   // of some # of breaks.
   if (arrayOfNodes.IsEmpty() || bOnlyBreaks) {
     // if only breaks, delete them
     if (bOnlyBreaks) {
       for (auto& node : arrayOfNodes) {
-        rv = HTMLEditorRef().DeleteNodeWithTransaction(*node);
+        rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*node);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
@@ -3990,17 +4005,17 @@ nsresult HTMLEditRules::MakeList(nsAtom&
       curList = nullptr;
     }
 
     // If curNode is a break, delete it, and quit remembering prev list item.
     // If an empty inline container, delete it, but still remember the previous
     // item.
     if (HTMLEditorRef().IsEditable(curNode) &&
         (TextEditUtils::IsBreak(curNode) || IsEmptyInline(curNode))) {
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       if (TextEditUtils::IsBreak(curNode)) {
         prevListItem = nullptr;
@@ -4411,17 +4426,18 @@ nsresult HTMLEditRules::MakeBasicBlock(n
 
       // If the first editable node after selection is a br, consume it.
       // Otherwise it gets pushed into a following block after the split,
       // which is visually bad.
       nsCOMPtr<nsIContent> brContent =
           HTMLEditorRef().GetNextEditableHTMLNode(pointToInsertBlock);
       if (brContent && brContent->IsHTMLElement(nsGkAtoms::br)) {
         AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock);
-        rv = HTMLEditorRef().DeleteNodeWithTransaction(*brContent);
+        rv = MOZ_KnownLive(HTMLEditorRef())
+                 .DeleteNodeWithTransaction(*brContent);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       // Do the splits!
@@ -4461,17 +4477,17 @@ nsresult HTMLEditRules::MakeBasicBlock(n
       return NS_OK;
     }
 
     // We are making a block.  Consume a br, if needed.
     nsCOMPtr<nsIContent> brNode =
         HTMLEditorRef().GetNextEditableHTMLNodeInBlock(pointToInsertBlock);
     if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
       AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock);
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*brNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // We don't need to act on this node any more
       arrayOfNodes.RemoveElement(brNode);
@@ -4491,17 +4507,17 @@ nsresult HTMLEditRules::MakeBasicBlock(n
     if (NS_WARN_IF(!block)) {
       return NS_ERROR_FAILURE;
     }
     // Remember our new block for postprocessing
     mNewBlock = block;
     // Delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
@@ -4686,17 +4702,17 @@ nsresult HTMLEditRules::IndentAroundSele
     nsresult rv = IncreaseMarginToIndent(*theBlock);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to increase indentation");
     // delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
@@ -4960,17 +4976,17 @@ nsresult HTMLEditRules::IndentAroundSele
     if (NS_WARN_IF(!theBlock)) {
       return NS_ERROR_FAILURE;
     }
     // remember our new block for postprocessing
     mNewBlock = theBlock;
     // delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
@@ -5520,17 +5536,17 @@ SplitRangeOffFromNodeResult HTMLEditRule
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
           }
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return SplitRangeOffFromNodeResult(rv);
           }
         } else {
           // Delete any non-list items for now
-          rv = HTMLEditorRef().DeleteNodeWithTransaction(*child);
+          rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*child);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
           }
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return SplitRangeOffFromNodeResult(rv);
           }
         }
         child = curNode->GetLastChild();
@@ -6002,17 +6018,18 @@ nsresult HTMLEditRules::AlignContentsAtS
       // we are, so it's safe to consume it.
       nsCOMPtr<nsIContent> sibling;
       if (pointToInsertDiv.GetChild()) {
         sibling =
             HTMLEditorRef().GetNextHTMLSibling(pointToInsertDiv.GetChild());
       }
       if (sibling && !IsBlockNode(*sibling)) {
         AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertDiv);
-        rv = HTMLEditorRef().DeleteNodeWithTransaction(*brContent);
+        rv = MOZ_KnownLive(HTMLEditorRef())
+                 .DeleteNodeWithTransaction(*brContent);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
@@ -6429,17 +6446,18 @@ nsresult HTMLEditRules::MaybeDeleteTopMo
       }
       case nsIEditor::eNone:
         break;
       default:
         MOZ_CRASH("CheckForEmptyBlock doesn't support this action yet");
     }
   }
   *aHandled = true;
-  nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*emptyBlock);
+  nsresult rv =
+      MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*emptyBlock);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
@@ -7717,17 +7735,17 @@ nsresult HTMLEditRules::ReturnInHeader(E
       if (NS_WARN_IF(createMozBrResult.Failed())) {
         return createMozBrResult.Rv();
       }
     }
   }
 
   // If the new (righthand) header node is empty, delete it
   if (IsEmptyBlockElement(aHeader, IgnoreSingleBR::eYes)) {
-    rv = HTMLEditorRef().DeleteNodeWithTransaction(aHeader);
+    rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(aHeader);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     // Layout tells the caret to blink in a weird place if we don't place a
     // break after the header.
@@ -8026,17 +8044,17 @@ nsresult HTMLEditRules::SplitParagraph(
   }
   if (NS_WARN_IF(!splitDivOrPResult.DidSplit())) {
     return NS_ERROR_FAILURE;
   }
 
   // Get rid of the break, if it is visible (otherwise it may be needed to
   // prevent an empty p).
   if (aNextBRNode && HTMLEditorRef().IsVisibleBRElement(aNextBRNode)) {
-    rv = HTMLEditorRef().DeleteNodeWithTransaction(*aNextBRNode);
+    rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*aNextBRNode);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
@@ -8143,17 +8161,18 @@ nsresult HTMLEditRules::ReturnInListItem
         error.SuppressException();
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     } else {
       // Otherwise kill this item
-      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
+      nsresult rv =
+          MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(aListItem);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       // Time to insert a paragraph
@@ -8257,17 +8276,18 @@ nsresult HTMLEditRules::ReturnInListItem
               HTMLEditorRef().CreateNodeWithTransaction(*listAtom,
                                                         atNextListItem);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(!newListItem)) {
             return NS_ERROR_FAILURE;
           }
-          rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
+          rv = MOZ_KnownLive(HTMLEditorRef())
+                   .DeleteNodeWithTransaction(aListItem);
           if (NS_WARN_IF(!CanHandleEditAction())) {
             return NS_ERROR_EDITOR_DESTROYED;
           }
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           ErrorResult error;
           SelectionRefPtr()->Collapse(EditorRawDOMPoint(newListItem, 0), error);
@@ -8636,17 +8656,18 @@ nsresult HTMLEditRules::ApplyBlockStyle(
     }
 
     if (curNode->IsHTMLElement(nsGkAtoms::br)) {
       // If the node is a break, we honor it by putting further nodes in a new
       // parent
       if (curBlock) {
         // Forget any previous block used for previous inline nodes
         curBlock = nullptr;
-        nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+        nsresult rv =
+            MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*curNode);
         if (NS_WARN_IF(!CanHandleEditAction())) {
           return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
@@ -9544,17 +9565,17 @@ nsresult HTMLEditRules::RemoveEmptyNodes
         skipList.AppendElement(*parent);
       }
     }
   }
 
   // now delete the empty nodes
   for (OwningNonNull<nsINode>& delNode : arrayOfEmptyNodes) {
     if (HTMLEditorRef().IsModifiableNode(delNode)) {
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*delNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*delNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
@@ -9575,17 +9596,17 @@ nsresult HTMLEditRules::RemoveEmptyNodes
               EditorRawDOMPoint(delNode));
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
     }
-    rv = HTMLEditorRef().DeleteNodeWithTransaction(*delNode);
+    rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*delNode);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
@@ -9799,17 +9820,18 @@ nsresult HTMLEditRules::RemoveListStruct
       }
       continue;
     }
 
     // Delete any non-list items for now
     // XXX This is not HTML5 aware.  HTML5 allows all list elements to have
     //     <script> and <template> and <dl> element to have <div> to group
     //     some <dt> and <dd> elements.  So, this may break valid children.
-    nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*child);
+    nsresult rv =
+        MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*child);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
@@ -10538,17 +10560,17 @@ nsresult HTMLEditRules::PrepareToMakeEle
     if (NS_WARN_IF(!positionedDiv)) {
       return NS_ERROR_FAILURE;
     }
     // Remember our new block for postprocessing
     *aTargetElement = positionedDiv;
     // Delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+      rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
@@ -10883,20 +10905,22 @@ void HTMLEditRules::OnModifyDocument() {
 
   // DeleteNodeWithTransaction() below may cause a flush, which could destroy
   // the editor
   nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
 
   // Delete our bogus node, if we have one, since the document might not be
   // empty any more.
   if (mBogusNode) {
+    // A mutation event listener may recreate bogus node again during the
+    // call of DeleteNodeWithTransaction().  So, move it first.
+    nsCOMPtr<nsIContent> bogusNode(std::move(mBogusNode));
     DebugOnly<nsresult> rv =
-        HTMLEditorRef().DeleteNodeWithTransaction(*mBogusNode);
+        MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*bogusNode);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove the bogus node");
-    mBogusNode = nullptr;
   }
 
   // Try to recreate the bogus node if needed.
   DebugOnly<nsresult> rv = CreateBogusNodeIfNeeded();
   NS_WARNING_ASSERTION(
       rv.value != NS_ERROR_EDITOR_DESTROYED,
       "The editor has been destroyed during creating a bogus node");
 }
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -165,17 +165,17 @@ class HTMLEditRules : public TextEditRul
   /**
    * Called before inserting something into the editor.
    * This method may removes mBougsNode if there is.  Therefore, this method
    * might cause destroying the editor.
    *
    * @param aCancel             Returns true if the operation is canceled.
    *                            This can be nullptr.
    */
-  MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
 
   /**
    * Called before inserting text.
    * This method may actually inserts text into the editor.  Therefore, this
    * might cause destroying the editor.
    *
    * @param aEditSubAction      Must be EditSubAction::eInsertTextComingFromIME
    *                            or EditSubAction::eInsertText.
@@ -192,17 +192,17 @@ class HTMLEditRules : public TextEditRul
                                        const nsAString* inString,
                                        nsAString* outString,
                                        int32_t aMaxLength);
 
   /**
    * WillLoadHTML() is called before loading enter document from source.
    * This removes bogus node if there is.
    */
-  MOZ_MUST_USE nsresult WillLoadHTML();
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult WillLoadHTML();
 
   /**
    * WillInsertParagraphSeparator() is called when insertParagraph command is
    * executed or something equivalent.  This method actually tries to insert
    * new paragraph or <br> element, etc.
    */
   MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE EditActionResult WillInsertParagraphSeparator();
@@ -210,16 +210,17 @@ class HTMLEditRules : public TextEditRul
   /**
    * If aNode is a text node that contains only collapsed whitespace, delete
    * it.  It doesn't serve any useful purpose, and we don't want it to confuse
    * code that doesn't correctly skip over it.
    *
    * If deleting the node fails (like if it's not editable), the caller should
    * proceed as usual, so don't return any errors.
    */
+  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult DeleteNodeIfCollapsedText(nsINode& aNode);
 
   /**
    * InsertBRElement() inserts a <br> element into aInsertToBreak.
    *
    * @param aInsertToBreak      The point where new <br> element will be
    *                            inserted before.
    */
@@ -249,17 +250,17 @@ class HTMLEditRules : public TextEditRul
       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.
    */
-  MOZ_MUST_USE nsresult DidDeleteSelection();
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult DidDeleteSelection();
 
   /**
    * InsertBRIfNeeded() determines if a br is needed for current selection to
    * not be spastic.  If so, it inserts one.  Callers responsibility to only
    * call with collapsed selection.
    */
   MOZ_MUST_USE nsresult InsertBRIfNeeded();
 
@@ -382,17 +383,17 @@ class HTMLEditRules : public TextEditRul
    * from the DOM tree.
    *
    * @param aNode               If this is not a table related element, this
    *                            node will be removed from the DOM tree.
    *                            Otherwise, this method calls itself recursively
    *                            with its children.
    *
    */
-  MOZ_MUST_USE nsresult
+  MOZ_CAN_RUN_SCRIPT 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,
@@ -482,16 +483,17 @@ class HTMLEditRules : public TextEditRul
    * This method actually changes z-index of nearest absolute positioned
    * element relatively.  Therefore, this might cause destroying the HTML
    * editor.
    *
    * @param aChange             Amount to change z-index.
    * @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 WillRelativeChangeZIndex(int32_t aChange, bool* aCancel,
                                                  bool* aHandled);
 
   /**
    * Called before creating aDefinitionListItemTag around Selection.  This
    * method just calls WillMakeList() with "dl" as aListType and
    * aDefinitionListItemTag as aItemType.
    *
@@ -877,16 +879,17 @@ class HTMLEditRules : public TextEditRul
    *                              Selection to after found empty ancestor.
    *                            - If ePrevious, ePreviousWord or
    *                              eToBeginningOfLine, collapse Selection to
    *                              end of previous editable node.
    *                            Otherwise, eNone is allowed but does nothing.
    * @param aHandled            Returns true if this method removes an empty
    *                            block ancestor of aStartNode.
    */
+  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult MaybeDeleteTopMostEmptyAncestor(
       nsINode& aStartNode, Element& aEditingHostElement,
       nsIEditor::EDirection aAction, bool* aHandled);
 
   enum class BRLocation { beforeBlock, blockEnd };
   Element* CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
                                int32_t aOffset = 0);
 
@@ -1216,16 +1219,17 @@ class HTMLEditRules : public TextEditRul
    * mDocChangeRange.  However, if mail-cite node has only a <br> element,
    * the node will be removed but <br> element is moved to where the
    * mail-cite node was.
    * XXX This method is expensive if mDocChangeRange is too wide and may
    *     remove unexpected empty element, e.g., it was created by JS, but
    *     we haven't touched it.  Cannot we remove this method and make
    *     guarantee that empty nodes won't be created?
    */
+  MOZ_CAN_RUN_SCRIPT
   MOZ_MUST_USE nsresult RemoveEmptyNodesInChangedRange();
 
   nsresult SelectionEndpointInNode(nsINode* aNode, bool* aResult);
   nsresult UpdateDocChangeRange(nsRange* aRange);
 
   /**
    * ConfirmSelectionInBody() makes sure that Selection is in editor root
    * element typically <body> element (see HTMLEditor::UpdateRootElement())
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -134,17 +134,17 @@ class HTMLEditor final : public TextEdit
   NS_IMETHOD SetFlags(uint32_t aFlags) override;
 
   virtual bool CanPaste(int32_t aClipboardType) const override;
   using EditorBase::CanPaste;
 
   MOZ_CAN_RUN_SCRIPT
   NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
 
-  NS_IMETHOD DeleteNode(nsINode* aNode) override;
+  MOZ_CAN_RUN_SCRIPT 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;
@@ -175,17 +175,17 @@ class HTMLEditor final : public TextEdit
    * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|.
    */
   virtual bool CanPasteTransferable(nsITransferable* aTransferable) override;
 
   /**
    * InsertLineBreakAsAction() is called when user inputs a line break with
    * Shift + Enter or something.
    */
-  virtual nsresult InsertLineBreakAsAction() override;
+  MOZ_CAN_RUN_SCRIPT virtual nsresult InsertLineBreakAsAction() override;
 
   /**
    * InsertParagraphSeparatorAsAction() is called when user tries to separate
    * current paragraph with Enter key press in HTMLEditor or something.
    */
   nsresult InsertParagraphSeparatorAsAction();
 
   /**
@@ -477,16 +477,17 @@ class HTMLEditor final : public TextEdit
    * with special processing for lines beginning with ">",
    * which will be treated as mail quotes and inserted
    * as plaintext quoted blocks.
    * If the selection is not collapsed, the selection is deleted
    * and the insertion takes place at the resulting collapsed selection.
    *
    * @param aString   the string to be inserted
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult InsertTextWithQuotations(const nsAString& aStringToInsert);
 
  protected:  // May be called by friends.
   /****************************************************************************
    * Some classes like TextEditRules, HTMLEditRules, WSRunObject which are
    * part of handling edit actions are allowed to call the following protected
    * methods.  However, those methods won't prepare caches of some objects
    * which are necessary for them.  So, if you want some following methods
@@ -497,27 +498,28 @@ class HTMLEditor final : public TextEdit
   /**
    * DeleteSelectionWithTransaction() removes selected content or content
    * around caret with transactions.
    *
    * @param aDirection          How much range should be removed.
    * @param aStripWrappers      Whether the parent blocks should be removed
    *                            when they become empty.
    */
+  MOZ_CAN_RUN_SCRIPT
   virtual nsresult DeleteSelectionWithTransaction(
       EDirection aAction, EStripWrappers aStripWrappers) override;
 
   /**
    * DeleteNodeWithTransaction() removes aNode from the DOM tree if it's
    * modifiable.  Note that this is not an override of same method of
    * EditorBase.
    *
    * @param aNode       The node to be removed from the DOM tree.
    */
-  nsresult DeleteNodeWithTransaction(nsINode& aNode);
+  MOZ_CAN_RUN_SCRIPT nsresult DeleteNodeWithTransaction(nsINode& aNode);
 
   /**
    * DeleteTextWithTransaction() removes text in the range from aCharData if
    * it's modifiable.  Note that this not an override of same method of
    * EditorBase.
    *
    * @param aCharData           The data node which should be modified.
    * @param aOffset             Start offset of removing text in aCharData.
@@ -1481,26 +1483,28 @@ class HTMLEditor final : public TextEdit
       nsIContent& aNode, const EditorDOMPointBase<PT, CT>& aPointToInsert,
       SplitAtEdges aSplitAtEdges);
 
   /**
    * InsertBrElementAtSelectionWithTransaction() inserts a new <br> element at
    * selection.  If there is non-collapsed selection ranges, the selected
    * ranges is deleted first.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult InsertBrElementAtSelectionWithTransaction();
 
   /**
    * InsertTextWithQuotationsInternal() replaces selection with new content.
    * First, this method splits aStringToInsert to multiple chunks which start
    * with non-linebreaker except first chunk and end with a linebreaker except
    * last chunk.  Then, each chunk starting with ">" is inserted after wrapping
    * with <span _moz_quote="true">, and each chunk not starting with ">" is
    * inserted as normal text.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult InsertTextWithQuotationsInternal(const nsAString& aStringToInsert);
 
   /**
    * IndentOrOutdentAsSubAction() indents or outdents the content around
    * Selection.  Callers have to guarantee that there is a placeholder
    * transaction.
    *
    * @param aEditSubAction      Must be EditSubAction::eIndent or
@@ -1861,31 +1865,33 @@ class HTMLEditor final : public TextEdit
   nsresult DeleteTableCellWithTransaction(int32_t aNumberOfCellsToDelete);
 
   /**
    * DeleteAllChildrenWithTransaction() removes all children of aElement from
    * the tree.
    *
    * @param aElement        The element whose children you want to remove.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteAllChildrenWithTransaction(Element& aElement);
 
   /**
    * Move all contents from aCellToMerge into aTargetCell (append at end).
    */
   MOZ_CAN_RUN_SCRIPT
   nsresult MergeCells(RefPtr<Element> aTargetCell, RefPtr<Element> aCellToMerge,
                       bool aDeleteCellToMerge);
 
   /**
    * DeleteTableElementAndChildren() removes aTableElement (and its children)
    * from the DOM tree with transaction.
    *
    * @param aTableElement   The <table> element which you want to remove.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteTableElementAndChildrenWithTransaction(Element& aTableElement);
 
   nsresult SetColSpan(Element* aCell, int32_t aColSpan);
   nsresult SetRowSpan(Element* aCell, int32_t aRowSpan);
 
   /**
    * Helper used to get nsTableWrapperFrame for a table.
    */
@@ -1966,27 +1972,28 @@ class HTMLEditor final : public TextEdit
    * Fallback method: Call this after using ClearSelection() and you
    * failed to set selection to some other content in the document.
    */
   nsresult SetSelectionAtDocumentStart();
 
   static Element* GetEnclosingTable(nsINode* aNode);
 
   // Methods for handling plaintext quotations
-  nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
+  MOZ_CAN_RUN_SCRIPT nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
 
   /**
    * Insert a string as quoted text, replacing the selected text (if any).
    * @param aQuotedText     The string to insert.
    * @param aAddCites       Whether to prepend extra ">" to each line
    *                        (usually true, unless those characters
    *                        have already been added.)
    * @return aNodeInserted  The node spanning the insertion, if applicable.
    *                        If aAddCites is false, this will be null.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText,
                                       bool aAddCites, nsINode** aNodeInserted);
 
   /**
    * InsertObject() inserts given object at aPointToInsert.
    */
   MOZ_CAN_RUN_SCRIPT
   nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -333,17 +333,17 @@ nsresult HTMLEditor::DoInsertHTMLWithCon
 
     // if there are any invisible br's after our insertion point, remove them.
     // this is because if there is a br at end of what we paste, it will make
     // the invisible br visible.
     WSRunObject wsObj(this, pointToInsert);
     if (wsObj.mEndReasonNode && TextEditUtils::IsBreak(wsObj.mEndReasonNode) &&
         !IsVisibleBRElement(wsObj.mEndReasonNode)) {
       AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert);
-      rv = DeleteNodeWithTransaction(*wsObj.mEndReasonNode);
+      rv = DeleteNodeWithTransaction(MOZ_KnownLive(*wsObj.mEndReasonNode));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // Remember if we are in a link.
     bool bStartedInLink = !!GetLinkElement(pointToInsert.GetContainer());
 
@@ -464,17 +464,18 @@ nsresult HTMLEditor::DoInsertHTMLWithCon
             if (HTMLEditUtils::IsListItem(pointToInsert.GetContainer())) {
               bool isEmpty;
               rv = IsEmptyNode(pointToInsert.GetContainer(), &isEmpty, true);
               if (NS_SUCCEEDED(rv) && isEmpty) {
                 if (NS_WARN_IF(
                         !pointToInsert.GetContainer()->GetParentNode())) {
                   // Is it an orphan node?
                 } else {
-                  DeleteNodeWithTransaction(*pointToInsert.GetContainer());
+                  DeleteNodeWithTransaction(
+                      MOZ_KnownLive(*pointToInsert.GetContainer()));
                   pointToInsert.Set(pointToInsert.GetContainer());
                 }
               }
             }
             EditorDOMPoint insertedPoint =
                 InsertNodeIntoProperAncestorWithTransaction(
                     *firstChild, pointToInsert,
                     SplitAtEdges::eDoNotCreateEmptyContainer);
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -1357,17 +1357,17 @@ nsresult HTMLEditor::DeleteTableColumnWi
                              "colspan should be 2 or larger");
         SetColSpan(cellData.mElement, cellData.mColSpan - 1);
       }
       if (!cellData.IsSpannedFromOtherColumn()) {
         // Cell is in column to be deleted, but must have colspan > 1,
         // so delete contents of cell instead of cell itself (We must have
         // reset colspan above).
         DebugOnly<nsresult> rv =
-            DeleteAllChildrenWithTransaction(*cellData.mElement);
+            DeleteAllChildrenWithTransaction(MOZ_KnownLive(*cellData.mElement));
         NS_WARNING_ASSERTION(
             NS_SUCCEEDED(rv),
             "Failed to remove all children of the cell element");
       }
       // Skip rows which the removed cell spanned.
       rowIndex += cellData.NumberOfFollowingRows();
       continue;
     }
@@ -1375,17 +1375,18 @@ nsresult HTMLEditor::DeleteTableColumnWi
     // Delete the cell
     int32_t numberOfCellsInRow =
         GetNumberOfCellsInRow(aTableElement, cellData.mCurrent.mRow);
     NS_WARNING_ASSERTION(numberOfCellsInRow > 0,
                          "Failed to count existing cells in the row");
     if (numberOfCellsInRow != 1) {
       // If removing cell is not the last cell of the row, we can just remove
       // it.
-      nsresult rv = DeleteNodeWithTransaction(*cellData.mElement);
+      nsresult rv =
+          DeleteNodeWithTransaction(MOZ_KnownLive(*cellData.mElement));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // Skip rows which the removed cell spanned.
       rowIndex += cellData.NumberOfFollowingRows();
       continue;
     }
 
@@ -2766,17 +2767,17 @@ nsresult HTMLEditor::MergeCells(RefPtr<E
     // If we fail or don't have children,
     // we insert at index 0
     int32_t insertIndex = 0;
 
     // Start inserting just after last child
     uint32_t len = aTargetCell->GetChildCount();
     if (len == 1 && IsEmptyCell(aTargetCell)) {
       // Delete the empty node
-      nsIContent* cellChild = aTargetCell->GetFirstChild();
+      nsCOMPtr<nsIContent> cellChild = aTargetCell->GetFirstChild();
       if (NS_WARN_IF(!cellChild)) {
         return NS_ERROR_FAILURE;
       }
       nsresult rv = DeleteNodeWithTransaction(*cellChild);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       insertIndex = 0;
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -388,23 +388,25 @@ nsresult TextEditRules::WillInsert(bool*
     *aCancel = false;
   }
 
   // check for the magic content node and delete it if it exists
   if (!mBogusNode) {
     return NS_OK;
   }
 
+  // A mutation event listener may recreate bogus node again during the
+  // call of DeleteNodeWithTransaction().  So, move it first.
+  nsCOMPtr<nsIContent> bogusNode(std::move(mBogusNode));
   DebugOnly<nsresult> rv =
-      TextEditorRef().DeleteNodeWithTransaction(*mBogusNode);
+      MOZ_KnownLive(TextEditorRef()).DeleteNodeWithTransaction(*bogusNode);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove the bogus node");
-  mBogusNode = nullptr;
   return NS_OK;
 }
 
 EditActionResult TextEditRules::WillInsertLineBreak(int32_t aMaxLength) {
   MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(!IsSingleLineEditor());
 
   CANCEL_OPERATION_AND_RETURN_EDIT_ACTION_RESULT_IF_READONLY_OF_DISABLED
@@ -420,18 +422,18 @@ EditActionResult TextEditRules::WillInse
     return EditActionIgnored(rv);
   }
   if (didTruncate) {
     return EditActionCanceled();
   }
 
   // if the selection isn't collapsed, delete it.
   if (!SelectionRefPtr()->IsCollapsed()) {
-    rv = TextEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
-                                                    nsIEditor::eStrip);
+    rv = MOZ_KnownLive(TextEditorRef())
+             .DeleteSelectionAsSubAction(nsIEditor::eNone, nsIEditor::eStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
   }
 
@@ -729,18 +731,18 @@ nsresult TextEditRules::WillInsertText(E
   // handle password field docs
   if (IsPasswordEditor()) {
     nsContentUtils::GetSelectionInTextControl(
         SelectionRefPtr(), TextEditorRef().GetRoot(), start, end);
   }
 
   // if the selection isn't collapsed, delete it.
   if (!SelectionRefPtr()->IsCollapsed()) {
-    rv = TextEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
-                                                    nsIEditor::eStrip);
+    rv = MOZ_KnownLive(TextEditorRef())
+             .DeleteSelectionAsSubAction(nsIEditor::eNone, nsIEditor::eStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
@@ -1158,44 +1160,46 @@ nsresult TextEditRules::DeleteSelectionW
     }
 
     rv = TextEditorRef().ExtendSelectionForDelete(&aCollapsedAction);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  nsresult rv = TextEditorRef().DeleteSelectionWithTransaction(
-      aCollapsedAction, nsIEditor::eStrip);
+  nsresult rv =
+      MOZ_KnownLive(TextEditorRef())
+          .DeleteSelectionWithTransaction(aCollapsedAction, nsIEditor::eStrip);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   *aHandled = true;
   ASSERT_PASSWORD_LENGTHS_EQUAL()
   return NS_OK;
 }
 
 nsresult TextEditRules::DidDeleteSelection() {
   MOZ_ASSERT(IsEditorDataAvailable());
 
-  EditorRawDOMPoint selectionStartPoint(
+  EditorDOMPoint selectionStartPoint(
       EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Delete empty text nodes at selection.
   if (selectionStartPoint.IsInTextNode() &&
       !selectionStartPoint.GetContainer()->Length()) {
-    nsresult rv = TextEditorRef().DeleteNodeWithTransaction(
-        *selectionStartPoint.GetContainer());
+    nsresult rv = MOZ_KnownLive(TextEditorRef())
+                      .DeleteNodeWithTransaction(
+                          MOZ_KnownLive(*selectionStartPoint.GetContainer()));
     if (NS_WARN_IF(!CanHandleEditAction())) {
       return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -212,17 +212,17 @@ class TextEditRules : public nsITimerCal
   /**
    * Called before inserting something into the editor.
    * This method may removes mBougsNode if there is.  Therefore, this method
    * might cause destroying the editor.
    *
    * @param aCancel             Returns true if the operation is canceled.
    *                            This can be nullptr.
    */
-  MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult WillInsert(bool* aCancel = nullptr);
 
   /**
    * Called before deleting selected content.
    * This method may actually remove the selected content with
    * DeleteSelectionWithTransaction().  So, this might cause destroying the
    * editor.
    *
    * @param aCaollapsedAction   Direction to extend the selection.
@@ -248,17 +248,17 @@ class TextEditRules : public nsITimerCal
   MOZ_MUST_USE nsresult DeleteSelectionWithTransaction(
       nsIEditor::EDirection aCollapsedAction, bool* aCancel, bool* aHandled);
 
   /**
    * Called after deleted selected content.
    * This method may remove empty text node and makes guarantee that caret
    * is never at left of <br> element.
    */
-  MOZ_MUST_USE nsresult DidDeleteSelection();
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult DidDeleteSelection();
 
   nsresult WillSetTextProperty(bool* aCancel, bool* aHandled);
 
   nsresult WillRemoveTextProperty(bool* aCancel, bool* aHandled);
 
   nsresult WillUndo(bool* aCancel, bool* aHandled);
   nsresult DidUndo(nsresult aResult);
 
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -50,29 +50,30 @@ class TextEditor : public EditorBase, pu
   TextEditor();
 
   // nsIPlaintextEditor methods
   NS_DECL_NSIPLAINTEXTEDITOR
 
   // Overrides of nsIEditor
   NS_IMETHOD GetDocumentIsEmpty(bool* aDocumentIsEmpty) override;
 
+  MOZ_CAN_RUN_SCRIPT
   NS_IMETHOD DeleteSelection(EDirection aAction,
                              EStripWrappers aStripWrappers) override;
 
   NS_IMETHOD SetDocumentCharacterSet(const nsACString& characterSet) override;
 
   // If there are some good name to create non-virtual Undo()/Redo() methods,
   // we should create them and those methods should just run them.
   MOZ_CAN_RUN_SCRIPT
   NS_IMETHOD Undo(uint32_t aCount) final;
   MOZ_CAN_RUN_SCRIPT
   NS_IMETHOD Redo(uint32_t aCount) final;
 
-  NS_IMETHOD Cut() override;
+  MOZ_CAN_RUN_SCRIPT NS_IMETHOD Cut() override;
   bool CanCut() const;
   NS_IMETHOD Copy() override;
   bool CanCopy() const;
   bool CanDelete() const;
   virtual bool CanPaste(int32_t aClipboardType) const;
 
   // Shouldn't be used internally, but we need these using declarations for
   // avoiding warnings of clang.
@@ -162,16 +163,17 @@ class TextEditor : public EditorBase, pu
    * caret with transactions.  This should be used for handling it as an
    * edit action.  If you'd like to remove selection for preparing to insert
    * something, you probably should use DeleteSelectionAsSubAction().
    *
    * @param aDirection          How much range should be removed.
    * @param aStripWrappers      Whether the parent blocks should be removed
    *                            when they become empty.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteSelectionAsAction(EDirection aDirection,
                                    EStripWrappers aStripWrappers);
 
   /**
    * The maximum number of characters allowed.
    *   default: -1 (unlimited).
    */
   int32_t MaxTextLength() const { return mMaxTextLength; }
@@ -197,17 +199,17 @@ class TextEditor : public EditorBase, pu
   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();
+  MOZ_CAN_RUN_SCRIPT virtual nsresult InsertLineBreakAsAction();
 
   /**
    * OnCompositionStart() is called when editor receives eCompositionStart
    * event which should be handled in this editor.
    */
   nsresult OnCompositionStart(WidgetCompositionEvent& aCompositionStartEvent);
 
   /**
@@ -299,43 +301,46 @@ class TextEditor : public EditorBase, pu
    * DeleteSelectionAsSubAction() removes selection content or content around
    * caret with transactions.  This should be used for handling it as an
    * edit sub-action.
    *
    * @param aDirection          How much range should be removed.
    * @param aStripWrappers      Whether the parent blocks should be removed
    *                            when they become empty.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult DeleteSelectionAsSubAction(EDirection aDirection,
                                       EStripWrappers aStripWrappers);
 
   /**
    * DeleteSelectionWithTransaction() removes selected content or content
    * around caret with transactions.
    *
    * @param aDirection          How much range should be removed.
    * @param aStripWrappers      Whether the parent blocks should be removed
    *                            when they become empty.
    */
+  MOZ_CAN_RUN_SCRIPT
   virtual nsresult DeleteSelectionWithTransaction(
       EDirection aAction, EStripWrappers aStripWrappers);
 
   /**
    * Replace existed string with aString.  Caller must guarantee that there
    * is a placeholder transaction which will have the transaction.
    *
    * @ param aString   The string to be set.
    */
-  nsresult SetTextAsSubAction(const nsAString& aString);
+  MOZ_CAN_RUN_SCRIPT nsresult SetTextAsSubAction(const nsAString& aString);
 
   /**
    * ReplaceSelectionAsSubAction() replaces selection with aString.
    *
    * @param aString    The string to replace.
    */
+  MOZ_CAN_RUN_SCRIPT
   nsresult ReplaceSelectionAsSubAction(const nsAString& aString);
 
   /**
    * InsertBrElementWithTransaction() creates a <br> element and inserts it
    * before aPointToInsert.  Then, tries to collapse selection at or after the
    * new <br> node if aSelect is not eNone.
    *
    * @param aPointToInsert      The DOM point where should be <br> node inserted
@@ -488,26 +493,27 @@ class TextEditor : public EditorBase, pu
 
   /**
    * DeleteSelectionAndCreateElement() creates a element whose name is aTag.
    * And insert it into the DOM tree after removing the selected content.
    *
    * @param aTag                The element name to be created.
    * @return                    Created new element.
    */
+  MOZ_CAN_RUN_SCRIPT
   already_AddRefed<Element> DeleteSelectionAndCreateElement(nsAtom& aTag);
 
   /**
    * This method first deletes the selection, if it's not collapsed.  Then if
    * the selection lies in a CharacterData node, it splits it.  If the
    * selection is at this point collapsed in a CharacterData node, it's
    * adjusted to be collapsed right before or after the node instead (which is
    * always possible, since the node was split).
    */
-  nsresult DeleteSelectionAndPrepareToCreateNode();
+  MOZ_CAN_RUN_SCRIPT nsresult DeleteSelectionAndPrepareToCreateNode();
 
   /**
    * Shared outputstring; returns whether selection is collapsed and resulting
    * string.
    */
   nsresult SharedOutputString(uint32_t aFlags, bool* aIsCollapsed,
                               nsAString& aResult);
 
--- a/editor/libeditor/WSRunObject.h
+++ b/editor/libeditor/WSRunObject.h
@@ -172,16 +172,17 @@ class MOZ_STACK_CLASS WSRunObject final 
               int32_t aScanStartOffset)
       : WSRunObject(aHTMLEditor,
                     EditorRawDOMPoint(aScanStartNode, aScanStartOffset),
                     EditorRawDOMPoint(aScanStartNode, aScanStartOffset)) {}
   ~WSRunObject();
 
   // ScrubBlockBoundary removes any non-visible whitespace at the specified
   // location relative to a block node.
+  MOZ_CAN_RUN_SCRIPT
   static nsresult ScrubBlockBoundary(HTMLEditor* aHTMLEditor,
                                      BlockBoundary aBoundary, nsINode* aBlock,
                                      int32_t aOffset = -1);
 
   // PrepareToJoinBlocks fixes up ws at the end of aLeftBlock and the
   // beginning of aRightBlock in preperation for them to be joined.  Example
   // of fixup: trailingws in aLeftBlock needs to be removed.
   MOZ_CAN_RUN_SCRIPT
@@ -382,18 +383,19 @@ class MOZ_STACK_CLASS WSRunObject final 
    * When aStartPoint and aEndPoint are same point, does nothing.
    * When aStartPoint and aEndPoint are in same text node, removes characters
    * between them.
    * When aStartPoint is in a text node, removes the text data after the point.
    * When aEndPoint is in a text node, removes the text data before the point.
    * Removes any nodes between them.
    */
   template <typename PT1, typename CT1, typename PT2, typename CT2>
-  nsresult DeleteRange(const EditorDOMPointBase<PT1, CT1>& aStartPoint,
-                       const EditorDOMPointBase<PT2, CT2>& aEndPoint);
+  MOZ_CAN_RUN_SCRIPT nsresult
+  DeleteRange(const EditorDOMPointBase<PT1, CT1>& aStartPoint,
+              const EditorDOMPointBase<PT2, CT2>& aEndPoint);
 
   /**
    * GetNextCharPoint() returns next character's point of aPoint.  If there is
    * no character after aPoint, mTextNode is set to nullptr.
    */
   template <typename PT, typename CT>
   WSPoint GetNextCharPoint(const EditorDOMPointBase<PT, CT>& aPoint) const;
   WSPoint GetNextCharPoint(const WSPoint& aPoint) const;
@@ -492,17 +494,17 @@ class MOZ_STACK_CLASS WSRunObject final 
    */
   template <typename PT, typename CT>
   MOZ_CAN_RUN_SCRIPT nsresult ReplacePreviousNBSPIfUnncessary(
       WSFragment* aRun, const EditorDOMPointBase<PT, CT>& aPoint);
 
   MOZ_CAN_RUN_SCRIPT
   nsresult CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode, int32_t aOffset);
 
-  nsresult Scrub();
+  MOZ_CAN_RUN_SCRIPT nsresult Scrub();
   bool IsBlockNode(nsINode* aNode);
 
   EditorRawDOMPoint StartPoint() const {
     return EditorRawDOMPoint(mStartNode, mStartOffset);
   }
   EditorRawDOMPoint EndPoint() const {
     return EditorRawDOMPoint(mEndNode, mEndOffset);
   }
--- a/editor/nsIEditor.idl
+++ b/editor/nsIEditor.idl
@@ -97,16 +97,17 @@ interface nsIEditor  : nsISupports
    * DeleteSelection removes all nodes in the current selection.
    * @param aDir  if eNext, delete to the right (for example, the DEL key)
    *              if ePrevious, delete to the left (for example, the BACKSPACE key)
    * @param stripWrappers If eStrip, strip any empty inline elements left
    *                      behind after the deletion; if eNoStrip, don't.  If in
    *                      doubt, pass eStrip -- eNoStrip is only for if you're
    *                      about to insert text or similar right after.
    */
+  [can_run_script]
   void deleteSelection(in short action, in short stripWrappers);
 
 
   /* ------------ Document info and file methods -------------- */
 
   /** Returns true if the document has no *meaningful* content */
   readonly attribute boolean documentIsEmpty;
 
@@ -260,16 +261,17 @@ interface nsIEditor  : nsISupports
 
   /* ------------ Clipboard methods -------------- */
 
   /** cut the currently selected text, putting it into the OS clipboard
     * What if no text is selected?
     * What about mixed selections?
     * What are the clipboard formats?
     */
+  [can_run_script]
   void cut();
 
   /** Can we cut? True if the doc is modifiable, and we have a non-
     * collapsed selection.
     */
   boolean canCut();
 
   /** copy the currently selected text, putting it into the OS clipboard
@@ -434,16 +436,17 @@ interface nsIEditor  : nsISupports
   void joinNodes(in Node leftNode,
                  in Node rightNode,
                  in Node parent);
 
   /**
    * deleteNode removes aChild from aParent.
    * @param aChild    The node to delete
    */
+  [can_run_script]
   void deleteNode(in Node child);
 
   /**
    * markNodeDirty() sets a special dirty attribute on the node.
    * Usually this will be called immediately after creating a new node.
    * @param aNode      The node for which to insert formatting.
    */
   void markNodeDirty(in Node node);