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

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: with missing files 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 case UnicodeRangeToken: { 177 case UnicodeRangeToken: {
159 value.id = CSSValueInvalid; 178 value.id = CSSValueInvalid;
160 value.isInt = false; 179 value.isInt = false;
161 value.m_unicodeRange.start = token.unicodeRangeStart(); 180 value.m_unicodeRange.start = token.unicodeRangeStart();
162 value.m_unicodeRange.end = token.unicodeRangeEnd(); 181 value.m_unicodeRange.end = token.unicodeRangeEnd();
163 value.unit = CSSParserValue::UnicodeRange; 182 value.unit = CSSParserValue::UnicodeRange;
164 break; 183 break;
165 } 184 }
166 case HashToken: 185 case HashToken:
167 case StringToken: 186 case StringToken:
187 case VariableReferenceToken:
168 case UrlToken: { 188 case UrlToken: {
169 value.id = CSSValueInvalid; 189 value.id = CSSValueInvalid;
170 value.isInt = false; 190 value.isInt = false;
171 if (token.type() == HashToken) 191 if (token.type() == HashToken)
172 value.unit = CSSParserValue::HexColor; 192 value.unit = CSSParserValue::HexColor;
173 else if (token.type() == StringToken) 193 else if (token.type() == StringToken)
174 value.unit = CSSPrimitiveValue::CSS_STRING; 194 value.unit = CSSPrimitiveValue::CSS_STRING;
175 else 195 else
176 value.unit = CSSPrimitiveValue::CSS_URI; 196 value.unit = CSSPrimitiveValue::CSS_URI;
177 value.string = token.value(); 197 value.string = token.value();
178 break; 198 break;
179 } 199 }
180 case DelimiterToken: 200 case DelimiterToken:
181 value.setFromOperator(token.delimiter()); 201 value.setFromOperator(token.delimiter());
182 if (calcDepth && token.delimiter() == '+' && (&token - 1)->type() != WhitespaceToken) { 202 if (calcDepth && token.delimiter() == '+' && (&token - 1)->type() != WhitespaceToken) {
183 // calc(1px+ 2px) is invalid 203 // calc(1px+ 2px) is invalid
184 destroyAndClear(); 204 checkForVariableReferencesOrDestroyAndClear(originalRangeForVari ables);
185 return; 205 return;
186 } 206 }
187 break; 207 break;
188 case CommaToken: 208 case CommaToken:
189 value.setFromOperator(','); 209 value.setFromOperator(',');
190 break; 210 break;
191 case LeftBracketToken: 211 case LeftBracketToken:
192 value.setFromOperator('['); 212 value.setFromOperator('[');
193 break; 213 break;
194 case RightBracketToken: 214 case RightBracketToken:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 258
239 static void destroy(Vector<CSSParserValue, 4>& values) 259 static void destroy(Vector<CSSParserValue, 4>& values)
240 { 260 {
241 size_t numValues = values.size(); 261 size_t numValues = values.size();
242 for (size_t i = 0; i < numValues; i++) { 262 for (size_t i = 0; i < numValues; i++) {
243 if (values[i].unit == CSSParserValue::Function) 263 if (values[i].unit == CSSParserValue::Function)
244 delete values[i].function; 264 delete values[i].function;
245 else if (values[i].unit == CSSParserValue::ValueList 265 else if (values[i].unit == CSSParserValue::ValueList
246 || values[i].unit == CSSParserValue::DimensionList) 266 || values[i].unit == CSSParserValue::DimensionList)
247 delete values[i].valueList; 267 delete values[i].valueList;
268 else if (values[i].unit == CSSParserValue::VariableValue)
269 values[i].variableData->deref();
248 } 270 }
249 } 271 }
250 272
273 void CSSParserValueList::checkForVariableReferencesOrDestroyAndClear(const CSSPa rserTokenRange& originalRange)
274 {
275 // We have to clear any state that may have been previously loaded
276 destroyAndClear();
277 if (CSSVariableParser::containsValidVariableReferences(originalRange))
278 consumeVariableValue(originalRange);
279 }
280
281 void CSSParserValueList::consumeVariableValue(const CSSParserTokenRange& origina lRange)
282 {
283 ASSERT(m_values.isEmpty());
284 CSSParserValue variableValue;
285 variableValue.id = CSSValueInternalVariableValue;
286 variableValue.isInt = false;
287 variableValue.unit = CSSParserValue::VariableValue;
288 variableValue.variableData = CSSVariableData::create(originalRange).leakRef( );
289 addValue(variableValue);
290 }
291
251 void CSSParserValueList::destroyAndClear() 292 void CSSParserValueList::destroyAndClear()
252 { 293 {
253 destroy(m_values); 294 destroy(m_values);
254 clearAndLeakValues(); 295 clearAndLeakValues();
255 } 296 }
256 297
257 CSSParserValueList::~CSSParserValueList() 298 CSSParserValueList::~CSSParserValueList()
258 { 299 {
259 destroy(m_values); 300 destroy(m_values);
260 } 301 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 bool CSSParserSelector::hasHostPseudoSelector() const 392 bool CSSParserSelector::hasHostPseudoSelector() const
352 { 393 {
353 for (CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); sel ector; selector = selector->tagHistory()) { 394 for (CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); sel ector; selector = selector->tagHistory()) {
354 if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseud oType() == CSSSelector::PseudoHostContext) 395 if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseud oType() == CSSSelector::PseudoHostContext)
355 return true; 396 return true;
356 } 397 }
357 return false; 398 return false;
358 } 399 }
359 400
360 } // namespace blink 401 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698