[css-grid] Add parsing support for <auto-repeat> syntax
authorsvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Apr 2016 12:21:57 +0000 (12:21 +0000)
committersvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Apr 2016 12:21:57 +0000 (12:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155583

Reviewed by Antti Koivisto.

Source/WebCore:

The repeat() notation allows now to specify auto-fill or auto-fit instead of
a fixed number of repetitions meaning that it will be automatically computed
depending on the available space.

This patch just adds the parsing support, the expansion of the repeat notation
will be implemented in a follow up patch because it cannot be done at
parsing level (since it requires knowledge about the available space).

Test: fast/css-grid-layout/grid-element-auto-repeat-get-set.html

* CMakeLists.txt:
* css/CSSGridAutoRepeatValue.cpp: Added.
(WebCore::CSSGridAutoRepeatValue::customCSSText):
* css/CSSGridAutoRepeatValue.h: Added.
(WebCore::CSSGridAutoRepeatValue::create):
(WebCore::CSSGridAutoRepeatValue::autoRepeatID):
(WebCore::CSSGridAutoRepeatValue::CSSGridAutoRepeatValue):
* css/CSSParser.cpp:
(WebCore::allTracksAreFixedSized):
(WebCore::CSSParser::parseGridTrackList):
(WebCore::CSSParser::parseGridTrackRepeatFunction):
(WebCore::CSSParser::parseGridTrackSize):
(WebCore::CSSParser::parseGridBreadth):
* css/CSSParser.h:
* css/CSSValue.cpp:
(WebCore::CSSValue::equals):
(WebCore::CSSValue::cssText):
(WebCore::CSSValue::destroy):
* css/CSSValue.h:
(WebCore::CSSValue::isGridAutoRepeatValue):
* css/CSSValueKeywords.in:

LayoutTests:

* fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt: Added.
* fast/css-grid-layout/grid-element-auto-repeat-get-set.html: Added.

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

13 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSGridAutoRepeatValue.cpp [new file with mode: 0644]
Source/WebCore/css/CSSGridAutoRepeatValue.h [new file with mode: 0644]
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSValue.cpp
Source/WebCore/css/CSSValue.h
Source/WebCore/css/CSSValueKeywords.in

index 33b3062..12ea625 100644 (file)
@@ -1,3 +1,13 @@
+2016-03-17  Sergio Villar Senin  <svillar@igalia.com>
+
+        [css-grid] Add parsing support for <auto-repeat> syntax
+        https://bugs.webkit.org/show_bug.cgi?id=155583
+
+        Reviewed by Antti Koivisto.
+
+        * fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt: Added.
+        * fast/css-grid-layout/grid-element-auto-repeat-get-set.html: Added.
+
 2016-04-12  Alex Christensen  <achristensen@webkit.org>
 
         Remove failing assertion in ANGLE
diff --git a/LayoutTests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt b/LayoutTests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt
new file mode 100644 (file)
index 0000000..14c5697
--- /dev/null
@@ -0,0 +1,60 @@
+Test that setting/getting -webkit-grid-template-{columns|rows} with repeat(auto-fill|auto-fit,) works as expected
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Test auto-repeat syntax.
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "[foo bar] 10px"
+PASS element.style.webkitGridTemplateColumns is "[foo bar] 10px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "20px [foo bar]"
+PASS element.style.webkitGridTemplateRows is "2em [foo bar]"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "[foo bar] 800px"
+PASS element.style.webkitGridTemplateColumns is "[foo bar] minmax(10px, 1fr)"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "[foo] 20px [bar]"
+PASS element.style.webkitGridTemplateRows is "[foo] minmax(2em, -webkit-max-content) [bar]"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "100px 20px 20px"
+PASS element.style.webkitGridTemplateColumns is "minmax(10px, 100px) 20px 20px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "70px 20px [bar foo] 10px [foo] 10px"
+PASS element.style.webkitGridTemplateRows is "70px minmax(2em, -webkit-max-content) [bar] [foo] 1em [foo] 1em"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "[foo bar] 10px"
+PASS element.style.webkitGridTemplateColumns is "[foo bar] 10px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "20px [foo bar]"
+PASS element.style.webkitGridTemplateRows is "2em [foo bar]"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "[foo bar] 800px"
+PASS element.style.webkitGridTemplateColumns is "[foo bar] minmax(10px, 1fr)"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "[foo] 20px [bar]"
+PASS element.style.webkitGridTemplateRows is "[foo] minmax(2em, -webkit-max-content) [bar]"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "10px 20px 20px"
+PASS element.style.webkitGridTemplateColumns is "minmax(10px, -webkit-min-content) 20px 20px"
+PASS getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-rows') is "60px 20px [bar foo] 10px [foo] 10px"
+PASS element.style.webkitGridTemplateRows is "10% minmax(2em, -webkit-max-content) [bar] [foo] 1em [foo] 1em"
+
+Test invalid repeat syntax.
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns') is "none"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html b/LayoutTests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html
new file mode 100644 (file)
index 0000000..f7defed
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<link href="resources/grid.css" rel="stylesheet">
+<script src="../../resources/js-test.js"></script>
+<script src="resources/grid-definitions-parsing-utils.js"></script>
+
+<body>
+</body>
+<script>
+    description('Test that setting/getting -webkit-grid-template-{columns|rows} with repeat(auto-fill|auto-fit,) works as expected');
+
+    debug("Test auto-repeat syntax.");
+    testGridTemplatesSetJSValues("repeat(auto-fill, [foo bar] 10px)", "repeat(auto-fill, 2em [foo bar])", "[foo bar] 10px", "20px [foo bar]", "[foo bar] 10px", "2em [foo bar]");
+    testGridTemplatesSetJSValues("repeat(auto-fill, [foo bar] minmax(10px, 1fr))", "repeat(auto-fill, [foo] minmax(2em, -webkit-max-content) [bar])", "[foo bar] 800px", "[foo] 20px [bar]", "[foo bar] minmax(10px, 1fr)", "[foo] minmax(2em, -webkit-max-content) [bar]");
+    testGridTemplatesSetJSValues("repeat(auto-fill, minmax(10px, 100px)) repeat(2, 20px)", "repeat(1, 70px) repeat(auto-fill, minmax(2em, -webkit-max-content) [bar]) repeat(2, [foo] 1em)", "100px 20px 20px", "70px 20px [bar foo] 10px [foo] 10px", "minmax(10px, 100px) 20px 20px", "70px minmax(2em, -webkit-max-content) [bar] [foo] 1em [foo] 1em");
+    testGridTemplatesSetJSValues("repeat(auto-fit, [foo bar] 10px)", "repeat(auto-fit, 2em [foo bar])", "[foo bar] 10px", "20px [foo bar]", "[foo bar] 10px", "2em [foo bar]");
+    testGridTemplatesSetJSValues("repeat(auto-fit, [foo bar] minmax(10px, 1fr))", "repeat(auto-fit, [foo] minmax(2em, -webkit-max-content) [bar])", "[foo bar] 800px", "[foo] 20px [bar]", "[foo bar] minmax(10px, 1fr)", "[foo] minmax(2em, -webkit-max-content) [bar]");
+    testGridTemplatesSetJSValues("repeat(auto-fit, minmax(10px, -webkit-min-content)) repeat(2, 20px)", "repeat(1, 10%) repeat(auto-fit, minmax(2em, -webkit-max-content) [bar]) repeat(2, [foo] 1em)", "10px 20px 20px", "60px 20px [bar foo] 10px [foo] 10px", "minmax(10px, -webkit-min-content) 20px 20px", "10% minmax(2em, -webkit-max-content) [bar] [foo] 1em [foo] 1em");
+
+    debug("");
+    debug("Test invalid repeat syntax.");
+    function testInvalidSyntax(gridColumn) {
+        element = document.createElement("div");
+        document.body.appendChild(element);
+        element.style.webkitGridTemplateColumns = gridColumn;
+        shouldBeEqualToString("window.getComputedStyle(element, '').getPropertyValue('-webkit-grid-template-columns')", "none");
+        document.body.removeChild(element);
+    }
+
+    testInvalidSyntax("repeat(auto-fill, 1fr)");
+    testInvalidSyntax("repeat(auto-fill, minmax(-webkit-min-content, 20px))");
+    testInvalidSyntax("repeat(auto-fill, [bar] auto)");
+    testInvalidSyntax("repeat(auto-fill, 20px 10px)");
+    testInvalidSyntax("repeat(auto-fill, 20px [foo bar] 10px)");
+    testInvalidSyntax("repeat(auto-fill,)");
+    testInvalidSyntax("repeat(auto-fill, [foo])");
+    testInvalidSyntax("repeat(auto-fit, 1fr)");
+    testInvalidSyntax("repeat(auto-fit, minmax(-webkit-min-content, 20px))");
+    testInvalidSyntax("repeat(auto-fit, [bar] auto)");
+    testInvalidSyntax("repeat(auto-fit, 20px 10px)");
+    testInvalidSyntax("repeat(auto-fit, 20px [foo bar] 10px)");
+    testInvalidSyntax("repeat(auto-fit,)");
+    testInvalidSyntax("repeat(auto-fit, [foo])");
+
+    // <auto-repeat> can only be used once in a <track-list>.
+    testInvalidSyntax("repeat(auto-fill, 10px) repeat(auto-fill, [foo] 2em)");
+    testInvalidSyntax("repeat(auto-fill, 10em [bar]) auto repeat(auto-fill, [foo] 2em)");
+    testInvalidSyntax("repeat(auto-fit, 10px) repeat(auto-fit, [foo] 2em)");
+    testInvalidSyntax("repeat(auto-fit, 10em [bar]) auto repeat(auto-fit, [foo] 2em)");
+    testInvalidSyntax("repeat(auto-fill, [foo] 1em [bar]) auto repeat(auto-fit, [foo] 32px)");
+    testInvalidSyntax("repeat(auto-fill, 1em [bar]) repeat(3, -webkit-max-content [last]) repeat(auto-fit, 32px)");
+
+    // <auto-repeat> requires definite minimum track sizes.
+    testInvalidSyntax("repeat(auto-fill, 10px) repeat(10, minmax(-webkit-min-content, auto))");
+    testInvalidSyntax("auto repeat(auto-fit, [foo] 10px)");
+    testInvalidSyntax("10% repeat(auto-fit, [foo] 10px) -webkit-min-content");
+    testInvalidSyntax("20px [bar] repeat(4, auto) [foo] repeat(auto-fill, 3em)");
+</script>
index 3b7f972..b3360a4 100644 (file)
@@ -1299,6 +1299,7 @@ set(WebCore_SOURCES
     css/CSSFontValue.cpp
     css/CSSFunctionValue.cpp
     css/CSSGradientValue.cpp
+    css/CSSGridAutoRepeatValue.cpp
     css/CSSGridLineNamesValue.cpp
     css/CSSGridTemplateAreasValue.cpp
     css/CSSGroupingRule.cpp
index fefe773..5f9ab24 100644 (file)
@@ -1,3 +1,42 @@
+2016-03-17  Sergio Villar Senin  <svillar@igalia.com>
+
+        [css-grid] Add parsing support for <auto-repeat> syntax
+        https://bugs.webkit.org/show_bug.cgi?id=155583
+
+        Reviewed by Antti Koivisto.
+
+        The repeat() notation allows now to specify auto-fill or auto-fit instead of
+        a fixed number of repetitions meaning that it will be automatically computed
+        depending on the available space.
+
+        This patch just adds the parsing support, the expansion of the repeat notation
+        will be implemented in a follow up patch because it cannot be done at
+        parsing level (since it requires knowledge about the available space).
+
+        Test: fast/css-grid-layout/grid-element-auto-repeat-get-set.html
+
+        * CMakeLists.txt:
+        * css/CSSGridAutoRepeatValue.cpp: Added.
+        (WebCore::CSSGridAutoRepeatValue::customCSSText):
+        * css/CSSGridAutoRepeatValue.h: Added.
+        (WebCore::CSSGridAutoRepeatValue::create):
+        (WebCore::CSSGridAutoRepeatValue::autoRepeatID):
+        (WebCore::CSSGridAutoRepeatValue::CSSGridAutoRepeatValue):
+        * css/CSSParser.cpp:
+        (WebCore::allTracksAreFixedSized):
+        (WebCore::CSSParser::parseGridTrackList):
+        (WebCore::CSSParser::parseGridTrackRepeatFunction):
+        (WebCore::CSSParser::parseGridTrackSize):
+        (WebCore::CSSParser::parseGridBreadth):
+        * css/CSSParser.h:
+        * css/CSSValue.cpp:
+        (WebCore::CSSValue::equals):
+        (WebCore::CSSValue::cssText):
+        (WebCore::CSSValue::destroy):
+        * css/CSSValue.h:
+        (WebCore::CSSValue::isGridAutoRepeatValue):
+        * css/CSSValueKeywords.in:
+
 2016-04-12  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] addStaticGlobals should emit SymbolTableEntry watchpoints to encourage constant folding in DFG
index cc147e7..849a358 100644 (file)
                E10B9B6D0B747599003ED890 /* NativeXPathNSResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E10B9B6B0B747599003ED890 /* NativeXPathNSResolver.cpp */; };
                E10B9CCC0B747A44003ED890 /* DOMCustomXPathNSResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = E10B9CCA0B747A44003ED890 /* DOMCustomXPathNSResolver.h */; };
                E10B9CCD0B747A44003ED890 /* DOMCustomXPathNSResolver.mm in Sources */ = {isa = PBXBuildFile; fileRef = E10B9CCB0B747A44003ED890 /* DOMCustomXPathNSResolver.mm */; };
+               E11003301C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E110032E1C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.cpp */; };
+               E11003311C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.h in Headers */ = {isa = PBXBuildFile; fileRef = E110032F1C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.h */; };
                E11AF15111B9A1A300805103 /* Cursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E11AF15011B9A1A300805103 /* Cursor.cpp */; };
                E11C9D9B0EB3681200E409DB /* ScriptExecutionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = E11C9D9A0EB3681200E409DB /* ScriptExecutionContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E11C9DB00EB3699500E409DB /* ScriptExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E11C9DAF0EB3699500E409DB /* ScriptExecutionContext.cpp */; };
                E10B9B6B0B747599003ED890 /* NativeXPathNSResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NativeXPathNSResolver.cpp; sourceTree = "<group>"; };
                E10B9CCA0B747A44003ED890 /* DOMCustomXPathNSResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMCustomXPathNSResolver.h; sourceTree = "<group>"; };
                E10B9CCB0B747A44003ED890 /* DOMCustomXPathNSResolver.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMCustomXPathNSResolver.mm; sourceTree = "<group>"; };
+               E110032E1C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSGridAutoRepeatValue.cpp; sourceTree = "<group>"; };
+               E110032F1C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSGridAutoRepeatValue.h; sourceTree = "<group>"; };
                E11AF15011B9A1A300805103 /* Cursor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cursor.cpp; sourceTree = "<group>"; };
                E11C9D9A0EB3681200E409DB /* ScriptExecutionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptExecutionContext.h; sourceTree = "<group>"; };
                E11C9DAF0EB3699500E409DB /* ScriptExecutionContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptExecutionContext.cpp; sourceTree = "<group>"; };
                F523D18402DE42E8018635CA /* css */ = {
                        isa = PBXGroup;
                        children = (
+                               E110032E1C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.cpp */,
+                               E110032F1C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.h */,
                                FBD6AF8415EF21D4008B7110 /* BasicShapeFunctions.cpp */,
                                FBD6AF8515EF21D4008B7110 /* BasicShapeFunctions.h */,
                                A80E6CDA0A1989CA007FB8C5 /* Counter.h */,
                                934F713C0D5A6F1900018D69 /* ResourceErrorBase.h in Headers */,
                                514C76790CE923A1007EF3CD /* ResourceHandle.h in Headers */,
                                26FAE4CD1852E3A5004C8C46 /* ResourceHandleCFURLConnectionDelegate.h in Headers */,
+                               E11003311C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.h in Headers */,
                                26C15CF71857E15E00F15C03 /* ResourceHandleCFURLConnectionDelegateWithOperationQueue.h in Headers */,
                                514C767A0CE923A1007EF3CD /* ResourceHandleClient.h in Headers */,
                                514C767B0CE923A1007EF3CD /* ResourceHandleInternal.h in Headers */,
                                FEB26D28167A8F2A00FDD26B /* DatabaseServer.cpp in Sources */,
                                97BC6A2D1505F081001B74AC /* DatabaseTask.cpp in Sources */,
                                97BC6A2F1505F081001B74AC /* DatabaseThread.cpp in Sources */,
+                               E11003301C9AC3DE00412DD0 /* CSSGridAutoRepeatValue.cpp in Sources */,
                                97BC6A311505F081001B74AC /* DatabaseTracker.cpp in Sources */,
                                BE23480C18A9870B00E4B6E8 /* DataCue.cpp in Sources */,
                                C5227DF21C3C6DF900F5ED54 /* DataDetection.mm in Sources */,
diff --git a/Source/WebCore/css/CSSGridAutoRepeatValue.cpp b/Source/WebCore/css/CSSGridAutoRepeatValue.cpp
new file mode 100644 (file)
index 0000000..fd0b5fe
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CSSGridAutoRepeatValue.h"
+
+#if ENABLE(CSS_GRID_LAYOUT)
+
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+String CSSGridAutoRepeatValue::customCSSText() const
+{
+    StringBuilder result;
+    result.append("repeat(");
+    result.append(getValueName(autoRepeatID()));
+    result.append(", ");
+    result.append(CSSValueList::customCSSText());
+    result.append(")");
+    return result.toString();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_GRID_LAYOUT)
diff --git a/Source/WebCore/css/CSSGridAutoRepeatValue.h b/Source/WebCore/css/CSSGridAutoRepeatValue.h
new file mode 100644 (file)
index 0000000..74c8d2c
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CSSGridAutoRepeatValue_h
+#define CSSGridAutoRepeatValue_h
+
+#if ENABLE(CSS_GRID_LAYOUT)
+
+#include "CSSValueKeywords.h"
+#include "CSSValueList.h"
+
+namespace WebCore {
+
+// CSSGridAutoRepeatValue stores the track sizes and line numbers when the auto-repeat
+// syntax is used
+//
+// Right now the auto-repeat syntax is as follows:
+// <auto-repeat>  = repeat( [ auto-fill | auto-fit ], <line-names>? <fixed-size> <line-names>? )
+//
+// meaning that only one fixed size track is allowed. It could be argued that a different
+// class storing two CSSGridLineNamesValue and one CSSValue (for the track size) fits
+// better but the CSSWG has left the door open to allow more than one track in the
+// future. That's why we're using a list, it's prepared for future changes and it also
+// allows us to keep the parsing algorithm almost intact.
+class CSSGridAutoRepeatValue : public CSSValueList {
+public:
+    static Ref<CSSGridAutoRepeatValue> create(CSSValueID id)
+    {
+        return adoptRef(*new CSSGridAutoRepeatValue(id));
+    }
+
+    String customCSSText() const;
+    CSSValueID autoRepeatID() const { return m_autoRepeatID; }
+
+private:
+    CSSGridAutoRepeatValue(CSSValueID id)
+        : CSSValueList(GridAutoRepeatClass, SpaceSeparator)
+        , m_autoRepeatID(id)
+    {
+        ASSERT(id == CSSValueAutoFill || id == CSSValueAutoFit);
+    }
+
+    const CSSValueID m_autoRepeatID;
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSGridAutoRepeatValue, isGridAutoRepeatValue());
+
+#endif // ENABLE(CSS_GRID_LAYOUT)
+
+#endif // CSSGridAutoRepeatValue_h
index 82c6ddd..b6bebcb 100644 (file)
 #include <wtf/text/StringImpl.h>
 
 #if ENABLE(CSS_GRID_LAYOUT)
+#include "CSSGridAutoRepeatValue.h"
 #include "CSSGridLineNamesValue.h"
 #include "CSSGridTemplateAreasValue.h"
 #endif
@@ -5840,6 +5841,28 @@ bool CSSParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList&
     return true;
 }
 
+static bool allTracksAreFixedSized(CSSValueList& valueList)
+{
+    for (auto& value : valueList) {
+        if (is<CSSGridLineNamesValue>(value))
+            continue;
+        // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax( <fixed-breadth>, <track-breadth> )
+        if (is<CSSGridAutoRepeatValue>(value)) {
+            if (!allTracksAreFixedSized(downcast<CSSValueList>(value.get())))
+                return false;
+            continue;
+        }
+        ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && downcast<CSSFunctionValue>(value.get()).arguments()));
+        const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue()
+            ? downcast<CSSPrimitiveValue>(value.get())
+            : downcast<CSSPrimitiveValue>(*downcast<CSSFunctionValue>(value.get()).arguments()->item(0));
+        CSSValueID valueID = primitiveValue.getValueID();
+        if (valueID == CSSValueWebkitMinContent || valueID == CSSValueWebkitMaxContent || valueID == CSSValueAuto || primitiveValue.isFlex())
+            return false;
+    }
+    return true;
+}
+
 RefPtr<CSSValue> CSSParser::parseGridTrackList()
 {
     CSSParserValue* value = m_valueList->current();
@@ -5855,14 +5878,19 @@ RefPtr<CSSValue> CSSParser::parseGridTrackList()
         parseGridLineNames(*m_valueList, *values);
 
     bool seenTrackSizeOrRepeatFunction = false;
+    bool seenAutoRepeat = false;
     while (CSSParserValue* currentValue = m_valueList->current()) {
         if (isForwardSlashOperator(*currentValue))
             break;
         if (currentValue->unit == CSSParserValue::Function && equalLettersIgnoringASCIICase(currentValue->function->name, "repeat(")) {
-            if (!parseGridTrackRepeatFunction(*values))
+            bool isAutoRepeat;
+            if (!parseGridTrackRepeatFunction(*values, isAutoRepeat))
                 return nullptr;
+            if (isAutoRepeat && seenAutoRepeat)
+                return nullptr;
+            seenAutoRepeat = seenAutoRepeat || isAutoRepeat;
         } else {
-            RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
+            RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList, seenAutoRepeat ? FixedSizeOnly : AllowAll);
             if (!value)
                 return nullptr;
             values->append(value.releaseNonNull());
@@ -5878,24 +5906,33 @@ RefPtr<CSSValue> CSSParser::parseGridTrackList()
     if (!seenTrackSizeOrRepeatFunction)
         return nullptr;
 
+    // <auto-repeat> requires definite minimum track sizes in order to compute the number of repetitions.
+    // The above while loop detects those appearances after the <auto-repeat> but not the ones before.
+    if (seenAutoRepeat && !allTracksAreFixedSized(*values))
+        return nullptr;
+
     return values;
 }
 
-bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list)
+bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list, bool& isAutoRepeat)
 {
     CSSParserValueList* arguments = m_valueList->current()->function->args.get();
-    if (!arguments || arguments->size() < 3)
+    if (!arguments || arguments->size() < 3 || !isComma(arguments->valueAt(1)))
         return false;
 
     ValueWithCalculation firstValueWithCalculation(*arguments->valueAt(0));
-    if (!validateUnit(firstValueWithCalculation, FPositiveInteger) || !isComma(arguments->valueAt(1)))
+    CSSValueID firstValueID = firstValueWithCalculation.value().id;
+    isAutoRepeat = firstValueID == CSSValueAutoFill || firstValueID == CSSValueAutoFit;
+    if (!isAutoRepeat && !validateUnit(firstValueWithCalculation, FPositiveInteger))
         return false;
 
     // If arguments->valueAt(0)->fValue > SIZE_MAX then repetitions becomes 0 during the type casting, that's why we
     // clamp it down to kGridMaxTracks before the type casting.
-    unsigned repetitions = clampTo<unsigned>(parsedDouble(firstValueWithCalculation), 0, kGridMaxTracks);
+    // The number of repetitions for <auto-repeat> is not important at parsing level
+    // because it will be computed later, let's set it to 1.
+    unsigned repetitions = isAutoRepeat ? 1 : clampTo<unsigned>(parsedDouble(firstValueWithCalculation), 0, kGridMaxTracks);
 
-    RefPtr<CSSValueList> repeatedValues = CSSValueList::createSpaceSeparated();
+    RefPtr<CSSValueList> repeatedValues = isAutoRepeat ? CSSGridAutoRepeatValue::create(firstValueID).get() : CSSValueList::createSpaceSeparated();
     arguments->next(); // Skip the repetition count.
     arguments->next(); // Skip the comma.
 
@@ -5905,8 +5942,12 @@ bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list)
         parseGridLineNames(*arguments, *repeatedValues);
 
     unsigned numberOfTracks = 0;
+    TrackSizeRestriction restriction = isAutoRepeat ? FixedSizeOnly : AllowAll;
     while (arguments->current()) {
-        RefPtr<CSSValue> trackSize = parseGridTrackSize(*arguments);
+        if (isAutoRepeat && numberOfTracks)
+            return false;
+
+        RefPtr<CSSValue> trackSize = parseGridTrackSize(*arguments, restriction);
         if (!trackSize)
             return false;
 
@@ -5936,7 +5977,7 @@ bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list)
     return true;
 }
 
-RefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList)
+RefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList, TrackSizeRestriction restriction)
 {
     CSSParserValue& currentValue = *inputList.current();
     inputList.next();
@@ -5950,7 +5991,7 @@ RefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList)
         if (!arguments || arguments->size() != 3 || !isComma(arguments->valueAt(1)))
             return nullptr;
 
-        RefPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(*arguments->valueAt(0));
+        RefPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(*arguments->valueAt(0), restriction);
         if (!minTrackBreadth)
             return nullptr;
 
@@ -5964,15 +6005,21 @@ RefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList)
         return CSSFunctionValue::create("minmax(", parsedArguments);
     }
 
-    return parseGridBreadth(currentValue);
+    return parseGridBreadth(currentValue, restriction);
 }
 
-RefPtr<CSSPrimitiveValue> CSSParser::parseGridBreadth(CSSParserValue& value)
+RefPtr<CSSPrimitiveValue> CSSParser::parseGridBreadth(CSSParserValue& value, TrackSizeRestriction restriction)
 {
-    if (value.id == CSSValueWebkitMinContent || value.id == CSSValueWebkitMaxContent || value.id == CSSValueAuto)
+    if (value.id == CSSValueWebkitMinContent || value.id == CSSValueWebkitMaxContent || value.id == CSSValueAuto) {
+        if (restriction == FixedSizeOnly)
+            return nullptr;
         return CSSValuePool::singleton().createIdentifierValue(value.id);
+    }
 
     if (value.unit == CSSPrimitiveValue::CSS_FR) {
+        if (restriction == FixedSizeOnly)
+            return nullptr;
+
         double flexValue = value.fValue;
 
         // Fractional unit is a non-negative dimension.
index 9a3f5f8..ef24390 100644 (file)
@@ -218,9 +218,10 @@ public:
     bool parseGridGapShorthand(bool important);
     bool parseSingleGridAreaLonghand(RefPtr<CSSValue>&);
     RefPtr<CSSValue> parseGridTrackList();
-    bool parseGridTrackRepeatFunction(CSSValueList&);
-    RefPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList);
-    RefPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue&);
+    bool parseGridTrackRepeatFunction(CSSValueList&, bool& isAutoRepeat);
+    enum TrackSizeRestriction { FixedSizeOnly, AllowAll };
+    RefPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList, TrackSizeRestriction = AllowAll);
+    RefPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue&, TrackSizeRestriction = AllowAll);
     bool parseGridTemplateAreasRow(NamedGridAreaMap&, const unsigned, unsigned&);
     RefPtr<CSSValue> parseGridTemplateAreas();
     bool parseGridLineNames(CSSParserValueList&, CSSValueList&, CSSGridLineNamesValue* = nullptr);
index 2298205..d5a401b 100644 (file)
@@ -65,6 +65,7 @@
 #include "WebKitCSSTransformValue.h"
 
 #if ENABLE(CSS_GRID_LAYOUT)
+#include "CSSGridAutoRepeatValue.h"
 #include "CSSGridLineNamesValue.h"
 #include "CSSGridTemplateAreasValue.h"
 #endif
@@ -208,6 +209,8 @@ bool CSSValue::equals(const CSSValue& other) const
         case RevertClass:
             return compareCSSValues<CSSRevertValue>(*this, other);
 #if ENABLE(CSS_GRID_LAYOUT)
+        case GridAutoRepeatClass:
+            return compareCSSValues<CSSGridAutoRepeatValue>(*this, other);
         case GridLineNamesClass:
             return compareCSSValues<CSSGridLineNamesValue>(*this, other);
         case GridTemplateAreasClass:
@@ -312,6 +315,8 @@ String CSSValue::cssText() const
     case RevertClass:
         return downcast<CSSRevertValue>(*this).customCSSText();
 #if ENABLE(CSS_GRID_LAYOUT)
+    case GridAutoRepeatClass:
+        return downcast<CSSGridAutoRepeatValue>(*this).customCSSText();
     case GridLineNamesClass:
         return downcast<CSSGridLineNamesValue>(*this).customCSSText();
     case GridTemplateAreasClass:
@@ -427,6 +432,9 @@ void CSSValue::destroy()
         delete downcast<CSSRevertValue>(this);
         return;
 #if ENABLE(CSS_GRID_LAYOUT)
+    case GridAutoRepeatClass:
+        delete downcast<CSSGridAutoRepeatValue>(this);
+        return;
     case GridLineNamesClass:
         delete downcast<CSSGridLineNamesValue>(this);
         return;
index 59dc617..6f7dab5 100644 (file)
@@ -111,6 +111,7 @@ public:
     bool isWebKitCSSFilterValue() const { return m_classType == WebKitCSSFilterClass; }
     bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; }
 #if ENABLE(CSS_GRID_LAYOUT)
+    bool isGridAutoRepeatValue() const { return m_classType == GridAutoRepeatClass; }
     bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; }
     bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; }
 #endif
@@ -202,6 +203,7 @@ protected:
         WebKitCSSTransformClass,
 #if ENABLE(CSS_GRID_LAYOUT)
         GridLineNamesClass,
+        GridAutoRepeatClass,
 #endif
         // Do not append non-list class types here.
     };
index fb79bf2..03996cb 100644 (file)
@@ -1201,3 +1201,9 @@ last
 // color-gamut
 p3
 rec2020
+
+#if defined(ENABLE_CSS_GRID_LAYOUT) && ENABLE_CSS_GRID_LAYOUT
+// auto-repeat
+auto-fill
+auto-fit
+#endif