OLD | NEW |
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/CSSVariableData.h" | |
26 #include "core/css/parser/CSSParserToken.h" | 25 #include "core/css/parser/CSSParserToken.h" |
27 #include "core/css/parser/CSSParserTokenRange.h" | 26 #include "core/css/parser/CSSParserTokenRange.h" |
28 #include "core/css/parser/CSSPropertyParser.h" | 27 #include "core/css/parser/CSSPropertyParser.h" |
29 #include "core/css/parser/CSSVariableParser.h" | |
30 #include "core/html/parser/HTMLParserIdioms.h" | 28 #include "core/html/parser/HTMLParserIdioms.h" |
31 | 29 |
32 namespace blink { | 30 namespace blink { |
33 | 31 |
34 using namespace WTF; | 32 using namespace WTF; |
35 | 33 |
36 CSSParserValueList::CSSParserValueList(CSSParserTokenRange range) | 34 CSSParserValueList::CSSParserValueList(CSSParserTokenRange range) |
37 : m_current(0) | 35 : m_current(0) |
38 { | 36 { |
39 CSSParserTokenRange originalRangeForVariables = range; | |
40 | |
41 Vector<CSSParserValueList*> stack; | 37 Vector<CSSParserValueList*> stack; |
42 Vector<int> bracketCounts; | 38 Vector<int> bracketCounts; |
43 stack.append(this); | 39 stack.append(this); |
44 bracketCounts.append(0); | 40 bracketCounts.append(0); |
45 while (!range.atEnd()) { | 41 while (!range.atEnd()) { |
46 ASSERT(stack.size() == bracketCounts.size()); | 42 ASSERT(stack.size() == bracketCounts.size()); |
47 ASSERT(!stack.isEmpty()); | 43 ASSERT(!stack.isEmpty()); |
48 const CSSParserToken& token = range.peek(); | 44 const CSSParserToken& token = range.peek(); |
49 if (token.type() != FunctionToken) | 45 if (token.type() != FunctionToken) |
50 range.consume(); | 46 range.consume(); |
51 CSSParserValue value; | 47 CSSParserValue value; |
52 switch (token.type()) { | 48 switch (token.type()) { |
53 case FunctionToken: { | 49 case FunctionToken: { |
54 if (token.valueEqualsIgnoringCase("url")) { | 50 if (token.valueEqualsIgnoringCase("url")) { |
55 range.consume(); | 51 range.consume(); |
56 const CSSParserToken& next = range.consumeIncludingWhitespace(); | 52 const CSSParserToken& next = range.consumeIncludingWhitespace(); |
57 if (next.type() == BadStringToken || range.consume().type() != R
ightParenthesisToken) { | 53 if (next.type() == BadStringToken || range.consume().type() != R
ightParenthesisToken) { |
58 checkForVariableReferencesOrDestroyAndClear(originalRangeFor
Variables); | 54 destroyAndClear(); |
59 return; | 55 return; |
60 } | 56 } |
61 ASSERT(next.type() == StringToken); | 57 ASSERT(next.type() == StringToken); |
62 value.id = CSSValueInvalid; | 58 value.id = CSSValueInvalid; |
63 value.isInt = false; | 59 value.isInt = false; |
64 value.m_unit = CSSParserValue::URI; | 60 value.m_unit = CSSParserValue::URI; |
65 value.string = next.value(); | 61 value.string = next.value(); |
66 break; | 62 break; |
67 } else if (token.valueEqualsIgnoringCase("var")) { | |
68 checkForVariableReferencesOrDestroyAndClear(originalRangeForVari
ables); | |
69 return; | |
70 } | 63 } |
71 | 64 |
72 value.id = CSSValueInvalid; | 65 value.id = CSSValueInvalid; |
73 value.isInt = false; | 66 value.isInt = false; |
74 | 67 |
75 CSSValueID id = token.functionId(); | 68 CSSValueID id = token.functionId(); |
76 if (id == CSSValueCalc || id == CSSValueWebkitCalc) { | 69 if (id == CSSValueCalc || id == CSSValueWebkitCalc) { |
77 value.m_unit = CSSParserValue::CalcFunction; | 70 value.m_unit = CSSParserValue::CalcFunction; |
78 value.calcFunction = new CSSParserCalcFunction(range.consumeBloc
k()); | 71 value.calcFunction = new CSSParserCalcFunction(range.consumeBloc
k()); |
79 break; | 72 break; |
(...skipping 18 matching lines...) Expand all Loading... |
98 stack.last()->addValue(value); | 91 stack.last()->addValue(value); |
99 stack.append(list); | 92 stack.append(list); |
100 bracketCounts.append(0); | 93 bracketCounts.append(0); |
101 continue; | 94 continue; |
102 } | 95 } |
103 case RightParenthesisToken: { | 96 case RightParenthesisToken: { |
104 if (bracketCounts.last() == 0) { | 97 if (bracketCounts.last() == 0) { |
105 stack.removeLast(); | 98 stack.removeLast(); |
106 bracketCounts.removeLast(); | 99 bracketCounts.removeLast(); |
107 if (bracketCounts.isEmpty()) { | 100 if (bracketCounts.isEmpty()) { |
108 checkForVariableReferencesOrDestroyAndClear(originalRangeFor
Variables); | 101 destroyAndClear(); |
109 return; | 102 return; |
110 } | 103 } |
111 continue; | 104 continue; |
112 } | 105 } |
113 bracketCounts.last()--; | 106 bracketCounts.last()--; |
114 value.setFromOperator(')'); | 107 value.setFromOperator(')'); |
115 break; | 108 break; |
116 } | 109 } |
117 case IdentToken: { | 110 case IdentToken: { |
118 value.id = token.id(); | 111 value.id = token.id(); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 ASSERT_NOT_REACHED(); | 195 ASSERT_NOT_REACHED(); |
203 case CDOToken: | 196 case CDOToken: |
204 case CDCToken: | 197 case CDCToken: |
205 case AtKeywordToken: | 198 case AtKeywordToken: |
206 case IncludeMatchToken: | 199 case IncludeMatchToken: |
207 case DashMatchToken: | 200 case DashMatchToken: |
208 case PrefixMatchToken: | 201 case PrefixMatchToken: |
209 case SuffixMatchToken: | 202 case SuffixMatchToken: |
210 case SubstringMatchToken: | 203 case SubstringMatchToken: |
211 case ColumnToken: | 204 case ColumnToken: |
| 205 case BadStringToken: |
| 206 case BadUrlToken: |
212 case ColonToken: | 207 case ColonToken: |
213 case SemicolonToken: | 208 case SemicolonToken: |
214 checkForVariableReferencesOrDestroyAndClear(originalRangeForVariable
s); | |
215 return; | |
216 case BadStringToken: | |
217 case BadUrlToken: | |
218 destroyAndClear(); | 209 destroyAndClear(); |
219 return; | 210 return; |
220 } | 211 } |
221 stack.last()->addValue(value); | 212 stack.last()->addValue(value); |
222 } | 213 } |
223 | 214 |
224 CSSParserValue rightParenthesis; | 215 CSSParserValue rightParenthesis; |
225 rightParenthesis.setFromOperator(')'); | 216 rightParenthesis.setFromOperator(')'); |
226 while (!stack.isEmpty()) { | 217 while (!stack.isEmpty()) { |
227 while (bracketCounts.last() > 0) { | 218 while (bracketCounts.last() > 0) { |
228 bracketCounts.last()--; | 219 bracketCounts.last()--; |
229 stack.last()->addValue(rightParenthesis); | 220 stack.last()->addValue(rightParenthesis); |
230 } | 221 } |
231 stack.removeLast(); | 222 stack.removeLast(); |
232 bracketCounts.removeLast(); | 223 bracketCounts.removeLast(); |
233 } | 224 } |
234 } | 225 } |
235 | 226 |
236 static void destroy(Vector<CSSParserValue, 4>& values) | 227 static void destroy(Vector<CSSParserValue, 4>& values) |
237 { | 228 { |
238 size_t numValues = values.size(); | 229 size_t numValues = values.size(); |
239 for (size_t i = 0; i < numValues; i++) { | 230 for (size_t i = 0; i < numValues; i++) { |
240 if (values[i].m_unit == CSSParserValue::Function) | 231 if (values[i].m_unit == CSSParserValue::Function) |
241 delete values[i].function; | 232 delete values[i].function; |
242 else if (values[i].m_unit == CSSParserValue::CalcFunction) | 233 else if (values[i].m_unit == CSSParserValue::CalcFunction) |
243 delete values[i].calcFunction; | 234 delete values[i].calcFunction; |
244 else if (values[i].m_unit == CSSParserValue::ValueList | 235 else if (values[i].m_unit == CSSParserValue::ValueList |
245 || values[i].m_unit == CSSParserValue::DimensionList) | 236 || values[i].m_unit == CSSParserValue::DimensionList) |
246 delete values[i].valueList; | 237 delete values[i].valueList; |
247 else if (values[i].id == CSSValueInternalVariableValue) | |
248 values[i].variableData->deref(); | |
249 } | 238 } |
250 } | 239 } |
251 | 240 |
252 void CSSParserValueList::checkForVariableReferencesOrDestroyAndClear(const CSSPa
rserTokenRange& originalRange) | |
253 { | |
254 // We have to clear any state that may have been previously loaded | |
255 destroyAndClear(); | |
256 if (RuntimeEnabledFeatures::cssVariablesEnabled() && CSSVariableParser::cont
ainsValidVariableReferences(originalRange)) | |
257 consumeVariableValue(originalRange); | |
258 } | |
259 | |
260 void CSSParserValueList::consumeVariableValue(const CSSParserTokenRange& origina
lRange) | |
261 { | |
262 ASSERT(m_values.isEmpty()); | |
263 CSSParserValue variableValue; | |
264 variableValue.id = CSSValueInternalVariableValue; | |
265 variableValue.isInt = false; | |
266 variableValue.variableData = CSSVariableData::create(originalRange).leakRef(
); | |
267 addValue(variableValue); | |
268 } | |
269 | |
270 | |
271 void CSSParserValueList::destroyAndClear() | 241 void CSSParserValueList::destroyAndClear() |
272 { | 242 { |
273 destroy(m_values); | 243 destroy(m_values); |
274 clearAndLeakValues(); | 244 clearAndLeakValues(); |
275 } | 245 } |
276 | 246 |
277 CSSParserValueList::~CSSParserValueList() | 247 CSSParserValueList::~CSSParserValueList() |
278 { | 248 { |
279 destroy(m_values); | 249 destroy(m_values); |
280 } | 250 } |
281 | 251 |
282 void CSSParserValueList::addValue(const CSSParserValue& v) | 252 void CSSParserValueList::addValue(const CSSParserValue& v) |
283 { | 253 { |
284 m_values.append(v); | 254 m_values.append(v); |
285 } | 255 } |
286 | 256 |
287 } // namespace blink | 257 } // namespace blink |
OLD | NEW |