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/CSSCustomVariableValue.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 { | |
Timothy Loh
2015/08/25 09:21:10
Probably a good idea to check the token type is an
| |
16 CSSParserString value = token.value(); | |
17 return value.length() >= 2 && value[0] == '-' && value[0] == value[1]; | |
Timothy Loh
2015/08/25 09:21:11
err.. value[1] == '-'?
| |
18 } | |
19 | |
20 static bool isValidVariableReference(CSSParserTokenRange& range) | |
Timothy Loh
2015/08/25 09:21:10
Use consumeBlock in the calling function and make
| |
21 { | |
22 bool foundVariableIdentToken = false; | |
23 bool foundComma = false; | |
24 bool contentAfterComma = false; | |
25 | |
26 // TODO(leviw): Use CSSParserToken::BlockType signals instead of checking fo r these directly. | |
27 int parenthesisCount = 0; | |
28 int braceCount = 0; | |
29 int bracketCount = 0; | |
30 while (!range.atEnd()) { | |
31 const CSSParserToken& token = range.consume(); | |
32 | |
33 if (!foundVariableIdentToken) { | |
Timothy Loh
2015/08/25 09:21:10
This would be easier without the state machine loo
| |
34 if (token.type() == IdentToken) { | |
35 if (!isValidVariableName(token)) | |
36 return false; | |
37 foundVariableIdentToken = true; | |
38 } else if (token.type() != WhitespaceToken) { | |
39 return false; | |
40 } | |
41 continue; | |
42 } | |
43 | |
44 if (!foundComma) { | |
45 if (token.type() == CommaToken) | |
46 foundComma = true; | |
47 else if (token.type() == RightParenthesisToken) | |
48 return true; | |
49 else if (token.type() != WhitespaceToken) | |
50 return false; | |
51 continue; | |
52 } | |
53 | |
54 if (!contentAfterComma) { | |
55 if (token.type() == RightParenthesisToken) | |
56 return false; | |
57 contentAfterComma = true; | |
58 } | |
59 | |
60 switch (token.type()) { | |
61 case DelimiterToken: | |
62 if (token.delimiter() == '!' && !parenthesisCount && !bracketCount & & !braceCount) | |
63 return false; | |
64 break; | |
65 case FunctionToken: | |
66 case LeftParenthesisToken: | |
67 parenthesisCount++; | |
68 break; | |
69 case RightParenthesisToken: | |
70 if (!parenthesisCount) | |
71 return true; | |
72 parenthesisCount--; | |
73 break; | |
74 case RightBraceToken: | |
75 if (!braceCount) | |
76 return false; | |
77 braceCount--; | |
78 break; | |
79 case LeftBraceToken: | |
80 braceCount++; | |
81 break; | |
82 case RightBracketToken: | |
83 if (!bracketCount) | |
84 return false; | |
85 bracketCount--; | |
86 break; | |
87 case LeftBracketToken: | |
88 bracketCount++; | |
89 break; | |
90 case BadStringToken: | |
91 case BadUrlToken: | |
92 return false; | |
93 case CommentToken: | |
94 case EOFToken: | |
95 ASSERT_NOT_REACHED(); | |
96 case SemicolonToken: | |
97 if (!parenthesisCount && !bracketCount && !braceCount) | |
98 return false; | |
99 break; | |
100 default: | |
101 break; | |
102 } | |
103 } | |
104 return foundVariableIdentToken && (!foundComma || contentAfterComma); | |
105 } | |
106 | |
107 static CSSValueID classifyVariableRange(CSSParserTokenRange& originalRange, bool & hasReferences) | |
Timothy Loh
2015/08/25 09:21:11
CSSParserTokenRange& originalRange -> CSSParserTok
| |
108 { | |
109 hasReferences = false; | |
110 CSSParserTokenRange range = originalRange; | |
111 | |
112 int parenthesisCount = 0; | |
113 int braceCount = 0; | |
114 int bracketCount = 0; | |
115 | |
116 range.consumeWhitespace(); | |
117 if (range.peek().type() == IdentToken) { | |
118 const CSSParserToken& ident = range.consumeIncludingWhitespace(); | |
119 if (range.atEnd()) { | |
120 if (ident.valueEqualsIgnoringCase("inherit")) | |
121 return CSSValueInherit; | |
122 if (ident.valueEqualsIgnoringCase("initial")) | |
123 return CSSValueInitial; | |
124 if (ident.valueEqualsIgnoringCase("unset")) | |
125 return CSSValueUnset; | |
126 } | |
127 } | |
128 | |
129 // TODO(leviw): Use consumeBlock to keep track of nesting instead of doing i t directly here. | |
130 while (!range.atEnd()) { | |
131 const CSSParserToken& token = range.consume(); | |
132 switch (token.type()) { | |
133 case FunctionToken: | |
134 if (token.valueEqualsIgnoringCase("var")) { | |
135 if (!isValidVariableReference(range)) | |
136 return CSSValueInvalid; // Bail if any references are invali d | |
137 hasReferences = true; | |
138 } else { | |
139 parenthesisCount++; | |
140 } | |
141 break; | |
142 case CommentToken: | |
143 case EOFToken: | |
144 ASSERT_NOT_REACHED(); | |
145 case DelimiterToken: { | |
146 if (token.delimiter() == '!' && !parenthesisCount && !bracketCount & & !braceCount) | |
147 return CSSValueInvalid; | |
148 break; | |
149 } | |
150 case RightParenthesisToken: | |
151 if (!parenthesisCount) | |
152 return CSSValueInvalid; | |
153 parenthesisCount--; | |
154 break; | |
155 case LeftParenthesisToken: | |
156 parenthesisCount++; | |
157 break; | |
158 case RightBraceToken: | |
159 if (!braceCount) | |
160 return CSSValueInvalid; | |
161 braceCount--; | |
162 break; | |
163 case LeftBraceToken: | |
164 braceCount++; | |
165 break; | |
166 case RightBracketToken: | |
167 if (!bracketCount) | |
168 return CSSValueInvalid; | |
169 bracketCount--; | |
170 break; | |
171 case LeftBracketToken: | |
172 bracketCount++; | |
173 break; | |
174 case BadStringToken: | |
175 case BadUrlToken: | |
176 return CSSValueInvalid; | |
177 case WhitespaceToken: | |
178 break; | |
179 case SemicolonToken: | |
180 if (!parenthesisCount && !bracketCount && !braceCount) | |
181 return CSSValueInvalid; | |
182 default: | |
183 break; | |
184 } | |
185 } | |
186 if (parenthesisCount) | |
187 return CSSValueInvalid; | |
188 return CSSValueInternalVariableValue; | |
189 } | |
190 | |
191 bool CSSVariableParser::containsValidVariableReferences(const CSSParserTokenRang e& originalRange) | |
Timothy Loh
2015/08/25 09:21:10
CSSParserTokenRange& originalRange -> CSSParserTok
| |
192 { | |
193 CSSParserTokenRange range = originalRange; | |
194 bool hasReferences; | |
195 CSSValueID type = classifyVariableRange(range, hasReferences); | |
196 return type == CSSValueInternalVariableValue && hasReferences; | |
197 } | |
198 | |
199 PassRefPtrWillBeRawPtr<CSSCustomVariableValue> CSSVariableParser::parseDeclarati onValue(const AtomicString& variableName, CSSParserTokenRange& originalRange) | |
Timothy Loh
2015/08/25 09:21:11
CSSParserTokenRange& originalRange -> CSSParserTok
| |
200 { | |
201 if (originalRange.atEnd()) | |
202 return nullptr; | |
203 | |
204 bool hasReferences; | |
205 CSSValueID type = classifyVariableRange(originalRange, hasReferences); | |
206 | |
207 if (type == CSSValueInvalid) | |
208 return nullptr; | |
209 if (type == CSSValueInternalVariableValue) | |
210 return CSSCustomVariableValue::create(variableName, CSSVariableData::cre ate(originalRange, hasReferences)); | |
211 return CSSCustomVariableValue::create(variableName, type); | |
212 } | |
213 | |
214 } // namespace blink | |
OLD | NEW |