Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Unified Diff: Source/core/css/parser/CSSVariableParser.cpp

Issue 1192983003: CSS Custom Properties (Variables) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: ToTed Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/css/parser/CSSVariableParser.cpp
diff --git a/Source/core/css/parser/CSSVariableParser.cpp b/Source/core/css/parser/CSSVariableParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..230a7b26965224b430387c2dddcde7e6041403ac
--- /dev/null
+++ b/Source/core/css/parser/CSSVariableParser.cpp
@@ -0,0 +1,214 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/css/parser/CSSVariableParser.h"
+
+#include "core/css/CSSCustomVariableValue.h"
+#include "core/css/parser/CSSParserTokenRange.h"
+#include "core/css/parser/CSSParserValues.h"
+
+namespace blink {
+
+static bool isValidVariableName(const CSSParserToken& token)
+{
Timothy Loh 2015/08/25 09:21:10 Probably a good idea to check the token type is an
+ CSSParserString value = token.value();
+ return value.length() >= 2 && value[0] == '-' && value[0] == value[1];
Timothy Loh 2015/08/25 09:21:11 err.. value[1] == '-'?
+}
+
+static bool isValidVariableReference(CSSParserTokenRange& range)
Timothy Loh 2015/08/25 09:21:10 Use consumeBlock in the calling function and make
+{
+ bool foundVariableIdentToken = false;
+ bool foundComma = false;
+ bool contentAfterComma = false;
+
+ // TODO(leviw): Use CSSParserToken::BlockType signals instead of checking for these directly.
+ int parenthesisCount = 0;
+ int braceCount = 0;
+ int bracketCount = 0;
+ while (!range.atEnd()) {
+ const CSSParserToken& token = range.consume();
+
+ if (!foundVariableIdentToken) {
Timothy Loh 2015/08/25 09:21:10 This would be easier without the state machine loo
+ if (token.type() == IdentToken) {
+ if (!isValidVariableName(token))
+ return false;
+ foundVariableIdentToken = true;
+ } else if (token.type() != WhitespaceToken) {
+ return false;
+ }
+ continue;
+ }
+
+ if (!foundComma) {
+ if (token.type() == CommaToken)
+ foundComma = true;
+ else if (token.type() == RightParenthesisToken)
+ return true;
+ else if (token.type() != WhitespaceToken)
+ return false;
+ continue;
+ }
+
+ if (!contentAfterComma) {
+ if (token.type() == RightParenthesisToken)
+ return false;
+ contentAfterComma = true;
+ }
+
+ switch (token.type()) {
+ case DelimiterToken:
+ if (token.delimiter() == '!' && !parenthesisCount && !bracketCount && !braceCount)
+ return false;
+ break;
+ case FunctionToken:
+ case LeftParenthesisToken:
+ parenthesisCount++;
+ break;
+ case RightParenthesisToken:
+ if (!parenthesisCount)
+ return true;
+ parenthesisCount--;
+ break;
+ case RightBraceToken:
+ if (!braceCount)
+ return false;
+ braceCount--;
+ break;
+ case LeftBraceToken:
+ braceCount++;
+ break;
+ case RightBracketToken:
+ if (!bracketCount)
+ return false;
+ bracketCount--;
+ break;
+ case LeftBracketToken:
+ bracketCount++;
+ break;
+ case BadStringToken:
+ case BadUrlToken:
+ return false;
+ case CommentToken:
+ case EOFToken:
+ ASSERT_NOT_REACHED();
+ case SemicolonToken:
+ if (!parenthesisCount && !bracketCount && !braceCount)
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+ return foundVariableIdentToken && (!foundComma || contentAfterComma);
+}
+
+static CSSValueID classifyVariableRange(CSSParserTokenRange& originalRange, bool& hasReferences)
Timothy Loh 2015/08/25 09:21:11 CSSParserTokenRange& originalRange -> CSSParserTok
+{
+ hasReferences = false;
+ CSSParserTokenRange range = originalRange;
+
+ int parenthesisCount = 0;
+ int braceCount = 0;
+ int bracketCount = 0;
+
+ range.consumeWhitespace();
+ if (range.peek().type() == IdentToken) {
+ const CSSParserToken& ident = range.consumeIncludingWhitespace();
+ if (range.atEnd()) {
+ if (ident.valueEqualsIgnoringCase("inherit"))
+ return CSSValueInherit;
+ if (ident.valueEqualsIgnoringCase("initial"))
+ return CSSValueInitial;
+ if (ident.valueEqualsIgnoringCase("unset"))
+ return CSSValueUnset;
+ }
+ }
+
+ // TODO(leviw): Use consumeBlock to keep track of nesting instead of doing it directly here.
+ while (!range.atEnd()) {
+ const CSSParserToken& token = range.consume();
+ switch (token.type()) {
+ case FunctionToken:
+ if (token.valueEqualsIgnoringCase("var")) {
+ if (!isValidVariableReference(range))
+ return CSSValueInvalid; // Bail if any references are invalid
+ hasReferences = true;
+ } else {
+ parenthesisCount++;
+ }
+ break;
+ case CommentToken:
+ case EOFToken:
+ ASSERT_NOT_REACHED();
+ case DelimiterToken: {
+ if (token.delimiter() == '!' && !parenthesisCount && !bracketCount && !braceCount)
+ return CSSValueInvalid;
+ break;
+ }
+ case RightParenthesisToken:
+ if (!parenthesisCount)
+ return CSSValueInvalid;
+ parenthesisCount--;
+ break;
+ case LeftParenthesisToken:
+ parenthesisCount++;
+ break;
+ case RightBraceToken:
+ if (!braceCount)
+ return CSSValueInvalid;
+ braceCount--;
+ break;
+ case LeftBraceToken:
+ braceCount++;
+ break;
+ case RightBracketToken:
+ if (!bracketCount)
+ return CSSValueInvalid;
+ bracketCount--;
+ break;
+ case LeftBracketToken:
+ bracketCount++;
+ break;
+ case BadStringToken:
+ case BadUrlToken:
+ return CSSValueInvalid;
+ case WhitespaceToken:
+ break;
+ case SemicolonToken:
+ if (!parenthesisCount && !bracketCount && !braceCount)
+ return CSSValueInvalid;
+ default:
+ break;
+ }
+ }
+ if (parenthesisCount)
+ return CSSValueInvalid;
+ return CSSValueInternalVariableValue;
+}
+
+bool CSSVariableParser::containsValidVariableReferences(const CSSParserTokenRange& originalRange)
Timothy Loh 2015/08/25 09:21:10 CSSParserTokenRange& originalRange -> CSSParserTok
+{
+ CSSParserTokenRange range = originalRange;
+ bool hasReferences;
+ CSSValueID type = classifyVariableRange(range, hasReferences);
+ return type == CSSValueInternalVariableValue && hasReferences;
+}
+
+PassRefPtrWillBeRawPtr<CSSCustomVariableValue> CSSVariableParser::parseDeclarationValue(const AtomicString& variableName, CSSParserTokenRange& originalRange)
Timothy Loh 2015/08/25 09:21:11 CSSParserTokenRange& originalRange -> CSSParserTok
+{
+ if (originalRange.atEnd())
+ return nullptr;
+
+ bool hasReferences;
+ CSSValueID type = classifyVariableRange(originalRange, hasReferences);
+
+ if (type == CSSValueInvalid)
+ return nullptr;
+ if (type == CSSValueInternalVariableValue)
+ return CSSCustomVariableValue::create(variableName, CSSVariableData::create(originalRange, hasReferences));
+ return CSSCustomVariableValue::create(variableName, type);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698