Bug 1234311 part 1 - [css-grid][css-grid-2] Simplify and improve calculation of 'grid-template-rows/columns' resolved value when the element has no box. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Sat, 12 Oct 2019 17:15:43 +0000
changeset 497364 43f18d905d75ef27a2e76591e9efba0d9442ffd1
parent 497363 a0f1057c6f5042b1c80f411a9208a18b46b710cd
child 497365 2ac943ae442445f96f5a68d5298b320f30b1313a
push id97838
push usermpalmgren@mozilla.com
push dateSat, 12 Oct 2019 17:17:04 +0000
treeherderautoland@2ac943ae4424 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1234311
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1234311 part 1 - [css-grid][css-grid-2] Simplify and improve calculation of 'grid-template-rows/columns' resolved value when the element has no box. r=dholbert Differential Revision: https://phabricator.services.mozilla.com/D49026
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1542,17 +1542,17 @@ already_AddRefed<nsROCSSPrimitiveValue> 
   minmaxStr.Append(char16_t(')'));
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetString(minmaxStr);
   return val.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
     const StyleGridTemplateComponent& aTrackList,
-    const ComputedGridTrackInfo* aTrackInfo) {
+    const ComputedGridTrackInfo& aTrackInfo) {
   if (aTrackList.IsSubgrid()) {
     // XXX TODO: add support for repeat(auto-fill) for 'subgrid' (bug 1234311)
     RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
     auto& subgrid = *aTrackList.AsSubgrid();
 
     RefPtr<nsROCSSPrimitiveValue> subgridKeyword = new nsROCSSPrimitiveValue;
     subgridKeyword->SetIdent(eCSSKeyword_subgrid);
@@ -1570,245 +1570,187 @@ already_AddRefed<CSSValue> nsComputedDOM
       if (MOZ_UNLIKELY(i == subgrid.fill_idx)) {
         RefPtr<nsROCSSPrimitiveValue> end = new nsROCSSPrimitiveValue;
         end->SetString(NS_LITERAL_STRING(")"));
         valueList->AppendCSSValue(end.forget());
       }
     }
     return valueList.forget();
   }
-  RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
-  if (aTrackInfo) {
-    uint32_t numSizes = aTrackInfo->mSizes.Length();
-    if (!numSizes && !aTrackList.HasRepeatAuto()) {
-      RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-      val->SetIdent(eCSSKeyword_none);
-      return val.forget();
-    }
+
+  uint32_t numSizes = aTrackInfo.mSizes.Length();
+  if (!numSizes && !aTrackList.HasRepeatAuto()) {
+    RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+    val->SetIdent(eCSSKeyword_none);
+    return val.forget();
+  }
 
-    // We've done layout on the grid and have resolved the sizes of its tracks,
-    // so we'll return those sizes here.  The grid spec says we MAY use
-    // repeat(<positive-integer>, Npx) here for consecutive tracks with the same
-    // size, but that doesn't seem worth doing since even for repeat(auto-*)
-    // the resolved size might differ for the repeated tracks.
-    const nsTArray<nscoord>& trackSizes = aTrackInfo->mSizes;
-    const uint32_t numExplicitTracks = aTrackInfo->mNumExplicitTracks;
-    const uint32_t numLeadingImplicitTracks =
-        aTrackInfo->mNumLeadingImplicitTracks;
-    MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks);
+  // We've done layout on the grid and have resolved the sizes of its tracks,
+  // so we'll return those sizes here.  The grid spec says we MAY use
+  // repeat(<positive-integer>, Npx) here for consecutive tracks with the same
+  // size, but that doesn't seem worth doing since even for repeat(auto-*)
+  // the resolved size might differ for the repeated tracks.
+  RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
+  const nsTArray<nscoord>& trackSizes = aTrackInfo.mSizes;
+  const uint32_t numExplicitTracks = aTrackInfo.mNumExplicitTracks;
+  const uint32_t numLeadingImplicitTracks =
+      aTrackInfo.mNumLeadingImplicitTracks;
+  MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks);
 
-    // Add any leading implicit tracks.
-    for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
-      RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-      val->SetAppUnits(trackSizes[i]);
-      valueList->AppendCSSValue(val.forget());
+  // Add any leading implicit tracks.
+  for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
+    RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+    val->SetAppUnits(trackSizes[i]);
+    valueList->AppendCSSValue(val.forget());
+  }
+
+  // Then add any explicit tracks and removed auto-fit tracks.
+  if (numExplicitTracks || aTrackList.HasRepeatAuto()) {
+    uint32_t endOfRepeat = 0;  // first index after any repeat() tracks
+    int32_t offsetToLastRepeat = 0;
+    if (aTrackList.HasRepeatAuto()) {
+      // offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty
+      offsetToLastRepeat =
+          numExplicitTracks + 1 - aTrackInfo.mResolvedLineNames.Length();
+      endOfRepeat = aTrackInfo.mRepeatFirstTrack + offsetToLastRepeat + 1;
     }
 
-    // Then add any explicit tracks and removed auto-fit tracks.
-    if (numExplicitTracks || aTrackList.HasRepeatAuto()) {
-      uint32_t endOfRepeat = 0;  // first index after any repeat() tracks
-      int32_t offsetToLastRepeat = 0;
-      if (aTrackList.HasRepeatAuto()) {
-        // offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty
-        offsetToLastRepeat =
-            numExplicitTracks + 1 - aTrackInfo->mResolvedLineNames.Length();
-        endOfRepeat = aTrackInfo->mRepeatFirstTrack + offsetToLastRepeat + 1;
-      }
+    auto* autoRepeatValue = aTrackList.GetRepeatAutoValue();
+    auto beforeAutoRepeat =
+        autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[0].AsSpan()
+                        : Span<StyleCustomIdent>();
+    auto afterAutoRepeat =
+        autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[1].AsSpan()
+                        : Span<StyleCustomIdent>();
+    uint32_t repeatIndex = 0;
+    uint32_t numRepeatTracks = aTrackInfo.mRemovedRepeatTracks.Length();
+    enum LinePlacement { LinesPrecede, LinesFollow, LinesBetween };
+    auto AppendRemovedAutoFits =
+        [&aTrackInfo, &valueList, aTrackList, beforeAutoRepeat, afterAutoRepeat,
+         &repeatIndex, numRepeatTracks](LinePlacement aPlacement) {
+          // Add in removed auto-fit tracks and lines here, if necessary
+          bool atLeastOneTrackReported = false;
+          while (repeatIndex < numRepeatTracks &&
+                 aTrackInfo.mRemovedRepeatTracks[repeatIndex]) {
+            if ((aPlacement == LinesPrecede) ||
+                ((aPlacement == LinesBetween) && atLeastOneTrackReported)) {
+              // Precede it with the lines between repeats.
+              AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
+            }
 
-      auto* autoRepeatValue = aTrackList.GetRepeatAutoValue();
-      auto beforeAutoRepeat =
-          autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[0].AsSpan()
-                          : Span<StyleCustomIdent>();
-      auto afterAutoRepeat =
-          autoRepeatValue ? autoRepeatValue->line_names.AsSpan()[1].AsSpan()
-                          : Span<StyleCustomIdent>();
-      uint32_t repeatIndex = 0;
-      uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
-      enum LinePlacement { LinesPrecede, LinesFollow, LinesBetween };
-      auto AppendRemovedAutoFits = [aTrackInfo, &valueList, aTrackList,
-                                    beforeAutoRepeat, afterAutoRepeat,
-                                    &repeatIndex,
-                                    numRepeatTracks](LinePlacement aPlacement) {
-        // Add in removed auto-fit tracks and lines here, if necessary
-        bool atLeastOneTrackReported = false;
-        while (repeatIndex < numRepeatTracks &&
-               aTrackInfo->mRemovedRepeatTracks[repeatIndex]) {
-          if ((aPlacement == LinesPrecede) ||
-              ((aPlacement == LinesBetween) && atLeastOneTrackReported)) {
-            // Precede it with the lines between repeats.
-            AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
-          }
+            // Removed 'auto-fit' tracks are reported as 0px.
+            RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+            val->SetAppUnits(0);
+            valueList->AppendCSSValue(val.forget());
+            atLeastOneTrackReported = true;
 
-          // Removed 'auto-fit' tracks are reported as 0px.
-          RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-          val->SetAppUnits(0);
-          valueList->AppendCSSValue(val.forget());
-          atLeastOneTrackReported = true;
-
-          if (aPlacement == LinesFollow) {
-            // Follow it with the lines between repeats.
-            AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
+            if (aPlacement == LinesFollow) {
+              // Follow it with the lines between repeats.
+              AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
+            }
+            repeatIndex++;
           }
           repeatIndex++;
-        }
-        repeatIndex++;
-      };
+        };
 
-      for (uint32_t i = 0;; i++) {
-        if (aTrackList.HasRepeatAuto()) {
-          if (i == aTrackInfo->mRepeatFirstTrack) {
-            const nsTArray<StyleCustomIdent>& lineNames =
-                aTrackInfo->mResolvedLineNames[i];
-            if (i == endOfRepeat) {
-              // All auto-fit tracks are empty, but we report them anyway.
-              AppendGridLineNames(valueList, lineNames);
+    for (uint32_t i = 0;; i++) {
+      if (aTrackList.HasRepeatAuto()) {
+        if (i == aTrackInfo.mRepeatFirstTrack) {
+          const nsTArray<StyleCustomIdent>& lineNames =
+              aTrackInfo.mResolvedLineNames[i];
+          if (i == endOfRepeat) {
+            // All auto-fit tracks are empty, but we report them anyway.
+            AppendGridLineNames(valueList, lineNames);
 
-              AppendRemovedAutoFits(LinesBetween);
+            AppendRemovedAutoFits(LinesBetween);
 
-              AppendGridLineNames(valueList,
-                                  aTrackInfo->mResolvedLineNames[i + 1]);
-            } else {
-              AppendGridLineNames(valueList, lineNames);
-              AppendRemovedAutoFits(LinesFollow);
-            }
-          } else if (i == endOfRepeat) {
-            // Before appending the last line, finish off any removed auto-fits.
-            AppendRemovedAutoFits(LinesPrecede);
+            AppendGridLineNames(valueList,
+                                aTrackInfo.mResolvedLineNames[i + 1]);
+          } else {
+            AppendGridLineNames(valueList, lineNames);
+            AppendRemovedAutoFits(LinesFollow);
+          }
+        } else if (i == endOfRepeat) {
+          // Before appending the last line, finish off any removed auto-fits.
+          AppendRemovedAutoFits(LinesPrecede);
 
-            const nsTArray<StyleCustomIdent>& lineNames =
-                aTrackInfo
-                    ->mResolvedLineNames[aTrackInfo->mRepeatFirstTrack + 1];
-            AppendGridLineNames(valueList, lineNames);
-          } else if (i > aTrackInfo->mRepeatFirstTrack && i < endOfRepeat) {
-            AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
-            AppendRemovedAutoFits(LinesFollow);
-          } else {
-            uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i;
-            const nsTArray<StyleCustomIdent>& lineNames =
-                aTrackInfo->mResolvedLineNames[j];
-            AppendGridLineNames(valueList, lineNames);
-          }
+          const nsTArray<StyleCustomIdent>& lineNames =
+              aTrackInfo.mResolvedLineNames[aTrackInfo.mRepeatFirstTrack + 1];
+          AppendGridLineNames(valueList, lineNames);
+        } else if (i > aTrackInfo.mRepeatFirstTrack && i < endOfRepeat) {
+          AppendGridLineNames(valueList, afterAutoRepeat, beforeAutoRepeat);
+          AppendRemovedAutoFits(LinesFollow);
         } else {
+          uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i;
           const nsTArray<StyleCustomIdent>& lineNames =
-              aTrackInfo->mResolvedLineNames[i];
+              aTrackInfo.mResolvedLineNames[j];
           AppendGridLineNames(valueList, lineNames);
         }
-        if (i == numExplicitTracks) {
-          break;
-        }
-        RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-        val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
-        valueList->AppendCSSValue(val.forget());
+      } else {
+        const nsTArray<StyleCustomIdent>& lineNames =
+            aTrackInfo.mResolvedLineNames[i];
+        AppendGridLineNames(valueList, lineNames);
       }
-    }
-
-    // Add any trailing implicit tracks.
-    for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks;
-         i < numSizes; ++i) {
+      if (i == numExplicitTracks) {
+        break;
+      }
       RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-      val->SetAppUnits(trackSizes[i]);
+      val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
       valueList->AppendCSSValue(val.forget());
     }
-  } else {
-    if (aTrackList.IsNone()) {
-      RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-      val->SetIdent(eCSSKeyword_none);
-      return val.forget();
-    }
-    // We don't have a frame.  So, we'll just return a serialization of
-    // the tracks from the style (without resolved sizes).
-    auto& trackList = *aTrackList.AsTrackList();
-    auto nameLists = trackList.line_names.AsSpan();
-    auto values = trackList.values.AsSpan();
-    uint32_t numSizes = values.Length();
-    for (uint32_t i = 0;; i++) {
-      auto names = nameLists[i].AsSpan();
-      if (!names.IsEmpty()) {
-        AppendGridLineNames(valueList, names);
-      }
-      if (i == numSizes) {
-        break;
-      }
-      auto& value = values[i];
-      if (value.IsTrackRepeat()) {
-        auto& repeat = value.AsTrackRepeat();
-        nsAutoString string;
-        string.AppendLiteral("repeat(");
-        if (repeat.count.IsNumber()) {
-          nsStyleUtil::AppendCSSNumber(repeat.count.AsNumber(), string);
-        } else if (repeat.count.IsAutoFit()) {
-          string.AppendLiteral("auto-fit");
-        } else {
-          MOZ_ASSERT(repeat.count.IsAutoFill());
-          string.AppendLiteral("auto-fill");
-        }
-        string.AppendLiteral(",");
+  }
 
-        auto repeat_names = repeat.line_names.AsSpan();
-        auto repeat_sizes = repeat.track_sizes.AsSpan();
-        MOZ_ASSERT(repeat_names.Length() == repeat_sizes.Length() ||
-                   repeat_names.Length() == repeat_sizes.Length() + 1);
-        for (auto i : IntegerRange(repeat_sizes.Length())) {
-          auto names = repeat_names[i];
-          if (!names.IsEmpty()) {
-            string.Append(' ');
-            AppendGridLineNames(string, names.AsSpan(), Brackets::Yes);
-          }
-          string.Append(' ');
-          RefPtr<nsROCSSPrimitiveValue> size =
-              GetGridTrackSize(repeat_sizes[i]);
-          nsAutoString tmp;
-          size->GetCssText(tmp);
-          string.Append(tmp);
-        }
-        if (repeat_names.Length() == repeat_sizes.Length() + 1) {
-          auto lastList = repeat_names[repeat_sizes.Length()].AsSpan();
-          if (!lastList.IsEmpty()) {
-            string.Append(' ');
-            AppendGridLineNames(string, lastList, Brackets::Yes);
-          }
-        }
-        string.Append(')');
-        RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
-        value->SetString(string);
-        valueList->AppendCSSValue(value.forget());
-      } else {
-        valueList->AppendCSSValue(GetGridTrackSize(value.AsTrackSize()));
-      }
-    }
+  // Add any trailing implicit tracks.
+  for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks; i < numSizes;
+       ++i) {
+    RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+    val->SetAppUnits(trackSizes[i]);
+    valueList->AppendCSSValue(val.forget());
   }
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetGridTemplateColumns() {
-  const ComputedGridTrackInfo* info = nullptr;
-
   nsGridContainerFrame* gridFrame =
       nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame);
-
-  if (gridFrame) {
-    info = gridFrame->GetComputedTemplateColumns();
+  if (!gridFrame) {
+    // The element doesn't have a box - return the computed value.
+    // https://drafts.csswg.org/css-grid/#resolved-track-list
+    nsAutoString string;
+    Servo_GetPropertyValue(mComputedStyle, eCSSProperty_grid_template_columns,
+                           &string);
+    RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
+    value->SetString(string);
+    return value.forget();
   }
 
+  // GetGridFrameWithComputedInfo() above ensures that this returns non-null:
+  const ComputedGridTrackInfo* info = gridFrame->GetComputedTemplateColumns();
   return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns,
-                                    info);
+                                    *info);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetGridTemplateRows() {
-  const ComputedGridTrackInfo* info = nullptr;
-
   nsGridContainerFrame* gridFrame =
       nsGridContainerFrame::GetGridFrameWithComputedInfo(mInnerFrame);
-
-  if (gridFrame) {
-    info = gridFrame->GetComputedTemplateRows();
+  if (!gridFrame) {
+    // The element doesn't have a box - return the computed value.
+    // https://drafts.csswg.org/css-grid/#resolved-track-list
+    nsAutoString string;
+    Servo_GetPropertyValue(mComputedStyle, eCSSProperty_grid_template_rows,
+                           &string);
+    RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
+    value->SetString(string);
+    return value.forget();
   }
 
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, info);
+  // GetGridFrameWithComputedInfo() above ensures that this returns non-null:
+  const ComputedGridTrackInfo* info = gridFrame->GetComputedTemplateRows();
+  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, *info);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetPaddingTop() {
   return GetPaddingWidthFor(eSideTop);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetPaddingBottom() {
   return GetPaddingWidthFor(eSideBottom);
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -192,17 +192,17 @@ class nsComputedDOMStyle final : public 
   already_AddRefed<nsROCSSPrimitiveValue> GetGridTrackSize(
       const mozilla::StyleTrackSize&);
   already_AddRefed<nsROCSSPrimitiveValue> GetGridTrackBreadth(
       const mozilla::StyleTrackBreadth&);
   void SetValueToTrackBreadth(nsROCSSPrimitiveValue*,
                               const mozilla::StyleTrackBreadth&);
   already_AddRefed<CSSValue> GetGridTemplateColumnsRows(
       const mozilla::StyleGridTemplateComponent& aTrackList,
-      const mozilla::ComputedGridTrackInfo* aTrackInfo);
+      const mozilla::ComputedGridTrackInfo& aTrackInfo);
 
   bool GetLineHeightCoord(nscoord& aCoord);
 
   bool ShouldHonorMinSizeAutoInAxis(mozilla::PhysicalAxis aAxis);
 
   /* Properties queryable as CSSValues.
    * To avoid a name conflict with nsIDOM*CSS2Properties, these are all
    * DoGetXXX instead of GetXXX.