Bug 1144096 part 1 - [css-grid] Refactor nsGridContainerFrame state and methods. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Fri, 11 Mar 2016 17:39:25 +0100
changeset 339554 a8b7c33f5687a244a3abffb7b02b7c2ca231b7f8
parent 339553 4916251eb38968263c69c633fee264d129570768
child 339555 3737062990186ca27ee7fd31c2afd2fabfedab5c
push id12762
push userbmo:rail@mozilla.com
push dateFri, 11 Mar 2016 19:47:45 +0000
reviewersdholbert
bugs1144096
milestone48.0a1
Bug 1144096 part 1 - [css-grid] Refactor nsGridContainerFrame state and methods. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -971,29 +971,62 @@ struct MOZ_STACK_CLASS nsGridContainerFr
                       aRS.GetWritingMode())
   {}
   GridReflowState(nsGridContainerFrame* aFrame,
                   nsRenderingContext&   aRC)
     : GridReflowState(aFrame, aRC, nullptr, aFrame->StylePosition(),
                       aFrame->GetWritingMode())
   {}
 
+  /**
+   * Calculate our track sizes.
+   */
+  void CalculateTrackSizes(const Grid&        aGrid,
+                           const LogicalSize& aContentBox,
+                           IntrinsicISizeType aConstraint);
+
+  /**
+   * Return the containing block for a grid item occupying aArea.
+   */
+  LogicalRect ContainingBlockFor(const GridArea& aArea) const;
+
+  /**
+   * Return the containing block for an abs.pos. grid item occupying aArea.
+   * Any 'auto' lines in the grid area will be aligned with grid container
+   * containing block on that side.
+   * @param aGridOrigin the origin of the grid
+   * @param aGridCB the grid container containing block (its padding area)
+   */
+  LogicalRect ContainingBlockForAbsPos(const GridArea&     aArea,
+                                       const LogicalPoint& aGridOrigin,
+                                       const LogicalRect&  aGridCB) const;
+
   GridItemCSSOrderIterator mIter;
   const nsStylePosition* const mGridStyle;
   Tracks mCols;
   Tracks mRows;
   TrackSizingFunctions mColFunctions;
   TrackSizingFunctions mRowFunctions;
   /**
+   * Info about each (normal flow) grid item.
+   */
+  nsTArray<GridItemInfo> mGridItems;
+  /**
+   * Info about each grid-aligned abs.pos. child.
+   */
+  nsTArray<GridItemInfo> mAbsPosItems;
+
+  /**
    * @note mReflowState may be null when using the 2nd ctor above. In this case
    * we'll construct a dummy parent reflow state if we need it to calculate
    * min/max-content contributions when sizing tracks.
    */
-  const nsHTMLReflowState* mReflowState;
+  const nsHTMLReflowState* const mReflowState;
   nsRenderingContext& mRenderingContext;
+  nsGridContainerFrame* const mFrame;
   const WritingMode mWM;
 
 private:
   GridReflowState(nsGridContainerFrame*    aFrame,
                   nsRenderingContext&      aRenderingContext,
                   const nsHTMLReflowState* aReflowState,
                   const nsStylePosition*   aGridStyle,
                   const WritingMode&       aWM)
@@ -1004,73 +1037,425 @@ private:
     , mColFunctions(mGridStyle->mGridTemplateColumns,
                     mGridStyle->mGridAutoColumnsMin,
                     mGridStyle->mGridAutoColumnsMax)
     , mRowFunctions(mGridStyle->mGridTemplateRows,
                     mGridStyle->mGridAutoRowsMin,
                     mGridStyle->mGridAutoRowsMax)
     , mReflowState(aReflowState)
     , mRenderingContext(aRenderingContext)
+    , mFrame(aFrame)
     , mWM(aWM)
-  {}
+  {
+    MOZ_ASSERT(!aReflowState || aReflowState->frame == mFrame);
+  }
 };
 
-static
-bool IsMinContent(const nsStyleCoord& aCoord)
+/**
+ * The Grid implements grid item placement and the state of the grid -
+ * the size of the explicit/implicit grid, which cells are occupied etc.
+ */
+struct MOZ_STACK_CLASS nsGridContainerFrame::Grid
 {
-  return aCoord.GetUnit() == eStyleUnit_Enumerated &&
-         aCoord.GetIntValue() == NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT;
-}
+  /**
+   * Place all child frames into the grid and expand the (implicit) grid as
+   * needed.  The allocated GridAreas are stored in the GridAreaProperty
+   * frame property on the child frame.
+   * @param aComputedMinSize the container's min-size - used to determine
+   *   the number of repeat(auto-fill/fit) tracks.
+   * @param aComputedSize the container's size - used to determine
+   *   the number of repeat(auto-fill/fit) tracks.
+   * @param aComputedMaxSize the container's max-size - used to determine
+   *   the number of repeat(auto-fill/fit) tracks.
+   */
+  void PlaceGridItems(GridReflowState& aState,
+                      const LogicalSize& aComputedMinSize,
+                      const LogicalSize& aComputedSize,
+                      const LogicalSize& aComputedMaxSize);
+
+  /**
+   * As above but for an abs.pos. child.  Any 'auto' lines will be represented
+   * by kAutoLine in the LineRange result.
+   * @param aGridStart the first line in the final, but untranslated grid
+   * @param aGridEnd the last line in the final, but untranslated grid
+   */
+  LineRange ResolveAbsPosLineRange(const nsStyleGridLine& aStart,
+                                   const nsStyleGridLine& aEnd,
+                                   const LineNameMap& aNameMap,
+                                   uint32_t GridNamedArea::* aAreaStart,
+                                   uint32_t GridNamedArea::* aAreaEnd,
+                                   uint32_t aExplicitGridEnd,
+                                   int32_t aGridStart,
+                                   int32_t aGridEnd,
+                                   const nsStylePosition* aStyle);
+
+  /**
+   * Return a GridArea for abs.pos. item with non-auto lines placed at
+   * a definite line (1-based) with placement errors resolved.  One or both
+   * positions may still be 'auto'.
+   * @param aChild the abs.pos. grid item to place
+   * @param aStyle the StylePosition() for the grid container
+   */
+  GridArea PlaceAbsPos(nsIFrame* aChild,
+                       const LineNameMap& aColLineNameMap,
+                       const LineNameMap& aRowLineNameMap,
+                       const nsStylePosition* aStyle);
+
+  /**
+   * Find the first column in row aLockedRow starting at aStartCol where aArea
+   * could be placed without overlapping other items.  The returned column may
+   * cause aArea to overflow the current implicit grid bounds if placed there.
+   */
+  uint32_t FindAutoCol(uint32_t aStartCol, uint32_t aLockedRow,
+                       const GridArea* aArea) const;
+
+  /**
+   * Place aArea in the first column (in row aArea->mRows.mStart) starting at
+   * aStartCol without overlapping other items.  The resulting aArea may
+   * overflow the current implicit grid bounds.
+   * Pre-condition: aArea->mRows.IsDefinite() is true.
+   * Post-condition: aArea->IsDefinite() is true.
+   */
+  void PlaceAutoCol(uint32_t aStartCol, GridArea* aArea) const;
+
+  /**
+   * Find the first row in column aLockedCol starting at aStartRow where aArea
+   * could be placed without overlapping other items.  The returned row may
+   * cause aArea to overflow the current implicit grid bounds if placed there.
+   */
+  uint32_t FindAutoRow(uint32_t aLockedCol, uint32_t aStartRow,
+                       const GridArea* aArea) const;
+
+  /**
+   * Place aArea in the first row (in column aArea->mCols.mStart) starting at
+   * aStartRow without overlapping other items. The resulting aArea may
+   * overflow the current implicit grid bounds.
+   * Pre-condition: aArea->mCols.IsDefinite() is true.
+   * Post-condition: aArea->IsDefinite() is true.
+   */
+  void PlaceAutoRow(uint32_t aStartRow, GridArea* aArea) const;
+
+  /**
+   * Place aArea in the first column starting at aStartCol,aStartRow without
+   * causing it to overlap other items or overflow mGridColEnd.
+   * If there's no such column in aStartRow, continue in position 1,aStartRow+1.
+   * Pre-condition: aArea->mCols.IsAuto() && aArea->mRows.IsAuto() is true.
+   * Post-condition: aArea->IsDefinite() is true.
+   */
+  void PlaceAutoAutoInRowOrder(uint32_t aStartCol,
+                               uint32_t aStartRow,
+                               GridArea* aArea) const;
+
+  /**
+   * Place aArea in the first row starting at aStartCol,aStartRow without
+   * causing it to overlap other items or overflow mGridRowEnd.
+   * If there's no such row in aStartCol, continue in position aStartCol+1,1.
+   * Pre-condition: aArea->mCols.IsAuto() && aArea->mRows.IsAuto() is true.
+   * Post-condition: aArea->IsDefinite() is true.
+   */
+  void PlaceAutoAutoInColOrder(uint32_t aStartCol,
+                               uint32_t aStartRow,
+                               GridArea* aArea) const;
 
-/**
- * A convenience method to lookup a name in 'grid-template-areas'.
- * @param aStyle the StylePosition() for the grid container
- * @return null if not found
- */
-static const css::GridNamedArea*
-FindNamedArea(const nsSubstring& aName, const nsStylePosition* aStyle)
-{
-  if (!aStyle->mGridTemplateAreas) {
+  /**
+   * Return aLine if it's inside the aMin..aMax range (inclusive),
+   * otherwise return kAutoLine.
+   */
+  static int32_t
+  AutoIfOutside(int32_t aLine, int32_t aMin, int32_t aMax)
+  {
+    MOZ_ASSERT(aMin <= aMax);
+    if (aLine < aMin || aLine > aMax) {
+      return kAutoLine;
+    }
+    return aLine;
+  }
+
+  /**
+   * Inflate the implicit grid to include aArea.
+   * @param aArea may be definite or auto
+   */
+  void InflateGridFor(const GridArea& aArea)
+  {
+    mGridColEnd = std::max(mGridColEnd, aArea.mCols.HypotheticalEnd());
+    mGridRowEnd = std::max(mGridRowEnd, aArea.mRows.HypotheticalEnd());
+    MOZ_ASSERT(mGridColEnd <= kTranslatedMaxLine &&
+               mGridRowEnd <= kTranslatedMaxLine);
+  }
+
+  enum LineRangeSide {
+    eLineRangeSideStart, eLineRangeSideEnd
+  };
+  /**
+   * Return a line number for (non-auto) aLine, per:
+   * http://dev.w3.org/csswg/css-grid/#line-placement
+   * @param aLine style data for the line (must be non-auto)
+   * @param aNth a number of lines to find from aFromIndex, negative if the
+   *             search should be in reverse order.  In the case aLine has
+   *             a specified line name, it's permitted to pass in zero which
+   *             will be treated as one.
+   * @param aFromIndex the zero-based index to start counting from
+   * @param aLineNameList the explicit named lines
+   * @param aAreaStart a pointer to GridNamedArea::mColumnStart/mRowStart
+   * @param aAreaEnd a pointer to GridNamedArea::mColumnEnd/mRowEnd
+   * @param aExplicitGridEnd the last line in the explicit grid
+   * @param aEdge indicates whether we are resolving a start or end line
+   * @param aStyle the StylePosition() for the grid container
+   * @return a definite line (1-based), clamped to the kMinLine..kMaxLine range
+   */
+  int32_t ResolveLine(const nsStyleGridLine& aLine,
+                      int32_t aNth,
+                      uint32_t aFromIndex,
+                      const LineNameMap& aNameMap,
+                      uint32_t GridNamedArea::* aAreaStart,
+                      uint32_t GridNamedArea::* aAreaEnd,
+                      uint32_t aExplicitGridEnd,
+                      LineRangeSide aSide,
+                      const nsStylePosition* aStyle);
+
+  /**
+   * Helper method for ResolveLineRange.
+   * @see ResolveLineRange
+   * @return a pair (start,end) of lines
+   */
+  typedef std::pair<int32_t, int32_t> LinePair;
+  LinePair ResolveLineRangeHelper(const nsStyleGridLine& aStart,
+                                  const nsStyleGridLine& aEnd,
+                                  const LineNameMap& aNameMap,
+                                  uint32_t GridNamedArea::* aAreaStart,
+                                  uint32_t GridNamedArea::* aAreaEnd,
+                                  uint32_t aExplicitGridEnd,
+                                  const nsStylePosition* aStyle);
+
+  /**
+   * Return a LineRange based on the given style data. Non-auto lines
+   * are resolved to a definite line number (1-based) per:
+   * http://dev.w3.org/csswg/css-grid/#line-placement
+   * with placement errors corrected per:
+   * http://dev.w3.org/csswg/css-grid/#grid-placement-errors
+   * @param aStyle the StylePosition() for the grid container
+   * @param aStart style data for the start line
+   * @param aEnd style data for the end line
+   * @param aLineNameList the explicit named lines
+   * @param aAreaStart a pointer to GridNamedArea::mColumnStart/mRowStart
+   * @param aAreaEnd a pointer to GridNamedArea::mColumnEnd/mRowEnd
+   * @param aExplicitGridEnd the last line in the explicit grid
+   * @param aStyle the StylePosition() for the grid container
+   */
+  LineRange ResolveLineRange(const nsStyleGridLine& aStart,
+                             const nsStyleGridLine& aEnd,
+                             const LineNameMap& aNameMap,
+                             uint32_t GridNamedArea::* aAreaStart,
+                             uint32_t GridNamedArea::* aAreaEnd,
+                             uint32_t aExplicitGridEnd,
+                             const nsStylePosition* aStyle);
+
+  /**
+   * Return a GridArea with non-auto lines placed at a definite line (1-based)
+   * with placement errors resolved.  One or both positions may still
+   * be 'auto'.
+   * @param aChild the grid item
+   * @param aStyle the StylePosition() for the grid container
+   */
+  GridArea PlaceDefinite(nsIFrame*              aChild,
+                         const LineNameMap&     aColLineNameMap,
+                         const LineNameMap&     aRowLineNameMap,
+                         const nsStylePosition* aStyle);
+
+  bool HasImplicitNamedArea(const nsString& aName) const
+  {
+    return mAreas && mAreas->Contains(aName);
+  }
+
+  /**
+   * A convenience method to lookup a name in 'grid-template-areas'.
+   * @param aStyle the StylePosition() for the grid container
+   * @return null if not found
+   */
+  static const css::GridNamedArea*
+  FindNamedArea(const nsSubstring& aName, const nsStylePosition* aStyle)
+  {
+    if (!aStyle->mGridTemplateAreas) {
+      return nullptr;
+    }
+    const nsTArray<css::GridNamedArea>& areas =
+      aStyle->mGridTemplateAreas->mNamedAreas;
+    size_t len = areas.Length();
+    for (size_t i = 0; i < len; ++i) {
+      const css::GridNamedArea& area = areas[i];
+      if (area.mName == aName) {
+        return &area;
+      }
+    }
     return nullptr;
   }
-  const nsTArray<css::GridNamedArea>& areas =
-    aStyle->mGridTemplateAreas->mNamedAreas;
-  size_t len = areas.Length();
-  for (size_t i = 0; i < len; ++i) {
-    const css::GridNamedArea& area = areas[i];
-    if (area.mName == aName) {
-      return &area;
+
+  // Return true if aString ends in aSuffix and has at least one character before
+  // the suffix. Assign aIndex to where the suffix starts.
+  static bool
+  IsNameWithSuffix(const nsString& aString, const nsString& aSuffix,
+                   uint32_t* aIndex)
+  {
+    if (StringEndsWith(aString, aSuffix)) {
+      *aIndex = aString.Length() - aSuffix.Length();
+      return *aIndex != 0;
     }
+    return false;
+  }
+
+  static bool
+  IsNameWithEndSuffix(const nsString& aString, uint32_t* aIndex)
+  {
+    return IsNameWithSuffix(aString, NS_LITERAL_STRING("-end"), aIndex);
+  }
+
+  static bool
+  IsNameWithStartSuffix(const nsString& aString, uint32_t* aIndex)
+  {
+    return IsNameWithSuffix(aString, NS_LITERAL_STRING("-start"), aIndex);
   }
-  return nullptr;
-}
+
+  /**
+   * A CellMap holds state for each cell in the grid.
+   * It's row major.  It's sparse in the sense that it only has enough rows to
+   * cover the last row that has a grid item.  Each row only has enough entries
+   * to cover columns that are occupied *on that row*, i.e. it's not a full
+   * matrix covering the entire implicit grid.  An absent Cell means that it's
+   * unoccupied by any grid item.
+   */
+  struct CellMap {
+    struct Cell {
+      Cell() : mIsOccupied(false) {}
+      bool mIsOccupied : 1;
+    };
+
+    void Fill(const GridArea& aGridArea)
+    {
+      MOZ_ASSERT(aGridArea.IsDefinite());
+      MOZ_ASSERT(aGridArea.mRows.mStart < aGridArea.mRows.mEnd);
+      MOZ_ASSERT(aGridArea.mCols.mStart < aGridArea.mCols.mEnd);
+      const auto numRows = aGridArea.mRows.mEnd;
+      const auto numCols = aGridArea.mCols.mEnd;
+      mCells.EnsureLengthAtLeast(numRows);
+      for (auto i = aGridArea.mRows.mStart; i < numRows; ++i) {
+        nsTArray<Cell>& cellsInRow = mCells[i];
+        cellsInRow.EnsureLengthAtLeast(numCols);
+        for (auto j = aGridArea.mCols.mStart; j < numCols; ++j) {
+          cellsInRow[j].mIsOccupied = true;
+        }
+      }
+    }
+
+    void ClearOccupied()
+    {
+      const size_t numRows = mCells.Length();
+      for (size_t i = 0; i < numRows; ++i) {
+        nsTArray<Cell>& cellsInRow = mCells[i];
+        const size_t numCols = cellsInRow.Length();
+        for (size_t j = 0; j < numCols; ++j) {
+          cellsInRow[j].mIsOccupied = false;
+        }
+      }
+    }
 
-// Return true if aString ends in aSuffix and has at least one character before
-// the suffix. Assign aIndex to where the suffix starts.
-static bool
-IsNameWithSuffix(const nsString& aString, const nsString& aSuffix,
-                 uint32_t* aIndex)
+    uint32_t IsEmptyCol(uint32_t aCol) const
+    {
+      for (auto& row : mCells) {
+        if (aCol < row.Length() && row[aCol].mIsOccupied) {
+          return false;
+        }
+      }
+      return true;
+    }
+    uint32_t IsEmptyRow(uint32_t aRow) const
+    {
+      if (aRow >= mCells.Length()) {
+        return true;
+      }
+      for (const Cell& cell : mCells[aRow]) {
+        if (cell.mIsOccupied) {
+          return false;
+        }
+      }
+      return true;
+    }
+#ifdef DEBUG
+    void Dump() const
+    {
+      const size_t numRows = mCells.Length();
+      for (size_t i = 0; i < numRows; ++i) {
+        const nsTArray<Cell>& cellsInRow = mCells[i];
+        const size_t numCols = cellsInRow.Length();
+        printf("%lu:\t", (unsigned long)i + 1);
+        for (size_t j = 0; j < numCols; ++j) {
+          printf(cellsInRow[j].mIsOccupied ? "X " : ". ");
+        }
+        printf("\n");
+      }
+    }
+#endif
+
+    nsTArray<nsTArray<Cell>> mCells;
+  };
+
+  /**
+   * State for each cell in the grid.
+   */
+  CellMap mCellMap;
+  /**
+   * @see HasImplicitNamedArea.
+   */
+  ImplicitNamedAreas* mAreas;
+  /**
+   * The last column grid line (1-based) in the explicit grid.
+   * (i.e. the number of explicit columns + 1)
+   */
+  uint32_t mExplicitGridColEnd;
+  /**
+   * The last row grid line (1-based) in the explicit grid.
+   * (i.e. the number of explicit rows + 1)
+   */
+  uint32_t mExplicitGridRowEnd;
+  // Same for the implicit grid, except these become zero-based after
+  // resolving definite lines.
+  uint32_t mGridColEnd;
+  uint32_t mGridRowEnd;
+
+  /**
+   * Offsets from the start of the implicit grid to the start of the translated
+   * explicit grid.  They are zero if there are no implicit lines before 1,1.
+   * e.g. "grid-column: span 3 / 1" makes mExplicitGridOffsetCol = 3 and the
+   * corresponding GridArea::mCols will be 0 / 3 in the zero-based translated
+   * grid.
+   */
+  uint32_t mExplicitGridOffsetCol;
+  uint32_t mExplicitGridOffsetRow;
+
+};
+
+void
+nsGridContainerFrame::GridReflowState::CalculateTrackSizes(
+  const Grid&        aGrid,
+  const LogicalSize& aContentBox,
+  IntrinsicISizeType aConstraint)
 {
-  if (StringEndsWith(aString, aSuffix)) {
-    *aIndex = aString.Length() - aSuffix.Length();
-    return *aIndex != 0;
-  }
-  return false;
-}
+  mCols.Initialize(mColFunctions, mGridStyle->mGridColumnGap,
+                   aGrid.mGridColEnd, aContentBox.ISize(mWM));
+  mRows.Initialize(mRowFunctions, mGridStyle->mGridRowGap,
+                   aGrid.mGridRowEnd, aContentBox.BSize(mWM));
 
-static bool
-IsNameWithEndSuffix(const nsString& aString, uint32_t* aIndex)
-{
-  return IsNameWithSuffix(aString, NS_LITERAL_STRING("-end"), aIndex);
-}
+  mIter.Reset(); // XXX cleanup this Reset mess!
+  mCols.CalculateSizes(*this, mGridItems, mColFunctions,
+                       aContentBox.ISize(mWM), &GridArea::mCols,
+                       aConstraint);
 
-static bool
-IsNameWithStartSuffix(const nsString& aString, uint32_t* aIndex)
-{
-  return IsNameWithSuffix(aString, NS_LITERAL_STRING("-start"), aIndex);
+  mIter.Reset(); // XXX cleanup this Reset mess!
+  mRows.CalculateSizes(*this, mGridItems, mRowFunctions,
+                       aContentBox.BSize(mWM), &GridArea::mRows,
+                       aConstraint);
 }
 
 /**
  * (XXX share this utility function with nsFlexContainerFrame at some point)
  *
  * Helper for BuildDisplayList, to implement this special-case for grid
  * items from the spec:
  *   The painting order of grid items is exactly the same as inline blocks,
@@ -1432,18 +1817,18 @@ nsGridContainerFrame::AddImplicitNamedAr
   // Note: recording these names for fast lookup later is just an optimization.
   const uint32_t len =
     std::min(aLineNameLists.Length(), size_t(nsStyleGridLine::kMaxLine));
   nsTHashtable<nsStringHashKey> currentStarts;
   ImplicitNamedAreas* areas = GetImplicitNamedAreas();
   for (uint32_t i = 0; i < len; ++i) {
     for (const nsString& name : aLineNameLists[i]) {
       uint32_t index;
-      if (::IsNameWithStartSuffix(name, &index) ||
-          ::IsNameWithEndSuffix(name, &index)) {
+      if (Grid::IsNameWithStartSuffix(name, &index) ||
+          Grid::IsNameWithEndSuffix(name, &index)) {
         nsDependentSubstring area(name, 0, index);
         if (!areas) {
           areas = new ImplicitNamedAreas;
           Properties().Set(ImplicitNamedAreasProperty(), areas);
         }
         areas->PutEntry(area);
       }
     }
@@ -1462,40 +1847,39 @@ nsGridContainerFrame::InitImplicitNamedA
   AddImplicitNamedAreas(aStyle->mGridTemplateColumns.mLineNameLists);
   AddImplicitNamedAreas(aStyle->mGridTemplateRows.mLineNameLists);
   if (areas && areas->Count() == 0) {
     Properties().Delete(ImplicitNamedAreasProperty());
   }
 }
 
 int32_t
-nsGridContainerFrame::ResolveLine(
-  const nsStyleGridLine& aLine,
-  int32_t aNth,
-  uint32_t aFromIndex,
-  const LineNameMap& aNameMap,
-  uint32_t GridNamedArea::* aAreaStart,
-  uint32_t GridNamedArea::* aAreaEnd,
-  uint32_t aExplicitGridEnd,
-  LineRangeSide aSide,
-  const nsStylePosition* aStyle)
+nsGridContainerFrame::Grid::ResolveLine(const nsStyleGridLine& aLine,
+                                        int32_t aNth,
+                                        uint32_t aFromIndex,
+                                        const LineNameMap& aNameMap,
+                                        uint32_t GridNamedArea::* aAreaStart,
+                                        uint32_t GridNamedArea::* aAreaEnd,
+                                        uint32_t aExplicitGridEnd,
+                                        LineRangeSide aSide,
+                                        const nsStylePosition* aStyle)
 {
   MOZ_ASSERT(!aLine.IsAuto());
   int32_t line = 0;
   if (aLine.mLineName.IsEmpty()) {
     MOZ_ASSERT(aNth != 0, "css-grid 9.2: <integer> must not be zero.");
     line = int32_t(aFromIndex) + aNth;
   } else {
     if (aNth == 0) {
       // <integer> was omitted; treat it as 1.
       aNth = 1;
     }
     bool isNameOnly = !aLine.mHasSpan && aLine.mInteger == 0;
     if (isNameOnly) {
-      const GridNamedArea* area = ::FindNamedArea(aLine.mLineName, aStyle);
+      const GridNamedArea* area = FindNamedArea(aLine.mLineName, aStyle);
       if (area || HasImplicitNamedArea(aLine.mLineName)) {
         // The given name is a named area - look for explicit lines named
         // <name>-start/-end depending on which side we're resolving.
         // http://dev.w3.org/csswg/css-grid/#grid-placement-slot
         uint32_t implicitLine = 0;
         nsAutoString lineName(aLine.mLineName);
         if (aSide == eLineRangeSideStart) {
           lineName.AppendLiteral("-start");
@@ -1509,25 +1893,25 @@ nsGridContainerFrame::ResolveLine(
       }
     }
 
     if (line == 0) {
       // If mLineName ends in -start/-end, try the prefix as a named area.
       uint32_t implicitLine = 0;
       uint32_t index;
       auto GridNamedArea::* areaEdge = aAreaStart;
-      bool found = ::IsNameWithStartSuffix(aLine.mLineName, &index);
+      bool found = IsNameWithStartSuffix(aLine.mLineName, &index);
       if (!found) {
-        found = ::IsNameWithEndSuffix(aLine.mLineName, &index);
+        found = IsNameWithEndSuffix(aLine.mLineName, &index);
         areaEdge = aAreaEnd;
       }
       if (found) {
         const GridNamedArea* area =
-          ::FindNamedArea(nsDependentSubstring(aLine.mLineName, 0, index),
-                          aStyle);
+          FindNamedArea(nsDependentSubstring(aLine.mLineName, 0, index),
+                        aStyle);
         if (area) {
           implicitLine = area->*areaEdge;
         }
       }
       line = aNameMap.FindNamedLine(aLine.mLineName, &aNth, aFromIndex,
                                     implicitLine);
     }
 
@@ -1546,18 +1930,18 @@ nsGridContainerFrame::ResolveLine(
       // "If not enough lines with that name exist, all lines in the implicit
       // grid are assumed to have that name..."
       line = edgeLine + aNth;
     }
   }
   return clamped(line, nsStyleGridLine::kMinLine, nsStyleGridLine::kMaxLine);
 }
 
-nsGridContainerFrame::LinePair
-nsGridContainerFrame::ResolveLineRangeHelper(
+nsGridContainerFrame::Grid::LinePair
+nsGridContainerFrame::Grid::ResolveLineRangeHelper(
   const nsStyleGridLine& aStart,
   const nsStyleGridLine& aEnd,
   const LineNameMap& aNameMap,
   uint32_t GridNamedArea::* aAreaStart,
   uint32_t GridNamedArea::* aAreaEnd,
   uint32_t aExplicitGridEnd,
   const nsStylePosition* aStyle)
 {
@@ -1646,17 +2030,17 @@ nsGridContainerFrame::ResolveLineRangeHe
   if (start == int32_t(kAutoLine)) {
     // auto / definite line
     start = std::max(nsStyleGridLine::kMinLine, end - 1);
   }
   return LinePair(start, end);
 }
 
 nsGridContainerFrame::LineRange
-nsGridContainerFrame::ResolveLineRange(
+nsGridContainerFrame::Grid::ResolveLineRange(
   const nsStyleGridLine& aStart,
   const nsStyleGridLine& aEnd,
   const LineNameMap& aNameMap,
   uint32_t GridNamedArea::* aAreaStart,
   uint32_t GridNamedArea::* aAreaEnd,
   uint32_t aExplicitGridEnd,
   const nsStylePosition* aStyle)
 {
@@ -1679,35 +2063,35 @@ nsGridContainerFrame::ResolveLineRange(
       }
       r.second = r.first + 1; // XXX subgrid explicit size instead of 1?
     }
   }
   return LineRange(r.first, r.second);
 }
 
 nsGridContainerFrame::GridArea
-nsGridContainerFrame::PlaceDefinite(nsIFrame* aChild,
-                                    const LineNameMap& aColLineNameMap,
-                                    const LineNameMap& aRowLineNameMap,
-                                    const nsStylePosition* aStyle)
+nsGridContainerFrame::Grid::PlaceDefinite(nsIFrame* aChild,
+                                          const LineNameMap& aColLineNameMap,
+                                          const LineNameMap& aRowLineNameMap,
+                                          const nsStylePosition* aStyle)
 {
   const nsStylePosition* itemStyle = aChild->StylePosition();
   return GridArea(
     ResolveLineRange(itemStyle->mGridColumnStart, itemStyle->mGridColumnEnd,
                      aColLineNameMap,
                      &GridNamedArea::mColumnStart, &GridNamedArea::mColumnEnd,
                      mExplicitGridColEnd, aStyle),
     ResolveLineRange(itemStyle->mGridRowStart, itemStyle->mGridRowEnd,
                      aRowLineNameMap,
                      &GridNamedArea::mRowStart, &GridNamedArea::mRowEnd,
                      mExplicitGridRowEnd, aStyle));
 }
 
 nsGridContainerFrame::LineRange
-nsGridContainerFrame::ResolveAbsPosLineRange(
+nsGridContainerFrame::Grid::ResolveAbsPosLineRange(
   const nsStyleGridLine& aStart,
   const nsStyleGridLine& aEnd,
   const LineNameMap& aNameMap,
   uint32_t GridNamedArea::* aAreaStart,
   uint32_t GridNamedArea::* aAreaEnd,
   uint32_t aExplicitGridEnd,
   int32_t aGridStart,
   int32_t aGridEnd,
@@ -1750,19 +2134,45 @@ nsGridContainerFrame::ResolveAbsPosLineR
     // case should result in "auto / auto" unlike normal flow grid items.
     return LineRange(kAutoLine, kAutoLine);
   }
 
   return LineRange(AutoIfOutside(r.mUntranslatedStart, aGridStart, aGridEnd),
                    AutoIfOutside(r.mUntranslatedEnd, aGridStart, aGridEnd));
 }
 
+nsGridContainerFrame::GridArea
+nsGridContainerFrame::Grid::PlaceAbsPos(nsIFrame* aChild,
+                                        const LineNameMap& aColLineNameMap,
+                                        const LineNameMap& aRowLineNameMap,
+                                        const nsStylePosition* aStyle)
+{
+  const nsStylePosition* itemStyle = aChild->StylePosition();
+  int32_t gridColStart = 1 - mExplicitGridOffsetCol;
+  int32_t gridRowStart = 1 - mExplicitGridOffsetRow;
+  return GridArea(
+    ResolveAbsPosLineRange(itemStyle->mGridColumnStart,
+                           itemStyle->mGridColumnEnd,
+                           aColLineNameMap,
+                           &GridNamedArea::mColumnStart,
+                           &GridNamedArea::mColumnEnd,
+                           mExplicitGridColEnd, gridColStart, mGridColEnd,
+                           aStyle),
+    ResolveAbsPosLineRange(itemStyle->mGridRowStart,
+                           itemStyle->mGridRowEnd,
+                           aRowLineNameMap,
+                           &GridNamedArea::mRowStart,
+                           &GridNamedArea::mRowEnd,
+                           mExplicitGridRowEnd, gridRowStart, mGridRowEnd,
+                           aStyle));
+}
+
 uint32_t
-nsGridContainerFrame::FindAutoCol(uint32_t aStartCol, uint32_t aLockedRow,
-                                  const GridArea* aArea) const
+nsGridContainerFrame::Grid::FindAutoCol(uint32_t aStartCol, uint32_t aLockedRow,
+                                        const GridArea* aArea) const
 {
   const uint32_t extent = aArea->mCols.Extent();
   const uint32_t iStart = aLockedRow;
   const uint32_t iEnd = iStart + aArea->mRows.Extent();
   uint32_t candidate = aStartCol;
   for (uint32_t i = iStart; i < iEnd; ) {
     if (i >= mCellMap.mCells.Length()) {
       break;
@@ -1786,54 +2196,29 @@ nsGridContainerFrame::FindAutoCol(uint32
       i = iStart;
     } else {
       ++i;
     }
   }
   return candidate;
 }
 
-nsGridContainerFrame::GridArea
-nsGridContainerFrame::PlaceAbsPos(nsIFrame* aChild,
-                                  const LineNameMap& aColLineNameMap,
-                                  const LineNameMap& aRowLineNameMap,
-                                  const nsStylePosition* aStyle)
-{
-  const nsStylePosition* itemStyle = aChild->StylePosition();
-  int32_t gridColStart = 1 - mExplicitGridOffsetCol;
-  int32_t gridRowStart = 1 - mExplicitGridOffsetRow;
-  return GridArea(
-    ResolveAbsPosLineRange(itemStyle->mGridColumnStart,
-                           itemStyle->mGridColumnEnd,
-                           aColLineNameMap,
-                           &GridNamedArea::mColumnStart,
-                           &GridNamedArea::mColumnEnd,
-                           mExplicitGridColEnd, gridColStart, mGridColEnd,
-                           aStyle),
-    ResolveAbsPosLineRange(itemStyle->mGridRowStart,
-                           itemStyle->mGridRowEnd,
-                           aRowLineNameMap,
-                           &GridNamedArea::mRowStart,
-                           &GridNamedArea::mRowEnd,
-                           mExplicitGridRowEnd, gridRowStart, mGridRowEnd,
-                           aStyle));
-}
-
 void
-nsGridContainerFrame::PlaceAutoCol(uint32_t aStartCol, GridArea* aArea) const
+nsGridContainerFrame::Grid::PlaceAutoCol(uint32_t aStartCol,
+                                         GridArea* aArea) const
 {
   MOZ_ASSERT(aArea->mRows.IsDefinite() && aArea->mCols.IsAuto());
   uint32_t col = FindAutoCol(aStartCol, aArea->mRows.mStart, aArea);
   aArea->mCols.ResolveAutoPosition(col, mExplicitGridOffsetCol);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 uint32_t
-nsGridContainerFrame::FindAutoRow(uint32_t aLockedCol, uint32_t aStartRow,
-                                  const GridArea* aArea) const
+nsGridContainerFrame::Grid::FindAutoRow(uint32_t aLockedCol, uint32_t aStartRow,
+                                        const GridArea* aArea) const
 {
   const uint32_t extent = aArea->mRows.Extent();
   const uint32_t jStart = aLockedCol;
   const uint32_t jEnd = jStart + aArea->mCols.Extent();
   const uint32_t iEnd = mCellMap.mCells.Length();
   uint32_t candidate = aStartRow;
   // Find the first gap in the rows that's at least 'extent' tall.
   // ('gap' tracks how tall the current row gap is.)
@@ -1851,28 +2236,29 @@ nsGridContainerFrame::FindAutoRow(uint32
         break;
       }
     }
   }
   return candidate;
 }
 
 void
-nsGridContainerFrame::PlaceAutoRow(uint32_t aStartRow, GridArea* aArea) const
+nsGridContainerFrame::Grid::PlaceAutoRow(uint32_t aStartRow,
+                                         GridArea* aArea) const
 {
   MOZ_ASSERT(aArea->mCols.IsDefinite() && aArea->mRows.IsAuto());
   uint32_t row = FindAutoRow(aArea->mCols.mStart, aStartRow, aArea);
   aArea->mRows.ResolveAutoPosition(row, mExplicitGridOffsetRow);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 void
-nsGridContainerFrame::PlaceAutoAutoInRowOrder(uint32_t aStartCol,
-                                              uint32_t aStartRow,
-                                              GridArea* aArea) const
+nsGridContainerFrame::Grid::PlaceAutoAutoInRowOrder(uint32_t aStartCol,
+                                                    uint32_t aStartRow,
+                                                    GridArea* aArea) const
 {
   MOZ_ASSERT(aArea->mCols.IsAuto() && aArea->mRows.IsAuto());
   const uint32_t colExtent = aArea->mCols.Extent();
   const uint32_t gridRowEnd = mGridRowEnd;
   const uint32_t gridColEnd = mGridColEnd;
   uint32_t col = aStartCol;
   uint32_t row = aStartRow;
   for (; row < gridRowEnd; ++row) {
@@ -1885,19 +2271,19 @@ nsGridContainerFrame::PlaceAutoAutoInRow
   MOZ_ASSERT(row < gridRowEnd || col == 0,
              "expected column 0 for placing in a new row");
   aArea->mCols.ResolveAutoPosition(col, mExplicitGridOffsetCol);
   aArea->mRows.ResolveAutoPosition(row, mExplicitGridOffsetRow);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 void
-nsGridContainerFrame::PlaceAutoAutoInColOrder(uint32_t aStartCol,
-                                              uint32_t aStartRow,
-                                              GridArea* aArea) const
+nsGridContainerFrame::Grid::PlaceAutoAutoInColOrder(uint32_t aStartCol,
+                                                    uint32_t aStartRow,
+                                                    GridArea* aArea) const
 {
   MOZ_ASSERT(aArea->mCols.IsAuto() && aArea->mRows.IsAuto());
   const uint32_t rowExtent = aArea->mRows.Extent();
   const uint32_t gridRowEnd = mGridRowEnd;
   const uint32_t gridColEnd = mGridColEnd;
   uint32_t col = aStartCol;
   uint32_t row = aStartRow;
   for (; col < gridColEnd; ++col) {
@@ -1910,21 +2296,22 @@ nsGridContainerFrame::PlaceAutoAutoInCol
   MOZ_ASSERT(col < gridColEnd || row == 0,
              "expected row 0 for placing in a new column");
   aArea->mCols.ResolveAutoPosition(col, mExplicitGridOffsetCol);
   aArea->mRows.ResolveAutoPosition(row, mExplicitGridOffsetRow);
   MOZ_ASSERT(aArea->IsDefinite());
 }
 
 void
-nsGridContainerFrame::PlaceGridItems(GridReflowState& aState,
-                                     const LogicalSize& aComputedMinSize,
-                                     const LogicalSize& aComputedSize,
-                                     const LogicalSize& aComputedMaxSize)
+nsGridContainerFrame::Grid::PlaceGridItems(GridReflowState& aState,
+                                           const LogicalSize& aComputedMinSize,
+                                           const LogicalSize& aComputedSize,
+                                           const LogicalSize& aComputedMaxSize)
 {
+  mAreas = aState.mFrame->GetImplicitNamedAreas();
   const nsStylePosition* const gridStyle = aState.mGridStyle;
   mCellMap.ClearOccupied();
 
   // http://dev.w3.org/csswg/css-grid/#grid-definition
   // Initialize the end lines of the Explicit Grid (mExplicitGridCol[Row]End).
   // This is determined by the larger of the number of rows/columns defined
   // by 'grid-template-areas' and the 'grid-template-rows'/'-columns', plus one.
   // Also initialize the Implicit Grid (mGridCol[Row]End) to the same values.
@@ -1948,26 +2335,26 @@ nsGridContainerFrame::PlaceGridItems(Gri
   mGridRowEnd = mExplicitGridRowEnd =
     aState.mRowFunctions.ComputeExplicitGridEnd(areas ? areas->NRows() + 1 : 1);
   LineNameMap rowLineNameMap(gridStyle->mGridTemplateRows, numRepeatRows);
 
   // http://dev.w3.org/csswg/css-grid/#line-placement
   // Resolve definite positions per spec chap 9.2.
   int32_t minCol = 1;
   int32_t minRow = 1;
-  mGridItems.ClearAndRetainStorage();
+  aState.mGridItems.ClearAndRetainStorage();
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
     nsIFrame* child = *aState.mIter;
     GridItemInfo* info =
-      mGridItems.AppendElement(GridItemInfo(PlaceDefinite(child,
-                                                          colLineNameMap,
-                                                          rowLineNameMap,
-                                                          gridStyle)));
+      aState.mGridItems.AppendElement(GridItemInfo(PlaceDefinite(child,
+                                                                 colLineNameMap,
+                                                                 rowLineNameMap,
+                                                                 gridStyle)));
 #ifdef DEBUG
-    MOZ_ASSERT(aState.mIter.GridItemIndex() == mGridItems.Length() - 1,
+    MOZ_ASSERT(aState.mIter.GridItemIndex() == aState.mGridItems.Length() - 1,
                "GridItemIndex() is broken");
     info->mFrame = child;
 #endif
     GridArea& area = info->mArea;
     if (area.mCols.IsDefinite()) {
       minCol = std::min(minCol, area.mCols.mUntranslatedStart);
     }
     if (area.mRows.IsDefinite()) {
@@ -1981,17 +2368,17 @@ nsGridContainerFrame::PlaceGridItems(Gri
   aState.mColFunctions.mExplicitGridOffset = mExplicitGridOffsetCol;
   aState.mRowFunctions.mExplicitGridOffset = mExplicitGridOffsetRow;
   const int32_t offsetToColZero = int32_t(mExplicitGridOffsetCol) - 1;
   const int32_t offsetToRowZero = int32_t(mExplicitGridOffsetRow) - 1;
   mGridColEnd += offsetToColZero;
   mGridRowEnd += offsetToRowZero;
   aState.mIter.Reset();
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
-    GridArea& area = mGridItems[aState.mIter.GridItemIndex()].mArea;
+    GridArea& area = aState.mGridItems[aState.mIter.GridItemIndex()].mArea;
     if (area.mCols.IsDefinite()) {
       area.mCols.mStart = area.mCols.mUntranslatedStart + offsetToColZero;
       area.mCols.mEnd = area.mCols.mUntranslatedEnd + offsetToColZero;
     }
     if (area.mRows.IsDefinite()) {
       area.mRows.mStart = area.mRows.mUntranslatedStart + offsetToRowZero;
       area.mRows.mEnd = area.mRows.mUntranslatedEnd + offsetToRowZero;
     }
@@ -2008,21 +2395,21 @@ nsGridContainerFrame::PlaceGridItems(Gri
   const bool isRowOrder = (flowStyle & NS_STYLE_GRID_AUTO_FLOW_ROW);
   const bool isSparse = !(flowStyle & NS_STYLE_GRID_AUTO_FLOW_DENSE);
   // We need 1 cursor per row (or column) if placement is sparse.
   {
     Maybe<nsDataHashtable<nsUint32HashKey, uint32_t>> cursors;
     if (isSparse) {
       cursors.emplace();
     }
-    auto placeAutoMinorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoCol
-                                         : &nsGridContainerFrame::PlaceAutoRow;
+    auto placeAutoMinorFunc = isRowOrder ? &Grid::PlaceAutoCol
+                                         : &Grid::PlaceAutoRow;
     aState.mIter.Reset();
     for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
-      GridArea& area = mGridItems[aState.mIter.GridItemIndex()].mArea;
+      GridArea& area = aState.mGridItems[aState.mIter.GridItemIndex()].mArea;
       LineRange& major = isRowOrder ? area.mRows : area.mCols;
       LineRange& minor = isRowOrder ? area.mCols : area.mRows;
       if (major.IsDefinite() && minor.IsAuto()) {
         // Items with 'auto' in the minor dimension only.
         uint32_t cursor = 0;
         if (isSparse) {
           cursors->Get(major.mStart, &cursor);
         }
@@ -2042,23 +2429,23 @@ nsGridContainerFrame::PlaceGridItems(Gri
   // XXX https://www.w3.org/Bugs/Public/show_bug.cgi?id=16044
   // XXX seems to indicate it shouldn't.
   // XXX http://dev.w3.org/csswg/css-grid/#auto-placement-cursor
   // XXX now says it should (but didn't in earlier versions)
 
   // Step 3, place the remaining grid items
   uint32_t cursorMajor = 0; // for 'dense' these two cursors will stay at 0,0
   uint32_t cursorMinor = 0;
-  auto placeAutoMajorFunc = isRowOrder ? &nsGridContainerFrame::PlaceAutoRow
-                                       : &nsGridContainerFrame::PlaceAutoCol;
+  auto placeAutoMajorFunc = isRowOrder ? &Grid::PlaceAutoRow
+                                       : &Grid::PlaceAutoCol;
   aState.mIter.Reset();
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
-    GridArea& area = mGridItems[aState.mIter.GridItemIndex()].mArea;
-    MOZ_ASSERT(*aState.mIter == mGridItems[aState.mIter.GridItemIndex()].mFrame,
-               "iterator out of sync with mGridItems");
+    GridArea& area = aState.mGridItems[aState.mIter.GridItemIndex()].mArea;
+    MOZ_ASSERT(*aState.mIter == aState.mGridItems[aState.mIter.GridItemIndex()].mFrame,
+               "iterator out of sync with aState.mGridItems");
     LineRange& major = isRowOrder ? area.mRows : area.mCols;
     LineRange& minor = isRowOrder ? area.mCols : area.mRows;
     if (major.IsAuto()) {
       if (minor.IsDefinite()) {
         // Items with 'auto' in the major dimension only.
         if (isSparse) {
           if (minor.mStart < cursorMinor) {
             ++cursorMajor;
@@ -2090,38 +2477,39 @@ nsGridContainerFrame::PlaceGridItems(Gri
 #endif
         }
       }
       mCellMap.Fill(area);
       InflateGridFor(area);
     }
   }
 
-  if (IsAbsoluteContainer()) {
+  if (aState.mFrame->IsAbsoluteContainer()) {
     // 9.4 Absolutely-positioned Grid Items
     // http://dev.w3.org/csswg/css-grid/#abspos-items
     // We only resolve definite lines here; we'll align auto positions to the
     // grid container later during reflow.
-    nsFrameList children(GetChildList(GetAbsoluteListID()));
+    nsFrameList children(aState.mFrame->GetChildList(
+                           aState.mFrame->GetAbsoluteListID()));
     const int32_t offsetToColZero = int32_t(mExplicitGridOffsetCol) - 1;
     const int32_t offsetToRowZero = int32_t(mExplicitGridOffsetRow) - 1;
     // Untranslate the grid again temporarily while resolving abs.pos. lines.
     AutoRestore<uint32_t> save1(mGridColEnd);
     AutoRestore<uint32_t> save2(mGridRowEnd);
     mGridColEnd -= offsetToColZero;
     mGridRowEnd -= offsetToRowZero;
-    mAbsPosItems.ClearAndRetainStorage();
+    aState.mAbsPosItems.ClearAndRetainStorage();
     size_t i = 0;
     for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next(), ++i) {
       nsIFrame* child = e.get();
       GridItemInfo* info =
-        mAbsPosItems.AppendElement(GridItemInfo(PlaceAbsPos(child,
-                                                            colLineNameMap,
-                                                            rowLineNameMap,
-                                                            gridStyle)));
+        aState.mAbsPosItems.AppendElement(GridItemInfo(PlaceAbsPos(child,
+                                                                   colLineNameMap,
+                                                                   rowLineNameMap,
+                                                                   gridStyle)));
 #ifdef DEBUG
       info->mFrame = child;
 #endif
       GridArea& area = info->mArea;
       if (area.mCols.mUntranslatedStart != int32_t(kAutoLine)) {
         area.mCols.mStart = area.mCols.mUntranslatedStart + offsetToColZero;
       }
       if (area.mCols.mUntranslatedEnd != int32_t(kAutoLine)) {
@@ -2140,18 +2528,18 @@ nsGridContainerFrame::PlaceGridItems(Gri
   // |colAdjust| will have a count for each line in the grid of how many
   // tracks were empty between the start of the grid and that line.
   Maybe<nsTArray<uint32_t>> colAdjust;
   uint32_t numEmptyCols = 0;
   if (aState.mColFunctions.mHasRepeatAuto &&
       !gridStyle->mGridTemplateColumns.mIsAutoFill &&
       aState.mColFunctions.NumRepeatTracks() > 0) {
     for (uint32_t col = aState.mColFunctions.mRepeatAutoStart,
-                  endRepeat = aState.mColFunctions.mRepeatAutoEnd,
-                  numColLines = mGridColEnd + 1;
+           endRepeat = aState.mColFunctions.mRepeatAutoEnd,
+           numColLines = mGridColEnd + 1;
          col < numColLines; ++col) {
       if (numEmptyCols) {
         (*colAdjust)[col] = numEmptyCols;
       }
       if (col < endRepeat && mCellMap.IsEmptyCol(col)) {
         ++numEmptyCols;
         if (colAdjust.isNothing()) {
           colAdjust.emplace(numColLines);
@@ -2162,18 +2550,18 @@ nsGridContainerFrame::PlaceGridItems(Gri
     }
   }
   Maybe<nsTArray<uint32_t>> rowAdjust;
   uint32_t numEmptyRows = 0;
   if (aState.mRowFunctions.mHasRepeatAuto &&
       !gridStyle->mGridTemplateRows.mIsAutoFill &&
       aState.mRowFunctions.NumRepeatTracks() > 0) {
     for (uint32_t row = aState.mRowFunctions.mRepeatAutoStart,
-                  endRepeat = aState.mRowFunctions.mRepeatAutoEnd,
-                  numRowLines = mGridRowEnd + 1;
+           endRepeat = aState.mRowFunctions.mRepeatAutoEnd,
+           numRowLines = mGridRowEnd + 1;
          row < numRowLines; ++row) {
       if (numEmptyRows) {
         (*rowAdjust)[row] = numEmptyRows;
       }
       if (row < endRepeat && mCellMap.IsEmptyRow(row)) {
         ++numEmptyRows;
         if (rowAdjust.isNothing()) {
           rowAdjust.emplace(numRowLines);
@@ -2181,26 +2569,26 @@ nsGridContainerFrame::PlaceGridItems(Gri
           PodZero(rowAdjust->Elements(), rowAdjust->Length());
         }
       }
     }
   }
   // Remove the empty 'auto-fit' tracks we found above, if any.
   if (numEmptyCols || numEmptyRows) {
     // Adjust the line numbers in the grid areas.
-    for (auto& item : mGridItems) {
+    for (auto& item : aState.mGridItems) {
       GridArea& area = item.mArea;
       if (numEmptyCols) {
         area.mCols.AdjustForRemovedTracks(*colAdjust);
       }
       if (numEmptyRows) {
         area.mRows.AdjustForRemovedTracks(*rowAdjust);
       }
     }
-    for (auto& item : mAbsPosItems) {
+    for (auto& item : aState.mAbsPosItems) {
       GridArea& area = item.mArea;
       if (numEmptyCols) {
         area.mCols.AdjustAbsPosForRemovedTracks(*colAdjust);
       }
       if (numEmptyRows) {
         area.mRows.AdjustAbsPosForRemovedTracks(*rowAdjust);
       }
     }
@@ -2212,16 +2600,23 @@ nsGridContainerFrame::PlaceGridItems(Gri
     // Adjust the track mapping to unmap the removed tracks.
     auto finalColRepeatCount = aState.mColFunctions.NumRepeatTracks() - numEmptyCols;
     aState.mColFunctions.SetNumRepeatTracks(finalColRepeatCount);
     auto finalRowRepeatCount = aState.mRowFunctions.NumRepeatTracks() - numEmptyRows;
     aState.mRowFunctions.SetNumRepeatTracks(finalRowRepeatCount);
   }
 }
 
+static
+bool IsMinContent(const nsStyleCoord& aCoord)
+{
+  return aCoord.GetUnit() == eStyleUnit_Enumerated &&
+         aCoord.GetIntValue() == NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT;
+}
+
 void
 nsGridContainerFrame::TrackSize::Initialize(nscoord aPercentageBasis,
                                             const nsStyleCoord& aMinCoord,
                                             const nsStyleCoord& aMaxCoord)
 {
   MOZ_ASSERT(mBase == 0 && mLimit == 0 && mState == 0,
              "track size data is expected to be initialized to zero");
   // http://dev.w3.org/csswg/css-grid/#algo-init
@@ -2419,38 +2814,16 @@ nsGridContainerFrame::Tracks::CalculateS
     if (freeSpace != NS_UNCONSTRAINEDSIZE) {
       freeSpace -= SumOfGridGaps();
     }
     DistributeFreeSpace(freeSpace);
     StretchFlexibleTracks(aState, aGridItems, aFunctions, freeSpace);
   }
 }
 
-void
-nsGridContainerFrame::CalculateTrackSizes(GridReflowState&   aState,
-                                          const LogicalSize& aContentBox,
-                                          IntrinsicISizeType aConstraint)
-{
-  const WritingMode& wm = aState.mWM;
-  const nsStylePosition* stylePos = aState.mGridStyle;
-  aState.mCols.Initialize(aState.mColFunctions, stylePos->mGridColumnGap,
-                          mGridColEnd, aContentBox.ISize(wm));
-  aState.mRows.Initialize(aState.mRowFunctions, stylePos->mGridRowGap,
-                          mGridRowEnd, aContentBox.BSize(wm));
-
-  aState.mCols.CalculateSizes(aState, mGridItems, aState.mColFunctions,
-                              aContentBox.ISize(wm), &GridArea::mCols,
-                              aConstraint);
-
-  aState.mIter.Reset(); // XXX cleanup this Reset mess!
-  aState.mRows.CalculateSizes(aState, mGridItems, aState.mRowFunctions,
-                              aContentBox.BSize(wm), &GridArea::mRows,
-                              aConstraint);
-}
-
 bool
 nsGridContainerFrame::Tracks::HasIntrinsicButNoFlexSizingInRange(
   const LineRange&      aRange,
   IntrinsicISizeType    aConstraint,
   TrackSize::StateBits* aState) const
 {
   MOZ_ASSERT(!aRange.IsAuto(), "must have a definite range");
   const uint32_t start = aRange.mStart;
@@ -3113,43 +3486,41 @@ nsGridContainerFrame::LineRange::ToPosit
       nscoord pos;
       ToPositionAndLength(aTracks.mSizes, &pos, aLength);
       *aPos = aGridOrigin + pos;
     }
   }
 }
 
 LogicalRect
-nsGridContainerFrame::ContainingBlockFor(const GridReflowState& aState,
-                                         const GridArea&        aArea) const
+nsGridContainerFrame::GridReflowState::ContainingBlockFor(const GridArea& aArea) const
 {
   nscoord i, b, iSize, bSize;
   MOZ_ASSERT(aArea.mCols.Extent() > 0, "grid items cover at least one track");
   MOZ_ASSERT(aArea.mRows.Extent() > 0, "grid items cover at least one track");
-  aArea.mCols.ToPositionAndLength(aState.mCols.mSizes, &i, &iSize);
-  aArea.mRows.ToPositionAndLength(aState.mRows.mSizes, &b, &bSize);
-  return LogicalRect(aState.mWM, i, b, iSize, bSize);
+  aArea.mCols.ToPositionAndLength(mCols.mSizes, &i, &iSize);
+  aArea.mRows.ToPositionAndLength(mRows.mSizes, &b, &bSize);
+  return LogicalRect(mWM, i, b, iSize, bSize);
 }
 
 LogicalRect
-nsGridContainerFrame::ContainingBlockForAbsPos(const GridReflowState& aState,
-                                               const GridArea&        aArea,
-                                               const LogicalPoint& aGridOrigin,
-                                               const LogicalRect& aGridCB) const
+nsGridContainerFrame::GridReflowState::ContainingBlockForAbsPos(
+  const GridArea&     aArea,
+  const LogicalPoint& aGridOrigin,
+  const LogicalRect&  aGridCB) const
 {
-  const WritingMode& wm = aState.mWM;
-  nscoord i = aGridCB.IStart(wm);
-  nscoord b = aGridCB.BStart(wm);
-  nscoord iSize = aGridCB.ISize(wm);
-  nscoord bSize = aGridCB.BSize(wm);
-  aArea.mCols.ToPositionAndLengthForAbsPos(aState.mCols, aGridOrigin.I(wm),
+  nscoord i = aGridCB.IStart(mWM);
+  nscoord b = aGridCB.BStart(mWM);
+  nscoord iSize = aGridCB.ISize(mWM);
+  nscoord bSize = aGridCB.BSize(mWM);
+  aArea.mCols.ToPositionAndLengthForAbsPos(mCols, aGridOrigin.I(mWM),
                                            &i, &iSize);
-  aArea.mRows.ToPositionAndLengthForAbsPos(aState.mRows, aGridOrigin.B(wm),
+  aArea.mRows.ToPositionAndLengthForAbsPos(mRows, aGridOrigin.B(mWM),
                                            &b, &bSize);
-  return LogicalRect(wm, i, b, iSize, bSize);
+  return LogicalRect(mWM, i, b, iSize, bSize);
 }
 
 void
 nsGridContainerFrame::ReflowChildren(GridReflowState&     aState,
                                      const LogicalRect&   aContentArea,
                                      nsHTMLReflowMetrics& aDesiredSize,
                                      nsReflowStatus&      aStatus)
 {
@@ -3164,21 +3535,21 @@ nsGridContainerFrame::ReflowChildren(Gri
   nsStyleContext* containerSC = StyleContext();
   LogicalMargin pad(aState.mReflowState->ComputedLogicalPadding());
   const LogicalPoint padStart(wm, pad.IStart(wm), pad.BStart(wm));
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
     nsIFrame* child = *aState.mIter;
     const bool isGridItem = child->GetType() != nsGkAtoms::placeholderFrame;
     LogicalRect cb(wm);
     if (MOZ_LIKELY(isGridItem)) {
-      MOZ_ASSERT(mGridItems[aState.mIter.GridItemIndex()].mFrame == child,
+      MOZ_ASSERT(aState.mGridItems[aState.mIter.GridItemIndex()].mFrame == child,
                  "iterator out of sync with mGridItems");
-      GridArea& area = mGridItems[aState.mIter.GridItemIndex()].mArea;
+      GridArea& area = aState.mGridItems[aState.mIter.GridItemIndex()].mArea;
       MOZ_ASSERT(area.IsDefinite());
-      cb = ContainingBlockFor(aState, area);
+      cb = aState.ContainingBlockFor(area);
       cb += gridOrigin;
     } else {
       cb = aContentArea;
     }
     WritingMode childWM = child->GetWritingMode();
     LogicalSize childCBSize = cb.Size(wm).ConvertTo(childWM, wm);
     LogicalSize percentBasis(childCBSize);
     // XXX temporary workaround to avoid being INCOMPLETE until we have
@@ -3248,21 +3619,21 @@ nsGridContainerFrame::ReflowChildren(Gri
       // with respect to the grid container's padding-box (CB).
       const LogicalRect gridCB(wm, 0, 0,
                                aContentArea.ISize(wm) + pad.IStartEnd(wm),
                                aContentArea.BSize(wm) + pad.BStartEnd(wm));
       const nsSize gridCBPhysicalSize = gridCB.Size(wm).GetPhysicalSize(wm);
       size_t i = 0;
       for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next(), ++i) {
         nsIFrame* child = e.get();
-        MOZ_ASSERT(i < mAbsPosItems.Length());
-        MOZ_ASSERT(mAbsPosItems[i].mFrame == child);
-        GridArea& area = mAbsPosItems[i].mArea;
+        MOZ_ASSERT(i < aState.mAbsPosItems.Length());
+        MOZ_ASSERT(aState.mAbsPosItems[i].mFrame == child);
+        GridArea& area = aState.mAbsPosItems[i].mArea;
         LogicalRect itemCB =
-          ContainingBlockForAbsPos(aState, area, padStart, gridCB);
+          aState.ContainingBlockForAbsPos(area, padStart, gridCB);
         // nsAbsoluteContainingBlock::Reflow uses physical coordinates.
         nsRect* cb = static_cast<nsRect*>(child->Properties().Get(
                        GridItemContainingBlockRect()));
         if (!cb) {
           cb = new nsRect;
           child->Properties().Set(GridItemContainingBlockRect(), cb);
         }
         *cb = itemCB.GetPhysicalRect(wm, gridCBPhysicalSize);
@@ -3321,23 +3692,23 @@ nsGridContainerFrame::Reflow(nsPresConte
        cbState->ComputedSize(wm).ISize(wm) == NS_UNCONSTRAINEDSIZE)) {
     computedMinSize.ISize(wm) = NS_UNCONSTRAINEDSIZE;
   }
   if (!stylePos->MinBSize(wm).IsCoordPercentCalcUnit() ||
       (stylePos->MinBSize(wm).HasPercent() && cbState &&
        cbState->ComputedSize(wm).BSize(wm) == NS_UNCONSTRAINEDSIZE)) {
     computedMinSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
   }
-
-  PlaceGridItems(gridReflowState, computedMinSize, computedSize,
-                 aReflowState.ComputedMaxSize());
+  Grid grid;
+  grid.PlaceGridItems(gridReflowState, computedMinSize, computedSize,
+                      aReflowState.ComputedMaxSize());
 
   gridReflowState.mIter.Reset();
-  CalculateTrackSizes(gridReflowState, computedSize,
-                      nsLayoutUtils::PREF_ISIZE);
+  gridReflowState.CalculateTrackSizes(grid, computedSize,
+                                      nsLayoutUtils::PREF_ISIZE);
 
   // FIXME bug 1229180: Instead of doing this on every reflow, we should only
   // set these properties if they are needed.
   nsTArray<nscoord> colTrackSizes(gridReflowState.mCols.mSizes.Length());
   for (const TrackSize& sz : gridReflowState.mCols.mSizes) {
     colTrackSizes.AppendElement(sz.mBase);
   }
   ComputedGridTrackInfo* colInfo = new ComputedGridTrackInfo(
@@ -3353,17 +3724,18 @@ nsGridContainerFrame::Reflow(nsPresConte
   ComputedGridTrackInfo* rowInfo = new ComputedGridTrackInfo(
     gridReflowState.mRowFunctions.mExplicitGridOffset,
     gridReflowState.mRowFunctions.NumExplicitTracks(),
     Move(rowTrackSizes));
   Properties().Set(GridRowTrackInfo(), rowInfo);
   
   nscoord bSize = 0;
   if (computedBSize == NS_AUTOHEIGHT) {
-    for (uint32_t i = 0; i < mGridRowEnd; ++i) {
+    const uint32_t numRows = gridReflowState.mRows.mSizes.Length();
+    for (uint32_t i = 0; i < numRows; ++i) {
       bSize += gridReflowState.mRows.mSizes[i].mBase;
     }
     bSize += gridReflowState.mRows.SumOfGridGaps();
     bSize = NS_CSS_MINMAX(bSize,
                           aReflowState.ComputedMinBSize(),
                           aReflowState.ComputedMaxBSize());
   } else {
     bSize = computedBSize;
@@ -3393,24 +3765,25 @@ nscoord
 nsGridContainerFrame::IntrinsicISize(nsRenderingContext* aRenderingContext,
                                      IntrinsicISizeType  aConstraint)
 {
   // Calculate the sum of column sizes under aConstraint.
   // http://dev.w3.org/csswg/css-grid/#intrinsic-sizes
   GridReflowState state(this, *aRenderingContext);
   InitImplicitNamedAreas(state.mGridStyle); // XXX optimize
   LogicalSize indefinite(state.mWM, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
-  PlaceGridItems(state, indefinite, indefinite, indefinite);  // XXX optimize
-  if (mGridColEnd == 0) {
+  Grid grid;
+  grid.PlaceGridItems(state, indefinite, indefinite, indefinite);  // XXX optimize
+  if (grid.mGridColEnd == 0) {
     return 0;
   }
   state.mCols.Initialize(state.mColFunctions, state.mGridStyle->mGridColumnGap,
-                         mGridColEnd, NS_UNCONSTRAINEDSIZE);
+                         grid.mGridColEnd, NS_UNCONSTRAINEDSIZE);
   state.mIter.Reset();
-  state.mCols.CalculateSizes(state, mGridItems, state.mColFunctions,
+  state.mCols.CalculateSizes(state, state.mGridItems, state.mColFunctions,
                              NS_UNCONSTRAINEDSIZE, &GridArea::mCols,
                              aConstraint);
   nscoord length = 0;
   for (const TrackSize& sz : state.mCols.mSizes) {
     length += sz.mBase;
   }
   return length + state.mCols.SumOfGridGaps();
 }
@@ -3485,63 +3858,17 @@ nsGridContainerFrame::BuildDisplayList(n
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsGridContainerFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("GridContainer"), aResult);
 }
 #endif
 
-void
-nsGridContainerFrame::CellMap::Fill(const GridArea& aGridArea)
-{
-  MOZ_ASSERT(aGridArea.IsDefinite());
-  MOZ_ASSERT(aGridArea.mRows.mStart < aGridArea.mRows.mEnd);
-  MOZ_ASSERT(aGridArea.mCols.mStart < aGridArea.mCols.mEnd);
-  const auto numRows = aGridArea.mRows.mEnd;
-  const auto numCols = aGridArea.mCols.mEnd;
-  mCells.EnsureLengthAtLeast(numRows);
-  for (auto i = aGridArea.mRows.mStart; i < numRows; ++i) {
-    nsTArray<Cell>& cellsInRow = mCells[i];
-    cellsInRow.EnsureLengthAtLeast(numCols);
-    for (auto j = aGridArea.mCols.mStart; j < numCols; ++j) {
-      cellsInRow[j].mIsOccupied = true;
-    }
-  }
-}
-
-void
-nsGridContainerFrame::CellMap::ClearOccupied()
-{
-  const size_t numRows = mCells.Length();
-  for (size_t i = 0; i < numRows; ++i) {
-    nsTArray<Cell>& cellsInRow = mCells[i];
-    const size_t numCols = cellsInRow.Length();
-    for (size_t j = 0; j < numCols; ++j) {
-      cellsInRow[j].mIsOccupied = false;
-    }
-  }
-}
-
 #ifdef DEBUG
-void
-nsGridContainerFrame::CellMap::Dump() const
-{
-  const size_t numRows = mCells.Length();
-  for (size_t i = 0; i < numRows; ++i) {
-    const nsTArray<Cell>& cellsInRow = mCells[i];
-    const size_t numCols = cellsInRow.Length();
-    printf("%lu:\t", (unsigned long)i + 1);
-    for (size_t j = 0; j < numCols; ++j) {
-      printf(cellsInRow[j].mIsOccupied ? "X " : ". ");
-    }
-    printf("\n");
-  }
-}
-
 static bool
 FrameWantsToBeInAnonymousGridItem(nsIFrame* aFrame)
 {
   // Note: This needs to match the logic in
   // nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem()
   return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
 }
 
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -125,16 +125,17 @@ protected:
   static const uint32_t kTranslatedMaxLine;
   typedef mozilla::LogicalPoint LogicalPoint;
   typedef mozilla::LogicalRect LogicalRect;
   typedef mozilla::LogicalSize LogicalSize;
   typedef mozilla::WritingMode WritingMode;
   typedef mozilla::css::GridNamedArea GridNamedArea;
   typedef nsLayoutUtils::IntrinsicISizeType IntrinsicISizeType;
   class GridItemCSSOrderIterator;
+  struct Grid;
   struct TrackSizingFunctions;
   struct Tracks;
   struct GridReflowState;
   class LineNameMap;
   friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
                                                     nsStyleContext* aContext);
   explicit nsGridContainerFrame(nsStyleContext* aContext)
     : nsContainerFrame(aContext)
@@ -323,58 +324,16 @@ protected:
   struct GridArea {
     GridArea(const LineRange& aCols, const LineRange& aRows)
       : mCols(aCols), mRows(aRows) {}
     bool IsDefinite() const { return mCols.IsDefinite() && mRows.IsDefinite(); }
     LineRange mCols;
     LineRange mRows;
   };
 
-  /**
-   * A CellMap holds state for each cell in the grid.
-   * It's row major.  It's sparse in the sense that it only has enough rows to
-   * cover the last row that has a grid item.  Each row only has enough entries
-   * to cover columns that are occupied *on that row*, i.e. it's not a full
-   * matrix covering the entire implicit grid.  An absent Cell means that it's
-   * unoccupied by any grid item.
-   */
-  struct CellMap {
-    struct Cell {
-      Cell() : mIsOccupied(false) {}
-      bool mIsOccupied : 1;
-    };
-    void Fill(const GridArea& aGridArea);
-    void ClearOccupied();
-    uint32_t IsEmptyCol(uint32_t aCol) const
-    {
-      for (auto& row : mCells) {
-        if (aCol < row.Length() && row[aCol].mIsOccupied) {
-          return false;
-        }
-      }
-      return true;
-    }
-    uint32_t IsEmptyRow(uint32_t aRow) const
-    {
-      if (aRow >= mCells.Length()) {
-        return true;
-      }
-      for (const Cell& cell : mCells[aRow]) {
-        if (cell.mIsOccupied) {
-          return false;
-        }
-      }
-      return true;
-    }
-#if DEBUG
-    void Dump() const;
-#endif
-    nsTArray<nsTArray<Cell>> mCells;
-  };
-
   struct GridItemInfo {
     explicit GridItemInfo(const GridArea& aArea)
       : mArea(aArea)
     {
       mIsFlexing[0] = false;
       mIsFlexing[1] = false;
     }
 
@@ -382,256 +341,30 @@ protected:
     bool mIsFlexing[2]; // does the item span a flex track? (LogicalAxis index)
     static_assert(mozilla::eLogicalAxisBlock == 0, "unexpected index value");
     static_assert(mozilla::eLogicalAxisInline == 1, "unexpected index value");
 #ifdef DEBUG
     nsIFrame* mFrame;
 #endif
   };
 
-  enum LineRangeSide {
-    eLineRangeSideStart, eLineRangeSideEnd
-  };
-  /**
-   * Return a line number for (non-auto) aLine, per:
-   * http://dev.w3.org/csswg/css-grid/#line-placement
-   * @param aLine style data for the line (must be non-auto)
-   * @param aNth a number of lines to find from aFromIndex, negative if the
-   *             search should be in reverse order.  In the case aLine has
-   *             a specified line name, it's permitted to pass in zero which
-   *             will be treated as one.
-   * @param aFromIndex the zero-based index to start counting from
-   * @param aNameMap for looking up explicit named lines
-   * @param aAreaStart a pointer to GridNamedArea::mColumnStart/mRowStart
-   * @param aAreaEnd a pointer to GridNamedArea::mColumnEnd/mRowEnd
-   * @param aExplicitGridEnd the last line in the explicit grid
-   * @param aEdge indicates whether we are resolving a start or end line
-   * @param aStyle the StylePosition() for the grid container
-   * @return a definite line (1-based), clamped to the kMinLine..kMaxLine range
-   */
-  int32_t ResolveLine(const nsStyleGridLine& aLine,
-                      int32_t aNth,
-                      uint32_t aFromIndex,
-                      const LineNameMap& aNameMap,
-                      uint32_t GridNamedArea::* aAreaStart,
-                      uint32_t GridNamedArea::* aAreaEnd,
-                      uint32_t aExplicitGridEnd,
-                      LineRangeSide aEdge,
-                      const nsStylePosition* aStyle);
-  /**
-   * Return a LineRange based on the given style data. Non-auto lines
-   * are resolved to a definite line number (1-based) per:
-   * http://dev.w3.org/csswg/css-grid/#line-placement
-   * with placement errors corrected per:
-   * http://dev.w3.org/csswg/css-grid/#grid-placement-errors
-   * @param aStyle the StylePosition() for the grid container
-   * @param aStart style data for the start line
-   * @param aEnd style data for the end line
-   * @param aNameMap for looking up explicit named lines
-   * @param aAreaStart a pointer to GridNamedArea::mColumnStart/mRowStart
-   * @param aAreaEnd a pointer to GridNamedArea::mColumnEnd/mRowEnd
-   * @param aExplicitGridEnd the last line in the explicit grid
-   * @param aStyle the StylePosition() for the grid container
-   */
-  LineRange ResolveLineRange(const nsStyleGridLine& aStart,
-                             const nsStyleGridLine& aEnd,
-                             const LineNameMap& aNameMap,
-                             uint32_t GridNamedArea::* aAreaStart,
-                             uint32_t GridNamedArea::* aAreaEnd,
-                             uint32_t aExplicitGridEnd,
-                             const nsStylePosition* aStyle);
-
-  /**
-   * As above but for an abs.pos. child.  Any 'auto' lines will be represented
-   * by kAutoLine in the LineRange result.
-   * @param aGridStart the first line in the final, but untranslated grid
-   * @param aGridEnd the last line in the final, but untranslated grid
-   */
-  LineRange
-  ResolveAbsPosLineRange(const nsStyleGridLine& aStart,
-                         const nsStyleGridLine& aEnd,
-                         const LineNameMap& aNameMap,
-                         uint32_t GridNamedArea::* aAreaStart,
-                         uint32_t GridNamedArea::* aAreaEnd,
-                         uint32_t aExplicitGridEnd,
-                         int32_t aGridStart,
-                         int32_t aGridEnd,
-                         const nsStylePosition* aStyle);
-
-  /**
-   * Return a GridArea with non-auto lines placed at a definite line (1-based)
-   * with placement errors resolved.  One or both positions may still
-   * be 'auto'.
-   * @param aChild the grid item
-   * @param aColLineNameMap for looking up explicit named column lines
-   * @param aRowLineNameMap for looking up explicit named row lines
-   * @param aStyle the StylePosition() for the grid container
-   */
-  GridArea PlaceDefinite(nsIFrame* aChild,
-                         const LineNameMap& aColLineNameMap,
-                         const LineNameMap& aRowLineNameMap,
-                         const nsStylePosition* aStyle);
-
-  /**
-   * Place aArea in the first column (in row aArea->mRows.mStart) starting at
-   * aStartCol without overlapping other items.  The resulting aArea may
-   * overflow the current implicit grid bounds.
-   * Pre-condition: aArea->mRows.IsDefinite() is true.
-   * Post-condition: aArea->IsDefinite() is true.
-   */
-  void PlaceAutoCol(uint32_t aStartCol, GridArea* aArea) const;
-
-  /**
-   * Find the first column in row aLockedRow starting at aStartCol where aArea
-   * could be placed without overlapping other items.  The returned column may
-   * cause aArea to overflow the current implicit grid bounds if placed there.
-   */
-  uint32_t FindAutoCol(uint32_t aStartCol, uint32_t aLockedRow,
-                       const GridArea* aArea) const;
-
-  /**
-   * Place aArea in the first row (in column aArea->mCols.mStart) starting at
-   * aStartRow without overlapping other items. The resulting aArea may
-   * overflow the current implicit grid bounds.
-   * Pre-condition: aArea->mCols.IsDefinite() is true.
-   * Post-condition: aArea->IsDefinite() is true.
-   */
-  void PlaceAutoRow(uint32_t aStartRow, GridArea* aArea) const;
-
-  /**
-   * Find the first row in column aLockedCol starting at aStartRow where aArea
-   * could be placed without overlapping other items.  The returned row may
-   * cause aArea to overflow the current implicit grid bounds if placed there.
-   */
-  uint32_t FindAutoRow(uint32_t aLockedCol, uint32_t aStartRow,
-                       const GridArea* aArea) const;
-
-  /**
-   * Place aArea in the first column starting at aStartCol,aStartRow without
-   * causing it to overlap other items or overflow mGridColEnd.
-   * If there's no such column in aStartRow, continue in position 1,aStartRow+1.
-   * Pre-condition: aArea->mCols.IsAuto() && aArea->mRows.IsAuto() is true.
-   * Post-condition: aArea->IsDefinite() is true.
-   */
-  void PlaceAutoAutoInRowOrder(uint32_t aStartCol, uint32_t aStartRow,
-                               GridArea* aArea) const;
-
-  /**
-   * Place aArea in the first row starting at aStartCol,aStartRow without
-   * causing it to overlap other items or overflow mGridRowEnd.
-   * If there's no such row in aStartCol, continue in position aStartCol+1,1.
-   * Pre-condition: aArea->mCols.IsAuto() && aArea->mRows.IsAuto() is true.
-   * Post-condition: aArea->IsDefinite() is true.
-   */
-  void PlaceAutoAutoInColOrder(uint32_t aStartCol, uint32_t aStartRow,
-                               GridArea* aArea) const;
-
-  /**
-   * Return a GridArea for abs.pos. item with non-auto lines placed at
-   * a definite line (1-based) with placement errors resolved.  One or both
-   * positions may still be 'auto'.
-   * @param aChild the abs.pos. grid item to place
-   * @param aColLineNameMap for looking up explicit named column lines
-   * @param aRowLineNameMap for looking up explicit named row lines
-   * @param aStyle the StylePosition() for the grid container
-   */
-  GridArea PlaceAbsPos(nsIFrame* aChild,
-                       const LineNameMap& aColLineNameMap,
-                       const LineNameMap& aRowLineNameMap,
-                       const nsStylePosition* aStyle);
-
-  /**
-   * Place all child frames into the grid and expand the (implicit) grid as
-   * needed.  The allocated GridAreas are stored in the GridAreaProperty
-   * frame property on the child frame.
-   * @param aComputedMinSize the container's min-size - used to determine
-   *   the number of repeat(auto-fill/fit) tracks.
-   * @param aComputedSize the container's size - used to determine
-   *   the number of repeat(auto-fill/fit) tracks.
-   * @param aComputedMaxSize the container's max-size - used to determine
-   *   the number of repeat(auto-fill/fit) tracks.
-   */
-  void PlaceGridItems(GridReflowState&   aState,
-                      const LogicalSize& aComputedMinSize,
-                      const LogicalSize& aComputedSize,
-                      const LogicalSize& aComputedMaxSize);
-  // Helper for the above.
-  void PlaceGridItems(GridReflowState&   aState,
-                      const LineNameMap& aColLineNameMap,
-                      const LineNameMap& aRowLineNameMap);
-
-  /**
-   * Inflate the implicit grid to include aArea.
-   * @param aArea may be definite or auto
-   */
-  void InflateGridFor(const GridArea& aArea)
-  {
-    mGridColEnd = std::max(mGridColEnd, aArea.mCols.HypotheticalEnd());
-    mGridRowEnd = std::max(mGridRowEnd, aArea.mRows.HypotheticalEnd());
-    MOZ_ASSERT(mGridColEnd <= kTranslatedMaxLine &&
-               mGridRowEnd <= kTranslatedMaxLine);
-  }
-
-  /**
-   * Calculate track sizes.
-   */
-  void CalculateTrackSizes(GridReflowState&            aState,
-                           const mozilla::LogicalSize& aContentBox,
-                           IntrinsicISizeType          aConstraint);
-
-  /**
-   * Helper method for ResolveLineRange.
-   * @see ResolveLineRange
-   * @return a pair (start,end) of lines
-   */
-  typedef std::pair<int32_t, int32_t> LinePair;
-  LinePair ResolveLineRangeHelper(const nsStyleGridLine& aStart,
-                                  const nsStyleGridLine& aEnd,
-                                  const LineNameMap& aNameMap,
-                                  uint32_t GridNamedArea::* aAreaStart,
-                                  uint32_t GridNamedArea::* aAreaEnd,
-                                  uint32_t aExplicitGridEnd,
-                                  const nsStylePosition* aStyle);
-
   /**
    * XXX temporary - move the ImplicitNamedAreas stuff to the style system.
    * The implicit area names that come from x-start .. x-end lines in
    * grid-template-columns / grid-template-rows are stored in this frame
    * property when needed, as a ImplicitNamedAreas* value.
    */
   typedef nsTHashtable<nsStringHashKey> ImplicitNamedAreas;
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ImplicitNamedAreasProperty,
                                       ImplicitNamedAreas)
   void InitImplicitNamedAreas(const nsStylePosition* aStyle);
   void AddImplicitNamedAreas(const nsTArray<nsTArray<nsString>>& aLineNameLists);
   ImplicitNamedAreas* GetImplicitNamedAreas() const {
     return Properties().Get(ImplicitNamedAreasProperty());
   }
-  bool HasImplicitNamedArea(const nsString& aName) const {
-    ImplicitNamedAreas* areas = GetImplicitNamedAreas();
-    return areas && areas->Contains(aName);
-  }
-
-  /**
-   * Return the containing block for a grid item occupying aArea.
-   */
-  LogicalRect ContainingBlockFor(const GridReflowState& aState,
-                                 const GridArea&        aArea) const;
-
-  /**
-   * Return the containing block for an abs.pos. grid item occupying aArea.
-   * Any 'auto' lines in the grid area will be aligned with grid container
-   * containing block on that side.
-   * @param aGridOrigin the origin of the grid
-   * @param aGridCB the grid container containing block (its padding area)
-   */
-  LogicalRect ContainingBlockForAbsPos(const GridReflowState& aState,
-                                       const GridArea&        aArea,
-                                       const LogicalPoint&    aGridOrigin,
-                                       const LogicalRect&     aGridCB) const;
 
   /**
    * Reflow and place our children.
    */
   void ReflowChildren(GridReflowState&     aState,
                       const LogicalRect&   aContentArea,
                       nsHTMLReflowMetrics& aDesiredSize,
                       nsReflowStatus&      aStatus);
@@ -643,56 +376,16 @@ protected:
                          IntrinsicISizeType  aConstraint);
 
 #ifdef DEBUG
   void SanityCheckAnonymousGridItems() const;
 #endif // DEBUG
 
 private:
   /**
-   * Info about each (normal flow) grid item.
-   */
-  nsTArray<GridItemInfo> mGridItems;
-
-  /**
-   * Info about each grid-aligned abs.pos. child.
-   */
-  nsTArray<GridItemInfo> mAbsPosItems;
-
-  /**
-   * State for each cell in the grid.
-   */
-  CellMap mCellMap;
-
-  /**
-   * The last column grid line (1-based) in the explicit grid.
-   * (i.e. the number of explicit columns + 1)
-   */
-  uint32_t mExplicitGridColEnd;
-  /**
-   * The last row grid line (1-based) in the explicit grid.
-   * (i.e. the number of explicit rows + 1)
-   */
-  uint32_t mExplicitGridRowEnd;
-  // Same for the implicit grid, except these become zero-based after
-  // resolving definite lines.
-  uint32_t mGridColEnd;
-  uint32_t mGridRowEnd;
-
-  /**
-   * Offsets from the start of the implicit grid to the start of the translated
-   * explicit grid.  They are zero if there are no implicit lines before 1,1.
-   * e.g. "grid-column: span 3 / 1" makes mExplicitGridOffsetCol = 3 and the
-   * corresponding GridArea::mCols will be 0 / 3 in the zero-based translated
-   * grid.
-   */
-  uint32_t mExplicitGridOffsetCol;
-  uint32_t mExplicitGridOffsetRow;
-
-  /**
    * Cached values to optimize GetMinISize/GetPrefISize.
    */
   nscoord mCachedMinISize;
   nscoord mCachedPrefISize;
 
   /**
    * True iff the normal flow children are already in CSS 'order' in the
    * order they occur in the child frame list.