Skip to content

Instantly share code, notes, and snippets.

@emilio
Created June 4, 2017 23:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emilio/812eed04fa62e1d696c7ba1f0223f16c to your computer and use it in GitHub Desktop.
Save emilio/812eed04fa62e1d696c7ba1f0223f16c to your computer and use it in GitHub Desktop.
From 665e847a61fdada67d77b7c65977c88c2d61c223 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= <ecobos@igalia.com>
Date: Mon, 5 Jun 2017 00:31:34 +0200
Subject: [PATCH] wip
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Emilio Cobos Álvarez <ecobos@igalia.com>
---
LayoutTests/css3/supports-dom-api-expected.txt | 13 ++++++++
LayoutTests/css3/supports-dom-api.html | 14 +++++++++
Source/WebCore/css/parser/CSSParserTokenRange.h | 4 +++
Source/WebCore/css/parser/CSSSupportsParser.cpp | 42 +++++++++++++++----------
Source/WebCore/css/parser/CSSSupportsParser.h | 6 ++--
5 files changed, 60 insertions(+), 19 deletions(-)
diff --git a/LayoutTests/css3/supports-dom-api-expected.txt b/LayoutTests/css3/supports-dom-api-expected.txt
index 9c9776c2f31..acc73f1b9fd 100644
--- a/LayoutTests/css3/supports-dom-api-expected.txt
+++ b/LayoutTests/css3/supports-dom-api-expected.txt
@@ -4,6 +4,15 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS CSS.supports("display: none") is true
+PASS CSS.supports("display: deadbeef") is false
+PASS CSS.supports("(display: none) and ((display: block) or (display: inline))") is true
+PASS CSS.supports("(not (display: deadbeef)) and (display: block)") is true
+PASS CSS.supports("top: -webkit-calc(80% - 20px)") is true
+PASS CSS.supports("background-color: rgb(0, 128, 0)") is true
+PASS CSS.supports("background: url('/blah')") is true
+PASS CSS.supports("background: invalid('/blah')") is false
+PASS CSS.supports("display: none;") is false
+PASS CSS.supports("display: none; garbage") is false
PASS CSS.supports("(display: none)") is true
PASS CSS.supports("(display: deadbeef)") is false
PASS CSS.supports("not (display: deadbeef)") is true
@@ -19,6 +28,8 @@ PASS CSS.supports("(display: none) or (display: deadbeef) or (display: inline)")
PASS CSS.supports("(display: ohhai) or (display: deadbeef) or (display: rainbows)") is false
PASS CSS.supports("(display: none) and (display: block) or (display: inline)") is false
PASS CSS.supports("not (display: deadbeef) and (display: block)") is false
+PASS CSS.supports("(display: none) and (display: block) or (display: inline)") is false
+PASS CSS.supports("not (display: deadbeef) and (display: block)") is false
PASS CSS.supports("(not (border: 1px 1px 1px 1px 1px solid #000)) and (display: block)") is true
PASS CSS.supports("(display: block !important) and ((display: inline) or (display: deadbeef))") is true
PASS CSS.supports("not ((not (display: block)) or ((display: none) and (deadbeef: 1px)))") is true
@@ -28,7 +39,9 @@ PASS CSS.supports("(display: none)or(-webkit-transition: all 1s)") is true
PASS CSS.supports("(display: none) or(-webkit-transition: all 1s )") is true
PASS CSS.supports("(((((((display: none)))))))") is true
PASS CSS.supports("(!important)") is false
+PASS CSS.supports("!important") is false
PASS CSS.supports("not not not not (display: none)") is false
+PASS CSS.supports("top baz bar: -webkit-calc(80% - 20px)") is false
PASS CSS.supports("(top: -webkit-calc(80% - 20px))") is true
PASS CSS.supports("(background-color: rgb(0, 128, 0))") is true
PASS CSS.supports("(background: url('/blah'))") is true
diff --git a/LayoutTests/css3/supports-dom-api.html b/LayoutTests/css3/supports-dom-api.html
index 4d240b57df6..be066515a60 100644
--- a/LayoutTests/css3/supports-dom-api.html
+++ b/LayoutTests/css3/supports-dom-api.html
@@ -8,6 +8,16 @@
description("Test window.CSS.supports()");
shouldBeTrue('CSS.supports("display: none")');
+ shouldBeFalse('CSS.supports("display: deadbeef")');
+ shouldBeTrue('CSS.supports("(display: none) and ((display: block) or (display: inline))")');
+ shouldBeTrue('CSS.supports("(not (display: deadbeef)) and (display: block)")');
+ shouldBeTrue('CSS.supports("top: -webkit-calc(80% - 20px)")');
+ shouldBeTrue('CSS.supports("background-color: rgb(0, 128, 0)")');
+ shouldBeTrue('CSS.supports("background: url(\'/blah\')")');
+ shouldBeFalse('CSS.supports("background: invalid(\'/blah\')")');
+ shouldBeFalse('CSS.supports("display: none;")');
+ shouldBeFalse('CSS.supports("display: none; garbage")');
+
shouldBeTrue('CSS.supports("(display: none)")');
shouldBeFalse('CSS.supports("(display: deadbeef)")');
@@ -31,6 +41,8 @@
// Bad syntax. Can't mix operators without a layer of parentheses..
shouldBeFalse('CSS.supports("(display: none) and (display: block) or (display: inline)")');
shouldBeFalse('CSS.supports("not (display: deadbeef) and (display: block)")');
+ shouldBeFalse('CSS.supports("(display: none) and (display: block) or (display: inline)")');
+ shouldBeFalse('CSS.supports("not (display: deadbeef) and (display: block)")');
// Mix 'n match.
shouldBeTrue('CSS.supports("(not (border: 1px 1px 1px 1px 1px solid #000)) and (display: block)")');
@@ -44,7 +56,9 @@
shouldBeTrue('CSS.supports("(display: none) or(-webkit-transition: all 1s )")');
shouldBeTrue('CSS.supports("(((((((display: none)))))))")');
shouldBeFalse('CSS.supports("(!important)")');
+ shouldBeFalse('CSS.supports("!important")');
shouldBeFalse('CSS.supports("not not not not (display: none)")');
+ shouldBeFalse('CSS.supports("top baz bar: -webkit-calc(80% - 20px)")');
// Functions.
shouldBeTrue('CSS.supports("(top: -webkit-calc(80% - 20px))")');
diff --git a/Source/WebCore/css/parser/CSSParserTokenRange.h b/Source/WebCore/css/parser/CSSParserTokenRange.h
index 8a9dd439db5..624643b3f82 100644
--- a/Source/WebCore/css/parser/CSSParserTokenRange.h
+++ b/Source/WebCore/css/parser/CSSParserTokenRange.h
@@ -85,6 +85,10 @@ public:
++m_first;
}
+ void consumeFully() {
+ m_first = m_last;
+ }
+
String serialize() const;
const CSSParserToken* begin() const { return m_first; }
diff --git a/Source/WebCore/css/parser/CSSSupportsParser.cpp b/Source/WebCore/css/parser/CSSSupportsParser.cpp
index 8222f8bc6bb..ae99ac1d8ed 100644
--- a/Source/WebCore/css/parser/CSSSupportsParser.cpp
+++ b/Source/WebCore/css/parser/CSSSupportsParser.cpp
@@ -36,32 +36,29 @@ namespace WebCore {
CSSSupportsParser::SupportsResult CSSSupportsParser::supportsCondition(CSSParserTokenRange range, CSSParserImpl& parser, SupportsParsingMode mode)
{
- bool implicitParentheses = mode == ForWindowCSS;
// FIXME: The spec allows leading whitespace in @supports but not CSS.supports,
// but major browser vendors allow it in CSS.supports also.
range.consumeWhitespace();
- auto result = CSSSupportsParser(parser).consumeCondition(range);
- if (!implicitParentheses || result != Invalid)
- return result;
- return range.peek().type() == IdentToken && parser.supportsDeclaration(range) ? Supported : Unsupported;
+ return CSSSupportsParser(parser).consumeCondition(range, mode == ForWindowCSS);
}
enum ClauseType { Unresolved, Conjunction, Disjunction };
-CSSSupportsParser::SupportsResult CSSSupportsParser::consumeCondition(CSSParserTokenRange range)
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeCondition(CSSParserTokenRange& range, bool alreadyUnwrapped)
{
- if (range.peek().type() == IdentToken || range.peek().type() == FunctionToken)
+ if (!alreadyUnwrapped && (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, previousTokenType);
+ SupportsResult nextResult = alreadyUnwrapped ? consumeUnwrappedCondition(range) : consumeConditionInParenthesis(range, previousTokenType);
if (nextResult == Invalid)
return Invalid;
+ alreadyUnwrapped = false;
bool nextSupported = nextResult;
if (clauseType == Unresolved)
result = nextSupported;
@@ -94,7 +91,7 @@ CSSSupportsParser::SupportsResult CSSSupportsParser::consumeCondition(CSSParserT
return result ? Supported : Unsupported;
}
-CSSSupportsParser::SupportsResult CSSSupportsParser::consumeNegation(CSSParserTokenRange range)
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeNegation(CSSParserTokenRange& range)
{
ASSERT(range.peek().type() == IdentToken || range.peek().type() == FunctionToken);
auto tokenType = range.peek().type();
@@ -116,16 +113,27 @@ CSSSupportsParser::SupportsResult CSSSupportsParser::consumeConditionInParenthes
CSSParserTokenRange innerRange = range.consumeBlock();
innerRange.consumeWhitespace();
- SupportsResult result = consumeCondition(innerRange);
- if (result != Invalid)
- return result;
-
- if (innerRange.peek().type() == FunctionToken) {
- innerRange.consumeComponentValue();
+ return consumeUnwrappedCondition(innerRange);
+}
+
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeUnwrappedCondition(CSSParserTokenRange& range)
+{
+ {
+ CSSParserTokenRange copy = range;
+ SupportsResult result = consumeCondition(range);
+ if (result != Invalid)
+ return result;
+ range = copy;
+ }
+
+ if (range.peek().type() == FunctionToken) {
+ range.consumeComponentValue();
return Unsupported;
}
- return innerRange.peek().type() == IdentToken && m_parser.supportsDeclaration(innerRange) ? Supported : Unsupported;
+ bool result = range.peek().type() == IdentToken && m_parser.supportsDeclaration(range);
+ range.consumeFully();
+ return result ? Supported : Unsupported;
}
} // namespace WebCore
diff --git a/Source/WebCore/css/parser/CSSSupportsParser.h b/Source/WebCore/css/parser/CSSSupportsParser.h
index 577ff2ccc36..ae180bf6e6d 100644
--- a/Source/WebCore/css/parser/CSSSupportsParser.h
+++ b/Source/WebCore/css/parser/CSSSupportsParser.h
@@ -55,11 +55,13 @@ private:
CSSSupportsParser(CSSParserImpl& parser)
: m_parser(parser) { }
- SupportsResult consumeCondition(CSSParserTokenRange);
- SupportsResult consumeNegation(CSSParserTokenRange);
+ SupportsResult consumeCondition(CSSParserTokenRange&, bool allowImplicitParenthesis = false);
+ SupportsResult consumeNegation(CSSParserTokenRange&);
SupportsResult consumeConditionInParenthesis(CSSParserTokenRange&, CSSParserTokenType);
+ SupportsResult consumeUnwrappedCondition(CSSParserTokenRange&);
+
CSSParserImpl& m_parser;
};
--
2.13.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment