Bug 812687 part 3: Move CSSOrderAwareFrameIterator code to its own .h/.cpp file. r=mats
authorDaniel Holbert <dholbert@cs.stanford.edu>
Wed, 05 Apr 2017 19:31:47 -0700
changeset 351428 947d5e737c2d05f038f01ddc2f02a01289db7ba8
parent 351427 1732e9dd1f9e28ec85eecb1ae45730a3d36e2dd5
child 351429 f6cc0dd3e7b8d90d0b1d29d5835a1bc4075211e4
push id88868
push userdholbert@mozilla.com
push dateThu, 06 Apr 2017 02:32:04 +0000
treeherdermozilla-inbound@001fd3755ac1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs812687
milestone55.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 812687 part 3: Move CSSOrderAwareFrameIterator code to its own .h/.cpp file. r=mats This patch just moves code, so it should not affect our behavior at all. MozReview-Commit-ID: 4yxSR5rWUV1
layout/generic/CSSOrderAwareFrameIterator.cpp
layout/generic/CSSOrderAwareFrameIterator.h
layout/generic/moz.build
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
new file mode 100644
--- /dev/null
+++ b/layout/generic/CSSOrderAwareFrameIterator.cpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Iterator class for frame lists that respect CSS "order" during layout */
+
+#include "CSSOrderAwareFrameIterator.h"
+
+namespace mozilla {
+
+template<>
+bool
+CSSOrderAwareFrameIterator::CSSOrderComparator(nsIFrame* const& a,
+                                               nsIFrame* const& b)
+{ return a->StylePosition()->mOrder < b->StylePosition()->mOrder; }
+
+template<>
+bool
+CSSOrderAwareFrameIterator::IsForward() const { return true; }
+
+template<>
+nsFrameList::iterator
+CSSOrderAwareFrameIterator::begin(const nsFrameList& aList)
+{ return aList.begin(); }
+
+template<>
+nsFrameList::iterator CSSOrderAwareFrameIterator::end(const nsFrameList& aList)
+{ return aList.end(); }
+
+template<>
+bool
+ReverseCSSOrderAwareFrameIterator::CSSOrderComparator(nsIFrame* const& a,
+                                                      nsIFrame* const& b)
+{ return a->StylePosition()->mOrder > b->StylePosition()->mOrder; }
+
+template<>
+bool
+ReverseCSSOrderAwareFrameIterator::IsForward() const
+{ return false; }
+
+template<>
+nsFrameList::reverse_iterator
+ReverseCSSOrderAwareFrameIterator::begin(const nsFrameList& aList)
+{ return aList.rbegin(); }
+
+template<>
+nsFrameList::reverse_iterator
+ReverseCSSOrderAwareFrameIterator::end(const nsFrameList& aList)
+{ return aList.rend(); }
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/generic/CSSOrderAwareFrameIterator.h
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Iterator class for frame lists that respect CSS "order" during layout */
+
+#ifndef mozilla_CSSOrderAwareFrameIterator_h
+#define mozilla_CSSOrderAwareFrameIterator_h
+
+#include <algorithm>
+#include "nsFrameList.h"
+#include "nsIFrame.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Assertions.h"
+
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 8
+#define CLANG_CRASH_BUG 1
+#endif
+
+namespace mozilla {
+
+template<typename Iterator>
+class CSSOrderAwareFrameIteratorT
+{
+public:
+  enum OrderState { eUnknownOrder, eKnownOrdered, eKnownUnordered };
+  enum ChildFilter { eSkipPlaceholders, eIncludeAll };
+  CSSOrderAwareFrameIteratorT(nsIFrame* aContainer,
+                              nsIFrame::ChildListID aListID,
+                              ChildFilter aFilter = eSkipPlaceholders,
+                              OrderState aState = eUnknownOrder)
+    : mChildren(aContainer->GetChildList(aListID))
+    , mArrayIndex(0)
+    , mItemIndex(0)
+    , mSkipPlaceholders(aFilter == eSkipPlaceholders)
+#ifdef DEBUG
+    , mContainer(aContainer)
+    , mListID(aListID)
+#endif
+  {
+    size_t count = 0;
+    bool isOrdered = aState != eKnownUnordered;
+    if (aState == eUnknownOrder) {
+      auto maxOrder = std::numeric_limits<int32_t>::min();
+      for (auto child : mChildren) {
+        ++count;
+        int32_t order = child->StylePosition()->mOrder;
+        if (order < maxOrder) {
+          isOrdered = false;
+          break;
+        }
+        maxOrder = order;
+      }
+    }
+    if (isOrdered) {
+      mIter.emplace(begin(mChildren));
+      mIterEnd.emplace(end(mChildren));
+    } else {
+      count *= 2; // XXX somewhat arbitrary estimate for now...
+      mArray.emplace(count);
+      for (Iterator i(begin(mChildren)), iEnd(end(mChildren)); i != iEnd; ++i) {
+        mArray->AppendElement(*i);
+      }
+      // XXX replace this with nsTArray::StableSort when bug 1147091 is fixed.
+      std::stable_sort(mArray->begin(), mArray->end(), CSSOrderComparator);
+    }
+
+    if (mSkipPlaceholders) {
+      SkipPlaceholders();
+    }
+  }
+  ~CSSOrderAwareFrameIteratorT()
+  {
+    MOZ_ASSERT(IsForward() == mItemCount.isNothing());
+  }
+
+  bool IsForward() const;
+  Iterator begin(const nsFrameList& aList);
+  Iterator end(const nsFrameList& aList);
+
+  nsIFrame* operator*() const
+  {
+    MOZ_ASSERT(!AtEnd());
+    if (mIter.isSome()) {
+      return **mIter;
+    }
+    return (*mArray)[mArrayIndex];
+  }
+
+  /**
+   * Return the child index of the current item, placeholders not counted.
+   * It's forbidden to call this method when the current frame is placeholder.
+   */
+  size_t ItemIndex() const
+  {
+    MOZ_ASSERT(!AtEnd());
+    MOZ_ASSERT((**this)->GetType() != nsGkAtoms::placeholderFrame,
+               "MUST not call this when at a placeholder");
+    MOZ_ASSERT(IsForward() || mItemIndex < *mItemCount,
+               "Returning an out-of-range mItemIndex...");
+    return mItemIndex;
+  }
+
+  void SetItemCount(size_t aItemCount)
+  {
+#ifndef CLANG_CRASH_BUG
+    MOZ_ASSERT(mIter.isSome() || aItemCount <= mArray->Length(),
+               "item count mismatch");
+#endif
+    mItemCount.emplace(aItemCount);
+    // Note: it's OK if mItemIndex underflows -- ItemIndex()
+    // will not be called unless there is at least one item.
+    mItemIndex = IsForward() ? 0 : *mItemCount - 1;
+  }
+
+  /**
+   * Skip over placeholder children.
+   */
+  void SkipPlaceholders()
+  {
+    if (mIter.isSome()) {
+      for (; *mIter != *mIterEnd; ++*mIter) {
+        nsIFrame* child = **mIter;
+        if (child->GetType() != nsGkAtoms::placeholderFrame) {
+          return;
+        }
+      }
+    } else {
+      for (; mArrayIndex < mArray->Length(); ++mArrayIndex) {
+        nsIFrame* child = (*mArray)[mArrayIndex];
+        if (child->GetType() != nsGkAtoms::placeholderFrame) {
+          return;
+        }
+      }
+    }
+  }
+
+  bool AtEnd() const
+  {
+#ifndef CLANG_CRASH_BUG
+    // Clang 3.6.2 crashes when compiling this assertion:
+    MOZ_ASSERT(mIter.isSome() || mArrayIndex <= mArray->Length());
+#endif
+    return mIter ? (*mIter == *mIterEnd) : mArrayIndex >= mArray->Length();
+  }
+
+  void Next()
+  {
+#ifdef DEBUG
+    MOZ_ASSERT(!AtEnd());
+    nsFrameList list = mContainer->GetChildList(mListID);
+    MOZ_ASSERT(list.FirstChild() == mChildren.FirstChild() &&
+               list.LastChild() == mChildren.LastChild(),
+               "the list of child frames must not change while iterating!");
+#endif
+    if (mSkipPlaceholders ||
+        (**this)->GetType() != nsGkAtoms::placeholderFrame) {
+      IsForward() ? ++mItemIndex : --mItemIndex;
+    }
+    if (mIter.isSome()) {
+      ++*mIter;
+    } else {
+      ++mArrayIndex;
+    }
+    if (mSkipPlaceholders) {
+      SkipPlaceholders();
+    }
+  }
+
+  void Reset(ChildFilter aFilter = eSkipPlaceholders)
+  {
+    if (mIter.isSome()) {
+      mIter.reset();
+      mIter.emplace(begin(mChildren));
+      mIterEnd.reset();
+      mIterEnd.emplace(end(mChildren));
+    } else {
+      mArrayIndex = 0;
+    }
+    mItemIndex = IsForward() ? 0 : *mItemCount - 1;
+    mSkipPlaceholders = aFilter == eSkipPlaceholders;
+    if (mSkipPlaceholders) {
+      SkipPlaceholders();
+    }
+  }
+
+  bool IsValid() const { return mIter.isSome() || mArray.isSome(); }
+
+  void Invalidate()
+  {
+    mIter.reset();
+    mArray.reset();
+    mozWritePoison(&mChildren, sizeof(mChildren));
+  }
+
+  bool ItemsAreAlreadyInOrder() const { return mIter.isSome(); }
+
+  static bool CSSOrderComparator(nsIFrame* const& a, nsIFrame* const& b);
+private:
+  nsFrameList mChildren;
+  // Used if child list is already in ascending 'order'.
+  Maybe<Iterator> mIter;
+  Maybe<Iterator> mIterEnd;
+  // Used if child list is *not* in ascending 'order'.
+  // This array is pre-sorted in reverse order for a reverse iterator.
+  Maybe<nsTArray<nsIFrame*>> mArray;
+  size_t mArrayIndex;
+  // The index of the current item (placeholders excluded).
+  size_t mItemIndex;
+  // The number of items (placeholders excluded).
+  // It's only initialized and used in a reverse iterator.
+  Maybe<size_t> mItemCount;
+  // Skip placeholder children in the iteration?
+  bool mSkipPlaceholders;
+#ifdef DEBUG
+  nsIFrame* mContainer;
+  nsIFrame::ChildListID mListID;
+#endif
+};
+
+typedef CSSOrderAwareFrameIteratorT<nsFrameList::iterator>
+  CSSOrderAwareFrameIterator;
+typedef CSSOrderAwareFrameIteratorT<nsFrameList::reverse_iterator>
+  ReverseCSSOrderAwareFrameIterator;
+
+} // namespace mozilla
+
+#endif // mozilla_CSSOrderAwareFrameIterator_h
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -105,16 +105,17 @@ EXPORTS += [
     'RubyUtils.h',
     'ScrollbarActivity.h',
     'ScrollSnap.h',
     'Visibility.h',
 ]
 
 EXPORTS.mozilla += [
     'CSSAlignUtils.h',
+    'CSSOrderAwareFrameIterator.h',
     'ReflowInput.h',
     'ReflowOutput.h',
     'ViewportFrame.h',
     'WritingModes.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'Selection.h',
@@ -124,16 +125,17 @@ EXPORTS.mozilla.layout += [
     'FrameChildList.h',
 ]
 
 UNIFIED_SOURCES += [
     'AsyncScrollBase.cpp',
     'BlockReflowInput.cpp',
     'BRFrame.cpp',
     'CSSAlignUtils.cpp',
+    'CSSOrderAwareFrameIterator.cpp',
     'DetailsFrame.cpp',
     'FrameChildList.cpp',
     'MathMLTextRunFactory.cpp',
     'nsAbsoluteContainingBlock.cpp',
     'nsBackdropFrame.cpp',
     'nsBlockFrame.cpp',
     'nsBlockReflowContext.cpp',
     'nsBulletFrame.cpp',
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -7,16 +7,17 @@
 /* rendering object for CSS "display: grid | inline-grid" */
 
 #include "nsGridContainerFrame.h"
 
 #include <algorithm> // for std::stable_sort
 #include <functional>
 #include <limits>
 #include "mozilla/CSSAlignUtils.h"
+#include "mozilla/CSSOrderAwareFrameIterator.h"
 #include "mozilla/dom/GridBinding.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/PodOperations.h" // for PodZero
 #include "mozilla/Poison.h"
 #include "nsAbsoluteContainingBlock.h"
 #include "nsAlgorithm.h" // for clamped()
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSFrameConstructor.h"
@@ -26,20 +27,16 @@
 #include "nsIFrameInlines.h"
 #include "nsPresContext.h"
 #include "nsReadableUtils.h"
 #include "nsRenderingContext.h"
 #include "nsRuleNode.h"
 #include "nsStyleContext.h"
 #include "nsTableWrapperFrame.h"
 
-#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 8
-#define CLANG_CRASH_BUG 1
-#endif
-
 using namespace mozilla;
 
 typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 typedef nsGridContainerFrame::TrackSize TrackSize;
 const uint32_t nsGridContainerFrame::kTranslatedMaxLine =
   uint32_t(nsStyleGridLine::kMaxLine - nsStyleGridLine::kMinLine);
 const uint32_t nsGridContainerFrame::kAutoLine = kTranslatedMaxLine + 3457U;
 typedef nsTHashtable< nsPtrHashKey<nsIFrame> > FrameHashtable;
@@ -380,258 +377,16 @@ MergeSortedFrameLists(nsFrameList& aDest
 
 static void
 MergeSortedFrameListsFor(nsFrameList& aDest, nsFrameList& aSrc,
                          nsContainerFrame* aParent)
 {
   MergeSortedFrameLists(aDest, aSrc, aParent->GetContent());
 }
 
-template<typename Iterator>
-class nsGridContainerFrame::CSSOrderAwareFrameIteratorT
-{
-public:
-  enum OrderState { eUnknownOrder, eKnownOrdered, eKnownUnordered };
-  enum ChildFilter { eSkipPlaceholders, eIncludeAll };
-  CSSOrderAwareFrameIteratorT(nsIFrame* aContainer,
-                              nsIFrame::ChildListID aListID,
-                              ChildFilter aFilter = eSkipPlaceholders,
-                              OrderState aState = eUnknownOrder)
-    : mChildren(aContainer->GetChildList(aListID))
-    , mArrayIndex(0)
-    , mItemIndex(0)
-    , mSkipPlaceholders(aFilter == eSkipPlaceholders)
-#ifdef DEBUG
-    , mContainer(aContainer)
-    , mListID(aListID)
-#endif
-  {
-    size_t count = 0;
-    bool isOrdered = aState != eKnownUnordered;
-    if (aState == eUnknownOrder) {
-      auto maxOrder = std::numeric_limits<int32_t>::min();
-      for (auto child : mChildren) {
-        ++count;
-        int32_t order = child->StylePosition()->mOrder;
-        if (order < maxOrder) {
-          isOrdered = false;
-          break;
-        }
-        maxOrder = order;
-      }
-    }
-    if (isOrdered) {
-      mIter.emplace(begin(mChildren));
-      mIterEnd.emplace(end(mChildren));
-    } else {
-      count *= 2; // XXX somewhat arbitrary estimate for now...
-      mArray.emplace(count);
-      for (Iterator i(begin(mChildren)), iEnd(end(mChildren)); i != iEnd; ++i) {
-        mArray->AppendElement(*i);
-      }
-      // XXX replace this with nsTArray::StableSort when bug 1147091 is fixed.
-      std::stable_sort(mArray->begin(), mArray->end(), CSSOrderComparator);
-    }
-
-    if (mSkipPlaceholders) {
-      SkipPlaceholders();
-    }
-  }
-  ~CSSOrderAwareFrameIteratorT()
-  {
-    MOZ_ASSERT(IsForward() == mItemCount.isNothing());
-  }
-
-  bool IsForward() const;
-  Iterator begin(const nsFrameList& aList);
-  Iterator end(const nsFrameList& aList);
-
-  nsIFrame* operator*() const
-  {
-    MOZ_ASSERT(!AtEnd());
-    if (mIter.isSome()) {
-      return **mIter;
-    }
-    return (*mArray)[mArrayIndex];
-  }
-
-  /**
-   * Return the child index of the current item, placeholders not counted.
-   * It's forbidden to call this method when the current frame is placeholder.
-   */
-  size_t ItemIndex() const
-  {
-    MOZ_ASSERT(!AtEnd());
-    MOZ_ASSERT((**this)->GetType() != nsGkAtoms::placeholderFrame,
-               "MUST not call this when at a placeholder");
-    MOZ_ASSERT(IsForward() || mItemIndex < *mItemCount,
-               "Returning an out-of-range mItemIndex...");
-    return mItemIndex;
-  }
-
-  void SetItemCount(size_t aItemCount)
-  {
-#ifndef CLANG_CRASH_BUG
-    MOZ_ASSERT(mIter.isSome() || aItemCount <= mArray->Length(),
-               "item count mismatch");
-#endif
-    mItemCount.emplace(aItemCount);
-    // Note: it's OK if mItemIndex underflows -- ItemIndex()
-    // will not be called unless there is at least one item.
-    mItemIndex = IsForward() ? 0 : *mItemCount - 1;
-  }
-
-  /**
-   * Skip over placeholder children.
-   */
-  void SkipPlaceholders()
-  {
-    if (mIter.isSome()) {
-      for (; *mIter != *mIterEnd; ++*mIter) {
-        nsIFrame* child = **mIter;
-        if (child->GetType() != nsGkAtoms::placeholderFrame) {
-          return;
-        }
-      }
-    } else {
-      for (; mArrayIndex < mArray->Length(); ++mArrayIndex) {
-        nsIFrame* child = (*mArray)[mArrayIndex];
-        if (child->GetType() != nsGkAtoms::placeholderFrame) {
-          return;
-        }
-      }
-    }
-  }
-
-  bool AtEnd() const
-  {
-#ifndef CLANG_CRASH_BUG
-    // Clang 3.6.2 crashes when compiling this assertion:
-    MOZ_ASSERT(mIter.isSome() || mArrayIndex <= mArray->Length());
-#endif
-    return mIter ? (*mIter == *mIterEnd) : mArrayIndex >= mArray->Length();
-  }
-
-  void Next()
-  {
-#ifdef DEBUG
-    MOZ_ASSERT(!AtEnd());
-    nsFrameList list = mContainer->GetChildList(mListID);
-    MOZ_ASSERT(list.FirstChild() == mChildren.FirstChild() &&
-               list.LastChild() == mChildren.LastChild(),
-               "the list of child frames must not change while iterating!");
-#endif
-    if (mSkipPlaceholders ||
-        (**this)->GetType() != nsGkAtoms::placeholderFrame) {
-      IsForward() ? ++mItemIndex : --mItemIndex;
-    }
-    if (mIter.isSome()) {
-      ++*mIter;
-    } else {
-      ++mArrayIndex;
-    }
-    if (mSkipPlaceholders) {
-      SkipPlaceholders();
-    }
-  }
-
-  void Reset(ChildFilter aFilter = eSkipPlaceholders)
-  {
-    if (mIter.isSome()) {
-      mIter.reset();
-      mIter.emplace(begin(mChildren));
-      mIterEnd.reset();
-      mIterEnd.emplace(end(mChildren));
-    } else {
-      mArrayIndex = 0;
-    }
-    mItemIndex = IsForward() ? 0 : *mItemCount - 1;
-    mSkipPlaceholders = aFilter == eSkipPlaceholders;
-    if (mSkipPlaceholders) {
-      SkipPlaceholders();
-    }
-  }
-
-  bool IsValid() const { return mIter.isSome() || mArray.isSome(); }
-
-  void Invalidate()
-  {
-    mIter.reset();
-    mArray.reset();
-    mozWritePoison(&mChildren, sizeof(mChildren));
-  }
-
-  bool ItemsAreAlreadyInOrder() const { return mIter.isSome(); }
-
-  static bool CSSOrderComparator(nsIFrame* const& a, nsIFrame* const& b);
-private:
-  nsFrameList mChildren;
-  // Used if child list is already in ascending 'order'.
-  Maybe<Iterator> mIter;
-  Maybe<Iterator> mIterEnd;
-  // Used if child list is *not* in ascending 'order'.
-  // This array is pre-sorted in reverse order for a reverse iterator.
-  Maybe<nsTArray<nsIFrame*>> mArray;
-  size_t mArrayIndex;
-  // The index of the current item (placeholders excluded).
-  size_t mItemIndex;
-  // The number of items (placeholders excluded).
-  // It's only initialized and used in a reverse iterator.
-  Maybe<size_t> mItemCount;
-  // Skip placeholder children in the iteration?
-  bool mSkipPlaceholders;
-#ifdef DEBUG
-  nsIFrame* mContainer;
-  nsIFrame::ChildListID mListID;
-#endif
-};
-
-using CSSOrderAwareFrameIterator = nsGridContainerFrame::CSSOrderAwareFrameIterator;
-using ReverseCSSOrderAwareFrameIterator = nsGridContainerFrame::ReverseCSSOrderAwareFrameIterator;
-
-template<>
-bool
-CSSOrderAwareFrameIterator::CSSOrderComparator(nsIFrame* const& a,
-                                               nsIFrame* const& b)
-{ return a->StylePosition()->mOrder < b->StylePosition()->mOrder; }
-
-template<>
-bool
-CSSOrderAwareFrameIterator::IsForward() const { return true; }
-
-template<>
-nsFrameList::iterator
-CSSOrderAwareFrameIterator::begin(const nsFrameList& aList)
-{ return aList.begin(); }
-
-template<>
-nsFrameList::iterator CSSOrderAwareFrameIterator::end(const nsFrameList& aList)
-{ return aList.end(); }
-
-template<>
-bool
-ReverseCSSOrderAwareFrameIterator::CSSOrderComparator(nsIFrame* const& a,
-                                                      nsIFrame* const& b)
-{ return a->StylePosition()->mOrder > b->StylePosition()->mOrder; }
-
-template<>
-bool
-ReverseCSSOrderAwareFrameIterator::IsForward() const
-{ return false; }
-
-template<>
-nsFrameList::reverse_iterator
-ReverseCSSOrderAwareFrameIterator::begin(const nsFrameList& aList)
-{ return aList.rbegin(); }
-
-template<>
-nsFrameList::reverse_iterator
-ReverseCSSOrderAwareFrameIterator::end(const nsFrameList& aList)
-{ return aList.rend(); }
-
 /**
  * A LineRange can be definite or auto - when it's definite it represents
  * a consecutive set of tracks between a starting line and an ending line.
  * Before it's definite it can also represent an auto position with a span,
  * where mStart == kAutoLine and mEnd is the (non-zero positive) span.
  * For normal-flow items, the invariant mStart < mEnd holds when both
  * lines are definite.
  *
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -18,16 +18,24 @@
 /**
  * Factory function.
  * @return a newly allocated nsGridContainerFrame (infallible)
  */
 nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
                                            nsStyleContext* aContext);
 
 namespace mozilla {
+
+// Forward-declare typedefs for grid item iterator helper-class:
+template<typename Iterator> class CSSOrderAwareFrameIteratorT;
+typedef CSSOrderAwareFrameIteratorT<nsFrameList::iterator>
+  CSSOrderAwareFrameIterator;
+typedef CSSOrderAwareFrameIteratorT<nsFrameList::reverse_iterator>
+  ReverseCSSOrderAwareFrameIterator;
+
 /**
  * The number of implicit / explicit tracks and their sizes.
  */
 struct ComputedGridTrackInfo
 {
   ComputedGridTrackInfo(uint32_t aNumLeadingImplicitTracks,
                         uint32_t aNumExplicitTracks,
                         uint32_t aStartFragmentTrack,
@@ -214,35 +222,33 @@ public:
    * @return nullptr if aFrame has no grid container, or frame was destroyed
    * @note this might destroy layout/style data since it may flush layout
    */
   static nsGridContainerFrame* GetGridFrameWithComputedInfo(nsIFrame* aFrame);
 
   struct TrackSize;
   struct GridItemInfo;
   struct GridReflowInput;
-  template<typename Iterator> class CSSOrderAwareFrameIteratorT;
-  typedef CSSOrderAwareFrameIteratorT<nsFrameList::iterator>
-    CSSOrderAwareFrameIterator;
-  typedef CSSOrderAwareFrameIteratorT<nsFrameList::reverse_iterator>
-    ReverseCSSOrderAwareFrameIterator;
   struct FindItemInGridOrderResult
   {
     // The first(last) item in (reverse) grid order.
     const GridItemInfo* mItem;
     // Does the above item span the first(last) track?
     bool mIsInEdgeTrack;
   };
 protected:
   static const uint32_t kAutoLine;
   // The maximum line number, in the zero-based translated grid.
   static const uint32_t kTranslatedMaxLine;
   typedef mozilla::LogicalPoint LogicalPoint;
   typedef mozilla::LogicalRect LogicalRect;
   typedef mozilla::LogicalSize LogicalSize;
+  typedef mozilla::CSSOrderAwareFrameIterator CSSOrderAwareFrameIterator;
+  typedef mozilla::ReverseCSSOrderAwareFrameIterator
+    ReverseCSSOrderAwareFrameIterator;
   typedef mozilla::WritingMode WritingMode;
   typedef mozilla::css::GridNamedArea GridNamedArea;
   typedef mozilla::layout::AutoFrameListPtr AutoFrameListPtr;
   typedef nsLayoutUtils::IntrinsicISizeType IntrinsicISizeType;
   struct Grid;
   struct GridArea;
   class LineNameMap;
   struct LineRange;