Bug 1388255 - Make nsStylePosition::mGridTemplate{Columns,Rows} a UniquePtr. r?dholbert,canaltinova draft
authorXidorn Quan <me@upsuper.org>
Wed, 09 Aug 2017 11:30:25 +1000
changeset 643645 38a49c5392f3e49f75df80d5f692bba5d411225d
parent 642999 83ce8e9879697925fcac4796dad5b17dc22db301
child 725362 ef80dd9d9897eb209fc831aca8855e63629fe2f3
push id73165
push userxquan@mozilla.com
push dateThu, 10 Aug 2017 00:21:02 +0000
reviewersdholbert, canaltinova
bugs1388255
milestone57.0a1
Bug 1388255 - Make nsStylePosition::mGridTemplate{Columns,Rows} a UniquePtr. r?dholbert,canaltinova MozReview-Commit-ID: 8SOE6sAavCX
js/src/devtools/rootAnalysis/analyzeHeapWrites.js
layout/generic/nsGridContainerFrame.cpp
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoBindings.toml
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
servo/components/style/properties/gecko.mako.rs
--- a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
+++ b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
@@ -177,18 +177,17 @@ function treatAsSafeArgument(entry, varN
         ["Gecko_DestroyClipPath", "aClip", null],
         ["Gecko_ResetFilters", "effects", null],
         ["Gecko_CopyFiltersFrom", "aDest", null],
         [/Gecko_CSSValue_Set/, "aCSSValue", null],
         ["Gecko_CSSValue_Drop", "aCSSValue", null],
         ["Gecko_CSSFontFaceRule_GetCssText", "aResult", null],
         ["Gecko_EnsureTArrayCapacity", "aArray", null],
         ["Gecko_ClearPODTArray", "aArray", null],
-        ["Gecko_SetStyleGridTemplateArrayLengths", "aValue", null],
-        ["Gecko_SetGridTemplateLineNamesLength", "aValue", null],
+        ["Gecko_SetStyleGridTemplate", "aGridTemplate", null],
         ["Gecko_ResizeTArrayForStrings", "aArray", null],
         ["Gecko_ClearAndResizeStyleContents", "aContent", null],
         [/Gecko_ClearAndResizeCounter/, "aContent", null],
         [/Gecko_CopyCounter.*?From/, "aContent", null],
         [/Gecko_SetContentDataImageValue/, "aList", null],
         [/Gecko_SetContentData/, "aContent", null],
         ["Gecko_SetCounterFunction", "aContent", null],
         [/Gecko_EnsureStyle.*?ArrayLength/, "aArray", null],
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -1925,20 +1925,20 @@ private:
                   gfxContext&              aRenderingContext,
                   const ReflowInput* aReflowInput,
                   const nsStylePosition*   aGridStyle,
                   const WritingMode&       aWM)
     : mIter(aFrame, kPrincipalList)
     , mGridStyle(aGridStyle)
     , mCols(eLogicalAxisInline)
     , mRows(eLogicalAxisBlock)
-    , mColFunctions(mGridStyle->mGridTemplateColumns,
+    , mColFunctions(mGridStyle->GridTemplateColumns(),
                     mGridStyle->mGridAutoColumnsMin,
                     mGridStyle->mGridAutoColumnsMax)
-    , mRowFunctions(mGridStyle->mGridTemplateRows,
+    , mRowFunctions(mGridStyle->GridTemplateRows(),
                     mGridStyle->mGridAutoRowsMin,
                     mGridStyle->mGridAutoRowsMax)
     , mReflowInput(aReflowInput)
     , mRenderingContext(aRenderingContext)
     , mFrame(aFrame)
     , mSharedGridData(nullptr)
     , mBorderPadding(aWM)
     , mFragBStart(0)
@@ -2615,18 +2615,18 @@ void
 nsGridContainerFrame::InitImplicitNamedAreas(const nsStylePosition* aStyle)
 {
   ImplicitNamedAreas* areas = GetImplicitNamedAreas();
   if (areas) {
     // Clear it, but reuse the hashtable itself for now.  We'll remove it
     // below if it isn't needed anymore.
     areas->Clear();
   }
-  AddImplicitNamedAreas(aStyle->mGridTemplateColumns.mLineNameLists);
-  AddImplicitNamedAreas(aStyle->mGridTemplateRows.mLineNameLists);
+  AddImplicitNamedAreas(aStyle->GridTemplateColumns().mLineNameLists);
+  AddImplicitNamedAreas(aStyle->GridTemplateRows().mLineNameLists);
   if (areas && areas->Count() == 0) {
     DeleteProperty(ImplicitNamedAreasProperty());
   }
 }
 
 int32_t
 nsGridContainerFrame::Grid::ResolveLine(const nsStyleGridLine& aLine,
                                         int32_t aNth,
@@ -3096,26 +3096,26 @@ nsGridContainerFrame::Grid::PlaceGridIte
   auto areas = gridStyle->mGridTemplateAreas.get();
   uint32_t numRepeatCols = aState.mColFunctions.InitRepeatTracks(
                              gridStyle->mGridColumnGap,
                              aComputedMinSize.ISize(aState.mWM),
                              aComputedSize.ISize(aState.mWM),
                              aComputedMaxSize.ISize(aState.mWM));
   mGridColEnd = mExplicitGridColEnd =
     aState.mColFunctions.ComputeExplicitGridEnd(areas ? areas->mNColumns + 1 : 1);
-  LineNameMap colLineNameMap(gridStyle->mGridTemplateColumns, numRepeatCols);
+  LineNameMap colLineNameMap(gridStyle->GridTemplateColumns(), numRepeatCols);
 
   uint32_t numRepeatRows = aState.mRowFunctions.InitRepeatTracks(
                              gridStyle->mGridRowGap,
                              aComputedMinSize.BSize(aState.mWM),
                              aComputedSize.BSize(aState.mWM),
                              aComputedMaxSize.BSize(aState.mWM));
   mGridRowEnd = mExplicitGridRowEnd =
     aState.mRowFunctions.ComputeExplicitGridEnd(areas ? areas->NRows() + 1 : 1);
-  LineNameMap rowLineNameMap(gridStyle->mGridTemplateRows, numRepeatRows);
+  LineNameMap rowLineNameMap(gridStyle->GridTemplateRows(), 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;
   aState.mGridItems.ClearAndRetainStorage();
   aState.mIter.Reset();
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
@@ -3298,17 +3298,17 @@ nsGridContainerFrame::Grid::PlaceGridIte
   }
 
   // Count empty 'auto-fit' tracks in the repeat() range.
   // |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 &&
+      !gridStyle->GridTemplateColumns().mIsAutoFill &&
       aState.mColFunctions.NumRepeatTracks() > 0) {
     for (uint32_t col = aState.mColFunctions.mRepeatAutoStart,
            endRepeat = aState.mColFunctions.mRepeatAutoEnd,
            numColLines = mGridColEnd + 1;
          col < numColLines; ++col) {
       if (numEmptyCols) {
         (*colAdjust)[col] = numEmptyCols;
       }
@@ -3325,17 +3325,17 @@ nsGridContainerFrame::Grid::PlaceGridIte
                    repeatIndex);
         aState.mColFunctions.mRemovedRepeatTracks[repeatIndex] = true;
       }
     }
   }
   Maybe<nsTArray<uint32_t>> rowAdjust;
   uint32_t numEmptyRows = 0;
   if (aState.mRowFunctions.mHasRepeatAuto &&
-      !gridStyle->mGridTemplateRows.mIsAutoFill &&
+      !gridStyle->GridTemplateRows().mIsAutoFill &&
       aState.mRowFunctions.NumRepeatTracks() > 0) {
     for (uint32_t row = aState.mRowFunctions.mRepeatAutoStart,
            endRepeat = aState.mRowFunctions.mRepeatAutoEnd,
            numRowLines = mGridRowEnd + 1;
          row < numRowLines; ++row) {
       if (numEmptyRows) {
         (*rowAdjust)[row] = numEmptyRows;
       }
@@ -6201,17 +6201,17 @@ nsGridContainerFrame::Reflow(nsPresConte
     // Generate the line info properties. We need to provide the number of
     // repeat tracks produced in the reflow. Only explicit names are assigned
     // to lines here; the mozilla::dom::GridLines class will later extract
     // implicit names from grid areas and assign them to the appropriate lines.
 
     // Generate column lines first.
     uint32_t capacity = gridReflowInput.mCols.mSizes.Length();
     const nsStyleGridTemplate& gridColTemplate =
-      gridReflowInput.mGridStyle->mGridTemplateColumns;
+      gridReflowInput.mGridStyle->GridTemplateColumns();
     nsTArray<nsTArray<nsString>> columnLineNames(capacity);
     for (col = 0; col <= gridReflowInput.mCols.mSizes.Length(); col++) {
       // Offset col by the explicit grid offset, to get the original names.
       nsTArray<nsString> explicitNames =
         gridReflowInput.mCols.GetExplicitLineNamesAtIndex(
           gridColTemplate,
           gridReflowInput.mColFunctions,
           col - gridReflowInput.mColFunctions.mExplicitGridOffset);
@@ -6222,17 +6222,17 @@ nsGridContainerFrame::Reflow(nsPresConte
       Move(columnLineNames),
       gridColTemplate.mRepeatAutoLineNameListBefore,
       gridColTemplate.mRepeatAutoLineNameListAfter);
     SetProperty(GridColumnLineInfo(), columnLineInfo);
 
     // Generate row lines next.
     capacity = gridReflowInput.mRows.mSizes.Length();
     const nsStyleGridTemplate& gridRowTemplate =
-      gridReflowInput.mGridStyle->mGridTemplateRows;
+      gridReflowInput.mGridStyle->GridTemplateRows();
     nsTArray<nsTArray<nsString>> rowLineNames(capacity);
     for (row = 0; row <= gridReflowInput.mRows.mSizes.Length(); row++) {
       // Offset row by the explicit grid offset, to get the original names.
       nsTArray<nsString> explicitNames =
         gridReflowInput.mRows.GetExplicitLineNamesAtIndex(
           gridRowTemplate,
           gridReflowInput.mRowFunctions,
           row - gridReflowInput.mRowFunctions.mExplicitGridOffset);
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1674,40 +1674,47 @@ Gecko_ClearPODTArray(void* aArray, size_
   auto base =
     reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
                                    nsTArray_CopyWithMemutils>*>(aArray);
 
   base->template ShiftData<nsTArrayInfallibleAllocator>(0, base->Length(), 0,
                                                         aElementSize, aElementAlign);
 }
 
-void Gecko_SetStyleGridTemplateArrayLengths(nsStyleGridTemplate* aValue,
-                                            uint32_t aTrackSizes)
-{
-  aValue->mMinTrackSizingFunctions.SetLength(aTrackSizes);
-  aValue->mMaxTrackSizingFunctions.SetLength(aTrackSizes);
-  aValue->mLineNameLists.SetLength(aTrackSizes + 1);
-}
-
-void Gecko_SetGridTemplateLineNamesLength(nsStyleGridTemplate* aValue,
-                                          uint32_t aNames)
-{
-  aValue->mLineNameLists.SetLength(aNames);
-}
-
 void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* aArray, uint32_t aLength)
 {
   aArray->SetLength(aLength);
 }
 
 void
-Gecko_CopyStyleGridTemplateValues(nsStyleGridTemplate* aGridTemplate,
+Gecko_SetStyleGridTemplate(UniquePtr<nsStyleGridTemplate>* aGridTemplate,
+                           nsStyleGridTemplate* aValue)
+{
+  aGridTemplate->reset(aValue);
+}
+
+nsStyleGridTemplate*
+Gecko_CreateStyleGridTemplate(uint32_t aTrackSizes, uint32_t aNameSize)
+{
+  nsStyleGridTemplate* result = new nsStyleGridTemplate;
+  result->mMinTrackSizingFunctions.SetLength(aTrackSizes);
+  result->mMaxTrackSizingFunctions.SetLength(aTrackSizes);
+  result->mLineNameLists.SetLength(aNameSize);
+  return result;
+}
+
+void
+Gecko_CopyStyleGridTemplateValues(UniquePtr<nsStyleGridTemplate>* aGridTemplate,
                                   const nsStyleGridTemplate* aOther)
 {
-  *aGridTemplate = *aOther;
+  if (aOther) {
+    *aGridTemplate = MakeUnique<nsStyleGridTemplate>(*aOther);
+  } else {
+    *aGridTemplate = nullptr;
+  }
 }
 
 mozilla::css::GridTemplateAreasValue*
 Gecko_NewGridTemplateAreasValue(uint32_t aAreas, uint32_t aTemplates, uint32_t aColumns)
 {
   RefPtr<mozilla::css::GridTemplateAreasValue> value = new mozilla::css::GridTemplateAreasValue;
   value->mNamedAreas.SetLength(aAreas);
   value->mTemplates.SetLength(aTemplates);
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -410,23 +410,23 @@ void Gecko_EnsureTArrayCapacity(void* ar
 // Same here, `array` must be an nsTArray<T>, for some T.
 //
 // Important note: Only valid for POD types, since destructors won't be run
 // otherwise. This is ensured with rust traits for the relevant structs.
 void Gecko_ClearPODTArray(void* array, size_t elem_size, size_t elem_align);
 
 void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* array, uint32_t length);
 
-void Gecko_SetStyleGridTemplateArrayLengths(nsStyleGridTemplate* grid_template,
-                                            uint32_t track_sizes);
+void Gecko_SetStyleGridTemplate(mozilla::UniquePtr<nsStyleGridTemplate>* grid_template,
+                                nsStyleGridTemplate* value);
 
-void Gecko_SetGridTemplateLineNamesLength(nsStyleGridTemplate* grid_template,
-                                          uint32_t track_sizes);
+nsStyleGridTemplate* Gecko_CreateStyleGridTemplate(uint32_t track_sizes,
+                                                   uint32_t name_size);
 
-void Gecko_CopyStyleGridTemplateValues(nsStyleGridTemplate* grid_template,
+void Gecko_CopyStyleGridTemplateValues(mozilla::UniquePtr<nsStyleGridTemplate>* grid_template,
                                        const nsStyleGridTemplate* other);
 
 mozilla::css::GridTemplateAreasValue* Gecko_NewGridTemplateAreasValue(uint32_t areas,
                                                                       uint32_t templates,
                                                                       uint32_t columns);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::GridTemplateAreasValue, GridTemplateAreasValue);
 
 // Clear the mContents, mCounterIncrements, or mCounterResets field in nsStyleContent. This is
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -363,16 +363,17 @@ whitelist-functions = ["Servo_.*", "Geck
 structs-types = [
     "mozilla::css::GridTemplateAreasValue",
     "mozilla::css::ErrorReporter",
     "mozilla::css::ImageValue",
     "mozilla::css::URLValue",
     "mozilla::css::URLValueData",
     "mozilla::MallocSizeOf",
     "mozilla::Side",
+    "mozilla::UniquePtr",
     "nsIContent",
     "nsIDocument",
     "nsIDocument_DocumentTheme",
     "RawGeckoAnimationPropertySegment",
     "RawGeckoComputedTiming",
     "RawGeckoCSSPropertyIDList",
     "RawGeckoDocument",
     "RawGeckoElement",
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -3103,33 +3103,34 @@ nsComputedDOMStyle::DoGetGridTemplateCol
   nsGridContainerFrame* gridFrame =
     nsGridContainerFrame::GetGridFrameWithComputedInfo(
       mContent->GetPrimaryFrame());
 
   if (gridFrame) {
     info = gridFrame->GetComputedTemplateColumns();
   }
 
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, info);
+  return GetGridTemplateColumnsRows(
+    StylePosition()->GridTemplateColumns(), info);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetGridTemplateRows()
 {
   const ComputedGridTrackInfo* info = nullptr;
 
   nsGridContainerFrame* gridFrame =
     nsGridContainerFrame::GetGridFrameWithComputedInfo(
       mContent->GetPrimaryFrame());
 
   if (gridFrame) {
     info = gridFrame->GetComputedTemplateRows();
   }
 
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, info);
+  return GetGridTemplateColumnsRows(StylePosition()->GridTemplateRows(), info);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine)
 {
   if (aGridLine.IsAuto()) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     val->SetIdent(eCSSKeyword_auto);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -8312,132 +8312,123 @@ AppendGridLineNames(const nsCSSValue& aV
       item->mValue.GetStringValue(*name);
       item = item->mNext;
     } while (item);
   }
 }
 
 static void
 SetGridTrackList(const nsCSSValue& aValue,
-                 nsStyleGridTemplate& aResult,
-                 const nsStyleGridTemplate& aParentValue,
+                 UniquePtr<nsStyleGridTemplate>& aResult,
+                 const nsStyleGridTemplate* aParentValue,
                  GeckoStyleContext* aStyleContext,
                  nsPresContext* aPresContext,
                  RuleNodeCacheConditions& aConditions)
 
 {
   switch (aValue.GetUnit()) {
   case eCSSUnit_Null:
     break;
 
   case eCSSUnit_Inherit:
     aConditions.SetUncacheable();
-    aResult = aParentValue;
+    if (aParentValue) {
+      aResult = MakeUnique<nsStyleGridTemplate>(*aParentValue);
+    } else {
+      aResult = nullptr;
+    }
     break;
 
   case eCSSUnit_Initial:
   case eCSSUnit_Unset:
   case eCSSUnit_None:
-    aResult.mIsSubgrid = false;
-    aResult.mLineNameLists.Clear();
-    aResult.mMinTrackSizingFunctions.Clear();
-    aResult.mMaxTrackSizingFunctions.Clear();
-    aResult.mRepeatAutoLineNameListBefore.Clear();
-    aResult.mRepeatAutoLineNameListAfter.Clear();
-    aResult.mRepeatAutoIndex = -1;
-    aResult.mIsAutoFill = false;
+    aResult = nullptr;
     break;
 
   default:
-    aResult.mLineNameLists.Clear();
-    aResult.mMinTrackSizingFunctions.Clear();
-    aResult.mMaxTrackSizingFunctions.Clear();
-    aResult.mRepeatAutoLineNameListBefore.Clear();
-    aResult.mRepeatAutoLineNameListAfter.Clear();
-    aResult.mRepeatAutoIndex = -1;
-    aResult.mIsAutoFill = false;
+    aResult = MakeUnique<nsStyleGridTemplate>();
     const nsCSSValueList* item = aValue.GetListValue();
     if (item->mValue.GetUnit() == eCSSUnit_Enumerated &&
         item->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) {
       // subgrid <line-name-list>?
-      aResult.mIsSubgrid = true;
+      aResult->mIsSubgrid = true;
       item = item->mNext;
       for (int32_t i = 0; item && i < nsStyleGridLine::kMaxLine; ++i) {
         if (item->mValue.GetUnit() == eCSSUnit_Pair) {
           // This is a 'auto-fill' <name-repeat> expression.
           const nsCSSValuePair& pair = item->mValue.GetPairValue();
-          MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
+          MOZ_ASSERT(aResult->mRepeatAutoIndex == -1,
                      "can only have one <name-repeat> with auto-fill");
-          aResult.mRepeatAutoIndex = i;
-          aResult.mIsAutoFill = true;
+          aResult->mRepeatAutoIndex = i;
+          aResult->mIsAutoFill = true;
           MOZ_ASSERT(pair.mXValue.GetIntValue() == NS_STYLE_GRID_REPEAT_AUTO_FILL,
                      "unexpected repeat() enum value for subgrid");
           const nsCSSValueList* list = pair.mYValue.GetListValue();
-          AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
+          AppendGridLineNames(list->mValue, aResult->mRepeatAutoLineNameListBefore);
         } else {
           AppendGridLineNames(item->mValue,
-                              *aResult.mLineNameLists.AppendElement());
+                              *aResult->mLineNameLists.AppendElement());
         }
         item = item->mNext;
       }
     } else {
       // <track-list>
       // The list is expected to have odd number of items, at least 3
       // starting with a <line-names> (sub list of identifiers),
       // and alternating between that and <track-size>.
-      aResult.mIsSubgrid = false;
+      aResult->mIsSubgrid = false;
       for (int32_t line = 1;  ; ++line) {
         AppendGridLineNames(item->mValue,
-                            *aResult.mLineNameLists.AppendElement());
+                            *aResult->mLineNameLists.AppendElement());
         item = item->mNext;
 
         if (!item || line == nsStyleGridLine::kMaxLine) {
           break;
         }
 
         if (item->mValue.GetUnit() == eCSSUnit_Pair) {
           // This is a 'auto-fill' / 'auto-fit' <auto-repeat> expression.
           const nsCSSValuePair& pair = item->mValue.GetPairValue();
-          MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
+          MOZ_ASSERT(aResult->mRepeatAutoIndex == -1,
                      "can only have one <auto-repeat>");
-          aResult.mRepeatAutoIndex = line - 1;
+          aResult->mRepeatAutoIndex = line - 1;
           switch (pair.mXValue.GetIntValue()) {
             case NS_STYLE_GRID_REPEAT_AUTO_FILL:
-              aResult.mIsAutoFill = true;
+              aResult->mIsAutoFill = true;
               break;
             case NS_STYLE_GRID_REPEAT_AUTO_FIT:
-              aResult.mIsAutoFill = false;
+              aResult->mIsAutoFill = false;
               break;
             default:
               MOZ_ASSERT_UNREACHABLE("unexpected repeat() enum value");
           }
           const nsCSSValueList* list = pair.mYValue.GetListValue();
-          AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
+          AppendGridLineNames(list->mValue, aResult->mRepeatAutoLineNameListBefore);
           list = list->mNext;
-          nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
-          nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
+          nsStyleCoord& min = *aResult->mMinTrackSizingFunctions.AppendElement();
+          nsStyleCoord& max = *aResult->mMaxTrackSizingFunctions.AppendElement();
           SetGridTrackSize(list->mValue, min, max,
                            aStyleContext, aPresContext, aConditions);
           list = list->mNext;
-          AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListAfter);
+          AppendGridLineNames(list->mValue, aResult->mRepeatAutoLineNameListAfter);
         } else {
-          nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
-          nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
+          nsStyleCoord& min = *aResult->mMinTrackSizingFunctions.AppendElement();
+          nsStyleCoord& max = *aResult->mMaxTrackSizingFunctions.AppendElement();
           SetGridTrackSize(item->mValue, min, max,
                            aStyleContext, aPresContext, aConditions);
         }
 
         item = item->mNext;
         MOZ_ASSERT(item, "Expected a eCSSUnit_List of odd length");
       }
-      MOZ_ASSERT(!aResult.mMinTrackSizingFunctions.IsEmpty() &&
-                 aResult.mMinTrackSizingFunctions.Length() ==
-                 aResult.mMaxTrackSizingFunctions.Length() &&
-                 aResult.mMinTrackSizingFunctions.Length() + 1 ==
-                 aResult.mLineNameLists.Length(),
+      MOZ_ASSERT(!aResult->mMinTrackSizingFunctions.IsEmpty() &&
+                 aResult->mMinTrackSizingFunctions.Length() ==
+                 aResult->mMaxTrackSizingFunctions.Length() &&
+                 aResult->mMinTrackSizingFunctions.Length() + 1 ==
+                 aResult->mLineNameLists.Length(),
                  "Inconstistent array lengths for nsStyleGridTemplate");
     }
   }
 }
 
 static void
 SetGridTemplateAreas(const nsCSSValue& aValue,
                      RefPtr<css::GridTemplateAreasValue>* aResult,
@@ -8778,22 +8769,24 @@ nsRuleNode::ComputePositionData(void* aS
                          pos->mGridAutoRowsMin,
                          pos->mGridAutoRowsMax,
                          parentPos->mGridAutoRowsMin,
                          parentPos->mGridAutoRowsMax,
                          aContext, mPresContext, conditions);
 
   // grid-template-columns
   SetGridTrackList(*aRuleData->ValueForGridTemplateColumns(),
-                   pos->mGridTemplateColumns, parentPos->mGridTemplateColumns,
+                   pos->mGridTemplateColumns,
+                   parentPos->mGridTemplateColumns.get(),
                    aContext, mPresContext, conditions);
 
   // grid-template-rows
   SetGridTrackList(*aRuleData->ValueForGridTemplateRows(),
-                   pos->mGridTemplateRows, parentPos->mGridTemplateRows,
+                   pos->mGridTemplateRows,
+                   parentPos->mGridTemplateRows.get(),
                    aContext, mPresContext, conditions);
 
   // grid-tempate-areas
   SetGridTemplateAreas(*aRuleData->ValueForGridTemplateAreas(),
                        &pos->mGridTemplateAreas,
                        parentPos->mGridTemplateAreas,
                        conditions);
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -30,16 +30,17 @@
 
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 #include "CounterStyleManager.h"
 
 #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ImageTracker.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Likely.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #include <algorithm>
 #include "ImageLoader.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -1508,41 +1509,61 @@ nsStylePosition::nsStylePosition(const n
   , mJustifySelf(aSource.mJustifySelf)
   , mFlexDirection(aSource.mFlexDirection)
   , mFlexWrap(aSource.mFlexWrap)
   , mObjectFit(aSource.mObjectFit)
   , mOrder(aSource.mOrder)
   , mFlexGrow(aSource.mFlexGrow)
   , mFlexShrink(aSource.mFlexShrink)
   , mZIndex(aSource.mZIndex)
-  , mGridTemplateColumns(aSource.mGridTemplateColumns)
-  , mGridTemplateRows(aSource.mGridTemplateRows)
   , mGridTemplateAreas(aSource.mGridTemplateAreas)
   , mGridColumnStart(aSource.mGridColumnStart)
   , mGridColumnEnd(aSource.mGridColumnEnd)
   , mGridRowStart(aSource.mGridRowStart)
   , mGridRowEnd(aSource.mGridRowEnd)
   , mGridColumnGap(aSource.mGridColumnGap)
   , mGridRowGap(aSource.mGridRowGap)
 {
   MOZ_COUNT_CTOR(nsStylePosition);
+
+  if (aSource.mGridTemplateColumns) {
+    mGridTemplateColumns =
+      MakeUnique<nsStyleGridTemplate>(*aSource.mGridTemplateColumns);
+  }
+  if (aSource.mGridTemplateRows) {
+    mGridTemplateRows =
+      MakeUnique<nsStyleGridTemplate>(*aSource.mGridTemplateRows);
+  }
 }
 
 static bool
 IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2)
 {
   NS_FOR_CSS_SIDES(side) {
     if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
         (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
       return false;
     }
   }
   return true;
 }
 
+static bool
+IsGridTemplateEqual(const UniquePtr<nsStyleGridTemplate>& aOldData,
+                    const UniquePtr<nsStyleGridTemplate>& aNewData)
+{
+  if (aOldData == aNewData) {
+    return true;
+  }
+  if (!aOldData || !aNewData) {
+    return false;
+  }
+  return *aOldData == *aNewData;
+}
+
 nsChangeHint
 nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
                                 const nsStyleVisibility* aOldStyleVisibility) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   // Changes to "z-index" require a repaint.
   if (mZIndex != aNewData.mZIndex) {
@@ -1597,18 +1618,20 @@ nsStylePosition::CalcDifference(const ns
       mFlexWrap != aNewData.mFlexWrap) {
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Properties that apply to grid containers:
   // FIXME: only for grid containers
   // (ie. 'display: grid' or 'display: inline-grid')
-  if (mGridTemplateColumns != aNewData.mGridTemplateColumns ||
-      mGridTemplateRows != aNewData.mGridTemplateRows ||
+  if (!IsGridTemplateEqual(mGridTemplateColumns,
+                           aNewData.mGridTemplateColumns) ||
+      !IsGridTemplateEqual(mGridTemplateRows,
+                           aNewData.mGridTemplateRows) ||
       mGridTemplateAreas != aNewData.mGridTemplateAreas ||
       mGridAutoColumnsMin != aNewData.mGridAutoColumnsMin ||
       mGridAutoColumnsMax != aNewData.mGridAutoColumnsMax ||
       mGridAutoRowsMin != aNewData.mGridAutoRowsMin ||
       mGridAutoRowsMax != aNewData.mGridAutoRowsMax ||
       mGridAutoFlow != aNewData.mGridAutoFlow) {
     return hint |
            nsChangeHint_AllReflowHints;
@@ -1730,16 +1753,40 @@ nsStylePosition::UsedJustifySelf(nsStyle
   }
   if (MOZ_LIKELY(aParent)) {
     auto inheritedJustifyItems = aParent->StylePosition()->mJustifyItems;
     return inheritedJustifyItems & ~NS_STYLE_JUSTIFY_LEGACY;
   }
   return NS_STYLE_JUSTIFY_NORMAL;
 }
 
+static StaticAutoPtr<nsStyleGridTemplate> sDefaultGridTemplate;
+
+static const nsStyleGridTemplate&
+DefaultGridTemplate()
+{
+  if (!sDefaultGridTemplate) {
+    sDefaultGridTemplate = new nsStyleGridTemplate;
+    ClearOnShutdown(&sDefaultGridTemplate);
+  }
+  return *sDefaultGridTemplate;
+}
+
+const nsStyleGridTemplate&
+nsStylePosition::GridTemplateColumns() const
+{
+  return mGridTemplateColumns ? *mGridTemplateColumns : DefaultGridTemplate();
+}
+
+const nsStyleGridTemplate&
+nsStylePosition::GridTemplateRows() const
+{
+  return mGridTemplateRows ? *mGridTemplateRows : DefaultGridTemplate();
+}
+
 // --------------------
 // nsStyleTable
 //
 
 nsStyleTable::nsStyleTable(const nsPresContext* aContext)
   : mLayoutStrategy(NS_STYLE_TABLE_LAYOUT_AUTO)
   , mSpan(1)
 {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1623,26 +1623,26 @@ struct nsStyleGridTemplate
 
   nsStyleGridTemplate()
     : mRepeatAutoIndex(-1)
     , mIsAutoFill(false)
     , mIsSubgrid(false)
   {
   }
 
-  inline bool operator!=(const nsStyleGridTemplate& aOther) const {
+  inline bool operator==(const nsStyleGridTemplate& aOther) const {
     return
-      mIsSubgrid != aOther.mIsSubgrid ||
-      mLineNameLists != aOther.mLineNameLists ||
-      mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
-      mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions ||
-      mIsAutoFill != aOther.mIsAutoFill ||
-      mRepeatAutoIndex != aOther.mRepeatAutoIndex ||
-      mRepeatAutoLineNameListBefore != aOther.mRepeatAutoLineNameListBefore ||
-      mRepeatAutoLineNameListAfter != aOther.mRepeatAutoLineNameListAfter;
+      mIsSubgrid == aOther.mIsSubgrid &&
+      mLineNameLists == aOther.mLineNameLists &&
+      mMinTrackSizingFunctions == aOther.mMinTrackSizingFunctions &&
+      mMaxTrackSizingFunctions == aOther.mMaxTrackSizingFunctions &&
+      mIsAutoFill == aOther.mIsAutoFill &&
+      mRepeatAutoIndex == aOther.mRepeatAutoIndex &&
+      mRepeatAutoLineNameListBefore == aOther.mRepeatAutoLineNameListBefore &&
+      mRepeatAutoLineNameListAfter == aOther.mRepeatAutoLineNameListAfter;
   }
 
   bool HasRepeatAuto() const {
     return mRepeatAutoIndex != -1;
   }
 
   bool IsRepeatAutoIndex(uint32_t aIndex) const {
     MOZ_ASSERT(aIndex < uint32_t(2*nsStyleGridLine::kMaxLine));
@@ -1718,18 +1718,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   uint8_t       mJustifySelf;           // [reset] see nsStyleConsts.h
   uint8_t       mFlexDirection;         // [reset] see nsStyleConsts.h
   uint8_t       mFlexWrap;              // [reset] see nsStyleConsts.h
   uint8_t       mObjectFit;             // [reset] see nsStyleConsts.h
   int32_t       mOrder;                 // [reset] integer
   float         mFlexGrow;              // [reset] float
   float         mFlexShrink;            // [reset] float
   nsStyleCoord  mZIndex;                // [reset] integer, auto
-  nsStyleGridTemplate mGridTemplateColumns;
-  nsStyleGridTemplate mGridTemplateRows;
+  mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateColumns;
+  mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateRows;
 
   // nullptr for 'none'
   RefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
 
   nsStyleGridLine mGridColumnStart;
   nsStyleGridLine mGridColumnEnd;
   nsStyleGridLine mGridRowStart;
   nsStyleGridLine mGridRowEnd;
@@ -1803,16 +1803,19 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   inline const nsStyleCoord& MaxBSize(mozilla::WritingMode aWM) const;
   inline bool ISizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MinISizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool BSizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
 
+  const nsStyleGridTemplate& GridTemplateColumns() const;
+  const nsStyleGridTemplate& GridTemplateRows() const;
+
 private:
   static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
   static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
     { return aCoord.HasPercent(); }
 };
 
 struct nsStyleTextOverflowSide
 {
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1683,17 +1683,17 @@ fn static_assert() {
 
     pub fn clone_grid_auto_${kind}(&self) -> longhands::grid_auto_${kind}::computed_value::T {
         ::values::generics::grid::TrackSize::from_gecko_style_coords(&self.gecko.mGridAuto${kind.title()}Min,
                                                                      &self.gecko.mGridAuto${kind.title()}Max)
     }
 
     pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) {
         <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
-        use gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine};
+        use gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine, nsStyleGridTemplate};
         use nsstring::nsStringRepr;
         use std::usize;
         use values::CustomIdent;
         use values::generics::grid::TrackListType::Auto;
         use values::generics::grid::{GridTemplateComponent, RepeatCount};
 
         #[inline]
         fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<nsStringRepr>) {
@@ -1701,152 +1701,136 @@ fn static_assert() {
                 bindings::Gecko_ResizeTArrayForStrings(gecko_names, servo_names.len() as u32);
             }
 
             for (servo_name, gecko_name) in servo_names.iter().zip(gecko_names.iter_mut()) {
                 gecko_name.assign(servo_name.0.as_slice());
             }
         }
 
-        // Set defaults
-        ${self_grid}.mRepeatAutoIndex = -1;
-        ${self_grid}.set_mIsAutoFill(false);
-        ${self_grid}.set_mIsSubgrid(false);
-
         let max_lines = nsStyleGridLine_kMaxLine as usize - 1;      // for accounting the final <line-names>
 
-        match v {
+        let result: *mut nsStyleGridTemplate = match v {
+            GridTemplateComponent::None => ptr::null_mut(),
             GridTemplateComponent::TrackList(track) => {
+                let mut num_values = track.values.len();
+                if let Auto(_) = track.list_type {
+                    num_values += 1;
+                }
+
+                num_values = cmp::min(num_values, max_lines);
+                let value = unsafe {
+                    bindings::Gecko_CreateStyleGridTemplate(num_values as u32,
+                                                            (num_values + 1) as u32).as_mut().unwrap()
+                };
+
                 let mut auto_idx = usize::MAX;
                 let mut auto_track_size = None;
                 if let Auto(idx) = track.list_type {
                     auto_idx = idx as usize;
                     let auto_repeat = track.auto_repeat.as_ref().expect("expected <auto-track-repeat> value");
 
                     if auto_repeat.count == RepeatCount::AutoFill {
-                        ${self_grid}.set_mIsAutoFill(true);
+                        value.set_mIsAutoFill(true);
                     }
 
-                    ${self_grid}.mRepeatAutoIndex = idx as i16;
+                    value.mRepeatAutoIndex = idx as i16;
                     // NOTE: Gecko supports only one set of values in <auto-repeat>
                     // i.e., it can only take repeat(auto-fill, [a] 10px [b]), and no more.
-                    set_line_names(&auto_repeat.line_names[0], &mut ${self_grid}.mRepeatAutoLineNameListBefore);
-                    set_line_names(&auto_repeat.line_names[1], &mut ${self_grid}.mRepeatAutoLineNameListAfter);
+                    set_line_names(&auto_repeat.line_names[0], &mut value.mRepeatAutoLineNameListBefore);
+                    set_line_names(&auto_repeat.line_names[1], &mut value.mRepeatAutoLineNameListAfter);
                     auto_track_size = Some(auto_repeat.track_sizes.get(0).unwrap().clone());
                 } else {
                     unsafe {
                         bindings::Gecko_ResizeTArrayForStrings(
-                            &mut ${self_grid}.mRepeatAutoLineNameListBefore, 0);
+                            &mut value.mRepeatAutoLineNameListBefore, 0);
                         bindings::Gecko_ResizeTArrayForStrings(
-                            &mut ${self_grid}.mRepeatAutoLineNameListAfter, 0);
+                            &mut value.mRepeatAutoLineNameListAfter, 0);
                     }
                 }
 
-                let mut num_values = track.values.len();
-                if auto_track_size.is_some() {
-                    num_values += 1;
-                }
-
-                num_values = cmp::min(num_values, max_lines);
-                unsafe {
-                    bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, num_values as u32);
-                }
-
                 let mut line_names = track.line_names.into_iter();
                 let mut values_iter = track.values.into_iter();
-                let min_max_iter = ${self_grid}.mMinTrackSizingFunctions.iter_mut()
-                                               .zip(${self_grid}.mMaxTrackSizingFunctions.iter_mut());
-
-                for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate().take(max_lines) {
-                    let name_list = line_names.next().expect("expected line-names");
-                    set_line_names(&name_list, &mut ${self_grid}.mLineNameLists[i]);
-                    if i == auto_idx {
-                        let track_size = auto_track_size.take().expect("expected <track-size> for <auto-track-repeat>");
+                {
+                    let min_max_iter = value.mMinTrackSizingFunctions.iter_mut()
+                                            .zip(value.mMaxTrackSizingFunctions.iter_mut());
+                    for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate().take(max_lines) {
+                        let name_list = line_names.next().expect("expected line-names");
+                        set_line_names(&name_list, &mut value.mLineNameLists[i]);
+                        if i == auto_idx {
+                            let track_size = auto_track_size.take()
+                                .expect("expected <track-size> for <auto-track-repeat>");
+                            track_size.to_gecko_style_coords(gecko_min, gecko_max);
+                            continue
+                        }
+
+                        let track_size = values_iter.next().expect("expected <track-size> value");
                         track_size.to_gecko_style_coords(gecko_min, gecko_max);
-                        continue
                     }
-
-                    let track_size = values_iter.next().expect("expected <track-size> value");
-                    track_size.to_gecko_style_coords(gecko_min, gecko_max);
                 }
 
                 let final_names = line_names.next().unwrap();
-                set_line_names(&final_names, ${self_grid}.mLineNameLists.last_mut().unwrap());
-            },
-            GridTemplateComponent::None => {
-                unsafe {
-                    bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, 0);
-                    bindings::Gecko_ResizeTArrayForStrings(
-                        &mut ${self_grid}.mRepeatAutoLineNameListBefore, 0);
-                    bindings::Gecko_ResizeTArrayForStrings(
-                        &mut ${self_grid}.mRepeatAutoLineNameListAfter, 0);
-                }
+                set_line_names(&final_names, value.mLineNameLists.last_mut().unwrap());
+
+                value
             },
             GridTemplateComponent::Subgrid(list) => {
-                ${self_grid}.set_mIsSubgrid(true);
                 let names_length = match list.fill_idx {
                     Some(_) => list.names.len() - 1,
                     None => list.names.len(),
                 };
                 let num_values = cmp::min(names_length, max_lines + 1);
-
-                unsafe {
-                    bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, 0);
-                    bindings::Gecko_SetGridTemplateLineNamesLength(&mut ${self_grid}, num_values as u32);
-                    bindings::Gecko_ResizeTArrayForStrings(
-                        &mut ${self_grid}.mRepeatAutoLineNameListBefore, 0);
-                    bindings::Gecko_ResizeTArrayForStrings(
-                        &mut ${self_grid}.mRepeatAutoLineNameListAfter, 0);
-                }
+                let value = unsafe {
+                    bindings::Gecko_CreateStyleGridTemplate(0, num_values as u32).as_mut().unwrap()
+                };
+                value.set_mIsSubgrid(true);
 
                 let mut names = list.names.into_vec();
                 if let Some(idx) = list.fill_idx {
-                    ${self_grid}.set_mIsAutoFill(true);
-                    ${self_grid}.mRepeatAutoIndex = idx as i16;
+                    value.set_mIsAutoFill(true);
+                    value.mRepeatAutoIndex = idx as i16;
                     set_line_names(&names.swap_remove(idx as usize),
-                                   &mut ${self_grid}.mRepeatAutoLineNameListBefore);
+                                   &mut value.mRepeatAutoLineNameListBefore);
                 }
 
-                for (servo_names, gecko_names) in names.iter().zip(${self_grid}.mLineNameLists.iter_mut()) {
+                for (servo_names, gecko_names) in names.iter().zip(value.mLineNameLists.iter_mut()) {
                     set_line_names(servo_names, gecko_names);
                 }
+
+                value
             },
-        }
+        };
+
+        unsafe { bindings::Gecko_SetStyleGridTemplate(&mut ${self_grid}, result); }
     }
 
     pub fn copy_grid_template_${kind}_from(&mut self, other: &Self) {
         unsafe {
             bindings::Gecko_CopyStyleGridTemplateValues(&mut ${self_grid},
-                                                        &other.gecko.mGridTemplate${kind.title()});
+                                                        other.gecko.mGridTemplate${kind.title()}.mPtr);
         }
     }
 
     pub fn reset_grid_template_${kind}(&mut self, other: &Self) {
         self.copy_grid_template_${kind}_from(other)
     }
 
     pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T {
         <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
         use Atom;
         use gecko_bindings::structs::nsTArray;
         use nsstring::nsStringRepr;
         use values::CustomIdent;
         use values::generics::grid::{GridTemplateComponent, LineNameList, RepeatCount};
         use values::generics::grid::{TrackList, TrackListType, TrackRepeat, TrackSize};
 
-        if ${self_grid}.mRepeatAutoLineNameListBefore.len() == 0 &&
-           ${self_grid}.mRepeatAutoLineNameListAfter.len() == 0 &&
-           ${self_grid}.mMinTrackSizingFunctions.len() == 0 &&
-           ${self_grid}.mMaxTrackSizingFunctions.len() == 0 &&
-           ${self_grid}.mLineNameLists.len() == 0 &&
-           ${self_grid}.mRepeatAutoIndex == -1 &&
-           !${self_grid}.mIsAutoFill() &&
-           !${self_grid}.mIsSubgrid() {
-           return GridTemplateComponent::None;
-        }
+        let value = match unsafe { ${self_grid}.mPtr.as_ref() } {
+            None => return GridTemplateComponent::None,
+            Some(value) => value,
+        };
 
         #[inline]
         fn to_boxed_customident_slice(gecko_names: &nsTArray<nsStringRepr>) -> Box<[CustomIdent]> {
             let idents: Vec<CustomIdent> = gecko_names.iter().map(|gecko_name| {
                 CustomIdent(Atom::from(gecko_name.to_string()))
             }).collect();
             idents.into_boxed_slice()
         }
@@ -1854,56 +1838,56 @@ fn static_assert() {
         #[inline]
         fn to_line_names_vec(gecko_line_names: &nsTArray<nsTArray<nsStringRepr>>)
             -> Vec<Box<[CustomIdent]>> {
             gecko_line_names.iter().map(|gecko_names| {
                 to_boxed_customident_slice(gecko_names)
             }).collect()
         }
 
-        let repeat_auto_index = ${self_grid}.mRepeatAutoIndex as usize;
-        if ${self_grid}.mIsSubgrid() {
-            let mut names_vec = to_line_names_vec(&${self_grid}.mLineNameLists);
-            let fill_idx = if ${self_grid}.mIsAutoFill() {
+        let repeat_auto_index = value.mRepeatAutoIndex as usize;
+        if value.mIsSubgrid() {
+            let mut names_vec = to_line_names_vec(&value.mLineNameLists);
+            let fill_idx = if value.mIsAutoFill() {
                 names_vec.insert(
                     repeat_auto_index,
-                    to_boxed_customident_slice(&${self_grid}.mRepeatAutoLineNameListBefore));
+                    to_boxed_customident_slice(&value.mRepeatAutoLineNameListBefore));
                 Some(repeat_auto_index as u32)
             } else {
                 None
             };
             let names = names_vec.into_boxed_slice();
 
             GridTemplateComponent::Subgrid(LineNameList{names, fill_idx})
         } else {
             let mut auto_repeat = None;
             let mut list_type = TrackListType::Normal;
-            let line_names = to_line_names_vec(&${self_grid}.mLineNameLists).into_boxed_slice();
-            let mut values = Vec::with_capacity(${self_grid}.mMinTrackSizingFunctions.len());
-
-            let min_max_iter = ${self_grid}.mMinTrackSizingFunctions.iter()
-                .zip(${self_grid}.mMaxTrackSizingFunctions.iter());
+            let line_names = to_line_names_vec(&value.mLineNameLists).into_boxed_slice();
+            let mut values = Vec::with_capacity(value.mMinTrackSizingFunctions.len());
+
+            let min_max_iter = value.mMinTrackSizingFunctions.iter()
+                .zip(value.mMaxTrackSizingFunctions.iter());
             for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate() {
                 let track_size = TrackSize::from_gecko_style_coords(gecko_min, gecko_max);
 
                 if i == repeat_auto_index {
                     list_type = TrackListType::Auto(repeat_auto_index as u16);
 
-                    let count = if ${self_grid}.mIsAutoFill() {
+                    let count = if value.mIsAutoFill() {
                         RepeatCount::AutoFill
                     } else {
                         RepeatCount::AutoFit
                     };
 
                     let line_names = {
                         let mut vec: Vec<Box<[CustomIdent]>> = Vec::with_capacity(2);
                         vec.push(to_boxed_customident_slice(
-                            &${self_grid}.mRepeatAutoLineNameListBefore));
+                            &value.mRepeatAutoLineNameListBefore));
                         vec.push(to_boxed_customident_slice(
-                            &${self_grid}.mRepeatAutoLineNameListAfter));
+                            &value.mRepeatAutoLineNameListAfter));
                         vec.into_boxed_slice()
                     };
 
                     let track_sizes = vec!(track_size);
 
                     auto_repeat = Some(TrackRepeat{count, line_names, track_sizes});
                 } else {
                     values.push(track_size);