OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "core/css/parser/CSSVariableParser.h" | |
7 | |
8 #include "core/css/CSSCustomPropertyDeclaration.h" | |
9 #include "core/css/parser/CSSParserTokenRange.h" | |
10 #include "core/css/parser/CSSParserValues.h" | |
11 | |
12 namespace blink { | |
13 | |
14 static bool isValidVariableName(const CSSParserToken& token) | |
15 { | |
16 if (token.type() != IdentToken) | |
17 return false; | |
18 | |
19 CSSParserString value = token.value(); | |
20 return value.length() >= 2 && value[0] == '-' && value[1] == '-'; | |
21 } | |
22 | |
23 static bool isValidVariableReference(CSSParserTokenRange range) | |
24 { | |
25 range.consumeWhitespace(); | |
26 if (!isValidVariableName(range.consumeIncludingWhitespace())) | |
27 return false; | |
28 if (range.atEnd()) | |
29 return true; | |
30 | |
31 range.consumeWhitespace(); | |
Timothy Loh
2015/09/30 02:09:28
This is a no-op because we used consumeIncludingWh
| |
32 if (range.consume().type() != CommaToken) | |
33 return false; | |
34 if (range.atEnd()) | |
35 return false; | |
36 | |
37 int blockNestingLevel = 0; | |
Timothy Loh
2015/09/30 02:09:28
Can we just call classifyBlock recursively here?
| |
38 while (!range.atEnd()) { | |
39 const CSSParserToken& token = range.consume(); | |
40 | |
41 if (token.blockType() == CSSParserToken::BlockStart) { | |
42 blockNestingLevel++; | |
43 } else if (token.blockType() == CSSParserToken::BlockEnd) { | |
44 blockNestingLevel--; | |
45 if (blockNestingLevel < 0) | |
46 return false; | |
47 } | |
48 | |
49 switch (token.type()) { | |
50 case DelimiterToken: | |
51 if (token.delimiter() == '!' && !blockNestingLevel) | |
52 return false; | |
53 break; | |
54 case BadStringToken: | |
55 case BadUrlToken: | |
56 return false; | |
57 case CommentToken: | |
58 case EOFToken: | |
59 ASSERT_NOT_REACHED(); | |
60 case SemicolonToken: | |
61 if (!blockNestingLevel) | |
62 return false; | |
63 break; | |
64 default: | |
65 break; | |
66 } | |
67 } | |
68 return true; | |
69 } | |
70 | |
71 bool classifyBlock(CSSParserTokenRange range, bool& hasReferences, bool isTopLev elBlock = true) | |
72 { | |
73 int parenthesisCount = 0; | |
74 int braceCount = 0; | |
75 int bracketCount = 0; | |
76 | |
77 // TODO(leviw): Use consumeBlock to keep track of nesting instead of doing i t directly here. | |
78 while (!range.atEnd()) { | |
79 if (range.peek().blockType() == CSSParserToken::BlockStart) { | |
80 const CSSParserToken& token = range.peek(); | |
81 CSSParserTokenRange block = range.consumeBlock(); | |
82 if (token.type() == FunctionToken && token.valueEqualsIgnoringCase(" var")) { | |
83 if (!isValidVariableReference(block)) | |
84 return false; // Bail if any references are invalid | |
85 hasReferences = true; | |
86 continue; | |
87 } | |
88 if (!classifyBlock(block, hasReferences, false)) | |
89 return false; | |
90 continue; | |
91 } | |
92 | |
93 const CSSParserToken& token = range.consume(); | |
94 switch (token.type()) { | |
95 case FunctionToken: | |
96 ASSERT_NOT_REACHED(); | |
97 break; | |
98 case CommentToken: | |
Timothy Loh
2015/09/30 02:09:28
I would probably leave out the ASSERT_NOT_REACHED
| |
99 case EOFToken: | |
100 ASSERT_NOT_REACHED(); | |
101 case DelimiterToken: { | |
102 if (token.delimiter() == '!' && isTopLevelBlock) | |
103 return false; | |
104 break; | |
105 } | |
106 case RightParenthesisToken: | |
107 if (!parenthesisCount) | |
108 return false; | |
109 parenthesisCount--; | |
110 break; | |
111 case LeftParenthesisToken: | |
112 parenthesisCount++; | |
113 break; | |
114 case RightBraceToken: | |
115 if (!braceCount) | |
116 return false; | |
117 braceCount--; | |
118 break; | |
119 case LeftBraceToken: | |
120 braceCount++; | |
121 break; | |
122 case RightBracketToken: | |
123 if (!bracketCount) | |
124 return false; | |
125 bracketCount--; | |
126 break; | |
127 case LeftBracketToken: | |
128 bracketCount++; | |
129 break; | |
130 case BadStringToken: | |
131 case BadUrlToken: | |
132 return false; | |
133 case WhitespaceToken: | |
134 break; | |
135 case SemicolonToken: | |
136 if (isTopLevelBlock) | |
137 return false; | |
138 break; | |
139 default: | |
140 break; | |
141 } | |
142 } | |
143 return true; | |
144 } | |
145 | |
146 static CSSValueID classifyVariableRange(CSSParserTokenRange range, bool& hasRefe rences) | |
147 { | |
148 hasReferences = false; | |
149 | |
150 range.consumeWhitespace(); | |
151 if (range.peek().type() == IdentToken) { | |
152 const CSSParserToken& ident = range.consumeIncludingWhitespace(); | |
Timothy Loh
2015/09/30 02:09:28
We have a helper function now so we can write
CSS
| |
153 if (range.atEnd()) { | |
154 if (ident.valueEqualsIgnoringCase("inherit")) | |
155 return CSSValueInherit; | |
156 if (ident.valueEqualsIgnoringCase("initial")) | |
157 return CSSValueInitial; | |
158 if (ident.valueEqualsIgnoringCase("unset")) | |
159 return CSSValueUnset; | |
160 } | |
161 } | |
162 | |
163 if (classifyBlock(range, hasReferences)) | |
164 return CSSValueInternalVariableValue; | |
165 return CSSValueInvalid; | |
166 } | |
167 | |
168 bool CSSVariableParser::containsValidVariableReferences(CSSParserTokenRange rang e) | |
169 { | |
170 bool hasReferences; | |
171 CSSValueID type = classifyVariableRange(range, hasReferences); | |
172 return type == CSSValueInternalVariableValue && hasReferences; | |
173 } | |
174 | |
175 PassRefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> CSSVariableParser::parseDec larationValue(const AtomicString& variableName, CSSParserTokenRange range) | |
176 { | |
177 if (range.atEnd()) | |
178 return nullptr; | |
179 | |
180 bool hasReferences; | |
181 CSSValueID type = classifyVariableRange(range, hasReferences); | |
182 | |
183 if (type == CSSValueInvalid) | |
184 return nullptr; | |
185 if (type == CSSValueInternalVariableValue) | |
186 return CSSCustomPropertyDeclaration::create(variableName, CSSVariableDat a::create(range, hasReferences)); | |
187 return CSSCustomPropertyDeclaration::create(variableName, type); | |
188 } | |
189 | |
190 } // namespace blink | |
OLD | NEW |