Bug 1574852 - part 105: Get rid of `TextEditRules::WillSetProperty()` and `TextEditRules::WillRemoveProperty()` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 12 Sep 2019 09:13:00 +0000
changeset 492978 41bc3a403c3125de85b84b60ecf0cd01bd861864
parent 492977 1bc2978543d1b4ff9e4c3253ff67f7b38af70844
child 492979 cbec1b8d83edf24146e48d6819dda24d9ab7a57b
push id36570
push useropoprus@mozilla.com
push dateFri, 13 Sep 2019 09:28:59 +0000
treeherdermozilla-central@cbec1b8d83ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1574852
milestone71.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 1574852 - part 105: Get rid of `TextEditRules::WillSetProperty()` and `TextEditRules::WillRemoveProperty()` r=m_kato Oddly, they are used only by `HTMLEditor`, but implemented by `TextEditRules`. They cancels when the editor is in plaintext mode. So, actual things are implemented by each caller. This patch cleans them up too. Differential Revision: https://phabricator.services.mozilla.com/D45299
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -804,19 +804,21 @@ nsresult HTMLEditRules::WillDoAction(Edi
     case EditSubAction::eInsertHTMLSource:
     case EditSubAction::eInsertParagraphSeparator:
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertTextComingFromIME:
     case EditSubAction::eOutdent:
     case EditSubAction::eUndo:
     case EditSubAction::eRedo:
     case EditSubAction::eRemoveList:
+    case EditSubAction::eRemoveTextProperty:
     case EditSubAction::eSetOrClearAlignment:
     case EditSubAction::eSetPositionToAbsolute:
     case EditSubAction::eSetPositionToStatic:
+    case EditSubAction::eSetTextProperty:
       MOZ_ASSERT_UNREACHABLE("This path should've been dead code");
       return NS_ERROR_UNEXPECTED;
     default:
       return TextEditRules::WillDoAction(aInfo, aCancel, aHandled);
   }
 }
 
 nsresult HTMLEditRules::DidDoAction(EditSubActionInfo& aInfo,
@@ -842,19 +844,21 @@ nsresult HTMLEditRules::DidDoAction(Edit
     case EditSubAction::eInsertLineBreak:
     case EditSubAction::eInsertParagraphSeparator:
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertTextComingFromIME:
     case EditSubAction::eOutdent:
     case EditSubAction::eUndo:
     case EditSubAction::eRedo:
     case EditSubAction::eRemoveList:
+    case EditSubAction::eRemoveTextProperty:
     case EditSubAction::eSetOrClearAlignment:
     case EditSubAction::eSetPositionToAbsolute:
     case EditSubAction::eSetPositionToStatic:
+    case EditSubAction::eSetTextProperty:
       MOZ_ASSERT_UNREACHABLE("This path should've been dead code");
       return NS_ERROR_UNEXPECTED;
     default:
       return TextEditRules::DidDoAction(aInfo, aResult);
   }
 }
 
 bool HTMLEditRules::DocumentIsEmpty() const {
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -4145,152 +4145,171 @@ nsresult HTMLEditor::SetCSSBackgroundCol
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (NS_WARN_IF(!mRules)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   CommitComposition();
 
-  // Protect the edit rules object from dying
-  RefPtr<TextEditRules> rules(mRules);
-
-  bool isCollapsed = SelectionRefPtr()->IsCollapsed();
+  // XXX Shouldn't we do this before calling `CommitComposition()`?
+  if (IsPlaintextEditor()) {
+    return NS_OK;
+  }
+
+  EditActionResult result = CanHandleHTMLEditSubAction();
+  if (NS_WARN_IF(result.Failed()) || result.Canceled()) {
+    return result.Rv();
+  }
+
+  bool selectionIsCollapsed = SelectionRefPtr()->IsCollapsed();
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoEditSubActionNotifier startToHandleEditSubAction(
       *this, EditSubAction::eInsertElement, nsIEditor::eNext);
-  AutoSelectionRestorer restoreSelectionLater(*this);
-  AutoTransactionsConserveSelection dontChangeMySelection(*this);
-
-  // XXX Although, this method may set background color of ancestor block
-  //     element, using EditSubAction::eSetTextProperty.
-  bool cancel, handled;
-  EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
-  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  if (!cancel && !handled) {
+
+  {
+    AutoSelectionRestorer restoreSelectionLater(*this);
+    AutoTransactionsConserveSelection dontChangeMySelection(*this);
+
     // Loop through the ranges in the selection
+    // XXX This is different from `SetInlinePropertyInternal()`.  It uses
+    //     AutoRangeArray to store all ranges first.  The result may be
+    //     different if mutation event listener changes the `Selection`.
     for (uint32_t i = 0; i < SelectionRefPtr()->RangeCount(); i++) {
       RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(i);
       if (NS_WARN_IF(!range)) {
         return NS_ERROR_FAILURE;
       }
 
-      nsCOMPtr<Element> cachedBlockParent;
-
-      // Check for easy case: both range endpoints in same text node
-      nsCOMPtr<nsINode> startNode = range->GetStartContainer();
-      int32_t startOffset = range->StartOffset();
-      nsCOMPtr<nsINode> endNode = range->GetEndContainer();
-      int32_t endOffset = range->EndOffset();
-      if (startNode == endNode && IsTextNode(startNode)) {
-        // Let's find the block container of the text node
-        nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
-        // And apply the background color to that block container
-        if (blockParent && cachedBlockParent != blockParent) {
-          cachedBlockParent = blockParent;
+      EditorDOMPoint startOfRange(range->StartRef());
+      EditorDOMPoint endOfRange(range->EndRef());
+      if (NS_WARN_IF(!startOfRange.IsSet()) ||
+          NS_WARN_IF(!endOfRange.IsSet())) {
+        continue;
+      }
+
+      if (startOfRange.GetContainer() == endOfRange.GetContainer()) {
+        // If the range is in a text node, set background color of its parent
+        // block.
+        if (startOfRange.IsInTextNode()) {
+          if (RefPtr<Element> blockParent =
+                  GetBlockNodeParent(startOfRange.GetContainer())) {
+            mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
+                blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+            if (NS_WARN_IF(Destroyed())) {
+              return NS_ERROR_EDITOR_DESTROYED;
+            }
+          }
+          continue;
+        }
+
+        // If `Selection` is collapsed in a `<body>` element, set background
+        // color of the `<body>` element.
+        // XXX Why do we refer whether the `Selection` is collapsed rather
+        //     than the `nsRange` is collapsed?
+        if (startOfRange.GetContainer()->IsHTMLElement(nsGkAtoms::body) &&
+            selectionIsCollapsed) {
           mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
-              blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+              MOZ_KnownLive(startOfRange.GetContainerAsElement()), nullptr,
+              nsGkAtoms::bgcolor, &aColor, false);
+          if (NS_WARN_IF(Destroyed())) {
+            return NS_ERROR_EDITOR_DESTROYED;
+          }
+          continue;
+        }
+        // If one node is selected, set background color of it if it's a
+        // block, or of its parent block otherwise.
+        if ((startOfRange.IsStartOfContainer() &&
+             endOfRange.IsStartOfContainer()) ||
+            startOfRange.Offset() + 1 == endOfRange.Offset()) {
+          if (NS_WARN_IF(startOfRange.IsInDataNode())) {
+            continue;
+          }
+          if (RefPtr<Element> blockParent =
+                  GetBlock(*startOfRange.GetChild())) {
+            mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
+                blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+            if (NS_WARN_IF(Destroyed())) {
+              return NS_ERROR_EDITOR_DESTROYED;
+            }
+          }
+          continue;
         }
-      } else if (startNode == endNode &&
-                 startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) {
-        // No block in the document, let's apply the background to the body
-        mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
-            MOZ_KnownLive(startNode->AsElement()), nullptr, nsGkAtoms::bgcolor,
-            &aColor, false);
-      } else if (startNode == endNode && (endOffset - startOffset == 1 ||
-                                          (!startOffset && !endOffset))) {
-        // A unique node is selected, let's also apply the background color to
-        // the containing block, possibly the node itself
-        nsCOMPtr<nsIContent> selectedNode = range->GetChildAtStartOffset();
-        nsCOMPtr<Element> blockParent = GetBlock(*selectedNode);
-        if (blockParent && cachedBlockParent != blockParent) {
-          cachedBlockParent = blockParent;
+      }
+
+      // Collect editable nodes which are entirely contained in the range.
+      AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContents;
+      ContentSubtreeIterator subtreeIter;
+      // If there is no node which is entirely in the range,
+      // `ContentSubtreeIterator::Init()` fails, but this is possible case,
+      // don't warn it.
+      if (NS_SUCCEEDED(subtreeIter.Init(range))) {
+        for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
+          nsINode* node = subtreeIter.GetCurrentNode();
+          if (NS_WARN_IF(!node)) {
+            return NS_ERROR_FAILURE;
+          }
+          if (node->IsContent() && IsEditable(node)) {
+            arrayOfContents.AppendElement(*node->AsContent());
+          }
+        }
+      }
+
+      // This caches block parent if we set its background color.
+      RefPtr<Element> handledBlockParent;
+
+      // If start node is a text node, set background color of its parent
+      // block.
+      if (startOfRange.IsInTextNode() &&
+          IsEditable(startOfRange.GetContainer())) {
+        RefPtr<Element> blockParent =
+            GetBlockNodeParent(startOfRange.GetContainer());
+        if (blockParent && handledBlockParent != blockParent) {
+          handledBlockParent = blockParent;
           mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
               blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
-        }
-      } else {
-        // Not the easy case.  Range not contained in single text node.  There
-        // are up to three phases here.  There are all the nodes reported by
-        // the subtree iterator to be processed.  And there are potentially a
-        // starting textnode and an ending textnode which are only partially
-        // contained by the range.
-
-        // Let's handle the nodes reported by the iterator.  These nodes are
-        // entirely contained in the selection range.  We build up a list of
-        // them (since doing operations on the document during iteration would
-        // perturb the iterator).
-
-        nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
-        nsCOMPtr<nsINode> node;
-
-        // Iterate range and build up array
-        ContentSubtreeIterator subtreeIter;
-        rv = subtreeIter.Init(range);
-        // Init returns an error if no nodes in range.  This can easily happen
-        // with the subtree iterator if the selection doesn't contain any
-        // *whole* nodes.
-        if (NS_SUCCEEDED(rv)) {
-          for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
-            node = subtreeIter.GetCurrentNode();
-            NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
-            if (IsEditable(node)) {
-              arrayOfNodes.AppendElement(*node);
-            }
+          if (NS_WARN_IF(Destroyed())) {
+            return NS_ERROR_EDITOR_DESTROYED;
           }
         }
-        // First check the start parent of the range to see if it needs to be
-        // separately handled (it does if it's a text node, due to how the
-        // subtree iterator works - it will not have reported it).
-        if (IsTextNode(startNode) && IsEditable(startNode)) {
-          nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
-          if (blockParent && cachedBlockParent != blockParent) {
-            cachedBlockParent = blockParent;
-            mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
-                blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+      }
+
+      // Then, set background color of each block or block parent of all nodes
+      // in the range entirely.
+      for (auto& content : arrayOfContents) {
+        RefPtr<Element> blockParent = GetBlock(content);
+        if (blockParent && handledBlockParent != blockParent) {
+          handledBlockParent = blockParent;
+          mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
+              blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+          if (NS_WARN_IF(Destroyed())) {
+            return NS_ERROR_EDITOR_DESTROYED;
           }
         }
-
-        // Then loop through the list, set the property on each node
-        for (auto& node : arrayOfNodes) {
-          nsCOMPtr<Element> blockParent = GetBlock(node);
-          if (blockParent && cachedBlockParent != blockParent) {
-            cachedBlockParent = blockParent;
-            mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
-                blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
-          }
-        }
-        arrayOfNodes.Clear();
-
-        // Last, check the end parent of the range to see if it needs to be
-        // separately handled (it does if it's a text node, due to how the
-        // subtree iterator works - it will not have reported it).
-        if (IsTextNode(endNode) && IsEditable(endNode)) {
-          nsCOMPtr<Element> blockParent = GetBlockNodeParent(endNode);
-          if (blockParent && cachedBlockParent != blockParent) {
-            cachedBlockParent = blockParent;
-            mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
-                blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+      }
+
+      // Finally, if end node is a text node, set background color of its
+      // parent block.
+      if (endOfRange.IsInTextNode() && IsEditable(endOfRange.GetContainer())) {
+        RefPtr<Element> blockParent =
+            GetBlockNodeParent(endOfRange.GetContainer());
+        if (blockParent && handledBlockParent != blockParent) {
+          mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
+              blockParent, nullptr, nsGkAtoms::bgcolor, &aColor, false);
+          if (NS_WARN_IF(Destroyed())) {
+            return NS_ERROR_EDITOR_DESTROYED;
           }
         }
       }
     }
   }
-  if (!cancel) {
-    // Post-process
-    rv = rules->DidDoAction(subActionInfo, rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-  }
-  return NS_OK;
+
+  // Restoring `Selection` may cause destroying us.
+  return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetBackgroundColor(const nsAString& aColor) {
   nsresult rv = SetBackgroundColorAsAction(aColor);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to set background color");
   return rv;
 }
@@ -4302,18 +4321,20 @@ nsresult HTMLEditor::SetBackgroundColorA
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   if (IsCSSEnabled()) {
     // if we are in CSS mode, we have to apply the background color to the
     // containing block (or the body if we have no block-level element in
     // the document)
-    return EditorBase::ToGenericNSResult(
-        SetCSSBackgroundColorWithTransaction(aColor));
+    nsresult rv = SetCSSBackgroundColorWithTransaction(aColor);
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "SetCSSBackgroundColorWithTransaction() failed");
+    return EditorBase::ToGenericNSResult(rv);
   }
 
   // but in HTML mode, we can only set the document's background color
   return EditorBase::ToGenericNSResult(
       SetHTMLBackgroundColorWithTransaction(aColor));
 }
 
 nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -3238,21 +3238,43 @@ class HTMLEditor final : public TextEdit
   /**
    * OutdentAsSubAction() outdents the content around Selection.
    */
   MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE EditActionResult OutdentAsSubAction();
 
   MOZ_CAN_RUN_SCRIPT
   nsresult LoadHTML(const nsAString& aInputString);
 
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetInlinePropertyInternal(nsAtom& aProperty, nsAtom* aAttribute,
-                                     const nsAString& aValue);
-  MOZ_CAN_RUN_SCRIPT
-  nsresult RemoveInlinePropertyInternal(nsAtom* aProperty, nsAtom* aAttribute);
+  /**
+   * SetInlinePropertyInternal() stores new style with `mTypeInState` if
+   * `Selection` is collapsed.  Otherwise, applying the style at all selection
+   * ranges.
+   *
+   * @param aProperty           One of the presentation tag names which we
+   *                            support in style editor.
+   * @param aAttribute          For some aProperty values, needs to be set to
+   *                            its attribute name.  Otherwise, nullptr.
+   * @param aAttributeValue     The value of aAttribute.
+   */
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult SetInlinePropertyInternal(
+      nsAtom& aProperty, nsAtom* aAttribute, const nsAString& aValue);
+
+  /**
+   * RemoveInlinePropertyInternal() removes specified style from `mTypeInState`
+   * if `Selection` is collapsed.  Otherwise, removing the style.
+   * XXX Looks like that this has a lot of bugs in HTML mode.
+   *
+   * @param aProperty           nullptr if you want to remove all inline styles.
+   *                            Otherwise, one of the presentation tag names
+   *                            which we support in style editor.
+   * @param aAttribute          For some aProperty values, need to be set to
+   *                            its attribute name.  Otherwise, nullptr.
+   */
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
+  RemoveInlinePropertyInternal(nsAtom* aProperty, nsAtom* aAttribute);
 
   /**
    * ReplaceHeadContentsWithSourceWithTransaction() replaces all children of
    * <head> element with given source code.  This is undoable.
    *
    * @param aSourceToInsert     HTML source fragment to replace the children
    *                            of <head> element.
    */
@@ -3267,20 +3289,20 @@ class HTMLEditor final : public TextEdit
   nsresult GetLastCellInRow(nsINode* aRowNode, nsINode** aCellNode);
 
   static nsresult GetCellFromRange(nsRange* aRange, Element** aCell);
 
   /**
    * This sets background on the appropriate container element (table, cell,)
    * or calls into nsTextEditor to set the page background.
    */
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
+  MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
+  SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
+  MOZ_CAN_RUN_SCRIPT nsresult
+  SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
 
   virtual void InitializeSelectionAncestorLimit(
       nsIContent& aAncestorLimit) override;
 
   /**
    * Make the given selection span the entire document.
    */
   MOZ_CAN_RUN_SCRIPT
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -95,20 +95,18 @@ nsresult HTMLEditor::SetInlinePropertyAs
   } else if (&aProperty == nsGkAtoms::sub) {
     // Superscript and Subscript styles are mutually exclusive.
     nsresult rv = RemoveInlinePropertyInternal(nsGkAtoms::sup, nullptr);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditorBase::ToGenericNSResult(rv);
     }
   }
   nsresult rv = SetInlinePropertyInternal(aProperty, aAttribute, aValue);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditorBase::ToGenericNSResult(rv);
-  }
-  return NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyInternal() failed");
+  return EditorBase::ToGenericNSResult(rv);
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetInlineProperty(const nsAString& aProperty,
                               const nsAString& aAttribute,
                               const nsAString& aValue) {
   RefPtr<nsAtom> property = NS_Atomize(aProperty);
   if (NS_WARN_IF(!property)) {
@@ -130,148 +128,155 @@ HTMLEditor::SetInlineProperty(const nsAS
     case EditAction::eSetColorProperty:
     case EditAction::eSetBackgroundColorPropertyInline:
       editActionData.SetColorData(aValue);
       break;
     default:
       break;
   }
   nsresult rv = SetInlinePropertyInternal(*property, attribute, aValue);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditorBase::ToGenericNSResult(rv);
-  }
-  return NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyInternal() failed");
+  return EditorBase::ToGenericNSResult(rv);
 }
 
-nsresult HTMLEditor::SetInlinePropertyInternal(nsAtom& aProperty,
-                                               nsAtom* aAttribute,
-                                               const nsAString& aValue) {
+nsresult HTMLEditor::SetInlinePropertyInternal(
+    nsAtom& aProperty, nsAtom* aAttribute, const nsAString& aAttributeValue) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (NS_WARN_IF(!mRules)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  RefPtr<TextEditRules> rules(mRules);
   CommitComposition();
 
   if (SelectionRefPtr()->IsCollapsed()) {
     // Manipulating text attributes on a collapsed selection only sets state
     // for the next text insertion
-    mTypeInState->SetProp(&aProperty, aAttribute, aValue);
+    mTypeInState->SetProp(&aProperty, aAttribute, aAttributeValue);
     return NS_OK;
   }
 
+  // XXX Shouldn't we return before calling `CommitComposition()`?
+  if (IsPlaintextEditor()) {
+    return NS_OK;
+  }
+
+  EditActionResult result = CanHandleHTMLEditSubAction();
+  if (NS_WARN_IF(result.Failed()) || result.Canceled()) {
+    return result.Rv();
+  }
+
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoEditSubActionNotifier startToHandleEditSubAction(
       *this, EditSubAction::eInsertElement, nsIEditor::eNext);
-  AutoSelectionRestorer restoreSelectionLater(*this);
-  AutoTransactionsConserveSelection dontChangeMySelection(*this);
+
+  {
+    AutoSelectionRestorer restoreSelectionLater(*this);
+    AutoTransactionsConserveSelection dontChangeMySelection(*this);
 
-  bool cancel, handled;
-  EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
-  // Protect the edit rules object from dying
-  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  if (!cancel && !handled) {
     // Loop through the ranges in the selection
+    // XXX This is different from `SetCSSBackgroundColorWithTransaction()`.
+    //     It refers `Selection::GetRangeAt()` in each time.  The result may
+    //     be different if mutation event listener changes the `Selection`.
     AutoRangeArray arrayOfRanges(SelectionRefPtr());
     for (auto& range : arrayOfRanges.mRanges) {
       // Adjust range to include any ancestors whose children are entirely
       // selected
-      rv = PromoteInlineRange(*range);
+      nsresult rv = PromoteInlineRange(*range);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
-      // Check for easy case: both range endpoints in same text node
-      nsCOMPtr<nsINode> startNode = range->GetStartContainer();
-      nsCOMPtr<nsINode> endNode = range->GetEndContainer();
-      if (startNode && startNode == endNode && startNode->GetAsText()) {
-        rv = SetInlinePropertyOnTextNode(
-            MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
-            range->EndOffset(), aProperty, aAttribute, aValue);
+      // XXX Shouldn't we skip the range if it's been collapsed by mutation
+      //     event listener?
+
+      EditorDOMPoint startOfRange(range->StartRef());
+      EditorDOMPoint endOfRange(range->EndRef());
+      if (NS_WARN_IF(!startOfRange.IsSet()) ||
+          NS_WARN_IF(!endOfRange.IsSet())) {
+        continue;
+      }
+
+      // If range is in a text node, apply new style simply.
+      if (startOfRange.GetContainer() == endOfRange.GetContainer() &&
+          startOfRange.IsInTextNode()) {
+        nsresult rv = SetInlinePropertyOnTextNode(
+            MOZ_KnownLive(*startOfRange.GetContainerAsText()),
+            startOfRange.Offset(), endOfRange.Offset(), aProperty, aAttribute,
+            aAttributeValue);
+        if (NS_WARN_IF(Destroyed())) {
+          return NS_ERROR_EDITOR_DESTROYED;
+        }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
 
-      // Not the easy case.  Range not contained in single text node.  There
-      // are up to three phases here.  There are all the nodes reported by the
-      // subtree iterator to be processed.  And there are potentially a
-      // starting textnode and an ending textnode which are only partially
-      // contained by the range.
-
-      // Let's handle the nodes reported by the iterator.  These nodes are
-      // entirely contained in the selection range.  We build up a list of them
-      // (since doing operations on the document during iteration would perturb
-      // the iterator).
-
-      nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
-
-      // Iterate range and build up array
+      // Collect editable nodes which are entirely contained in the range.
+      AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContents;
       ContentSubtreeIterator subtreeIter;
-      rv = subtreeIter.Init(range);
-      // Init returns an error if there are no nodes in range.  This can easily
-      // happen with the subtree iterator if the selection doesn't contain any
-      // *whole* nodes.
-      if (NS_SUCCEEDED(rv)) {
+      // If there is no node which is entirely in the range,
+      // `ContentSubtreeIterator::Init()` fails, but this is possible case,
+      // don't warn it.
+      if (NS_SUCCEEDED(subtreeIter.Init(range))) {
         for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
-          OwningNonNull<nsINode> node = *subtreeIter.GetCurrentNode();
-
+          nsINode* node = subtreeIter.GetCurrentNode();
+          if (NS_WARN_IF(!node)) {
+            return NS_ERROR_FAILURE;
+          }
           if (node->IsContent() && IsEditable(node)) {
-            arrayOfNodes.AppendElement(*node->AsContent());
+            arrayOfContents.AppendElement(*node->AsContent());
           }
         }
       }
-      // First check the start parent of the range to see if it needs to be
-      // separately handled (it does if it's a text node, due to how the
-      // subtree iterator works - it will not have reported it).
-      if (startNode && startNode->GetAsText() && IsEditable(startNode)) {
-        rv = SetInlinePropertyOnTextNode(
-            MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
-            startNode->Length(), aProperty, aAttribute, aValue);
+
+      // If start node is a text node, apply new style to a part of it.
+      if (startOfRange.IsInTextNode() &&
+          IsEditable(startOfRange.GetContainer())) {
+        nsresult rv = SetInlinePropertyOnTextNode(
+            MOZ_KnownLive(*startOfRange.GetContainerAsText()),
+            startOfRange.Offset(), startOfRange.GetContainer()->Length(),
+            aProperty, aAttribute, aAttributeValue);
+        if (NS_WARN_IF(Destroyed())) {
+          return NS_ERROR_EDITOR_DESTROYED;
+        }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
 
-      // Then loop through the list, set the property on each node
-      for (auto& node : arrayOfNodes) {
-        rv = SetInlinePropertyOnNode(*node, aProperty, aAttribute, aValue);
+      // Then, apply new style to all nodes in the range entirely.
+      for (auto& content : arrayOfContents) {
+        nsresult rv = SetInlinePropertyOnNode(*content, aProperty, aAttribute,
+                                              aAttributeValue);
+        if (NS_WARN_IF(Destroyed())) {
+          return NS_ERROR_EDITOR_DESTROYED;
+        }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
 
-      // Last check the end parent of the range to see if it needs to be
-      // separately handled (it does if it's a text node, due to how the
-      // subtree iterator works - it will not have reported it).
-      if (endNode && endNode->GetAsText() && IsEditable(endNode)) {
-        rv = SetInlinePropertyOnTextNode(MOZ_KnownLive(*endNode->GetAsText()),
-                                         0, range->EndOffset(), aProperty,
-                                         aAttribute, aValue);
+      // Finally, if end node is a text node, apply new style to a part ot it.
+      if (endOfRange.IsInTextNode() && IsEditable(endOfRange.GetContainer())) {
+        nsresult rv = SetInlinePropertyOnTextNode(
+            MOZ_KnownLive(*endOfRange.GetContainerAsText()), 0,
+            endOfRange.Offset(), aProperty, aAttribute, aAttributeValue);
+        if (NS_WARN_IF(Destroyed())) {
+          return NS_ERROR_EDITOR_DESTROYED;
+        }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
   }
-  if (cancel) {
-    return NS_OK;
-  }
-
-  rv = rules->DidDoAction(subActionInfo, rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+  // Restoring `Selection` may have destroyed us.
+  return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
 }
 
 // Helper function for SetInlinePropertyOn*: is aNode a simple old <b>, <font>,
 // <span style="">, etc. that we can reuse instead of creating a new one?
 bool HTMLEditor::IsSimpleModifiableNode(nsIContent* aContent, nsAtom* aProperty,
                                         nsAtom* aAttribute,
                                         const nsAString* aValue) {
   // aContent can be null, in which case we'll return false in a few lines
@@ -1254,20 +1259,19 @@ nsresult HTMLEditor::RemoveAllInlineProp
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoEditSubActionNotifier startToHandleEditSubAction(
       *this, EditSubAction::eRemoveAllTextProperties, nsIEditor::eNext);
 
   nsresult rv = RemoveInlinePropertyInternal(nullptr, nullptr);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditorBase::ToGenericNSResult(rv);
-  }
-  return NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "RemoveInlinePropertyInternal() failed");
+  return EditorBase::ToGenericNSResult(rv);
 }
 
 nsresult HTMLEditor::RemoveInlinePropertyAsAction(nsAtom& aProperty,
                                                   nsAtom* aAttribute,
                                                   nsIPrincipal* aPrincipal) {
   AutoEditActionDataSetter editActionData(
       *this,
       HTMLEditUtils::GetEditActionForFormatText(aProperty, aAttribute, false),
@@ -1283,20 +1287,19 @@ nsresult HTMLEditor::RemoveInlinePropert
     case EditAction::eRemoveColorProperty:
     case EditAction::eRemoveBackgroundColorPropertyInline:
       editActionData.SetColorData(EmptyString());
       break;
     default:
       break;
   }
   nsresult rv = RemoveInlinePropertyInternal(&aProperty, aAttribute);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditorBase::ToGenericNSResult(rv);
-  }
-  return NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "RemoveInlinePropertyInternal() failed");
+  return EditorBase::ToGenericNSResult(rv);
 }
 
 NS_IMETHODIMP
 HTMLEditor::RemoveInlineProperty(const nsAString& aProperty,
                                  const nsAString& aAttribute) {
   RefPtr<nsAtom> property = NS_Atomize(aProperty);
   RefPtr<nsAtom> attribute = AtomizeAttribute(aAttribute);
 
@@ -1314,20 +1317,19 @@ HTMLEditor::RemoveInlineProperty(const n
     case EditAction::eRemoveColorProperty:
     case EditAction::eRemoveBackgroundColorPropertyInline:
       editActionData.SetColorData(EmptyString());
       break;
     default:
       break;
   }
   nsresult rv = RemoveInlinePropertyInternal(property, attribute);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditorBase::ToGenericNSResult(rv);
-  }
-  return NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "RemoveInlinePropertyInternal() failed");
+  return EditorBase::ToGenericNSResult(rv);
 }
 
 nsresult HTMLEditor::RemoveInlinePropertyInternal(nsAtom* aProperty,
                                                   nsAtom* aAttribute) {
   MOZ_ASSERT(IsEditActionDataAvailable());
   MOZ_ASSERT(aAttribute != nsGkAtoms::_empty);
 
   if (NS_WARN_IF(!mRules)) {
@@ -1348,138 +1350,160 @@ nsresult HTMLEditor::RemoveInlinePropert
     if (aProperty) {
       mTypeInState->ClearProp(aProperty, aAttribute);
     } else {
       mTypeInState->ClearAllProps();
     }
     return NS_OK;
   }
 
+  // XXX Shouldn't we quit before calling `CommitComposition()`?
+  if (IsPlaintextEditor()) {
+    return NS_OK;
+  }
+
+  EditActionResult result = CanHandleHTMLEditSubAction();
+  if (NS_WARN_IF(result.Failed()) || result.Canceled()) {
+    return result.Rv();
+  }
+
   AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoEditSubActionNotifier startToHandleEditSubAction(
       *this, EditSubAction::eRemoveTextProperty, nsIEditor::eNext);
-  AutoSelectionRestorer restoreSelectionLater(*this);
-  AutoTransactionsConserveSelection dontChangeMySelection(*this);
 
-  bool cancel, handled;
-  EditSubActionInfo subActionInfo(EditSubAction::eRemoveTextProperty);
-  // Protect the edit rules object from dying
-  RefPtr<TextEditRules> rules(mRules);
-  nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  if (!cancel && !handled) {
+  {
+    AutoSelectionRestorer restoreSelectionLater(*this);
+    AutoTransactionsConserveSelection dontChangeMySelection(*this);
+
     // Loop through the ranges in the selection
     // Since ranges might be modified by SplitStyleAboveRange, we need hold
     // current ranges
     AutoRangeArray arrayOfRanges(SelectionRefPtr());
     for (auto& range : arrayOfRanges.mRanges) {
       if (aProperty == nsGkAtoms::name) {
         // Promote range if it starts or end in a named anchor and we want to
         // remove named anchors
-        rv = PromoteRangeIfStartsOrEndsInNamedAnchor(*range);
+        nsresult rv = PromoteRangeIfStartsOrEndsInNamedAnchor(*range);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       } else {
         // Adjust range to include any ancestors whose children are entirely
         // selected
-        rv = PromoteInlineRange(*range);
+        nsresult rv = PromoteInlineRange(*range);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
 
       // Remove this style from ancestors of our range endpoints, splitting
       // them as appropriate
-      rv = SplitStyleAboveRange(range, aProperty, aAttribute);
+      // FYI: `range` may be modified to a range starting from first right
+      //      node child at splitting at range start to first right node
+      //      child at splitting at range end.
+      nsresult rv = SplitStyleAboveRange(range, aProperty, aAttribute);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
-      // Check for easy case: both range endpoints in same text node
-      nsCOMPtr<nsINode> startNode = range->GetStartContainer();
-      nsCOMPtr<nsINode> endNode = range->GetEndContainer();
-      if (startNode && startNode == endNode && startNode->GetAsText()) {
-        // We're done with this range!
-        if (IsCSSEnabled() && CSSEditUtils::IsCSSEditableProperty(
-                                  startNode, aProperty, aAttribute)) {
-          // The HTML style defined by aProperty/aAttribute has a CSS
-          // equivalence in this implementation for startNode
-          if (CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
-                  startNode, aProperty, aAttribute, EmptyString(),
-                  CSSEditUtils::eComputed)) {
-            // startNode's computed style indicates the CSS equivalence to the
-            // HTML style to remove is applied; but we found no element in the
-            // ancestors of startNode carrying specified styles; assume it
-            // comes from a rule and try to insert a span "inverting" the style
-            if (CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
-              NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
-              SetInlinePropertyOnTextNode(
-                  MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
-                  range->EndOffset(), *aProperty, aAttribute, value);
-            }
-          }
+      EditorDOMPoint startOfRange(range->StartRef());
+      EditorDOMPoint endOfRange(range->EndRef());
+      if (NS_WARN_IF(!startOfRange.IsSet()) ||
+          NS_WARN_IF(!endOfRange.IsSet())) {
+        continue;
+      }
+
+      if (startOfRange.GetContainer() == endOfRange.GetContainer() &&
+          startOfRange.IsInTextNode()) {
+        // TODO: If parent block has the removing style, we should create
+        //       `<span>` element to remove the style even in HTML mode
+        //       since Chrome does it.  See bug 1566795.
+        if (!IsCSSEnabled()) {
+          continue;
+        }
+        if (!CSSEditUtils::IsCSSEditableProperty(startOfRange.GetContainer(),
+                                                 aProperty, aAttribute)) {
+          continue;
         }
-      } else {
-        // Not the easy case.  Range not contained in single text node.
-
-        nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
+        // The HTML style defined by aProperty/aAttribute has a CSS
+        // equivalence in this implementation for startOfRange.
+        if (!CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
+                startOfRange.GetContainer(), aProperty, aAttribute,
+                EmptyString(), CSSEditUtils::eComputed)) {
+          continue;
+        }
+        // startOfRange's computed style indicates the CSS equivalence to the
+        // HTML style to remove is applied; but we found no element in the
+        // ancestors of startOfRange carrying specified styles; assume it
+        // comes from a rule and try to insert a span "inverting" the style
+        if (!CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
+          continue;
+        }
+        NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
+        SetInlinePropertyOnTextNode(
+            MOZ_KnownLive(*startOfRange.GetContainerAsText()),
+            startOfRange.Offset(), endOfRange.Offset(), *aProperty, aAttribute,
+            value);
+        if (NS_WARN_IF(Destroyed())) {
+          return NS_ERROR_EDITOR_DESTROYED;
+        }
+        continue;
+      }
 
-        // Iterate range and build up array
-        ContentSubtreeIterator subtreeIter;
-        DebugOnly<nsresult> rvIgnored = subtreeIter.Init(range);
-        NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
-                             "Failed to initialize subtree iterator");
+      // Collect editable nodes which are entirely contained in the range.
+      AutoTArray<OwningNonNull<nsIContent>, 64> arrayOfContents;
+      ContentSubtreeIterator subtreeIter;
+      if (NS_SUCCEEDED(subtreeIter.Init(range))) {
         for (; !subtreeIter.IsDone(); subtreeIter.Next()) {
           nsCOMPtr<nsINode> node = subtreeIter.GetCurrentNode();
           if (NS_WARN_IF(!node)) {
             return NS_ERROR_FAILURE;
           }
-          if (IsEditable(node) && node->IsContent()) {
-            arrayOfNodes.AppendElement(*node->AsContent());
+          if (node->IsContent() && IsEditable(node)) {
+            arrayOfContents.AppendElement(*node->AsContent());
           }
         }
+      }
 
-        // Loop through the list, remove the property on each node
-        for (auto& node : arrayOfNodes) {
-          rv = RemoveStyleInside(node, aProperty, aAttribute);
-          if (NS_WARN_IF(NS_FAILED(rv))) {
-            return rv;
-          }
-          if (IsCSSEnabled() &&
-              CSSEditUtils::IsCSSEditableProperty(node, aProperty,
-                                                  aAttribute) &&
-              CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
-                  node, aProperty, aAttribute, EmptyString(),
-                  CSSEditUtils::eComputed) &&
-              // startNode's computed style indicates the CSS equivalence to
-              // the HTML style to remove is applied; but we found no element
-              // in the ancestors of startNode carrying specified styles;
-              // assume it comes from a rule and let's try to insert a span
-              // "inverting" the style
-              CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
-            NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
-            SetInlinePropertyOnNode(node, *aProperty, aAttribute, value);
-          }
+      for (auto& content : arrayOfContents) {
+        nsresult rv = RemoveStyleInside(content, aProperty, aAttribute);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        // TODO: If parent block has the removing style, we should create
+        //       `<span>` element to remove the style even in HTML mode
+        //       since Chrome does it.  See bug 1566795.
+        if (!IsCSSEnabled()) {
+          continue;
+        }
+        if (!CSSEditUtils::IsCSSEditableProperty(content, aProperty,
+                                                 aAttribute)) {
+          continue;
         }
+        if (!CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
+                content, aProperty, aAttribute, EmptyString(),
+                CSSEditUtils::eComputed)) {
+          continue;
+        }
+        // startOfRange's computed style indicates the CSS equivalence to
+        // the HTML style to remove is applied; but we found no element
+        // in the ancestors of startOfRange carrying specified styles;
+        // assume it comes from a rule and let's try to insert a span
+        // "inverting" the style
+        if (!CSSEditUtils::IsCSSInvertible(*aProperty, aAttribute)) {
+          continue;
+        }
+        NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
+        SetInlinePropertyOnNode(content, *aProperty, aAttribute, value);
       }
     }
   }
 
-  if (cancel) {
-    return NS_OK;
-  }
-
-  rv = rules->DidDoAction(subActionInfo, rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+  // Restoring `Selection` may cause destroying us.
+  return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::IncreaseFontSize() {
   nsresult rv = IncreaseFontSizeAsAction();
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to increase font size");
   return rv;
 }
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -202,20 +202,16 @@ nsresult TextEditRules::WillDoAction(Edi
 
   // my kingdom for dynamic cast
   switch (aInfo.mEditSubAction) {
     case EditSubAction::eSetText:
       TextEditorRef().UndefineCaretBidiLevel();
       return WillSetText(aCancel, aHandled, aInfo.inString, aInfo.maxLength);
     case EditSubAction::eDeleteSelectedContent:
       return WillDeleteSelection(aInfo.collapsedAction, aCancel, aHandled);
-    case EditSubAction::eSetTextProperty:
-      return WillSetTextProperty(aCancel, aHandled);
-    case EditSubAction::eRemoveTextProperty:
-      return WillRemoveTextProperty(aCancel, aHandled);
     case EditSubAction::eComputeTextToOutput:
       return WillOutputText(aInfo.outputFormat, aInfo.outString, aInfo.flags,
                             aCancel, aHandled);
     case EditSubAction::eInsertQuotedText: {
       CANCEL_OPERATION_IF_READONLY_OR_DISABLED
 
       // XXX Do we need to support paste-as-quotation in password editor (and
       //     also in single line editor)?
@@ -853,42 +849,16 @@ nsresult TextEditRules::WillSetText(bool
     NS_WARNING_ASSERTION(!ignoredError.Failed(),
                          "Selection::SetInterlinePoisition() failed");
   }
 
   *aHandled = true;
   return NS_OK;
 }
 
-nsresult TextEditRules::WillSetTextProperty(bool* aCancel, bool* aHandled) {
-  if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  // XXX: should probably return a success value other than NS_OK that means
-  // "not allowed"
-  if (IsPlaintextEditor()) {
-    *aCancel = true;
-  }
-  return NS_OK;
-}
-
-nsresult TextEditRules::WillRemoveTextProperty(bool* aCancel, bool* aHandled) {
-  if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  // XXX: should probably return a success value other than NS_OK that means
-  // "not allowed"
-  if (IsPlaintextEditor()) {
-    *aCancel = true;
-  }
-  return NS_OK;
-}
-
 nsresult TextEditRules::WillDeleteSelection(
     nsIEditor::EDirection aCollapsedAction, bool* aCancel, bool* aHandled) {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
     return NS_ERROR_INVALID_ARG;
   }
   CANCEL_OPERATION_IF_READONLY_OR_DISABLED
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -146,20 +146,16 @@ class TextEditRules {
    * @param aCaollapsedAction   Direction to extend the selection.
    * @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 DeleteSelectionWithTransaction(
       nsIEditor::EDirection aCollapsedAction, bool* aCancel, bool* aHandled);
 
-  nsresult WillSetTextProperty(bool* aCancel, bool* aHandled);
-
-  nsresult WillRemoveTextProperty(bool* aCancel, bool* aHandled);
-
   /**
    * Called prior to nsIEditor::OutputToString.
    *
    * @param aInFormat  The format requested for the output, a MIME type.
    * @param aOutText   The string to use for output, if aCancel is set to true.
    * @param aOutCancel If set to true, the caller should cancel the operation
    *                   and use aOutText as the result.
    */