Bug 1227231 - Use generic algorithms of loops of Layer trees (DRAFT) draft feature/APZ-generic-layers-traversal
authorKevin Wern <kevin.m.wern@gmail.com>
Sun, 10 Jan 2016 15:47:27 -0800
branchfeature/APZ-generic-layers-traversal
changeset 320360 52ea21b938ed9ffde844539a9ec15525057e434b
parent 319164 9d6ffc7a08b6b47056eefe1e652710a3849adbf7
child 724528 621ef91a608cc199336becf46575f35b2949233d
push id9176
push userbmo:kevin.m.wern@gmail.com
push dateSun, 10 Jan 2016 23:48:02 +0000
bugs1227231
milestone46.0a1
Bug 1227231 - Use generic algorithms of loops of Layer trees (DRAFT) - Rename ForEachNode to ForEachNodeReverse, as it deals with Nodes having methods GetLastChild and GetPrevSibling. Create new function named ForEachNode to deal with GetFirstChild and GetNextSibling. - Refactor existing instances of ForEachNode to call ForEachNodeReverse. - Refactor Layer tree loops to use ForEachNode.
gfx/layers/FrameMetrics.cpp
gfx/layers/LayerTreeInvalidation.cpp
gfx/layers/Layers.cpp
gfx/layers/RenderTrace.cpp
gfx/layers/TreeTraversal.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/tests/gtest/TestTreeTraversal.cpp
--- a/gfx/layers/FrameMetrics.cpp
+++ b/gfx/layers/FrameMetrics.cpp
@@ -14,9 +14,9 @@ const FrameMetrics FrameMetrics::sNullMe
 
 void
 FrameMetrics::SetUsesContainerScrolling(bool aValue) {
   MOZ_ASSERT_IF(aValue, gfxPrefs::LayoutUseContainersForRootFrames());
   mUsesContainerScrolling = aValue;
 }
 
 }
-}
\ No newline at end of file
+}
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr, nsAutoPtr, etc
 #include "nsDataHashtable.h"            // for nsDataHashtable
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsHashKeys.h"                 // for nsPtrHashKey
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRect.h"                     // for IntRect
 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray_Impl
+#include "TreeTraversal.h"
 #include "mozilla/layers/ImageHost.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
@@ -265,19 +266,26 @@ struct LayerPropertiesBase : public Laye
 
 struct ContainerLayerProperties : public LayerPropertiesBase
 {
   explicit ContainerLayerProperties(ContainerLayer* aLayer)
     : LayerPropertiesBase(aLayer)
     , mPreXScale(aLayer->GetPreXScale())
     , mPreYScale(aLayer->GetPreYScale())
   {
-    for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
-      mChildren.AppendElement(Move(CloneLayerTreePropertiesInternal(child)));
-    }
+    ContainerLayer* root = aLayer;
+    ForEachNode(aLayer,
+        [this, root](ContainerLayer* aLayer)
+        {
+	  if (aLayer != root)
+	  {
+	    mChildren.AppendElement(Move(CloneLayerTreePropertiesInternal(aLayer)));
+	  }
+        }
+    );
   }
 
   virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback,
                                             bool& aGeometryChanged)
   {
     ContainerLayer* container = mLayer->AsContainerLayer();
     nsIntRegion invalidOfLayer; // Invalid regions of this layer.
     nsIntRegion result;         // Invliad regions for children only.
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -36,16 +36,17 @@
 #include "mozilla/layers/LayersTypes.h"  // for TextureDumpMode
 #include "mozilla/layers/PersistentBufferProvider.h"
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowableLayer
 #include "nsAString.h"
 #include "nsCSSValue.h"                 // for nsCSSValue::Array, etc
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "nsStyleStruct.h"              // for nsTimingFunction, etc
 #include "protobuf/LayerScopePacket.pb.h"
+#include "TreeTraversal.h"
 #include "mozilla/Compression.h"
 
 uint8_t gLayerManagerLayerBuilder;
 
 namespace mozilla {
 namespace layers {
 
 FILE*
@@ -527,33 +528,34 @@ Layer::SetAnimations(const AnimationArra
   }
 
   Mutated();
 }
 
 void
 Layer::StartPendingAnimations(const TimeStamp& aReadyTime)
 {
-  bool updated = false;
-  for (size_t animIdx = 0, animEnd = mAnimations.Length();
-       animIdx < animEnd; animIdx++) {
-    Animation& anim = mAnimations[animIdx];
-    if (anim.startTime().IsNull()) {
-      anim.startTime() = aReadyTime - anim.initialCurrentTime();
-      updated = true;
-    }
-  }
-
-  if (updated) {
-    Mutated();
-  }
-
-  for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
-    child->StartPendingAnimations(aReadyTime);
-  }
+  ForEachNode(this,
+      [this, &aReadyTime](Layer* aLayer)
+      {
+        bool updated = false;
+        for (size_t animIdx = 0, animEnd = mAnimations.Length();
+             animIdx < animEnd; animIdx++) {
+          Animation& anim = mAnimations[animIdx];
+          if (anim.startTime().IsNull()) {
+            anim.startTime() = aReadyTime - anim.initialCurrentTime();
+            updated = true;
+          }
+        }
+      
+        if (updated) {
+          Mutated();
+        }
+      }
+  );
 }
 
 void
 Layer::SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller)
 {
   MOZ_ASSERT(aIndex < GetFrameMetricsCount());
   mApzcs[aIndex] = controller;
 }
@@ -574,20 +576,22 @@ void
 Layer::FrameMetricsChanged()
 {
   mApzcs.SetLength(GetFrameMetricsCount());
 }
 
 void
 Layer::ApplyPendingUpdatesToSubtree()
 {
-  ApplyPendingUpdatesForThisTransaction();
-  for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
-    child->ApplyPendingUpdatesToSubtree();
-  }
+  ForEachNode(this, 
+      [](Layer* aLayer) {
+        aLayer->ApplyPendingUpdatesForThisTransaction();
+        aLayer->ApplyPendingUpdatesToSubtree();
+      }
+  );
 }
 
 bool
 Layer::IsOpaqueForVisibility()
 {
   return GetLocalOpacity() == 1.0f &&
          GetEffectiveMixBlendMode() == CompositionOp::OP_OVER;
 }
@@ -1318,25 +1322,28 @@ ContainerLayer::HasMultipleChildren()
 }
 
 /**
  * Collect all leaf descendants of the current 3D context.
  */
 void
 ContainerLayer::Collect3DContextLeaves(nsTArray<Layer*>& aToSort)
 {
-  for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
-    ContainerLayer* container = l->AsContainerLayer();
-    if (container && container->Extend3DContext() &&
-        !container->UseIntermediateSurface()) {
-      container->Collect3DContextLeaves(aToSort);
-    } else {
-      aToSort.AppendElement(l);
-    }
-  }
+  ForEachNode(this,
+      [&aToSort] (Layer* aLayer)
+      {
+        ContainerLayer* container = aLayer->AsContainerLayer();
+        if (container && container->Extend3DContext() &&
+            !container->UseIntermediateSurface()) {
+          container->Collect3DContextLeaves(aToSort);
+        } else {
+          aToSort.AppendElement(aLayer);
+        }
+      }
+  );
 }
 
 void
 ContainerLayer::SortChildrenBy3DZOrder(nsTArray<Layer*>& aArray)
 {
   nsAutoTArray<Layer*, 10> toSort;
 
   for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
--- a/gfx/layers/RenderTrace.cpp
+++ b/gfx/layers/RenderTrace.cpp
@@ -20,41 +20,41 @@ static gfx::Matrix4x4 GetRootTransform(L
   layerTrans.ProjectTo2D();
   if (aLayer->GetParent() != nullptr) {
     return GetRootTransform(aLayer->GetParent()) * layerTrans;
   }
   return layerTrans;
 }
 
 void RenderTraceLayers(Layer *aLayer, const char *aColor, const gfx::Matrix4x4 aRootTransform, bool aReset) {
-  if (!aLayer)
-    return;
-
-  gfx::Matrix4x4 trans = aRootTransform * aLayer->GetTransform();
-  trans.ProjectTo2D();
-  gfx::IntRect clipRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
-  Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
-  trans.TransformBounds(rect);
+  
+  Layer* aLayer = root;
+  ForEachNode(aLayer,
+      [aColor, &aRootTransform, aReset, root](Layer *aLayer)
+      {
+        gfx::Matrix4x4 trans = aRootTransform * aLayer->GetTransform();
+        trans.ProjectTo2D();
+        gfx::IntRect clipRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
+        Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
+        trans.TransformBounds(rect);
 
-  if (strcmp(aLayer->Name(), "ContainerLayer") != 0 &&
-      strcmp(aLayer->Name(), "ContainerLayerComposite") != 0) {
-    printf_stderr("%s RENDERTRACE %u rect #%02X%s %i %i %i %i\n",
-      aLayer->Name(), (int)PR_IntervalNow(),
-      colorId, aColor,
-      (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
-  }
+        if (strcmp(aLayer->Name(), "ContainerLayer") != 0 &&
+            strcmp(aLayer->Name(), "ContainerLayerComposite") != 0) {
+          printf_stderr("%s RENDERTRACE %u rect #%02X%s %i %i %i %i\n",
+            aLayer->Name(), (int)PR_IntervalNow(),
+            colorId, aColor,
+            (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
+        }
 
-  colorId++;
-
-  for (Layer* child = aLayer->GetFirstChild();
-        child; child = child->GetNextSibling()) {
-    RenderTraceLayers(child, aColor, aRootTransform, false);
-  }
-
-  if (aReset) colorId = 0;
+        colorId++;
+        if (aReset && aLayer == root) {
+          colorId = 0;
+        }
+      }
+  );
 }
 
 void RenderTraceInvalidateStart(Layer *aLayer, const char *aColor, const gfx::IntRect aRect) {
   gfx::Matrix4x4 trans = GetRootTransform(aLayer);
   gfx::Rect rect(aRect.x, aRect.y, aRect.width, aRect.height);
   trans.TransformBounds(rect);
 
   printf_stderr("%s RENDERTRACE %u fillrect #%s %i %i %i %i\n",
--- a/gfx/layers/TreeTraversal.h
+++ b/gfx/layers/TreeTraversal.h
@@ -10,20 +10,20 @@
 #include <queue>
 #include <stack>
 
 namespace mozilla {
 namespace layers {
 
 
 /*
- * Returned by |aAction| in ForEachNode. If the action returns
+ * Returned by |aAction| in ForEachNodeReverse. If the action returns
  * TraversalFlag::Skip, the node's children are not added to the traverrsal
  * stack. Otherwise, a return value of TraversalFlag::Continue indicates that
- * ForEachNode should traverse each of the node's children.
+ * ForEachNodeReverse should traverse each of the node's children.
  */
 enum class TraversalFlag { Skip, Continue };
 
 /*
  * Do a breadth-first search of the tree rooted at |aRoot|, and return the
  * first visited node that satisfies |aCondition|, or nullptr if no such node
  * was found.
  *
@@ -91,20 +91,20 @@ Node* DepthFirstSearch(Node* aRoot, cons
 }
 
 /*
  * Do a depth-first traversal of the tree rooted at |aRoot|, performing
  * |aAction| for each node.  |aAction| can return a TraversalFlag to determine
  * whether or not to omit the children of a particular node.
  *
  * If |aAction| does not return a TraversalFlag, it must return nothing.  There
- * is no ForEachNode instance handling types other than void or TraversalFlag.
+ * is no ForEachNodeReverse instance handling types other than void or TraversalFlag.
  */
 template <typename Node, typename Action>
-auto ForEachNode(Node* aRoot, const Action& aAction) ->
+auto ForEachNodeReverse(Node* aRoot, const Action& aAction) ->
 typename EnableIf<IsSame<decltype(aAction(aRoot)), TraversalFlag>::value, void>::Type
 {
   if (!aRoot) {
     return;
   }
 
   std::stack<Node*> stack;
   stack.push(aRoot);
@@ -121,17 +121,17 @@ typename EnableIf<IsSame<decltype(aActio
            child = child->GetPrevSibling()) {
         stack.push(child);
       }
     }
   }
 }
 
 template <typename Node, typename Action>
-auto ForEachNode(Node* aRoot, const Action& aAction) ->
+auto ForEachNodeReverse(Node* aRoot, const Action& aAction) ->
 typename EnableIf<IsSame<decltype(aAction(aRoot)), void>::value, void>::Type
 {
   if (!aRoot) {
     return;
   }
 
   std::stack<Node*> stack;
   stack.push(aRoot);
@@ -145,12 +145,64 @@ typename EnableIf<IsSame<decltype(aActio
     for (Node* child = node->GetLastChild();
          child;
          child = child->GetPrevSibling()) {
       stack.push(child);
     }
   }
 }
 
+template <typename Node, typename Action>
+auto ForEachNode(Node* aRoot, const Action& aAction) ->
+typename EnableIf<IsSame<decltype(aAction(aRoot)), TraversalFlag>::value, void>::Type
+{
+  if (!aRoot) {
+    return;
+  }
+
+  std::stack<Node*> stack;
+  stack.push(aRoot);
+
+  while (!stack.empty()) {
+    Node* node = stack.top();
+    stack.pop();
+
+    TraversalFlag result = aAction(node);
+
+    if (result == TraversalFlag::Continue) {
+      for (Node* child = node->GetFirstChild();
+           child;
+           child = child->GetNextSibling()) {
+        stack.push(child);
+      }
+    }
+  }
+}
+
+template <typename Node, typename Action>
+auto ForEachNode(Node* aRoot, const Action& aAction) ->
+typename EnableIf<IsSame<decltype(aAction(aRoot)), void>::value, void>::Type
+{
+  if (!aRoot) {
+    return;
+  }
+
+  std::stack<Node*> stack;
+  stack.push(aRoot);
+
+  while (!stack.empty()) {
+    Node* node = stack.top();
+    stack.pop();
+
+    aAction(node);
+
+    for (Node* child = node->GetFirstChild();
+         child;
+         child = child->GetNextSibling()) {
+      stack.push(child);
+    }
+  }
+}
+
 }
 }
 
 #endif // mozilla_layers_TreeTraversal_h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -159,17 +159,17 @@ APZCTreeManager::UpdateHitTestingTree(Co
   // completely different place. In scenario (a) we would want to destroy the APZC while
   // walking the layer tree and noticing that the layer/APZC is no longer there. But if
   // we do that then we run into a problem in scenario (b) because we might encounter that
   // layer later during the walk. To handle both of these we have to 'remember' that the
   // layer was not found, and then do the destroy only at the end of the tree walk after
   // we are sure that the layer was removed and not just transplanted elsewhere. Doing that
   // as part of a recursive tree walk is hard and so maintaining a list and removing
   // APZCs that are still alive is much simpler.
-  ForEachNode(mRootNode.get(),
+  ForEachNodeReverse(mRootNode.get(),
       [&state] (HitTestingTreeNode* aNode)
       {
         state.mNodesToDestroy.AppendElement(aNode);
       });
   mRootNode = nullptr;
 
   if (aRoot) {
     mApzcTreeLog << "[start]\n";
@@ -1186,17 +1186,17 @@ APZCTreeManager::UpdateZoomConstraints(c
     APZCTM_LOG("Recording constraints %s for guid %s\n",
       Stringify(aConstraints.value()).c_str(), Stringify(aGuid).c_str());
     mZoomConstraints[aGuid] = aConstraints.ref();
   } else {
     APZCTM_LOG("Removing constraints for guid %s\n", Stringify(aGuid).c_str());
     mZoomConstraints.erase(aGuid);
   }
   if (node && aConstraints) {
-    ForEachNode(node.get(),
+    ForEachNodeReverse(node.get(),
         [&aConstraints, &node, this](HitTestingTreeNode* aNode)
         {
           if (aNode != node) {
             if (AsyncPanZoomController* childApzc = aNode->GetApzc()) {
               // We can have subtrees with their own zoom constraints or separate layers
               // id - leave these alone.
               if (childApzc->HasNoParentWithSameLayersId() ||
                   this->mZoomConstraints.find(childApzc->GetGuid()) != this->mZoomConstraints.end()) {
@@ -1233,17 +1233,17 @@ APZCTreeManager::FlushRepaintsToClearScr
   // know which APZC got hit! This leads to a circular dependency; the only way
   // to get out of it is to make sure that the untransform for all the possible
   // matched APZCs is the same. It is simplest to ensure that by flushing the
   // pending repaint requests, which makes all of the untransforms empty (and
   // therefore equal).
   MonitorAutoLock lock(mTreeLock);
   mTreeLock.AssertCurrentThreadOwns();
 
-  ForEachNode(mRootNode.get(),
+  ForEachNodeReverse(mRootNode.get(),
       [](HitTestingTreeNode* aNode)
       {
         if (aNode->IsPrimaryHolder()) {
           MOZ_ASSERT(aNode->GetApzc());
           aNode->GetApzc()->FlushRepaintForNewInputBlock();
         }
       });
 }
@@ -1264,21 +1264,21 @@ APZCTreeManager::ClearTree()
   // blocks. This breaks cycles from InputBlockState::mTargetApzc back to
   // the InputQueue.
   APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
     mInputQueue.get(), &InputQueue::Clear));
 
   MonitorAutoLock lock(mTreeLock);
 
   // Collect the nodes into a list, and then destroy each one.
-  // We can't destroy them as we collect them, because ForEachNode()
+  // We can't destroy them as we collect them, because ForEachNodeReverse()
   // does a pre-order traversal of the tree, and Destroy() nulls out
   // the fields needed to reach the children of the node.
   nsTArray<RefPtr<HitTestingTreeNode>> nodesToDestroy;
-  ForEachNode(mRootNode.get(),
+  ForEachNodeReverse(mRootNode.get(),
       [&nodesToDestroy](HitTestingTreeNode* aNode)
       {
         nodesToDestroy.AppendElement(aNode);
       });
 
   for (size_t i = 0; i < nodesToDestroy.Length(); i++) {
     nodesToDestroy[i]->Destroy();
   }
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -668,38 +668,38 @@ SampleAPZAnimations(const LayerMetricsWr
 }
 
 void
 AsyncCompositionManager::RecordShadowTransforms(Layer* aLayer)
 {
   MOZ_ASSERT(gfxPrefs::CollectScrollTransforms());
   MOZ_ASSERT(CompositorParent::IsInCompositorThread());
 
-  for (Layer* child = aLayer->GetFirstChild();
-      child; child = child->GetNextSibling()) {
-      RecordShadowTransforms(child);
-  }
-
-  for (uint32_t i = 0; i < aLayer->GetFrameMetricsCount(); i++) {
-    AsyncPanZoomController* apzc = aLayer->GetAsyncPanZoomController(i);
-    if (!apzc) {
-      continue;
-    }
-    gfx::Matrix4x4 shadowTransform = aLayer->AsLayerComposite()->GetShadowTransform();
-    if (!shadowTransform.Is2D()) {
-      continue;
-    }
-
-    Matrix transform = shadowTransform.As2D();
-    if (transform.IsTranslation() && !shadowTransform.IsIdentity()) {
-      Point translation = transform.GetTranslation();
-      mLayerTransformRecorder.RecordTransform(aLayer, translation);
-      return;
-    }
-  }
+  ForEachNode(aLayer,
+      [this](Layer* aLayer)
+      {
+        for (uint32_t i = 0; i < aLayer->GetFrameMetricsCount(); i++) {
+          AsyncPanZoomController* apzc = aLayer->GetAsyncPanZoomController(i);
+          if (!apzc) {
+            continue;
+          }
+          gfx::Matrix4x4 shadowTransform = aLayer->AsLayerComposite()->GetShadowTransform();
+          if (!shadowTransform.Is2D()) {
+            continue;
+          }
+      
+          Matrix transform = shadowTransform.As2D();
+          if (transform.IsTranslation() && !shadowTransform.IsIdentity()) {
+            Point translation = transform.GetTranslation();
+            mLayerTransformRecorder.RecordTransform(aLayer, translation);
+            break;
+          }
+        }
+      }
+  );
 }
 
 Matrix4x4
 AdjustForClip(const Matrix4x4& asyncTransform, Layer* aLayer)
 {
   Matrix4x4 result = asyncTransform;
 
   // Container layers start at the origin, but they are clipped to where they
--- a/gfx/tests/gtest/TestTreeTraversal.cpp
+++ b/gfx/tests/gtest/TestTreeTraversal.cpp
@@ -337,17 +337,17 @@ TEST(TreeTraversal, BreadthFirstSearchVa
 
   ASSERT_EQ(foundNode.get(), nullptr) 
       << "Search found something that should not exist.";
 }
 
 TEST(TreeTraversal, ForEachNodeNullStillRuns)
 {
   RefPtr<ForEachTestNode> nullNode;
-  ForEachNode(nullNode.get(),
+  ForEachNodeReverse(nullNode.get(),
     [](ForEachTestNode* aNode)
     {
       return TraversalFlag::Continue;
     });
 }
 
 TEST(TreeTraversal, ForEachNodeAllEligible)
 {
@@ -365,17 +365,17 @@ TEST(TreeTraversal, ForEachNodeAllEligib
   nodeList[1]->AddChild(nodeList[3]);
   nodeList[4]->AddChild(nodeList[5]);
   nodeList[4]->AddChild(nodeList[6]);
   nodeList[6]->AddChild(nodeList[7]);
   nodeList[7]->AddChild(nodeList[8]);
   nodeList[7]->AddChild(nodeList[9]);
 
 
-  ForEachNode(root.get(),
+  ForEachNodeReverse(root.get(),
       [&visitCount](ForEachTestNode* aNode)
       {
         aNode->SetActualTraversalRank(visitCount);
 	visitCount++;
         return aNode->GetType() == ForEachNodeType::Continue
 	    ? TraversalFlag::Continue : TraversalFlag::Skip;
       });
 
@@ -407,17 +407,17 @@ TEST(TreeTraversal, ForEachNodeSomeIneli
   expectedVisitedNodeList[0]->AddChild(expectedVisitedNodeList[1]);
   expectedVisitedNodeList[0]->AddChild(expectedVisitedNodeList[2]);
   expectedVisitedNodeList[1]->AddChild(expectedSkippedNodeList[0]);
   expectedVisitedNodeList[1]->AddChild(expectedSkippedNodeList[1]);
   expectedVisitedNodeList[2]->AddChild(expectedVisitedNodeList[3]);
   expectedVisitedNodeList[3]->AddChild(expectedSkippedNodeList[2]);
   expectedVisitedNodeList[3]->AddChild(expectedSkippedNodeList[3]);
 
-  ForEachNode(root.get(),
+  ForEachNodeReverse(root.get(),
       [&visitCount](ForEachTestNode* aNode)
       {
         aNode->SetActualTraversalRank(visitCount);
 	visitCount++;
         return aNode->GetType() == ForEachNodeType::Continue
 	    ? TraversalFlag::Continue : TraversalFlag::Skip;
       });
 
@@ -439,17 +439,17 @@ TEST(TreeTraversal, ForEachNodeSomeIneli
 TEST(TreeTraversal, ForEachNodeIneligibleRoot)
 {
   int visitCount = 0;
 
   RefPtr<ForEachTestNode> root = new ForEachTestNode(ForEachNodeType::Skip, 0);
   RefPtr<ForEachTestNode> childNode1 = new ForEachTestNode(ForEachNodeType::Continue);
   RefPtr<ForEachTestNode> chlidNode2 = new ForEachTestNode(ForEachNodeType::Skip);
 
-  ForEachNode(root.get(),
+  ForEachNodeReverse(root.get(),
       [&visitCount](ForEachTestNode* aNode)
       {
         aNode->SetActualTraversalRank(visitCount);
 	visitCount++;
         return aNode->GetType() == ForEachNodeType::Continue
 	    ? TraversalFlag::Continue : TraversalFlag::Skip;
       });
 
@@ -481,17 +481,17 @@ TEST(TreeTraversal, ForEachNodeLeavesIne
   nodeList[2]->AddChild(nodeList[3]);
   nodeList[2]->AddChild(nodeList[4]);
   nodeList[4]->AddChild(nodeList[5]);
   nodeList[4]->AddChild(nodeList[6]);
   nodeList[6]->AddChild(nodeList[7]);
   nodeList[7]->AddChild(nodeList[8]);
   nodeList[7]->AddChild(nodeList[9]);
 
-  ForEachNode(root.get(),
+  ForEachNodeReverse(root.get(),
       [&visitCount](ForEachTestNode* aNode)
       {
         aNode->SetActualTraversalRank(visitCount);
 	visitCount++;
         return aNode->GetType() == ForEachNodeType::Continue
 	    ? TraversalFlag::Continue : TraversalFlag::Skip;
       });
 
@@ -519,17 +519,17 @@ TEST(TreeTraversal, ForEachNodeLambdaRet
   nodeList[1]->AddChild(nodeList[3]);
   nodeList[4]->AddChild(nodeList[5]);
   nodeList[4]->AddChild(nodeList[6]);
   nodeList[6]->AddChild(nodeList[7]);
   nodeList[7]->AddChild(nodeList[8]);
   nodeList[7]->AddChild(nodeList[9]);
 
 
-  ForEachNode(root.get(),
+  ForEachNodeReverse(root.get(),
       [&visitCount](ForEachTestNode* aNode)
       {
         aNode->SetActualTraversalRank(visitCount);
 	visitCount++;
       });
 
   for (size_t i = 0; i < nodeList.size(); i++)
   {