| Index: Source/core/css/parser/CSSParserValues.cpp
|
| diff --git a/Source/core/css/parser/CSSParserValues.cpp b/Source/core/css/parser/CSSParserValues.cpp
|
| index d86010f0531e0937090fa5b4e7a129e53a2b04dd..9fcbecc661d49c424f0e35adda7f35c94c16c4b4 100644
|
| --- a/Source/core/css/parser/CSSParserValues.cpp
|
| +++ b/Source/core/css/parser/CSSParserValues.cpp
|
| @@ -23,19 +23,33 @@
|
|
|
| #include "core/css/CSSFunctionValue.h"
|
| #include "core/css/CSSSelectorList.h"
|
| +#include "core/css/CSSVariableData.h"
|
| #include "core/css/parser/CSSParserToken.h"
|
| #include "core/css/parser/CSSParserTokenRange.h"
|
| #include "core/css/parser/CSSPropertyParser.h"
|
| +#include "core/css/parser/CSSTokenizer.h"
|
| +#include "core/css/parser/CSSVariableParser.h"
|
| #include "core/html/parser/HTMLParserIdioms.h"
|
| +#include "wtf/text/StringBuilder.h"
|
|
|
| namespace blink {
|
|
|
| using namespace WTF;
|
|
|
| -CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemUnits)
|
| +struct SameSizeAsCSSParserValue {
|
| + CSSValueID id;
|
| + CSSParserString valueUnion;
|
| + int unit;
|
| +};
|
| +
|
| +static_assert(sizeof(CSSParserValue) == sizeof(SameSizeAsCSSParserValue), "CSSParserValue should stay small");
|
| +
|
| +CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemUnits, bool& usesVariables)
|
| : m_current(0)
|
| {
|
| - usesRemUnits = false;
|
| + CSSParserTokenRange originalRangeForVariables = range;
|
| +
|
| + usesRemUnits = usesVariables = false;
|
| Vector<CSSParserValueList*> stack;
|
| Vector<int> bracketCounts;
|
| stack.append(this);
|
| @@ -51,7 +65,7 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU
|
| if (token.valueEqualsIgnoringCase("url")) {
|
| const CSSParserToken& next = range.consumeIncludingWhitespace();
|
| if (next.type() == BadStringToken || range.consume().type() != RightParenthesisToken) {
|
| - destroyAndClear();
|
| + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables);
|
| return;
|
| }
|
| ASSERT(next.type() == StringToken);
|
| @@ -60,6 +74,9 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU
|
| value.unit = CSSPrimitiveValue::CSS_URI;
|
| value.string = next.value();
|
| break;
|
| + } else if (token.valueEqualsIgnoringCase("var")) {
|
| + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables);
|
| + return;
|
| }
|
|
|
| CSSParserFunction* function = new CSSParserFunction;
|
| @@ -76,6 +93,8 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU
|
| stack.append(list);
|
| bracketCounts.append(0);
|
| calcDepth += (function->id == CSSValueCalc || function->id == CSSValueWebkitCalc);
|
| + if (function->id == CSSValueVar)
|
| + usesVariables = true;
|
| continue;
|
| }
|
| case LeftParenthesisToken: {
|
| @@ -96,7 +115,7 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU
|
| stack.removeLast();
|
| bracketCounts.removeLast();
|
| if (bracketCounts.isEmpty()) {
|
| - destroyAndClear();
|
| + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables);
|
| return;
|
| }
|
| CSSParserValueList* currentList = stack.last();
|
| @@ -171,6 +190,7 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU
|
| }
|
| case HashToken:
|
| case StringToken:
|
| + case VariableReferenceToken:
|
| case UrlToken: {
|
| value.id = CSSValueInvalid;
|
| value.isInt = false;
|
| @@ -187,7 +207,7 @@ CSSParserValueList::CSSParserValueList(CSSParserTokenRange range, bool& usesRemU
|
| value.setFromOperator(token.delimiter());
|
| if (calcDepth && token.delimiter() == '+' && (&token - 1)->type() != WhitespaceToken) {
|
| // calc(1px+ 2px) is invalid
|
| - destroyAndClear();
|
| + checkForVariableReferencesOrDestroyAndClear(originalRangeForVariables);
|
| return;
|
| }
|
| break;
|
| @@ -251,9 +271,30 @@ static void destroy(Vector<CSSParserValue, 4>& values)
|
| else if (values[i].unit == CSSParserValue::ValueList
|
| || values[i].unit == CSSParserValue::DimensionList)
|
| delete values[i].valueList;
|
| + else if (values[i].unit == CSSParserValue::VariableValue)
|
| + values[i].variableData->deref();
|
| }
|
| }
|
|
|
| +void CSSParserValueList::checkForVariableReferencesOrDestroyAndClear(const CSSParserTokenRange& originalRange)
|
| +{
|
| + // We have to clear any state that may have been previously loaded
|
| + destroyAndClear();
|
| + if (CSSVariableParser::containsValidVariableReferences(originalRange))
|
| + consumeVariableValue(originalRange);
|
| +}
|
| +
|
| +void CSSParserValueList::consumeVariableValue(const CSSParserTokenRange& originalRange)
|
| +{
|
| + ASSERT(m_values.isEmpty());
|
| + CSSParserValue variableValue;
|
| + variableValue.id = CSSValueInternalVariableValue;
|
| + variableValue.isInt = false;
|
| + variableValue.unit = CSSParserValue::VariableValue;
|
| + variableValue.variableData = CSSVariableData::create(originalRange).leakRef();
|
| + addValue(variableValue);
|
| +}
|
| +
|
| void CSSParserValueList::destroyAndClear()
|
| {
|
| destroy(m_values);
|
|
|