# HG changeset patch
# User Masayuki Nakano <masayuki@d-toybox.com>
# Date 1468171433 -32400
#      Mon Jul 11 02:23:53 2016 +0900
# Branch THUNDERBIRD3880_2016050308_RELBRANCH
# Node ID 19248f256dd33e2d42edacf4485141c9b3e27ecf
# Parent  80b59738952bd12ded072634c5aa6ad62dff8c48
Bug 1258576 - Part 1: nsContentIterator should give up to find next/previous node if it reached the root node unexpectedly. r=smaug, a=rkent

nsContentIterator isn't designed as working fine with a tree whose some nodes are being removed.  In such case, NextNode() and PrevNode() meets orphan node (i.e., a node whose parent is nullptr).  Then, nsContentIterator should mark it as "done".

However, it should keep crashing if it's debug build for detecting bugs explicitly.

diff --git a/dom/base/nsContentIterator.cpp b/dom/base/nsContentIterator.cpp
--- a/dom/base/nsContentIterator.cpp
+++ b/dom/base/nsContentIterator.cpp
@@ -714,16 +714,21 @@
     }
 
     // else next sibling is next
     return GetNextSibling(node, aIndexes);
   }
 
   // post-order
   nsINode* parent = node->GetParentNode();
+  if (NS_WARN_IF(!parent)) {
+    MOZ_ASSERT(parent, "The node is the root node but not the last node");
+    mIsDone = true;
+    return node;
+  }
   nsIContent* sibling = nullptr;
   int32_t indx = 0;
 
   // get the cached index
   NS_ASSERTION(!aIndexes || !aIndexes->IsEmpty(),
                "ContentIterator stack underflow");
   if (aIndexes && !aIndexes->IsEmpty()) {
     // use the last entry on the Indexes array for the current index
@@ -777,16 +782,21 @@
 nsINode*
 nsContentIterator::PrevNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
 {
   nsINode* node = aNode;
 
   // if we are a Pre-order iterator, use pre-order
   if (mPre) {
     nsINode* parent = node->GetParentNode();
+    if (NS_WARN_IF(!parent)) {
+      MOZ_ASSERT(parent, "The node is the root node but not the first node");
+      mIsDone = true;
+      return aNode;
+    }
     nsIContent* sibling = nullptr;
     int32_t indx = 0;
 
     // get the cached index
     NS_ASSERTION(!aIndexes || !aIndexes->IsEmpty(),
                  "ContentIterator stack underflow");
     if (aIndexes && !aIndexes->IsEmpty()) {
       // use the last entry on the Indexes array for the current index
