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

Side by Side Diff: Source/core/css/parser/CSSParserValues.cpp

Issue 1192983003: CSS Custom Properties (Variables) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details. 13 * Library General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU Library General Public License 15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to 16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA. 18 * Boston, MA 02110-1301, USA.
19 */ 19 */
20 20
21 #include "config.h" 21 #include "config.h"
22 #include "core/css/parser/CSSParserValues.h" 22 #include "core/css/parser/CSSParserValues.h"
23 23
24 #include "core/css/CSSFunctionValue.h" 24 #include "core/css/CSSFunctionValue.h"
25 #include "core/css/CSSSelectorList.h" 25 #include "core/css/CSSSelectorList.h"
26 #include "core/css/CSSVariableData.h"
26 #include "core/css/parser/CSSParserToken.h" 27 #include "core/css/parser/CSSParserToken.h"
27 #include "core/css/parser/CSSParserTokenRange.h" 28 #include "core/css/parser/CSSParserTokenRange.h"
28 #include "core/css/parser/CSSPropertyParser.h" 29 #include "core/css/parser/CSSPropertyParser.h"
30 #include "core/css/parser/CSSTokenizer.h"
31 #include "core/css/parser/CSSVariableParser.h"
29 #include "core/html/parser/HTMLParserIdioms.h" 32 #include "core/html/parser/HTMLParserIdioms.h"
33 #include "wtf/text/StringBuilder.h"
30 34
31 namespace blink { 35 namespace blink {
32 36
33 using namespace WTF; 37 using namespace WTF;
34 38
35 CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU nits) 39 struct SameSizeAsCSSParserValue {
40 CSSValueID id;
41 CSSParserString valueUnion;
42 int unit;
43 };
44
45 static_assert(sizeof(CSSParserValue) == sizeof(SameSizeAsCSSParserValue), "CSSPa rserValue should stay small");
46
47 CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU nits, bool& usesVariables)
36 : m_current(0) 48 : m_current(0)
37 { 49 {
38 usesRemUnits = false; 50 CSSParserTokenRange originalRangeForVariables = range;
51
52 usesRemUnits = usesVariables = false;
39 Vector<CSSParserValueList*> stack; 53 Vector<CSSParserValueList*> stack;
40 Vector<int> bracketCounts; 54 Vector<int> bracketCounts;
41 stack.append(this); 55 stack.append(this);
42 bracketCounts.append(0); 56 bracketCounts.append(0);
43 unsigned calcDepth = 0; 57 unsigned calcDepth = 0;
44 while (!range.atEnd()) { 58 while (!range.atEnd()) {
45 ASSERT(stack.size() == bracketCounts.size()); 59 ASSERT(stack.size() == bracketCounts.size());
46 ASSERT(!stack.isEmpty()); 60 ASSERT(!stack.isEmpty());
47 const CSSParserToken& token = range.consume(); 61 const CSSParserToken& token = range.consume();
48 CSSParserValue value; 62 CSSParserValue value;
49 switch (token.type()) { 63 switch (token.type()) {
50 case FunctionToken: { 64 case FunctionToken: {
51 if (token.valueEqualsIgnoringCase("url")) { 65 if (token.valueEqualsIgnoringCase("url")) {
52 const CSSParserToken& next = range.consumeIncludingWhitespace(); 66 const CSSParserToken& next = range.consumeIncludingWhitespace();
53 if (next.type() == BadStringToken || range.consume().type() != R ightParenthesisToken) { 67 if (next.type() == BadStringToken || range.consume().type() != R ightParenthesisToken) {
54 destroyAndClear(); 68 checkForVariableReferencesOrDestroyAndClear(originalRangeFor Variables);
55 return; 69 return;
56 } 70 }
57 ASSERT(next.type() == StringToken); 71 ASSERT(next.type() == StringToken);
58 value.id = CSSValueInvalid; 72 value.id = CSSValueInvalid;
59 value.isInt = false; 73 value.isInt = false;
60 value.unit = CSSPrimitiveValue::CSS_URI; 74 value.unit = CSSPrimitiveValue::CSS_URI;
61 value.string = next.value(); 75 value.string = next.value();
62 break; 76 break;
77 } else if (token.valueEqualsIgnoringCase("var")) {
78 checkForVariableReferencesOrDestroyAndClear(originalRangeForVari ables);
79 return;
63 } 80 }
64 81
65 CSSParserFunction* function = new CSSParserFunction; 82 CSSParserFunction* function = new CSSParserFunction;
66 function->id = cssValueKeywordID(token.value()); 83 function->id = cssValueKeywordID(token.value());
67 CSSParserValueList* list = new CSSParserValueList; 84 CSSParserValueList* list = new CSSParserValueList;
68 function->args = adoptPtr(list); 85 function->args = adoptPtr(list);
69 86
70 value.id = CSSValueInvalid; 87 value.id = CSSValueInvalid;
71 value.isInt = false; 88 value.isInt = false;
72 value.unit = CSSParserValue::Function; 89 value.unit = CSSParserValue::Function;
73 value.function = function; 90 value.function = function;
74 91
75 stack.last()->addValue(value); 92 stack.last()->addValue(value);
76 stack.append(list); 93 stack.append(list);
77 bracketCounts.append(0); 94 bracketCounts.append(0);
78 calcDepth += (function->id == CSSValueCalc || function->id == CSSVal ueWebkitCalc); 95 calcDepth += (function->id == CSSValueCalc || function->id == CSSVal ueWebkitCalc);
96 if (function->id == CSSValueVar)
97 usesVariables = true;
79 continue; 98 continue;
80 } 99 }
81 case LeftParenthesisToken: { 100 case LeftParenthesisToken: {
82 if (calcDepth == 0) { 101 if (calcDepth == 0) {
83 CSSParserValueList* list = new CSSParserValueList; 102 CSSParserValueList* list = new CSSParserValueList;
84 value.setFromValueList(adoptPtr(list)); 103 value.setFromValueList(adoptPtr(list));
85 stack.last()->addValue(value); 104 stack.last()->addValue(value);
86 stack.append(list); 105 stack.append(list);
87 bracketCounts.append(0); 106 bracketCounts.append(0);
88 continue; 107 continue;
89 } 108 }
90 bracketCounts.last()++; 109 bracketCounts.last()++;
91 value.setFromOperator('('); 110 value.setFromOperator('(');
92 break; 111 break;
93 } 112 }
94 case RightParenthesisToken: { 113 case RightParenthesisToken: {
95 if (bracketCounts.last() == 0) { 114 if (bracketCounts.last() == 0) {
96 stack.removeLast(); 115 stack.removeLast();
97 bracketCounts.removeLast(); 116 bracketCounts.removeLast();
98 if (bracketCounts.isEmpty()) { 117 if (bracketCounts.isEmpty()) {
99 destroyAndClear(); 118 checkForVariableReferencesOrDestroyAndClear(originalRangeFor Variables);
100 return; 119 return;
101 } 120 }
102 CSSParserValueList* currentList = stack.last(); 121 CSSParserValueList* currentList = stack.last();
103 CSSParserValue* current = currentList->valueAt(currentList->size ()-1); 122 CSSParserValue* current = currentList->valueAt(currentList->size ()-1);
104 if (current->unit == CSSParserValue::Function) { 123 if (current->unit == CSSParserValue::Function) {
105 CSSValueID id = current->function->id; 124 CSSValueID id = current->function->id;
106 calcDepth -= (id == CSSValueCalc || id == CSSValueWebkitCalc ); 125 calcDepth -= (id == CSSValueCalc || id == CSSValueWebkitCalc );
107 } 126 }
108 continue; 127 continue;
109 } 128 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 case UnicodeRangeToken: { 183 case UnicodeRangeToken: {
165 value.id = CSSValueInvalid; 184 value.id = CSSValueInvalid;
166 value.isInt = false; 185 value.isInt = false;
167 value.m_unicodeRange.start = token.unicodeRangeStart(); 186 value.m_unicodeRange.start = token.unicodeRangeStart();
168 value.m_unicodeRange.end = token.unicodeRangeEnd(); 187 value.m_unicodeRange.end = token.unicodeRangeEnd();
169 value.unit = CSSParserValue::UnicodeRange; 188 value.unit = CSSParserValue::UnicodeRange;
170 break; 189 break;
171 } 190 }
172 case HashToken: 191 case HashToken:
173 case StringToken: 192 case StringToken:
193 case VariableReferenceToken:
174 case UrlToken: { 194 case UrlToken: {
175 value.id = CSSValueInvalid; 195 value.id = CSSValueInvalid;
176 value.isInt = false; 196 value.isInt = false;
177 if (token.type() == HashToken) 197 if (token.type() == HashToken)
178 value.unit = CSSParserValue::HexColor; 198 value.unit = CSSParserValue::HexColor;
179 else if (token.type() == StringToken) 199 else if (token.type() == StringToken)
180 value.unit = CSSPrimitiveValue::CSS_STRING; 200 value.unit = CSSPrimitiveValue::CSS_STRING;
181 else 201 else
182 value.unit = CSSPrimitiveValue::CSS_URI; 202 value.unit = CSSPrimitiveValue::CSS_URI;
183 value.string = token.value(); 203 value.string = token.value();
184 break; 204 break;
185 } 205 }
186 case DelimiterToken: 206 case DelimiterToken:
187 value.setFromOperator(token.delimiter()); 207 value.setFromOperator(token.delimiter());
188 if (calcDepth && token.delimiter() == '+' && (&token - 1)->type() != WhitespaceToken) { 208 if (calcDepth && token.delimiter() == '+' && (&token - 1)->type() != WhitespaceToken) {
189 // calc(1px+ 2px) is invalid 209 // calc(1px+ 2px) is invalid
190 destroyAndClear(); 210 checkForVariableReferencesOrDestroyAndClear(originalRangeForVari ables);
191 return; 211 return;
192 } 212 }
193 break; 213 break;
194 case CommaToken: 214 case CommaToken:
195 value.setFromOperator(','); 215 value.setFromOperator(',');
196 break; 216 break;
197 case LeftBracketToken: 217 case LeftBracketToken:
198 value.setFromOperator('['); 218 value.setFromOperator('[');
199 break; 219 break;
200 case RightBracketToken: 220 case RightBracketToken:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 264
245 static void destroy(Vector<CSSParserValue, 4>& values) 265 static void destroy(Vector<CSSParserValue, 4>& values)
246 { 266 {
247 size_t numValues = values.size(); 267 size_t numValues = values.size();
248 for (size_t i = 0; i < numValues; i++) { 268 for (size_t i = 0; i < numValues; i++) {
249 if (values[i].unit == CSSParserValue::Function) 269 if (values[i].unit == CSSParserValue::Function)
250 delete values[i].function; 270 delete values[i].function;
251 else if (values[i].unit == CSSParserValue::ValueList 271 else if (values[i].unit == CSSParserValue::ValueList
252 || values[i].unit == CSSParserValue::DimensionList) 272 || values[i].unit == CSSParserValue::DimensionList)
253 delete values[i].valueList; 273 delete values[i].valueList;
274 else if (values[i].unit == CSSParserValue::VariableValue)
275 values[i].variableData->deref();
254 } 276 }
255 } 277 }
256 278
279 void CSSParserValueList::checkForVariableReferencesOrDestroyAndClear(const CSSPa rserTokenRange& originalRange)
280 {
281 // We have to clear any state that may have been previously loaded
282 destroyAndClear();
283 if (CSSVariableParser::containsValidVariableReferences(originalRange))
284 consumeVariableValue(originalRange);
285 }
286
287 void CSSParserValueList::consumeVariableValue(const CSSParserTokenRange& origina lRange)
288 {
289 ASSERT(m_values.isEmpty());
290 CSSParserValue variableValue;
291 variableValue.id = CSSValueInternalVariableValue;
292 variableValue.isInt = false;
293 variableValue.unit = CSSParserValue::VariableValue;
294 variableValue.variableData = CSSVariableData::create(originalRange).leakRef( );
295 addValue(variableValue);
296 }
297
257 void CSSParserValueList::destroyAndClear() 298 void CSSParserValueList::destroyAndClear()
258 { 299 {
259 destroy(m_values); 300 destroy(m_values);
260 clearAndLeakValues(); 301 clearAndLeakValues();
261 } 302 }
262 303
263 CSSParserValueList::~CSSParserValueList() 304 CSSParserValueList::~CSSParserValueList()
264 { 305 {
265 destroy(m_values); 306 destroy(m_values);
266 } 307 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 bool CSSParserSelector::hasHostPseudoSelector() const 398 bool CSSParserSelector::hasHostPseudoSelector() const
358 { 399 {
359 for (CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); sel ector; selector = selector->tagHistory()) { 400 for (CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); sel ector; selector = selector->tagHistory()) {
360 if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseud oType() == CSSSelector::PseudoHostContext) 401 if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseud oType() == CSSSelector::PseudoHostContext)
361 return true; 402 return true;
362 } 403 }
363 return false; 404 return false;
364 } 405 }
365 406
366 } // namespace blink 407 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698