Bug 812687 part 3: Move CSSOrderAwareFrameIterator code to its own .h/.cpp file. r=mats draft
authorDaniel Holbert <dholbert@cs.stanford.edu>
Wed, 05 Apr 2017 13:59:56 -0700
changeset 556420 386fcd6028f88add467111edb9d1af53593d9b9e
parent 556419 4e9020ec30d28fa939fc29da89bf94429d1af89b
child 556421 1d335806f4fe56af66d82494c65e6c900584f426
push id52543
push userdholbert@mozilla.com
push dateWed, 05 Apr 2017 21:00:06 +0000
reviewersmats
bugs812687
milestone55.0a1
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;