[CSS Grid Layout] Implementation of the grid-template shorthand.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Apr 2014 12:06:53 +0000 (12:06 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Apr 2014 12:06:53 +0000 (12:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=128980

Patch by Javier Fernandez <jfernandez@igalia.com> on 2014-04-25
Reviewed by Darin Adler.

Source/WebCore:
This shorthand sets the values for the grid-template-columns,
grid-template-rows and grid-template-areas, so the implementation
tries to reuse as much available parsing functions as possible.

The "parsingGridTrackList" was refactored to return a CSSValue and
let the "parseValue" function to assign the property value. The
"forwardSlash" operator is now valid when the track-list clause is
part of a shorthand. The "parseValue" function checkouts that only
additional clauses are allowed when processing shorthands; the
grid-columns-rows-get-set.html tests was modified to verify this.

The "parseGridTemplateAreas" was refactored too, in order to
process single areas's rows. This is very useful for the
gris-template secondary syntax, which mixes areas and rows values.

Finally, the "parseGirdLineNames" function was modified as well by
defining an new argument to concatenate head/tail custom-ident
elements and ensure the identList is at the heading index, since
it's now possible the parseList was rewound.

The implementation of the grid-template shorthand tries first to
match the <grid-template-columns> / <grid-template-rows> syntax,
failing back to the secondary syntax if needed.  This approach
requires to rewind the parseList but it produces a clearer code.

Test: fast/css-grid-layout/grid-template-shorthand-get-set.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::propertyValue):
* css/CSSParser.cpp:
(WebCore::CSSParser::parseValue):
(WebCore::CSSParser::parseGridTemplateRowsAndAreas):
(WebCore::CSSParser::parseGridTemplateShorthand):
(WebCore::CSSParser::parseGridLineNames):
(WebCore::CSSParser::parseGridTrackList):
(WebCore::CSSParser::parseGridTemplateAreasRow):
(WebCore::CSSParser::parseGridTemplateAreas):
* css/CSSParser.h:
* css/CSSParserValues.h:
(WebCore::CSSParserValueList::setCurrentIndex):
* css/CSSPropertyNames.in:
* css/StylePropertyShorthand.cpp:
(WebCore::webkitGridTemplateShorthand):
* css/StylePropertyShorthand.h:

LayoutTests:
Layout Test for the basic functionality of the grid-template shorthand. It was
also added a new javascript file with some utility functions.

This shorthand sets the values for the grid-template-columns,
grid-template-rows and grid-template-areas, so the implementation
tries to reuse as much available parsing functions as possible.

* fast/css-grid-layout/grid-template-shorthand-get-set-expected.txt: Added.
* fast/css-grid-layout/grid-template-shorthand-get-set.html: Added.
* fast/css-grid-layout/resources/grid-template-shorthand-parsing-utils.js: Added.
(testGridDefinitionsValues):
(testGridDefinitionsSetJSValues):
(testNonGridDefinitionsSetJSValues):
(checkGridDefinitionsSetJSValues):
(testGridDefinitionsSetBadJSValues):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@167799 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-template-shorthand-get-set-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-template-shorthand-get-set.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/resources/grid-template-shorthand-parsing-utils.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSParserValues.h
Source/WebCore/css/CSSPropertyNames.in
Source/WebCore/css/StylePropertyShorthand.cpp
Source/WebCore/css/StylePropertyShorthand.h

index 0b54fe6..81e15c7 100644 (file)
@@ -1,3 +1,26 @@
+2014-04-25  Javier Fernandez  <jfernandez@igalia.com>
+
+        [CSS Grid Layout] Implementation of the grid-template shorthand.
+        https://bugs.webkit.org/show_bug.cgi?id=128980
+
+        Reviewed by Darin Adler.
+
+        Layout Test for the basic functionality of the grid-template shorthand. It was
+        also added a new javascript file with some utility functions.
+
+        This shorthand sets the values for the grid-template-columns,
+        grid-template-rows and grid-template-areas, so the implementation
+        tries to reuse as much available parsing functions as possible.
+
+        * fast/css-grid-layout/grid-template-shorthand-get-set-expected.txt: Added.
+        * fast/css-grid-layout/grid-template-shorthand-get-set.html: Added.
+        * fast/css-grid-layout/resources/grid-template-shorthand-parsing-utils.js: Added.
+        (testGridDefinitionsValues):
+        (testGridDefinitionsSetJSValues):
+        (testNonGridDefinitionsSetJSValues):
+        (checkGridDefinitionsSetJSValues):
+        (testGridDefinitionsSetBadJSValues):
+
 2014-04-25  Antoine Quint  <graouts@webkit.org>
 
         Implement Array.prototype.find()
diff --git a/LayoutTests/fast/css-grid-layout/grid-template-shorthand-get-set-expected.txt b/LayoutTests/fast/css-grid-layout/grid-template-shorthand-get-set-expected.txt
new file mode 100644 (file)
index 0000000..fd03ee2
--- /dev/null
@@ -0,0 +1,170 @@
+This test checks that the 'grid-template' shorthand is properly parsed and the longhand properties correctly assigned.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Test getting grid-template-areas set through CSS.
+PASS window.getComputedStyle(gridTemplateWithNone, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateWithNone, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateWithNone, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleForm, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateSimpleForm, '').getPropertyValue('-webkit-grid-template-rows') is "15px"
+PASS window.getComputedStyle(gridTemplateSimpleForm, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNoneColumns, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNoneColumns, '').getPropertyValue('-webkit-grid-template-rows') is "15px"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNoneColumns, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNoneRows, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNoneRows, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNoneRows, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNone, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNone, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithNone, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexForm, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateComplexForm, '').getPropertyValue('-webkit-grid-template-rows') is "15px"
+PASS window.getComputedStyle(gridTemplateComplexForm, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNames, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNames, '').getPropertyValue('-webkit-grid-template-rows') is "(head) 15px (tail)"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNames, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleColumns, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleColumns, '').getPropertyValue('-webkit-grid-template-rows') is "(head) 15px (tail)"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleColumns, '').getPropertyValue('-webkit-grid-template-areas') is "\"a b\""
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleRows, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleRows, '').getPropertyValue('-webkit-grid-template-rows') is "(head1) 15px (tail1 head2) 20px (tail2)"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleRows, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\" \"b\""
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleRowsAndColumns, '').getPropertyValue('-webkit-grid-template-columns') is "(first) 10px (nav nav2) 15px (nav nav2) 15px"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleRowsAndColumns, '').getPropertyValue('-webkit-grid-template-rows') is "100px (nav nav2) 25px (nav nav2) 25px (last)"
+PASS window.getComputedStyle(gridTemplateComplexFormWithLineNamesMultipleRowsAndColumns, '').getPropertyValue('-webkit-grid-template-areas') is "\"a b c\" \"d e f\" \"g h i\""
+PASS window.getComputedStyle(gridTemplateComplexFormWithAuto, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS window.getComputedStyle(gridTemplateComplexFormWithAuto, '').getPropertyValue('-webkit-grid-template-rows') is "0px"
+PASS window.getComputedStyle(gridTemplateComplexFormWithAuto, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+PASS window.getComputedStyle(gridTemplateComplexFormOnlyAreas, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormOnlyAreas, '').getPropertyValue('-webkit-grid-template-rows') is "0px"
+PASS window.getComputedStyle(gridTemplateComplexFormOnlyAreas, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+
+Test getting wrong values for grid-template shorthand through CSS (they should resolve to the default: 'none')
+PASS window.getComputedStyle(gridTemplateMultipleSlash, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateMultipleSlash, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateMultipleSlash, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormJustColumns, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormJustColumns, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormJustColumns, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoRows, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoRows, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoRows, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoColumns, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoColumns, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoColumns, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoColumnSize, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoColumnSize, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormNoColumnSize, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithFitContent, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithFitContent, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithFitContent, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithWrongRepeat, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithWrongRepeat, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithWrongRepeat, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone1, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone1, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone1, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone2, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone2, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone2, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone3, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone3, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone3, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone4, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone4, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateSimpleFormWithMisplacedNone4, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithRepeat, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithRepeat, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithRepeat, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithWrongRepeat, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithWrongRepeat, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithWrongRepeat, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(griTemplateComplexFormdWithFitAvailable, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(griTemplateComplexFormdWithFitAvailable, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(griTemplateComplexFormdWithFitAvailable, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormNoColumnSize, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormNoColumnSize, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormNoColumnSize, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormMisplacedRowsSize1, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormMisplacedRowsSize1, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormMisplacedRowsSize1, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormMisplacedRowsSize2, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormMisplacedRowsSize2, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormMisplacedRowsSize2, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormColumnsNotParsing1, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormColumnsNotParsing1, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormColumnsNotParsing1, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormColumnsNotParsing2, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormColumnsNotParsing2, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormColumnsNotParsing2, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithNoneColumns, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithNoneColumns, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(gridTemplateComplexFormWithNoneColumns, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+
+Test the initial value
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is 'none'
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is 'none'
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is 'none'
+
+Test setting grid-template-columns and grid-template-rows back to 'none' through JS
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS element.style.webkitGridTemplateColumns is "10px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "(line) 20px"
+PASS element.style.webkitGridTemplateRows is "(line) 20px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+PASS element.style.webkitGridTemplateAreas is "\"a\""
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS element.style.webkitGridTemplateColumns is "none"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS element.style.webkitGridTemplateRows is "none"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS element.style.webkitGridTemplateAreas is "none"
+
+Test getting and setting grid-template shorthand through JS
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "18px"
+PASS element.style.webkitGridTemplateColumns is "18px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "66px"
+PASS element.style.webkitGridTemplateRows is "66px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS element.style.webkitGridTemplateAreas is "none"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "10px"
+PASS element.style.webkitGridTemplateColumns is "10px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "(head) 15px (tail)"
+PASS element.style.webkitGridTemplateRows is "(head) 15px (tail)"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+PASS element.style.webkitGridTemplateAreas is "\"a\""
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS element.style.webkitGridTemplateColumns is "none"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "0px"
+PASS element.style.webkitGridTemplateRows is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "\"a\""
+PASS element.style.webkitGridTemplateAreas is "\"a\""
+
+Test setting grid-template shorthand to bad values through JS
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas') is "none"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css-grid-layout/grid-template-shorthand-get-set.html b/LayoutTests/fast/css-grid-layout/grid-template-shorthand-get-set.html
new file mode 100644 (file)
index 0000000..4e2a5ff
--- /dev/null
@@ -0,0 +1,221 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+#gridTemplateWithNone {
+    -webkit-grid-template: none;
+}
+#gridTemplateSimpleForm {
+    -webkit-grid-template: 10px / 15px;
+}
+#gridTemplateSimpleFormWithNoneColumns {
+    -webkit-grid-template: none / 15px;
+}
+#gridTemplateSimpleFormWithNoneRows {
+    -webkit-grid-template: 10px / none;
+}
+#gridTemplateSimpleFormWithNone {
+    -webkit-grid-template: none / none;
+}
+#gridTemplateComplexForm {
+    -webkit-grid-template: 10px / "a" 15px;
+}
+#gridTemplateComplexFormWithLineNames {
+    -webkit-grid-template: 10px / (head) "a" 15px (tail);
+}
+#gridTemplateComplexFormWithLineNamesMultipleColumns {
+    -webkit-grid-template: 10px / (head) "a b" 15px (tail)
+}
+#gridTemplateComplexFormWithLineNamesMultipleRows {
+    -webkit-grid-template: 10px / (head1) "a" 15px (tail1)
+                          (head2) "b" 20px (tail2);
+}
+#gridTemplateComplexFormWithLineNamesMultipleRowsAndColumns {
+    -webkit-grid-template: (first) 10px repeat(2, (nav nav2) 15px) /       "a b c" 100px (nav)
+                                                            (nav2) "d e f" 25px  (nav)
+                                                            (nav2) "g h i" 25px  (last);
+}
+#gridTemplateComplexFormWithAuto {
+    -webkit-grid-template: 10px / "a";
+}
+#gridTemplateComplexFormOnlyAreas {
+    -webkit-grid-template: "a";
+}
+
+/* Bad values. */
+
+#gridTemplateMultipleSlash {
+    -webkit-grid-template: 10px / 20px / 30px;
+}
+#gridTemplateSimpleFormJustColumns {
+    -webkit-grid-template: 10px;
+}
+#gridTemplateSimpleFormNoRows {
+    -webkit-grid-template: 10px /;
+}
+#gridTemplateSimpleFormNoColumns {
+    -webkit-grid-template: / 10px;
+}
+#gridTemplateSimpleFormNoColumnSize {
+    -webkit-grid-template: (line) / 10px;
+}
+#gridTemplateSimpleFormWithFitContent {
+    -webkit-grid-template: -webkit-fit-content / 10px;
+}
+#gridTemplateSimpleFormWithWrongRepeat {
+    -webkit-grid-template: repeat(2, 50% (title) a) / 10px;
+}
+#gridTemplateSimpleFormWithMisplacedNone1 {
+    -webkit-grid-template: 10px / none 20px;
+}
+#gridTemplateSimpleFormWithMisplacedNone2 {
+    -webkit-grid-template: 10px / 20px none;
+}
+#gridTemplateSimpleFormWithMisplacedNone3 {
+    -webkit-grid-template: none 10px / 20px;
+}
+#gridTemplateSimpleFormWithMisplacedNone4 {
+    -webkit-grid-template: 10px none / 20px;
+}
+#gridTemplateComplexFormWithRepeat {
+    -webkit-grid-template: 10px / "a" repeat(2, 50% (title));
+}
+#gridTemplateComplexFormWithWrongRepeat {
+    -webkit-grid-template: repeat(2, 50% (title) a) / "a";
+}
+#griTemplateComplexFormdWithFitAvailable {
+    -webkit-grid-template: -webkit-fit-available / "a";
+}
+#gridTemplateComplexFormNoColumnSize {
+    -webkit-grid-template: (line) / "a";
+}
+#gridTemplateComplexFormMisplacedRowsSize1 {
+    -webkit-grid-template: 25px / 10px "a";
+}
+#gridTemplateComplexFormMisplacedRowsSize2 {
+    -webkit-grid-template: 25px / "a" (name) 10px;
+}
+#gridTemplateComplexFormColumnsNotParsing1 {
+    -webkit-grid-template: a / "a" (name) 10px;
+}
+#gridTemplateComplexFormColumnsNotParsing2 {
+    -webkit-grid-template: "B" / "a" (name) 10px;
+}
+#gridTemplateComplexFormWithNoneColumns {
+    -webkit-grid-template: none / "a" (name) 10px;
+}
+
+</style>
+<script src="../../resources/js-test.js"></script>
+</head>
+<body>
+<div class="grid" id="gridTemplateWithNone"></div>
+<div class="grid" id="gridTemplateSimpleForm"></div>
+<div class="grid" id="gridTemplateSimpleFormWithNoneColumns"></div>
+<div class="grid" id="gridTemplateSimpleFormWithNoneRows"></div>
+<div class="grid" id="gridTemplateSimpleFormWithNone"></div>
+<div class="grid" id="gridTemplateComplexForm"></div>
+<div class="grid" id="gridTemplateComplexFormWithLineNames"></div>
+<div class="grid" id="gridTemplateComplexFormWithLineNamesMultipleColumns"></div>
+<div class="grid" id="gridTemplateComplexFormWithLineNamesMultipleRows"></div>
+<div class="grid" id="gridTemplateComplexFormWithLineNamesMultipleRowsAndColumns"></div>
+<div class="grid" id="gridTemplateComplexFormWithAuto"></div>
+<div class="grid" id="gridTemplateComplexFormOnlyAreas"></div>
+<div class="grid" id="gridTemplateMultipleSlash"></div>
+<div class="grid" id="gridTemplateSimpleFormJustColumns"></div>
+<div class="grid" id="gridTemplateSimpleFormNoRows"></div>
+<div class="grid" id="gridTemplateSimpleFormNoColumns"></div>
+<div class="grid" id="gridTemplateSimpleFormNoColumnSize"></div>
+<div class="grid" id="gridTemplateSimpleFormWithFitContent"></div>
+<div class="grid" id="gridTemplateSimpleFormWithWrongRepeat"></div>
+<div class="grid" id="gridTemplateSimpleFormWithMisplacedNone1"></div>
+<div class="grid" id="gridTemplateSimpleFormWithMisplacedNone2"></div>
+<div class="grid" id="gridTemplateSimpleFormWithMisplacedNone3"></div>
+<div class="grid" id="gridTemplateSimpleFormWithMisplacedNone4"></div>
+<div class="grid" id="gridTemplateComplexFormWithRepeat"></div>
+<div class="grid" id="gridTemplateComplexFormWithWrongRepeat"></div>
+<div class="grid" id="griTemplateComplexFormdWithFitAvailable"></div>
+<div class="grid" id="gridTemplateComplexFormNoColumnSize"></div>
+<div class="grid" id="gridTemplateComplexFormMisplacedRowsSize1"></div>
+<div class="grid" id="gridTemplateComplexFormMisplacedRowsSize2"></div>
+<div class="grid" id="gridTemplateComplexFormColumnsNotParsing1"></div>
+<div class="grid" id="gridTemplateComplexFormColumnsNotParsing2"></div>
+<div class="grid" id="gridTemplateComplexFormWithNoneColumns"></div>
+<script src="resources/grid-template-shorthand-parsing-utils.js"></script>
+<script>
+    description("This test checks that the 'grid-template' shorthand is properly parsed and the longhand properties correctly assigned.");
+
+    debug("Test getting grid-template-areas set through CSS.");
+    testGridDefinitionsValues(document.getElementById("gridTemplateWithNone"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleForm"), "10px", "15px", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithNoneColumns"), "none", "15px", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithNoneRows"), "10px", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithNone"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexForm"), "10px", "15px", '"a"');
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithLineNames"), "10px", "(head) 15px (tail)", '"a"');
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithLineNamesMultipleColumns"), "10px", "(head) 15px (tail)", '"a b"');
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithLineNamesMultipleRows"), "10px", "(head1) 15px (tail1 head2) 20px (tail2)", '"a" "b"');
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithLineNamesMultipleRowsAndColumns"), "(first) 10px (nav nav2) 15px (nav nav2) 15px", "100px (nav nav2) 25px (nav nav2) 25px (last)", '"a b c" "d e f" "g h i"');
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithAuto"), "10px", "0px", '"a"');
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormOnlyAreas"), "none", "0px", '"a"');
+
+    debug("");
+    debug("Test getting wrong values for grid-template shorthand through CSS (they should resolve to the default: 'none')");
+    testGridDefinitionsValues(document.getElementById("gridTemplateMultipleSlash"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormJustColumns"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormNoRows"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormNoColumns"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormNoColumnSize"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithFitContent"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithWrongRepeat"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithMisplacedNone1"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithMisplacedNone2"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithMisplacedNone3"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateSimpleFormWithMisplacedNone4"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithRepeat"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithWrongRepeat"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("griTemplateComplexFormdWithFitAvailable"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormNoColumnSize"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormMisplacedRowsSize1"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormMisplacedRowsSize2"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormColumnsNotParsing1"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormColumnsNotParsing2"), "none", "none", "none");
+    testGridDefinitionsValues(document.getElementById("gridTemplateComplexFormWithNoneColumns"), "none", "none", "none");
+
+    debug("");
+    debug("Test the initial value");
+    var element = document.createElement("div");
+    document.body.appendChild(element);
+    testGridDefinitionsValues(element, "none", "none", "none");
+    shouldBe("getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns')", "'none'");
+    shouldBe("getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows')", "'none'");
+    shouldBe("getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas')", "'none'");
+
+    debug("");
+    debug("Test setting grid-template-columns and grid-template-rows back to 'none' through JS");
+    testGridDefinitionsSetJSValues("10px / (line) 'a' 20px", "10px", "(line) 20px", "\"a\"");
+    testGridDefinitionsSetJSValues("none", "none", "none", "none");
+
+    debug("");
+    debug("Test getting and setting grid-template shorthand through JS");
+    testGridDefinitionsSetJSValues("18px / 66px", "18px", "66px", "none");
+    testGridDefinitionsSetJSValues("10px / (head) 'a' 15px (tail)", "10px", "(head) 15px (tail)", "\"a\"");
+    testGridDefinitionsSetJSValues("'a'", "none", "0px", "\"a\"", "none", "auto");
+
+    debug("");
+    debug("Test setting grid-template shorthand to bad values through JS");
+    testGridDefinitionsSetBadJSValues("none / 'a'");
+    testGridDefinitionsSetBadJSValues("25px / 'a' (name) 10px");
+    testGridDefinitionsSetBadJSValues("'a' / 'b'");
+    testGridDefinitionsSetBadJSValues("15px");
+    testGridDefinitionsSetBadJSValues("15px / 20px none");
+    testGridDefinitionsSetBadJSValues("25px / 10px 'a'");
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/resources/grid-template-shorthand-parsing-utils.js b/LayoutTests/fast/css-grid-layout/resources/grid-template-shorthand-parsing-utils.js
new file mode 100644 (file)
index 0000000..ef6b4b6
--- /dev/null
@@ -0,0 +1,51 @@
+function testGridDefinitionsValues(element, computedColumnsValue, computedRowsValue, computedAreasValue)
+{
+    window.element = element;
+    var elementID = element.id || "element";
+    shouldBeEqualToString("window.getComputedStyle(" + elementID + ", '').getPropertyValue('-webkit-grid-template-columns')", computedColumnsValue);
+    shouldBeEqualToString("window.getComputedStyle(" + elementID + ", '').getPropertyValue('-webkit-grid-template-rows')", computedRowsValue);
+    shouldBeEqualToString("window.getComputedStyle(" + elementID + ", '').getPropertyValue('-webkit-grid-template-areas')", computedAreasValue);
+}
+
+function testGridDefinitionsSetJSValues(shorthandValue, computedColumnsValue, computedRowsValue, computedAreasValue, jsColumnsValue, jsRowsValue, jsAreasValue)
+{
+    checkGridDefinitionsSetJSValues(true, shorthandValue, computedColumnsValue, computedRowsValue, computedAreasValue, jsColumnsValue, jsRowsValue, jsAreasValue);
+}
+
+function testNonGridDefinitionsSetJSValues(shorthandValue, computedColumnsValue, computedRowsValue, computedAreasValue, jsColumnsValue, jsRowsValue, jsAreasValue)
+{
+    checkGridDefinitionsSetJSValues(false, shorthandValue, computedColumnsValue, computedRowsValue, computedAreasValue, jsColumnsValue, jsRowsValue, jsAreasValue);
+}
+
+function checkGridDefinitionsSetJSValues(useGrid, shorthandValue, computedColumnsValue, computedRowsValue, computedAreasValue, jsColumnsValue, jsRowsValue, jsAreasValue)
+{
+    window.element = document.createElement("div");
+    document.body.appendChild(element);
+    if (useGrid) {
+        element.style.display = "-webkit-grid";
+        element.style.width = "800px";
+        element.style.height = "600px";
+    }
+
+    element.style.font = "10px Ahem"; // Used to resolve em font consistently.
+    element.style.webkitGridTemplate = shorthandValue;
+    shouldBeEqualToString("getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns')", computedColumnsValue);
+    shouldBeEqualToString("element.style.webkitGridTemplateColumns", jsColumnsValue || computedColumnsValue);
+    shouldBeEqualToString("getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows')", computedRowsValue);
+    shouldBeEqualToString("element.style.webkitGridTemplateRows", jsRowsValue || computedRowsValue);
+    shouldBeEqualToString("getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-areas')", computedAreasValue);
+    shouldBeEqualToString("element.style.webkitGridTemplateAreas", jsAreasValue || computedAreasValue);
+    document.body.removeChild(element);
+
+}
+
+function testGridDefinitionsSetBadJSValues(shorthandValue)
+{
+    window.element = document.createElement("div");
+    document.body.appendChild(element);
+
+    element.style.webkitGridTemplate = shorthandValue;
+    // We can't use testSetJSValues as element.style.webkitGridTemplateRows returns "".
+    testGridDefinitionsValues(element, "none", "none", "none");
+    document.body.removeChild(element);
+}
\ No newline at end of file
index 88eede5..6ce1a28 100644 (file)
@@ -1,3 +1,55 @@
+2014-04-25  Javier Fernandez  <jfernandez@igalia.com>
+
+        [CSS Grid Layout] Implementation of the grid-template shorthand.
+        https://bugs.webkit.org/show_bug.cgi?id=128980
+
+        Reviewed by Darin Adler.
+
+        This shorthand sets the values for the grid-template-columns,
+        grid-template-rows and grid-template-areas, so the implementation
+        tries to reuse as much available parsing functions as possible.
+
+        The "parsingGridTrackList" was refactored to return a CSSValue and
+        let the "parseValue" function to assign the property value. The
+        "forwardSlash" operator is now valid when the track-list clause is
+        part of a shorthand. The "parseValue" function checkouts that only
+        additional clauses are allowed when processing shorthands; the
+        grid-columns-rows-get-set.html tests was modified to verify this.
+
+        The "parseGridTemplateAreas" was refactored too, in order to
+        process single areas's rows. This is very useful for the
+        gris-template secondary syntax, which mixes areas and rows values.
+
+        Finally, the "parseGirdLineNames" function was modified as well by
+        defining an new argument to concatenate head/tail custom-ident
+        elements and ensure the identList is at the heading index, since
+        it's now possible the parseList was rewound.
+
+        The implementation of the grid-template shorthand tries first to
+        match the <grid-template-columns> / <grid-template-rows> syntax,
+        failing back to the secondary syntax if needed.  This approach
+        requires to rewind the parseList but it produces a clearer code.
+
+        Test: fast/css-grid-layout/grid-template-shorthand-get-set.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::ComputedStyleExtractor::propertyValue):
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseValue):
+        (WebCore::CSSParser::parseGridTemplateRowsAndAreas):
+        (WebCore::CSSParser::parseGridTemplateShorthand):
+        (WebCore::CSSParser::parseGridLineNames):
+        (WebCore::CSSParser::parseGridTrackList):
+        (WebCore::CSSParser::parseGridTemplateAreasRow):
+        (WebCore::CSSParser::parseGridTemplateAreas):
+        * css/CSSParser.h:
+        * css/CSSParserValues.h:
+        (WebCore::CSSParserValueList::setCurrentIndex):
+        * css/CSSPropertyNames.in:
+        * css/StylePropertyShorthand.cpp:
+        (WebCore::webkitGridTemplateShorthand):
+        * css/StylePropertyShorthand.h:
+
 2014-04-25  Andreas Kling  <akling@apple.com>
 
         Remove two unused SVGDocument functions.
index bd260e2..3ab7718 100644 (file)
@@ -2082,6 +2082,8 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
             return valueForGridPosition(style->gridItemRowEnd());
         case CSSPropertyWebkitGridArea:
             return getCSSPropertyValuesForGridShorthand(webkitGridAreaShorthand());
+        case CSSPropertyWebkitGridTemplate:
+            return getCSSPropertyValuesForGridShorthand(webkitGridTemplateShorthand());
         case CSSPropertyWebkitGridColumn:
             return getCSSPropertyValuesForGridShorthand(webkitGridColumnShorthand());
         case CSSPropertyWebkitGridRow:
index e20493b..2402210 100644 (file)
@@ -95,7 +95,6 @@
 
 #if ENABLE(CSS_GRID_LAYOUT)
 #include "CSSGridLineNamesValue.h"
-#include "CSSGridTemplateAreasValue.h"
 #endif
 
 #if ENABLE(CSS_IMAGE_SET)
@@ -2573,7 +2572,8 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
     case CSSPropertyWebkitGridTemplateRows:
         if (!cssGridLayoutEnabled())
             return false;
-        return parseGridTrackList(propId, important);
+        parsedValue = parseGridTrackList();
+        break;
 
     case CSSPropertyWebkitGridColumnStart:
     case CSSPropertyWebkitGridColumnEnd:
@@ -2593,6 +2593,11 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
         return parseGridItemPositionShorthand(propId, important);
     }
 
+    case CSSPropertyWebkitGridTemplate:
+        if (!cssGridLayoutEnabled())
+            return false;
+        return parseGridTemplateShorthand(important);
+
     case CSSPropertyWebkitGridArea:
         if (!cssGridLayoutEnabled())
             return false;
@@ -4796,6 +4801,113 @@ bool CSSParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool i
     return true;
 }
 
+bool CSSParser::parseGridTemplateRowsAndAreas(PassRefPtr<CSSValue> templateColumns, bool important)
+{
+    // At least template-areas strings must be defined.
+    if (!m_valueList->current())
+        return false;
+
+    NamedGridAreaMap gridAreaMap;
+    unsigned rowCount = 0;
+    unsigned columnCount = 0;
+    bool trailingIdentWasAdded = false;
+    RefPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated();
+
+    do {
+        // Handle leading <custom-ident>*.
+        if (m_valueList->current()->unit == CSSParserValue::ValueList) {
+            if (trailingIdentWasAdded) {
+                // A row's trailing ident must be concatenated with the next row's leading one.
+                parseGridLineNames(*m_valueList, *templateRows, static_cast<CSSGridLineNamesValue*>(templateRows->item(templateRows->length() - 1)));
+            } else
+                parseGridLineNames(*m_valueList, *templateRows);
+        }
+
+        // Handle a template-area's row.
+        if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount))
+            return false;
+        ++rowCount;
+
+        // Handle template-rows's track-size.
+        if (m_valueList->current() && m_valueList->current()->unit != CSSParserValue::ValueList && m_valueList->current()->unit != CSSPrimitiveValue::CSS_STRING) {
+            RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
+            if (!value)
+                return false;
+            templateRows->append(value.release());
+        } else
+            templateRows->append(cssValuePool().createIdentifierValue(CSSValueAuto));
+
+        // This will handle the trailing/leading <custom-ident>* in the grammar.
+        trailingIdentWasAdded = false;
+        if (m_valueList->current() && m_valueList->current()->unit == CSSParserValue::ValueList) {
+            parseGridLineNames(*m_valueList, *templateRows);
+            trailingIdentWasAdded = true;
+        }
+    } while (m_valueList->current());
+
+    // [<track-list> /]?
+    if (templateColumns)
+        addProperty(CSSPropertyWebkitGridTemplateColumns, templateColumns, important);
+    else
+        addProperty(CSSPropertyWebkitGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important);
+
+    // [<line-names>? <string> [<track-size> <line-names>]? ]+
+    RefPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount);
+    addProperty(CSSPropertyWebkitGridTemplateAreas, templateAreas.release(), important);
+    addProperty(CSSPropertyWebkitGridTemplateRows, templateRows.release(), important);
+
+    return true;
+}
+
+bool CSSParser::parseGridTemplateShorthand(bool important)
+{
+    ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
+
+    ShorthandScope scope(this, CSSPropertyWebkitGridTemplate);
+    ASSERT(gridTemplateShorthand().length() == 3);
+
+    // At least "none" must be defined.
+    if (!m_valueList->current())
+        return false;
+
+    bool firstValueIsNone = m_valueList->current()->id == CSSValueNone;
+
+    // 1- 'none' case.
+    if (firstValueIsNone && !m_valueList->next()) {
+        addProperty(CSSPropertyWebkitGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important);
+        addProperty(CSSPropertyWebkitGridTemplateRows, cssValuePool().createIdentifierValue(CSSValueNone), important);
+        addProperty(CSSPropertyWebkitGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important);
+        return true;
+    }
+
+    unsigned index = 0;
+    RefPtr<CSSValue> columnsValue = firstValueIsNone ? cssValuePool().createIdentifierValue(CSSValueNone) : parseGridTrackList();
+
+    // 2- <grid-template-columns> / <grid-template-columns> syntax.
+    if (columnsValue) {
+        if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current()) && m_valueList->next()))
+            return false;
+        index = m_valueList->currentIndex();
+        if (RefPtr<CSSValue> rowsValue = parseGridTrackList()) {
+            if (m_valueList->current())
+                return false;
+            addProperty(CSSPropertyWebkitGridTemplateColumns, columnsValue.release(), important);
+            addProperty(CSSPropertyWebkitGridTemplateRows, rowsValue.release(), important);
+            addProperty(CSSPropertyWebkitGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important);
+            return true;
+        }
+    }
+
+
+    // 3- [<track-list> /]? [<line-names>? <string> [<track-size> <line-names>]? ]+ syntax.
+    // The template-columns <track-list> can't be 'none'.
+    if (firstValueIsNone)
+        return false;
+    // It requires to rewind parsing due to previous syntax failures.
+    m_valueList->setCurrentIndex(index);
+    return parseGridTemplateRowsAndAreas(columnsValue, important);
+}
+
 bool CSSParser::parseGridAreaShorthand(bool important)
 {
     ASSERT(cssGridLayoutEnabled());
@@ -4850,7 +4962,7 @@ bool CSSParser::parseSingleGridAreaLonghand(RefPtr<CSSValue>& property)
     return true;
 }
 
-void CSSParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList)
+void CSSParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames)
 {
     ASSERT(inputList.current() && inputList.current()->unit == CSSParserValue::ValueList);
 
@@ -4860,26 +4972,27 @@ void CSSParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList&
         return;
     }
 
-    RefPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create();
+    // Need to ensure the identList is at the heading index, since the parserList might have been rewound.
+    identList->setCurrentIndex(0);
+
+    RefPtr<CSSGridLineNamesValue> lineNames = previousNamedAreaTrailingLineNames ? previousNamedAreaTrailingLineNames : CSSGridLineNamesValue::create();
     while (CSSParserValue* identValue = identList->current()) {
         ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT);
         lineNames->append(createPrimitiveStringValue(identValue));
         identList->next();
     }
-    valueList.append(lineNames.release());
+    if (!previousNamedAreaTrailingLineNames)
+        valueList.append(lineNames.release());
 
     inputList.next();
 }
 
-bool CSSParser::parseGridTrackList(CSSPropertyID propId, bool important)
+PassRefPtr<CSSValue> CSSParser::parseGridTrackList()
 {
     CSSParserValue* value = m_valueList->current();
     if (value->id == CSSValueNone) {
-        if (m_valueList->next())
-            return false;
-
-        addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
-        return true;
+        m_valueList->next();
+        return cssValuePool().createIdentifierValue(CSSValueNone);
     }
 
     RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
@@ -4890,13 +5003,15 @@ bool CSSParser::parseGridTrackList(CSSPropertyID propId, bool important)
 
     bool seenTrackSizeOrRepeatFunction = false;
     while (CSSParserValue* currentValue = m_valueList->current()) {
+        if (isForwardSlashOperator(currentValue))
+            break;
         if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "repeat(")) {
             if (!parseGridTrackRepeatFunction(*values))
-                return false;
+                return nullptr;
         } else {
             RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
             if (!value)
-                return false;
+                return nullptr;
             values->append(value.release());
         }
         seenTrackSizeOrRepeatFunction = true;
@@ -4908,10 +5023,9 @@ bool CSSParser::parseGridTrackList(CSSPropertyID propId, bool important)
     }
 
     if (!seenTrackSizeOrRepeatFunction)
-        return false;
+        return nullptr;
 
-    addProperty(propId, values.release(), important);
-    return true;
+    return values.release();
 }
 
 bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list)
@@ -5148,73 +5262,79 @@ bool CSSParser::parseDashboardRegions(CSSPropertyID propId, bool important)
 #endif /* ENABLE(DASHBOARD_SUPPORT) */
 
 #if ENABLE(CSS_GRID_LAYOUT)
-PassRefPtr<CSSValue> CSSParser::parseGridTemplateAreas()
+bool CSSParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, const unsigned rowCount, unsigned& columnCount)
 {
-    NamedGridAreaMap gridAreaMap;
-    size_t rowCount = 0;
-    size_t columnCount = 0;
+    CSSParserValue* currentValue = m_valueList->current();
+    if (!currentValue || currentValue->unit != CSSPrimitiveValue::CSS_STRING)
+        return false;
 
-    while (CSSParserValue* currentValue = m_valueList->current()) {
-        if (currentValue->unit != CSSPrimitiveValue::CSS_STRING)
-            return 0;
+    String gridRowNames = currentValue->string;
+    if (gridRowNames.isEmpty())
+        return false;
 
-        String gridRowNames = currentValue->string;
-        if (!gridRowNames.length())
-            return 0;
+    Vector<String> columnNames;
+    gridRowNames.split(' ', columnNames);
 
-        Vector<String> columnNames;
-        gridRowNames.split(' ', columnNames);
+    if (!columnCount) {
+        columnCount = columnNames.size();
+        ASSERT(columnCount);
+    } else if (columnCount != columnNames.size()) {
+        // The declaration is invalid is all the rows don't have the number of columns.
+        return false;
+    }
 
-        if (columnCount && (columnCount != columnNames.size())) {
-            // The declaration is invalid if all the rows don't have the number of columns.
-            return 0;
-        }
+    for (unsigned currentColumn = 0; currentColumn < columnCount; ++currentColumn) {
+        const String& gridAreaName = columnNames[currentColumn];
 
-        if (!columnCount) {
-            columnCount = columnNames.size();
-            ASSERT(columnCount);
-        }
+        // Unamed areas are always valid (we consider them to be 1x1).
+        if (gridAreaName == ".")
+            continue;
 
-        for (size_t currentColumn = 0; currentColumn < columnCount; ++currentColumn) {
-            const String& gridAreaName = columnNames[currentColumn];
+        // We handle several grid areas with the same name at once to simplify the validation code.
+        unsigned lookAheadColumn;
+        for (lookAheadColumn = currentColumn; lookAheadColumn < columnCount - 1; ++lookAheadColumn) {
+            if (columnNames[lookAheadColumn + 1] != gridAreaName)
+                break;
+        }
 
-            // Unamed areas are always valid (we consider them to be 1x1).
-            if (gridAreaName == ".")
-                continue;
+        auto gridAreaIterator = gridAreaMap.find(gridAreaName);
+        if (gridAreaIterator == gridAreaMap.end())
+            gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentColumn, lookAheadColumn)));
+        else {
+            GridCoordinate& gridCoordinate = gridAreaIterator->value;
 
-            // We handle several grid areas with the same name at once to simplify the validation code.
-            size_t lookAheadColumn;
-            for (lookAheadColumn = currentColumn; lookAheadColumn < (columnCount - 1); ++lookAheadColumn) {
-                if (columnNames[lookAheadColumn + 1] != gridAreaName)
-                    break;
-            }
+            // The following checks test that the grid area is a single filled-in rectangle.
+            // 1. The new row is adjacent to the previously parsed row.
+            if (rowCount != gridCoordinate.rows.finalPositionIndex + 1)
+                return 0;
 
-            auto gridAreaIterator = gridAreaMap.find(gridAreaName);
-            if (gridAreaIterator == gridAreaMap.end())
-                gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentColumn, lookAheadColumn)));
-            else {
-                GridCoordinate& gridCoordinate = gridAreaIterator->value;
+            // 2. The new area starts at the same position as the previously parsed area.
+            if (currentColumn != gridCoordinate.columns.initialPositionIndex)
+                return 0;
 
-                // The following checks test that the grid area is a single filled-in rectangle.
-                // 1. The new row is adjacent to the previously parsed row.
-                if (rowCount != gridCoordinate.rows.finalPositionIndex + 1)
-                    return 0;
+            // 3. The new area ends at the same position as the previously parsed area.
+            if (lookAheadColumn != gridCoordinate.columns.finalPositionIndex)
+                return 0;
 
-                // 2. The new area starts at the same position as the previously parsed area.
-                if (currentColumn != gridCoordinate.columns.initialPositionIndex)
-                    return 0;
+            ++gridCoordinate.rows.finalPositionIndex;
+        }
+        currentColumn = lookAheadColumn;
+    }
 
-                // 3. The new area ends at the same position as the previously parsed area.
-                if (lookAheadColumn != gridCoordinate.columns.finalPositionIndex)
-                    return 0;
+    m_valueList->next();
+    return true;
+}
 
-                ++gridCoordinate.rows.finalPositionIndex;
-            }
-            currentColumn = lookAheadColumn;
-        }
+PassRefPtr<CSSValue> CSSParser::parseGridTemplateAreas()
+{
+    NamedGridAreaMap gridAreaMap;
+    unsigned rowCount = 0;
+    unsigned columnCount = 0;
 
+    while (m_valueList->current()) {
+        if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount))
+            return 0;
         ++rowCount;
-        m_valueList->next();
     }
 
     if (!rowCount || !columnCount)
index 84058ac..7935c05 100644 (file)
 #include "WebKitCSSFilterValue.h"
 #endif
 
+#if ENABLE(CSS_GRID_LAYOUT)
+#include "CSSGridTemplateAreasValue.h"
+#endif
+
 namespace WebCore {
 
 class AnimationParseContext;
@@ -53,6 +57,7 @@ class CSSValue;
 class CSSValueList;
 class CSSBasicShape;
 class CSSBasicShapeInset;
+class CSSGridLineNamesValue;
 class Document;
 class Element;
 class ImmutableStyleProperties;
@@ -156,14 +161,17 @@ public:
     bool cssGridLayoutEnabled() const;
     PassRefPtr<CSSValue> parseGridPosition();
     bool parseGridItemPositionShorthand(CSSPropertyID, bool important);
+    bool parseGridTemplateRowsAndAreas(PassRefPtr<CSSValue>, bool important);
+    bool parseGridTemplateShorthand(bool important);
     bool parseGridAreaShorthand(bool important);
     bool parseSingleGridAreaLonghand(RefPtr<CSSValue>&);
-    bool parseGridTrackList(CSSPropertyID, bool important);
+    PassRefPtr<CSSValue> parseGridTrackList();
     bool parseGridTrackRepeatFunction(CSSValueList&);
     PassRefPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList);
     PassRefPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue*);
+    bool parseGridTemplateAreasRow(NamedGridAreaMap&, const unsigned, unsigned&);
     PassRefPtr<CSSValue> parseGridTemplateAreas();
-    void parseGridLineNames(CSSParserValueList&, CSSValueList&);
+    void parseGridLineNames(CSSParserValueList&, CSSValueList&, CSSGridLineNamesValue* = nullptr);
 #endif
 
     bool parseDashboardRegions(CSSPropertyID, bool important);
index 2a323cc..dd9f161 100644 (file)
@@ -155,6 +155,12 @@ public:
         --m_current;
         return current();
     }
+    void setCurrentIndex(unsigned index)
+    {
+        ASSERT(index < m_values.size());
+        if (index < m_values.size())
+            m_current = index;
+    }
 
     CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
 
index 5b75336..09027fc 100644 (file)
@@ -310,6 +310,7 @@ isolation
 -webkit-grid-auto-rows
 -webkit-grid-column-end
 -webkit-grid-column-start
+-webkit-grid-template
 -webkit-grid-template-columns
 -webkit-grid-template-rows
 -webkit-grid-row-end
index 96702bd..1f8228c 100644 (file)
@@ -352,6 +352,16 @@ StylePropertyShorthand webkitMarginCollapseShorthand()
 }
 
 #if ENABLE(CSS_GRID_LAYOUT)
+StylePropertyShorthand webkitGridTemplateShorthand()
+{
+    static const CSSPropertyID webkitGridTemplateProperties[] = {
+        CSSPropertyWebkitGridTemplateColumns,
+        CSSPropertyWebkitGridTemplateRows,
+        CSSPropertyWebkitGridTemplateAreas
+    };
+    return StylePropertyShorthand(CSSPropertyWebkitGridTemplate, webkitGridTemplateProperties, WTF_ARRAY_LENGTH(webkitGridTemplateProperties));
+}
+
 StylePropertyShorthand webkitGridAreaShorthand()
 {
     static const CSSPropertyID webkitGridAreaProperties[] = {
index 6f226d7..e2b6b84 100644 (file)
@@ -99,6 +99,7 @@ StylePropertyShorthand webkitColumnsShorthand();
 StylePropertyShorthand webkitColumnRuleShorthand();
 StylePropertyShorthand webkitFlexFlowShorthand();
 StylePropertyShorthand webkitFlexShorthand();
+StylePropertyShorthand webkitGridTemplateShorthand();
 StylePropertyShorthand webkitGridAreaShorthand();
 StylePropertyShorthand webkitGridColumnShorthand();
 StylePropertyShorthand webkitGridRowShorthand();