[css-grid] Fix line name positions after implicit tracks

When serializing grid-template-rows/columns of a grid container, we get
the list of used track sizes, and then insert line names at the
corresponding indices.

Before this patch, these indices were simply taken from the computed
value. However, leading implicit tracks appear in the used value but not
in the computed one. Therefore, we have to offset the indices so that
the line names appear at the proper positions.

BUG=790988

TEST=external/wpt/css/css-grid/parsing/grid-template-columns-computed-implicit-track.html
TEST=external/wpt/css/css-grid/parsing/grid-template-rows-computed-implicit-track.html

Change-Id: I778c73034c7ff9fc11a7d8a46a4042cfd1bcd1ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1863092
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Reviewed-by: Javier Fernandez <jfernandez@igalia.com>
Reviewed-by: Manuel Rego <rego@igalia.com>
Cr-Commit-Position: refs/heads/master@{#777829}
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index d81bcaa..57bdc39 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -1323,24 +1323,29 @@
                            OrderedNamedLinesCollector& collector,
                            const Vector<T>& tracks,
                            F getTrackSize,
-                           wtf_size_t start,
-                           wtf_size_t end,
-                           size_t offset = 0) {
-  DCHECK_LE(end, tracks.size());
-  for (wtf_size_t i = start; i < end; ++i) {
-    AddValuesForNamedGridLinesAtIndex(collector, i + offset, *list);
+                           int start,
+                           int end,
+                           int offset = 0) {
+  DCHECK_LE(0, start);
+  DCHECK_LE(start, end);
+  DCHECK_LE((unsigned)end, tracks.size());
+  for (int i = start; i < end; ++i) {
+    if (i + offset >= 0)
+      AddValuesForNamedGridLinesAtIndex(collector, i + offset, *list);
     list->Append(*getTrackSize(tracks[i]));
   }
-  AddValuesForNamedGridLinesAtIndex(collector, end + offset, *list);
+  if (end + offset >= 0)
+    AddValuesForNamedGridLinesAtIndex(collector, end + offset, *list);
 }
 
 template <typename T, typename F>
 void PopulateGridTrackList(CSSValueList* list,
                            OrderedNamedLinesCollector& collector,
                            const Vector<T>& tracks,
-                           F getTrackSize) {
+                           F getTrackSize,
+                           int offset = 0) {
   PopulateGridTrackList<T>(list, collector, tracks, getTrackSize, 0,
-                           tracks.size());
+                           tracks.size(), offset);
 }
 
 CSSValue* ComputedStyleUtils::ValueForGridTrackList(
@@ -1378,9 +1383,14 @@
     OrderedNamedLinesCollectorInGridLayout collector(
         style, is_row_axis, grid->AutoRepeatCountForDirection(direction),
         auto_repeat_track_sizes.size());
+    // Named grid line indices are relative to the explicit grid, but we are
+    // including all tracks. So we need to subtract the number of leading
+    // implicit tracks in order to get the proper line index.
+    int offset = -grid->ExplicitGridStartForDirection(direction);
     PopulateGridTrackList(
         list, collector, grid->TrackSizesForComputedStyle(direction),
-        [&](const LayoutUnit& v) { return ZoomAdjustedPixelValue(v, style); });
+        [&](const LayoutUnit& v) { return ZoomAdjustedPixelValue(v, style); },
+        offset);
     return list;
   }
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 18b5d56..e5e8c0d6 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4335,10 +4335,12 @@
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-minimum-contribution-baseline-shim-vertical-rl.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-minimum-contribution-baseline-shim.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-stretch-respects-min-size-001.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-columns-computed-implicit-track.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-columns-computed-withcontent.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-columns-computed.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-repeat-auto-computed-withcontent-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-repeat-auto-computed-withcontent-002.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-rows-computed-implicit-track.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-rows-computed-withcontent.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/parsing/grid-template-rows-computed.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/placement/grid-auto-flow-sparse-001.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-computed-implicit-track.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-computed-implicit-track.html
new file mode 100644
index 0000000..98d9efa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-computed-implicit-track.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: getComputedStyle().gridTemplateColumns</title>
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid/#resolved-track-list" title="7.2.6. Resolved Value of a Track Listing">
+<meta name="assert" content="Checks the resolved value of grid-template-columns on a grid container with a leading implicit track.">
+<style>
+#target {
+  display: grid;
+  width: 1px;
+  font-size: 1px;
+}
+#item {
+  grid-column: auto / 1;
+  width: 10px;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="target">
+  <div id="item"></div>
+</div>
+<script>
+// Can't use the test_computed_value from computed-testcommon.js
+// because grid-template-columns doesn't round-trip in this test.
+function grid_template_columns(specified, computed) {
+  test(() => {
+    const target = document.getElementById('target');
+    target.style.gridTemplateColumns = '';
+    target.style.gridTemplateColumns = specified;
+    assert_equals(getComputedStyle(target).gridTemplateColumns, computed);
+  }, `Property grid-template-columns value '${specified}' computes to '${computed}'`);
+}
+
+grid_template_columns("none", "10px");
+grid_template_columns("1px", "10px 1px");
+grid_template_columns("1px [a]", "10px 1px [a]");
+grid_template_columns("1px [a] 2px", "10px 1px [a] 2px");
+grid_template_columns("[a] 1px", "10px [a] 1px");
+grid_template_columns("[a] 1px [b]", "10px [a] 1px [b]");
+grid_template_columns("1px repeat(1, 2px) 3px", "10px 1px 2px 3px");
+grid_template_columns("1px repeat(auto-fill, 2px) 3px", "10px 1px 2px 3px");
+grid_template_columns("1px repeat(auto-fit, 2px) 3px", "10px 1px 0px 3px");
+grid_template_columns("1px [a] repeat(1, 2px 3px) [b] 4px", "10px 1px [a] 2px 3px [b] 4px");
+grid_template_columns("1px [a] repeat(auto-fill, 2px 3px) [b] 4px", "10px 1px [a] 2px 3px [b] 4px");
+grid_template_columns("1px [a] repeat(auto-fit, 2px 3px) [b] 4px", "10px 1px [a] 0px 0px [b] 4px");
+grid_template_columns("1px [a] repeat(1, [b] 2px [c]) [d] 3px", "10px 1px [a b] 2px [c d] 3px");
+grid_template_columns("1px [a] repeat(auto-fill, [b] 2px [c]) [d] 3px", "10px 1px [a b] 2px [c d] 3px");
+grid_template_columns("1px [a] repeat(auto-fit, [b] 2px [c]) [d] 3px", "10px 1px [a b] 0px [c d] 3px");
+grid_template_columns("[a] 1px repeat(1, 2px [b] 3px) 4px [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_columns("[a] 1px repeat(auto-fill, 2px [b] 3px) 4px [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_columns("[a] 1px repeat(auto-fit, 2px [b] 3px) 4px [d]", "10px [a] 1px 0px [b] 0px 4px [d]");
+grid_template_columns("100% [a] repeat(1, [b] 200% [c]) [d] 300%", "10px 1px [a b] 2px [c d] 3px");
+grid_template_columns("100% [a] repeat(auto-fill, [b] 200% [c]) [d] 300%", "10px 1px [a b] 2px [c d] 3px");
+grid_template_columns("100% [a] repeat(auto-fit, [b] 200% [c]) [d] 300%", "10px 1px [a b] 0px [c d] 3px");
+grid_template_columns("[a] 1em repeat(1, 2em [b] 3em) 4em [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_columns("[a] 1em repeat(auto-fill, 2em [b] 3em) 4em [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_columns("[a] 1em repeat(auto-fit, 2em [b] 3em) 4em [d]", "10px [a] 1px 0px [b] 0px 4px [d]");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-computed-implicit-track.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-computed-implicit-track.html
new file mode 100644
index 0000000..7ed3110
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-computed-implicit-track.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: getComputedStyle().gridTemplateRows</title>
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid/#resolved-track-list" title="7.2.6. Resolved Value of a Track Listing">
+<meta name="assert" content="Checks the resolved value of grid-template-rows on a grid container with a leading implicit track.">
+<style>
+#target {
+  display: grid;
+  height: 1px;
+  font-size: 1px;
+}
+#item {
+  grid-row: auto / 1;
+  height: 10px;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="target">
+  <div id="item"></div>
+</div>
+<script>
+// Can't use the test_computed_value from computed-testcommon.js
+// because grid-template-rows doesn't round-trip in this test.
+function grid_template_rows(specified, computed) {
+  test(() => {
+    const target = document.getElementById('target');
+    target.style.gridTemplateRows = '';
+    target.style.gridTemplateRows = specified;
+    assert_equals(getComputedStyle(target).gridTemplateRows, computed);
+  }, `Property grid-template-rows value '${specified}' computes to '${computed}'`);
+}
+
+grid_template_rows("none", "10px");
+grid_template_rows("1px", "10px 1px");
+grid_template_rows("1px [a]", "10px 1px [a]");
+grid_template_rows("1px [a] 2px", "10px 1px [a] 2px");
+grid_template_rows("[a] 1px", "10px [a] 1px");
+grid_template_rows("[a] 1px [b]", "10px [a] 1px [b]");
+grid_template_rows("1px repeat(1, 2px) 3px", "10px 1px 2px 3px");
+grid_template_rows("1px repeat(auto-fill, 2px) 3px", "10px 1px 2px 3px");
+grid_template_rows("1px repeat(auto-fit, 2px) 3px", "10px 1px 0px 3px");
+grid_template_rows("1px [a] repeat(1, 2px 3px) [b] 4px", "10px 1px [a] 2px 3px [b] 4px");
+grid_template_rows("1px [a] repeat(auto-fill, 2px 3px) [b] 4px", "10px 1px [a] 2px 3px [b] 4px");
+grid_template_rows("1px [a] repeat(auto-fit, 2px 3px) [b] 4px", "10px 1px [a] 0px 0px [b] 4px");
+grid_template_rows("1px [a] repeat(1, [b] 2px [c]) [d] 3px", "10px 1px [a b] 2px [c d] 3px");
+grid_template_rows("1px [a] repeat(auto-fill, [b] 2px [c]) [d] 3px", "10px 1px [a b] 2px [c d] 3px");
+grid_template_rows("1px [a] repeat(auto-fit, [b] 2px [c]) [d] 3px", "10px 1px [a b] 0px [c d] 3px");
+grid_template_rows("[a] 1px repeat(1, 2px [b] 3px) 4px [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_rows("[a] 1px repeat(auto-fill, 2px [b] 3px) 4px [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_rows("[a] 1px repeat(auto-fit, 2px [b] 3px) 4px [d]", "10px [a] 1px 0px [b] 0px 4px [d]");
+grid_template_rows("100% [a] repeat(1, [b] 200% [c]) [d] 300%", "10px 1px [a b] 2px [c d] 3px");
+grid_template_rows("100% [a] repeat(auto-fill, [b] 200% [c]) [d] 300%", "10px 1px [a b] 2px [c d] 3px");
+grid_template_rows("100% [a] repeat(auto-fit, [b] 200% [c]) [d] 300%", "10px 1px [a b] 0px [c d] 3px");
+grid_template_rows("[a] 1em repeat(1, 2em [b] 3em) 4em [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_rows("[a] 1em repeat(auto-fill, 2em [b] 3em) 4em [d]", "10px [a] 1px 2px [b] 3px 4px [d]");
+grid_template_rows("[a] 1em repeat(auto-fit, 2em [b] 3em) 4em [d]", "10px [a] 1px 0px [b] 0px 4px [d]");
+</script>