[CSS Parser] Fix bugs in the @supports parser
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Nov 2016 22:30:11 +0000 (22:30 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Nov 2016 22:30:11 +0000 (22:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165115

Reviewed by Zalan Bujtas.

* css/parser/CSSParserFastPaths.cpp:
(WebCore::CSSParserFastPaths::isValidKeywordPropertyAndValue):
Clean up the display property to match the old parser to ensure
that @supports conditions on display are the same.

* css/parser/CSSSupportsParser.cpp:
(WebCore::CSSSupportsParser::consumeCondition):
(WebCore::CSSSupportsParser::consumeNegation):
(WebCore::CSSSupportsParser::consumeConditionInParenthesis):
* css/parser/CSSSupportsParser.h:
What follows are all bugs in Blink that need to be fixed to pass our
tests.

Fix the supports parser to allow the whitespace after not/or/and to
be optional. Allow the whitespace following parenthetical conditions
to be optional.

With whitespace being optional, this means that "not(" will parse
as a FunctionToken type, as will "or(" and "and(". Handle this situation
by checking for FunctionToken along with IdentToken and parameterizing
consumeConditionInParenthesis to do the right thing when it starts with
a FunctionToken instead of an IdentToken.

Fix the general enclosure FunctionToken for forward compatibility to require that
the function still be enclosed within parentheses.

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

Source/WebCore/ChangeLog
Source/WebCore/css/parser/CSSParserFastPaths.cpp
Source/WebCore/css/parser/CSSSupportsParser.cpp
Source/WebCore/css/parser/CSSSupportsParser.h

index 779964d..ec06cfe 100644 (file)
@@ -1,3 +1,36 @@
+2016-11-28  Dave Hyatt  <hyatt@apple.com>
+
+        [CSS Parser] Fix bugs in the @supports parser
+        https://bugs.webkit.org/show_bug.cgi?id=165115
+
+        Reviewed by Zalan Bujtas.
+
+        * css/parser/CSSParserFastPaths.cpp:
+        (WebCore::CSSParserFastPaths::isValidKeywordPropertyAndValue):
+        Clean up the display property to match the old parser to ensure
+        that @supports conditions on display are the same.
+
+        * css/parser/CSSSupportsParser.cpp:
+        (WebCore::CSSSupportsParser::consumeCondition):
+        (WebCore::CSSSupportsParser::consumeNegation):
+        (WebCore::CSSSupportsParser::consumeConditionInParenthesis):
+        * css/parser/CSSSupportsParser.h:
+        What follows are all bugs in Blink that need to be fixed to pass our
+        tests.
+
+        Fix the supports parser to allow the whitespace after not/or/and to
+        be optional. Allow the whitespace following parenthetical conditions
+        to be optional.
+
+        With whitespace being optional, this means that "not(" will parse
+        as a FunctionToken type, as will "or(" and "and(". Handle this situation
+        by checking for FunctionToken along with IdentToken and parameterizing
+        consumeConditionInParenthesis to do the right thing when it starts with
+        a FunctionToken instead of an IdentToken.
+
+        Fix the general enclosure FunctionToken for forward compatibility to require that
+        the function still be enclosed within parentheses.
+
 2016-11-28  Mark Lam  <mark.lam@apple.com>
 
         Fix exception scope verification failures in ObjectConstructor.cpp and ObjectPrototype.cpp.
index f0a7ec5..4d57b1d 100644 (file)
@@ -548,7 +548,7 @@ bool CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyID propertyId
         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
         // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid
-        return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone
+        return (valueID >= CSSValueInline && valueID <= CSSValueContents) || valueID == CSSValueNone
 #if ENABLE(CSS_GRID_LAYOUT)
             || (RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid))
 #endif
index b3fbccf..0d71bec 100644 (file)
@@ -46,14 +46,16 @@ enum ClauseType { Unresolved, Conjunction, Disjunction };
 
 CSSSupportsParser::SupportsResult CSSSupportsParser::consumeCondition(CSSParserTokenRange range)
 {
-    if (range.peek().type() == IdentToken)
+    if (range.peek().type() == IdentToken || range.peek().type() == FunctionToken)
         return consumeNegation(range);
 
     bool result;
     ClauseType clauseType = Unresolved;
+    
+    auto previousTokenType = IdentToken;
 
     while (true) {
-        SupportsResult nextResult = consumeConditionInParenthesis(range);
+        SupportsResult nextResult = consumeConditionInParenthesis(range, previousTokenType);
         if (nextResult == Invalid)
             return Invalid;
         bool nextSupported = nextResult;
@@ -66,53 +68,59 @@ CSSSupportsParser::SupportsResult CSSSupportsParser::consumeCondition(CSSParserT
 
         if (range.atEnd())
             break;
-        if (range.consumeIncludingWhitespace().type() != WhitespaceToken)
-            return Invalid;
+        range.consumeWhitespace();
         if (range.atEnd())
             break;
 
-        const CSSParserToken& token = range.consume();
-        if (token.type() != IdentToken)
+        const CSSParserToken& token = range.peek();
+        if (token.type() != IdentToken && token.type() != FunctionToken)
             return Invalid;
+        
+        previousTokenType = token.type();
+        
         if (clauseType == Unresolved)
             clauseType = token.value().length() == 3 ? Conjunction : Disjunction;
         if ((clauseType == Conjunction && !equalIgnoringASCIICase(token.value(), "and"))
             || (clauseType == Disjunction && !equalIgnoringASCIICase(token.value(), "or")))
             return Invalid;
 
-        if (range.consumeIncludingWhitespace().type() != WhitespaceToken)
-            return Invalid;
+        if (token.type() == IdentToken)
+            range.consumeIncludingWhitespace();
     }
     return result ? Supported : Unsupported;
 }
 
 CSSSupportsParser::SupportsResult CSSSupportsParser::consumeNegation(CSSParserTokenRange range)
 {
-    ASSERT(range.peek().type() == IdentToken);
-    if (!equalIgnoringASCIICase(range.consume().value(), "not"))
+    ASSERT(range.peek().type() == IdentToken || range.peek().type() == FunctionToken);
+    auto tokenType = range.peek().type();
+    if (!equalIgnoringASCIICase(range.peek().value(), "not"))
         return Invalid;
-    if (range.consumeIncludingWhitespace().type() != WhitespaceToken)
-        return Invalid;
-    SupportsResult result = consumeConditionInParenthesis(range);
+    if (range.peek().type() == IdentToken)
+        range.consumeIncludingWhitespace();
+    SupportsResult result = consumeConditionInParenthesis(range, tokenType);
     range.consumeWhitespace();
     if (!range.atEnd() || result == Invalid)
         return Invalid;
     return result ? Unsupported : Supported;
 }
 
-CSSSupportsParser::SupportsResult CSSSupportsParser::consumeConditionInParenthesis(CSSParserTokenRange& range)
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeConditionInParenthesis(CSSParserTokenRange& range, CSSParserTokenType startTokenType)
 {
-    if (range.peek().type() == FunctionToken) {
-        range.consumeComponentValue();
-        return Unsupported;
-    }
-    if (range.peek().type() != LeftParenthesisToken)
+    if (startTokenType == IdentToken && range.peek().type() != LeftParenthesisToken)
         return Invalid;
+
     CSSParserTokenRange innerRange = range.consumeBlock();
     innerRange.consumeWhitespace();
     SupportsResult result = consumeCondition(innerRange);
     if (result != Invalid)
         return result;
+    
+    if (innerRange.peek().type() == FunctionToken) {
+        innerRange.consumeComponentValue();
+        return Unsupported;
+    }
+
     return innerRange.peek().type() == IdentToken && m_parser.supportsDeclaration(innerRange) ? Supported : Unsupported;
 }
 
index f484424..ecf3c80 100644 (file)
 
 #pragma once
 
+#include "CSSParserToken.h"
+
 namespace WebCore {
 
 class CSSParserImpl;
 class CSSParserTokenRange;
-
+    
 class CSSSupportsParser {
 public:
     enum SupportsResult {
@@ -51,7 +53,7 @@ private:
     SupportsResult consumeCondition(CSSParserTokenRange);
     SupportsResult consumeNegation(CSSParserTokenRange);
 
-    SupportsResult consumeConditionInParenthesis(CSSParserTokenRange&);
+    SupportsResult consumeConditionInParenthesis(CSSParserTokenRange&, CSSParserTokenType);
 
     CSSParserImpl& m_parser;
 };