Bug 181137 - part 5: Make all users of PostContentIterator treat it directly rather than via nsIContentIterator r=smaug
☠☠ backed out by 5562d6967f3d ☠ ☠
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 10 Jan 2019 08:46:32 +0000
changeset 510319 83bec02c21d965b6cd5eb0fc682a18ef6ac74b68
parent 510318 b7ab59bf545e46eb2e677eaf1f68adc100cbebae
child 510320 5385d5fd9b8bfaaec01f9757305f3a5cb0eb9e4e
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs181137
milestone66.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 181137 - part 5: Make all users of PostContentIterator treat it directly rather than via nsIContentIterator r=smaug Now, all users of PostContentIterator can access it directly. This patch makes them use the concrete class directly. Differential Revision: https://phabricator.services.mozilla.com/D15923
dom/base/ContentIterator.cpp
dom/base/ScriptableContentIterator.cpp
dom/base/ScriptableContentIterator.h
dom/base/Selection.cpp
dom/base/Selection.h
dom/base/nsIContentIterator.h
dom/base/nsRange.cpp
dom/events/ContentEventHandler.cpp
editor/libeditor/EditorUtils.cpp
editor/libeditor/EditorUtils.h
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLStyleEditor.cpp
editor/libeditor/TextEditor.cpp
editor/spellchecker/nsFilteredContentIterator.cpp
editor/spellchecker/nsFilteredContentIterator.h
--- a/dom/base/ContentIterator.cpp
+++ b/dom/base/ContentIterator.cpp
@@ -9,21 +9,16 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/RangeBoundary.h"
 
 #include "nsContentUtils.h"
 #include "nsElementTable.h"
 #include "nsIContent.h"
 #include "nsRange.h"
 
-already_AddRefed<nsIContentIterator> NS_NewContentIterator() {
-  nsCOMPtr<nsIContentIterator> iter = new mozilla::PostContentIterator();
-  return iter.forget();
-}
-
 namespace mozilla {
 
 ///////////////////////////////////////////////////////////////////////////
 // NodeIsInTraversalRange: returns true if content is visited during
 // the traversal of the range in the specified mode.
 //
 static bool NodeIsInTraversalRange(nsINode* aNode, bool aIsPreMode,
                                    const RawRangeBoundary& aStart,
--- a/dom/base/ScriptableContentIterator.cpp
+++ b/dom/base/ScriptableContentIterator.cpp
@@ -27,17 +27,17 @@ ScriptableContentIterator::ScriptableCon
 
 void ScriptableContentIterator::EnsureContentIterator() {
   if (mContentIterator) {
     return;
   }
   switch (mIteratorType) {
     case POST_ORDER_ITERATOR:
     default:
-      mContentIterator = NS_NewContentIterator();
+      mContentIterator = new PostContentIterator();
       break;
     case PRE_ORDER_ITERATOR:
       mContentIterator = new PreContentIterator();
       break;
     case SUBTREE_ITERATOR:
       mContentIterator = new ContentSubtreeIterator();
       break;
   }
--- a/dom/base/ScriptableContentIterator.h
+++ b/dom/base/ScriptableContentIterator.h
@@ -3,32 +3,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_scriptablecontentiterator_h
 #define mozilla_scriptablecontentiterator_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/ContentIterator.h"
 #include "nsCOMPtr.h"
-#include "nsIContentIterator.h"
 #include "nsIScriptableContentIterator.h"
 
 namespace mozilla {
 
 class ScriptableContentIterator final : public nsIScriptableContentIterator {
  public:
   ScriptableContentIterator();
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(ScriptableContentIterator)
   NS_DECL_NSISCRIPTABLECONTENTITERATOR
 
  protected:
   virtual ~ScriptableContentIterator() = default;
   void EnsureContentIterator();
 
   IteratorType mIteratorType;
-  nsCOMPtr<nsIContentIterator> mContentIterator;
+  RefPtr<ContentIteratorBase> mContentIterator;
 };
 
 }  // namespace mozilla
 
 #endif  // #ifndef mozilla_scriptablecontentiterator_h
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -1476,32 +1476,31 @@ void Selection::SelectFramesForContent(n
     textFrame->SetSelectedRange(0, aContent->GetText()->GetLength(), aSelected,
                                 mSelectionType);
   } else {
     frame->InvalidateFrameSubtree();  // frame continuations?
   }
 }
 
 // select all content children of aContent
-nsresult Selection::SelectAllFramesForContent(nsIContentIterator* aInnerIter,
-                                              nsIContent* aContent,
-                                              bool aSelected) {
+nsresult Selection::SelectAllFramesForContent(
+    PostContentIterator* aPostOrderIter, nsIContent* aContent, bool aSelected) {
   // If aContent doesn't have children, we should avoid to use the content
   // iterator for performance reason.
   if (!aContent->HasChildren()) {
     SelectFramesForContent(aContent, aSelected);
     return NS_OK;
   }
 
-  if (NS_WARN_IF(NS_FAILED(aInnerIter->Init(aContent)))) {
+  if (NS_WARN_IF(NS_FAILED(aPostOrderIter->Init(aContent)))) {
     return NS_ERROR_FAILURE;
   }
 
-  for (; !aInnerIter->IsDone(); aInnerIter->Next()) {
-    nsINode* node = aInnerIter->GetCurrentNode();
+  for (; !aPostOrderIter->IsDone(); aPostOrderIter->Next()) {
+    nsINode* node = aPostOrderIter->GetCurrentNode();
     MOZ_ASSERT(node);
     nsIContent* innercontent = node->IsContent() ? node->AsContent() : nullptr;
     SelectFramesForContent(innercontent, aSelected);
   }
 
   return NS_OK;
 }
 
@@ -1577,22 +1576,22 @@ nsresult Selection::SelectFrames(nsPresC
   }
 
   RefPtr<ContentSubtreeIterator> subtreeIter = new ContentSubtreeIterator();
   subtreeIter->Init(aRange);
   if (isFirstContentTextNode && !subtreeIter->IsDone() &&
       subtreeIter->GetCurrentNode() == startNode) {
     subtreeIter->Next();  // first content has already been handled.
   }
-  nsCOMPtr<nsIContentIterator> inneriter = NS_NewContentIterator();
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
   for (; !subtreeIter->IsDone(); subtreeIter->Next()) {
     nsINode* node = subtreeIter->GetCurrentNode();
     MOZ_ASSERT(node);
     nsIContent* content = node->IsContent() ? node->AsContent() : nullptr;
-    SelectAllFramesForContent(inneriter, content, aSelect);
+    SelectAllFramesForContent(postOrderIter, content, aSelect);
   }
 
   // We must now do the last one if it is not the same as the first
   if (endNode != startNode) {
     nsIContent* endContent =
         endNode->IsContent() ? endNode->AsContent() : nullptr;
     // XXX The range can end at a document node and such range can be
     //     added to Selection with JS.  Therefore, even in such cases,
--- a/dom/base/Selection.h
+++ b/dom/base/Selection.h
@@ -22,28 +22,28 @@
 #include "nsISelectionListener.h"
 #include "nsRange.h"
 #include "nsTArrayForwardDeclare.h"
 #include "nsThreadUtils.h"
 #include "nsWrapperCache.h"
 
 struct CachedOffsetForFrame;
 class nsAutoScrollTimer;
-class nsIContentIterator;
 class nsIFrame;
 class nsFrameSelection;
 class nsPIDOMWindowOuter;
 struct SelectionDetails;
 struct SelectionCustomColors;
 class nsCopySupport;
 class nsHTMLCopyEncoder;
 
 namespace mozilla {
 class ErrorResult;
 class HTMLEditor;
+class PostContentIterator;
 enum class TableSelection : uint32_t;
 struct AutoPrepareFocusRange;
 namespace dom {
 class DocGroup;
 }  // namespace dom
 }  // namespace mozilla
 
 struct RangeData {
@@ -587,17 +587,17 @@ class Selection final : public nsSupport
   /**
    * Set mAnchorFocusRange to mRanges[aIndex] if aIndex is a valid index.
    * Set mAnchorFocusRange to nullptr if aIndex is negative.
    * Otherwise, i.e., if aIndex is positive but out of bounds of mRanges, do
    * nothing.
    */
   void SetAnchorFocusRange(int32_t aIndex);
   void SelectFramesForContent(nsIContent* aContent, bool aSelected);
-  nsresult SelectAllFramesForContent(nsIContentIterator* aInnerIter,
+  nsresult SelectAllFramesForContent(PostContentIterator* aPostOrderIter,
                                      nsIContent* aContent, bool aSelected);
   nsresult SelectFrames(nsPresContext* aPresContext, nsRange* aRange,
                         bool aSelect);
 
   /**
    * Test whether the supplied range points to a single table element.
    * Result is one of the TableSelection constants. "None" means
    * a table element isn't selected.
--- a/dom/base/nsIContentIterator.h
+++ b/dom/base/nsIContentIterator.h
@@ -78,11 +78,9 @@ class nsIContentIterator : public nsISup
 
   /** PositionAt will position the iterator to the supplied node
    */
   virtual nsresult PositionAt(nsINode* aCurNode) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentIterator, NS_ICONTENTITERATOR_IID)
 
-already_AddRefed<nsIContentIterator> NS_NewContentIterator();
-
 #endif  // __nsIContentIterator_h___
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -2611,29 +2611,29 @@ void nsRange::ToString(nsAString& aRetur
     }
   }
 
   /* complex case: mStart.Container() != mEnd.Container(), or mStartParent not a
      text node revisit - there are potential optimizations here and also
      tradeoffs.
   */
 
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-  nsresult rv = iter->Init(this);
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
+  nsresult rv = postOrderIter->Init(this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aErr.Throw(rv);
     return;
   }
 
   nsString tempString;
 
   // loop through the content iterator, which returns nodes in the range in
   // close tag order, and grab the text from any text node
-  while (!iter->IsDone()) {
-    nsINode* n = iter->GetCurrentNode();
+  for (; !postOrderIter->IsDone(); postOrderIter->Next()) {
+    nsINode* n = postOrderIter->GetCurrentNode();
 
 #ifdef DEBUG_range
     // If debug, dump it:
     n->List(stdout);
 #endif /* DEBUG */
     Text* textNode = n->GetAsText();
     if (textNode)  // if it's a text node, get the text
     {
@@ -2646,18 +2646,16 @@ void nsRange::ToString(nsAString& aRetur
                  mEnd.Container()) {  // only include text before end offset
         textNode->SubstringData(0, mEnd.Offset(), tempString, IgnoreErrors());
         aReturn += tempString;
       } else {  // grab the whole kit-n-kaboodle
         textNode->GetData(tempString);
         aReturn += tempString;
       }
     }
-
-    iter->Next();
   }
 
 #ifdef DEBUG_range
   printf("End Range dump: -----------------------\n");
 #endif /* DEBUG */
 }
 
 void nsRange::Detach() {}
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -2105,18 +2105,18 @@ nsresult ContentEventHandler::OnQueryTex
   rv = SetRawRangeFromFlatTextOffset(
       &rawRange, aEvent->mInput.mOffset, aEvent->mInput.mLength, lineBreakType,
       true, &aEvent->mReply.mOffset, getter_AddRefs(lastTextContent));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = GenerateFlatTextContent(rawRange, aEvent->mReply.mString, lineBreakType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // used to iterate over all contents and their frames
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-  rv = iter->Init(rawRange.Start().AsRaw(), rawRange.End().AsRaw());
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
+  rv = postOrderIter->Init(rawRange.Start().AsRaw(), rawRange.End().AsRaw());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NS_ERROR_FAILURE;
   }
 
   // Get the first frame which causes some text after the offset.
   FrameAndNodeOffset firstFrame = GetFirstFrameInRangeForTextRect(rawRange);
 
   // If GetFirstFrameInRangeForTextRect() does not return valid frame, that
@@ -2293,18 +2293,18 @@ nsresult ContentEventHandler::OnQueryTex
     return NS_ERROR_FAILURE;
   }
 
   // iterate over all covered frames
   for (nsIFrame* frame = firstFrame; frame != lastFrame;) {
     frame = frame->GetNextContinuation();
     if (!frame) {
       do {
-        iter->Next();
-        nsINode* node = iter->GetCurrentNode();
+        postOrderIter->Next();
+        nsINode* node = postOrderIter->GetCurrentNode();
         if (!node) {
           break;
         }
         if (!node->IsContent()) {
           continue;
         }
         nsIFrame* primaryFrame = node->AsContent()->GetPrimaryFrame();
         // The node may be hidden by CSS.
@@ -2314,17 +2314,17 @@ nsresult ContentEventHandler::OnQueryTex
         // We should take only text frame's rect and br frame's rect.  We can
         // always use frame rect of text frame and GetLineBreakerRectBefore()
         // can return exactly correct rect only for <br> frame for now.  On the
         // other hand, GetLineBreakRectBefore() returns guessed caret rect for
         // the other frames.  We shouldn't include such odd rect to the result.
         if (primaryFrame->IsTextFrame() || primaryFrame->IsBrFrame()) {
           frame = primaryFrame;
         }
-      } while (!frame && !iter->IsDone());
+      } while (!frame && !postOrderIter->IsDone());
       if (!frame) {
         break;
       }
     }
     if (frame->IsTextFrame()) {
       frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size());
     } else {
       MOZ_ASSERT(frame->IsBrFrame());
--- a/editor/libeditor/EditorUtils.cpp
+++ b/editor/libeditor/EditorUtils.cpp
@@ -1,22 +1,22 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/EditorUtils.h"
 
+#include "mozilla/ContentIterator.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/OwningNonNull.h"
 #include "mozilla/dom/Selection.h"
 #include "nsComponentManagerUtils.h"
 #include "nsError.h"
 #include "nsIContent.h"
-#include "nsIContentIterator.h"
 #include "nsIDocShell.h"
 #include "mozilla/dom/Document.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINode.h"
 
 class nsISupports;
 class nsRange;
 
@@ -26,23 +26,23 @@ using namespace dom;
 
 /******************************************************************************
  * some helper classes for iterating the dom tree
  *****************************************************************************/
 
 DOMIterator::DOMIterator(
     nsINode& aNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-  mIter = NS_NewContentIterator();
+  mIter = new PostContentIterator();
   DebugOnly<nsresult> rv = mIter->Init(&aNode);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 nsresult DOMIterator::Init(nsRange& aRange) {
-  mIter = NS_NewContentIterator();
+  mIter = new PostContentIterator();
   return mIter->Init(&aRange);
 }
 
 DOMIterator::DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL) {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 }
 
 DOMIterator::~DOMIterator() {}
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -1,28 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_EditorUtils_h
 #define mozilla_EditorUtils_h
 
+#include "mozilla/ContentIterator.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/EditorBase.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/GuardObjects.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsIEditor.h"
 #include "nscore.h"
 
 class nsAtom;
-class nsIContentIterator;
 class nsISimpleEnumerator;
 class nsITransferable;
 class nsRange;
 
 namespace mozilla {
 template <class T>
 class OwningNonNull;
 
@@ -454,17 +454,17 @@ class MOZ_RAII DOMIterator {
 
   nsresult Init(nsRange& aRange);
 
   void AppendList(
       const BoolDomIterFunctor& functor,
       nsTArray<mozilla::OwningNonNull<nsINode>>& arrayOfNodes) const;
 
  protected:
-  nsCOMPtr<nsIContentIterator> mIter;
+  RefPtr<ContentIteratorBase> mIter;
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class MOZ_RAII DOMSubtreeIterator final : public DOMIterator {
  public:
   explicit DOMSubtreeIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
   virtual ~DOMSubtreeIterator();
 
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -7,16 +7,17 @@
 #include "HTMLEditRules.h"
 
 #include <stdlib.h>
 
 #include "HTMLEditUtils.h"
 #include "TextEditUtils.h"
 #include "WSRunObject.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/ContentIterator.h"
 #include "mozilla/CSSEditUtils.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/EditorUtils.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Move.h"
 #include "mozilla/Preferences.h"
@@ -34,17 +35,16 @@
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsAtom.h"
 #include "nsHTMLDocument.h"
 #include "nsIContent.h"
-#include "nsIContentIterator.h"
 #include "nsID.h"
 #include "nsIFrame.h"
 #include "nsIHTMLAbsPosEditor.h"
 #include "nsINode.h"
 #include "nsLiteralString.h"
 #include "nsRange.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
@@ -9433,29 +9433,29 @@ nsresult HTMLEditRules::RemoveEmptyNodes
   // the theory that if they weren't empty, we would have encountered a
   // non-empty child earlier and thus put this parent node on the skiplist.
   //
   // Unfortunately I can't use that strategy here, because the range may
   // include some children of a node while excluding others.  Thus I could find
   // all the _examined_ children empty, but still not have an empty parent.
 
   // need an iterator
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-
-  nsresult rv = iter->Init(mDocChangeRange);
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
+
+  nsresult rv = postOrderIter->Init(mDocChangeRange);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsTArray<OwningNonNull<nsINode>> arrayOfEmptyNodes, arrayOfEmptyCites,
       skipList;
 
   // Check for empty nodes
-  while (!iter->IsDone()) {
-    OwningNonNull<nsINode> node = *iter->GetCurrentNode();
+  for (; !postOrderIter->IsDone(); postOrderIter->Next()) {
+    OwningNonNull<nsINode> node = *postOrderIter->GetCurrentNode();
 
     nsCOMPtr<nsINode> parent = node->GetParentNode();
 
     size_t idx = skipList.IndexOf(node);
     if (idx != skipList.NoIndex) {
       // This node is on our skip list.  Skip processing for this node, and
       // replace its value in the skip list with the value of its parent
       if (parent) {
@@ -9510,18 +9510,16 @@ nsresult HTMLEditRules::RemoveEmptyNodes
         }
       }
 
       if (!isEmptyNode && parent) {
         // put parent on skip list
         skipList.AppendElement(*parent);
       }
     }
-
-    iter->Next();
   }
 
   // now delete the empty nodes
   for (OwningNonNull<nsINode>& delNode : arrayOfEmptyNodes) {
     if (HTMLEditorRef().IsModifiableNode(delNode)) {
       rv = HTMLEditorRef().DeleteNodeWithTransaction(*delNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
         return NS_ERROR_EDITOR_DESTROYED;
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -1119,44 +1119,44 @@ nsresult HTMLEditor::TabInTable(bool inI
   // find enclosing table
   RefPtr<Element> table = GetEnclosingTable(cellElement);
   if (NS_WARN_IF(!table)) {
     return NS_OK;
   }
 
   // advance to next cell
   // first create an iterator over the table
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-  nsresult rv = iter->Init(table);
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
+  nsresult rv = postOrderIter->Init(table);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
-  // position iter at block
-  rv = iter->PositionAt(cellElement);
+  // position postOrderIter at block
+  rv = postOrderIter->PositionAt(cellElement);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsINode> node;
   do {
     if (inIsShift) {
-      iter->Prev();
+      postOrderIter->Prev();
     } else {
-      iter->Next();
+      postOrderIter->Next();
     }
 
-    node = iter->GetCurrentNode();
+    node = postOrderIter->GetCurrentNode();
 
     if (node && HTMLEditUtils::IsTableCell(node) &&
         GetEnclosingTable(node) == table) {
       CollapseSelectionToDeepestNonTableFirstChild(node);
       *outHandled = true;
       return NS_OK;
     }
-  } while (!iter->IsDone());
+  } while (!postOrderIter->IsDone());
 
   if (!(*outHandled) && !inIsShift) {
     // If we haven't handled it yet, then we must have run off the end of the
     // table.  Insert a new row.
     // XXX We should investigate whether this behavior is supported by other
     //     browsers later.
     AutoEditActionDataSetter editActionData(*this,
                                             EditAction::eInsertTableRowElement);
@@ -2781,21 +2781,22 @@ already_AddRefed<Element> HTMLEditor::Ge
       }
     }
   }
 
   if (SelectionRefPtr()->IsCollapsed()) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-  iter->Init(firstRange);
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
+  postOrderIter->Init(firstRange);
 
   RefPtr<Element> lastElementInRange;
-  for (nsINode* lastNodeInRange = nullptr; !iter->IsDone(); iter->Next()) {
+  for (nsINode* lastNodeInRange = nullptr; !postOrderIter->IsDone();
+       postOrderIter->Next()) {
     if (lastElementInRange) {
       // When any node follows an element node, not only one element is
       // selected so that return nullptr.
       return nullptr;
     }
 
     // This loop ignored any non-element nodes before first element node.
     // Its purpose must be that this method allow to this case as selecting
@@ -2803,17 +2804,17 @@ already_AddRefed<Element> HTMLEditor::Ge
     // - <p>abc <b>d[ef</b>}</p>
     // because children of an element node is listed up before the element.
     // However, this case must not be expected by the initial developer:
     // - <p>a[bc <b>def</b>}</p>
     // When we meet non-parent and non-next-sibling node of previous node,
     // it means that the range across element boundary (open tag in HTML
     // source).  So, in this case, we should not say only the following
     // element is selected.
-    nsINode* currentNode = iter->GetCurrentNode();
+    nsINode* currentNode = postOrderIter->GetCurrentNode();
     MOZ_ASSERT(currentNode);
     if (lastNodeInRange && lastNodeInRange->GetParentNode() != currentNode &&
         lastNodeInRange->GetNextSibling() != currentNode) {
       return nullptr;
     }
 
     lastNodeInRange = currentNode;
 
@@ -3056,34 +3057,33 @@ HTMLEditor::GetLinkedObjects(nsIArray** 
   NS_ENSURE_TRUE(aNodeList, NS_ERROR_NULL_POINTER);
 
   nsresult rv;
   nsCOMPtr<nsIMutableArray> nodes = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
   RefPtr<Document> doc = GetDocument();
   NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
 
-  iter->Init(doc->GetRootElement());
+  postOrderIter->Init(doc->GetRootElement());
 
   // loop through the content iterator for each content node
-  while (!iter->IsDone()) {
-    nsCOMPtr<nsINode> node = iter->GetCurrentNode();
+  for (; !postOrderIter->IsDone(); postOrderIter->Next()) {
+    nsCOMPtr<nsINode> node = postOrderIter->GetCurrentNode();
     if (node) {
       // Let nsURIRefObject make the hard decisions:
       nsCOMPtr<nsIURIRefObject> refObject;
       rv = NS_NewHTMLURIRefObject(getter_AddRefs(refObject), node);
       if (NS_SUCCEEDED(rv)) {
         nodes->AppendElement(refObject);
       }
     }
-    iter->Next();
   }
 
   nodes.forget(aNodeList);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::AddOverrideStyleSheet(const nsAString& aURL) {
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -1036,28 +1036,30 @@ nsresult HTMLEditor::GetInlinePropertyBa
 
       isSet = IsTextPropertySetByContent(collapsedNode, &aProperty, aAttribute,
                                          aValue, outValue);
       *aFirst = *aAny = *aAll = isSet;
       return NS_OK;
     }
 
     // Non-collapsed selection
-    nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
+    RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
 
     nsAutoString firstValue, theValue;
 
     nsCOMPtr<nsINode> endNode = range->GetEndContainer();
     int32_t endOffset = range->EndOffset();
 
-    for (iter->Init(range); !iter->IsDone(); iter->Next()) {
-      if (!iter->GetCurrentNode()->IsContent()) {
+    for (postOrderIter->Init(range); !postOrderIter->IsDone();
+         postOrderIter->Next()) {
+      if (!postOrderIter->GetCurrentNode()->IsContent()) {
         continue;
       }
-      nsCOMPtr<nsIContent> content = iter->GetCurrentNode()->AsContent();
+      nsCOMPtr<nsIContent> content =
+          postOrderIter->GetCurrentNode()->AsContent();
 
       if (content->IsHTMLElement(nsGkAtoms::body)) {
         break;
       }
 
       // just ignore any non-editable nodes
       if (content->GetAsText() &&
           (!IsEditable(content) || IsEmptyTextNode(*content))) {
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -6,16 +6,17 @@
 #include "mozilla/TextEditor.h"
 
 #include "EditAggregateTransaction.h"
 #include "HTMLEditRules.h"
 #include "InternetCiter.h"
 #include "TextEditUtils.h"
 #include "gfxFontUtils.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/ContentIterator.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEditRules.h"
 #include "mozilla/TextComposition.h"
@@ -34,17 +35,16 @@
 #include "nsCopySupport.h"
 #include "nsDebug.h"
 #include "nsDependentSubstring.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIAbsorbingTransaction.h"
 #include "nsIClipboard.h"
 #include "nsIContent.h"
-#include "nsIContentIterator.h"
 #include "nsIDocumentEncoder.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
 #include "nsISelectionController.h"
 #include "nsISupportsPrimitives.h"
 #include "nsITransferable.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsNameSpaceManager.h"
@@ -1450,22 +1450,22 @@ TextEditor::GetTextLength(int32_t* aCoun
     return NS_OK;
   }
 
   Element* rootElement = GetRoot();
   if (NS_WARN_IF(!rootElement)) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
+  RefPtr<PostContentIterator> postOrderIter = new PostContentIterator();
 
   uint32_t totalLength = 0;
-  iter->Init(rootElement);
-  for (; !iter->IsDone(); iter->Next()) {
-    nsCOMPtr<nsINode> currentNode = iter->GetCurrentNode();
+  postOrderIter->Init(rootElement);
+  for (; !postOrderIter->IsDone(); postOrderIter->Next()) {
+    nsCOMPtr<nsINode> currentNode = postOrderIter->GetCurrentNode();
     if (IsTextNode(currentNode) && IsEditable(currentNode)) {
       totalLength += currentNode->Length();
     }
   }
 
   *aCount = totalLength;
   return NS_OK;
 }
--- a/editor/spellchecker/nsFilteredContentIterator.cpp
+++ b/editor/spellchecker/nsFilteredContentIterator.cpp
@@ -21,17 +21,17 @@
 #include "nsISupportsUtils.h"
 #include "nsRange.h"
 
 using namespace mozilla;
 
 //------------------------------------------------------------
 nsFilteredContentIterator::nsFilteredContentIterator(
     UniquePtr<nsComposeTxtSrvFilter> aFilter)
-    : mIterator(NS_NewContentIterator()),
+    : mPostIterator(new PostContentIterator()),
       mPreIterator(new PreContentIterator()),
       mFilter(std::move(aFilter)),
       mDidSkip(false),
       mIsOutOfRange(false),
       mDirection(eDirNotSet) {}
 
 //------------------------------------------------------------
 nsFilteredContentIterator::~nsFilteredContentIterator() {}
@@ -41,34 +41,34 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFilter
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFilteredContentIterator)
 
 NS_INTERFACE_MAP_BEGIN(nsFilteredContentIterator)
   NS_INTERFACE_MAP_ENTRY(nsIContentIterator)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentIterator)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsFilteredContentIterator)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION(nsFilteredContentIterator, mCurrentIterator, mIterator,
-                         mPreIterator, mRange)
+NS_IMPL_CYCLE_COLLECTION(nsFilteredContentIterator, mCurrentIterator,
+                         mPostIterator, mPreIterator, mRange)
 
 //------------------------------------------------------------
 nsresult nsFilteredContentIterator::Init(nsINode* aRoot) {
   NS_ENSURE_ARG_POINTER(aRoot);
   NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
-  NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(mPostIterator, NS_ERROR_FAILURE);
   mIsOutOfRange = false;
   mDirection = eForward;
   mCurrentIterator = mPreIterator;
 
   mRange = new nsRange(aRoot);
   mRange->SelectNode(*aRoot, IgnoreErrors());
 
   nsresult rv = mPreIterator->Init(mRange);
   NS_ENSURE_SUCCESS(rv, rv);
-  return mIterator->Init(mRange);
+  return mPostIterator->Init(mRange);
 }
 
 //------------------------------------------------------------
 nsresult nsFilteredContentIterator::Init(nsRange* aRange) {
   if (NS_WARN_IF(!aRange)) {
     return NS_ERROR_INVALID_ARG;
   }
 
@@ -106,40 +106,40 @@ nsresult nsFilteredContentIterator::Init
 
   return InitWithRange();
 }
 
 nsresult nsFilteredContentIterator::InitWithRange() {
   MOZ_ASSERT(mRange);
   MOZ_ASSERT(mRange->IsPositioned());
 
-  if (NS_WARN_IF(!mPreIterator) || NS_WARN_IF(!mIterator)) {
+  if (NS_WARN_IF(!mPreIterator) || NS_WARN_IF(!mPostIterator)) {
     return NS_ERROR_FAILURE;
   }
 
   mIsOutOfRange = false;
   mDirection = eForward;
   mCurrentIterator = mPreIterator;
 
   nsresult rv = mPreIterator->Init(mRange);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
-  return mIterator->Init(mRange);
+  return mPostIterator->Init(mRange);
 }
 
 //------------------------------------------------------------
 nsresult nsFilteredContentIterator::SwitchDirections(bool aChangeToForward) {
   nsINode* node = mCurrentIterator->GetCurrentNode();
 
   if (aChangeToForward) {
     mCurrentIterator = mPreIterator;
     mDirection = eForward;
   } else {
-    mCurrentIterator = mIterator;
+    mCurrentIterator = mPostIterator;
     mDirection = eBackward;
   }
 
   if (node) {
     nsresult rv = mCurrentIterator->PositionAt(node);
     if (NS_FAILED(rv)) {
       mIsOutOfRange = true;
       return rv;
@@ -182,17 +182,17 @@ void nsFilteredContentIterator::Last() {
     NS_ERROR("Missing iterator!");
 
     return;
   }
 
   // If we are switching directions then
   // we need to switch how we process the nodes
   if (mDirection != eBackward) {
-    mCurrentIterator = mIterator;
+    mCurrentIterator = mPostIterator;
     mDirection = eBackward;
     mIsOutOfRange = false;
   }
 
   mCurrentIterator->Last();
 
   if (mCurrentIterator->IsDone()) {
     return;
--- a/editor/spellchecker/nsFilteredContentIterator.h
+++ b/editor/spellchecker/nsFilteredContentIterator.h
@@ -58,18 +58,18 @@ class nsFilteredContentIterator final : 
   nsresult InitWithRange();
 
   // enum to give us the direction
   typedef enum { eDirNotSet, eForward, eBackward } eDirectionType;
   nsresult AdvanceNode(nsINode* aNode, nsINode*& aNewNode, eDirectionType aDir);
   void CheckAdvNode(nsINode* aNode, bool& aDidSkip, eDirectionType aDir);
   nsresult SwitchDirections(bool aChangeToForward);
 
-  nsCOMPtr<nsIContentIterator> mCurrentIterator;
-  nsCOMPtr<nsIContentIterator> mIterator;
+  RefPtr<mozilla::ContentIteratorBase> mCurrentIterator;
+  RefPtr<mozilla::PostContentIterator> mPostIterator;
   RefPtr<mozilla::PreContentIterator> mPreIterator;
 
   RefPtr<nsAtom> mBlockQuoteAtom;
   RefPtr<nsAtom> mScriptAtom;
   RefPtr<nsAtom> mTextAreaAtom;
   RefPtr<nsAtom> mSelectAreaAtom;
   RefPtr<nsAtom> mMapAtom;