Index: third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp |
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp |
index 47405f90588436f7d411e4038c95792cb5b3e9f0..21ba3a2570db92fc01d57ed7d1656a39d04cb1ee 100644 |
--- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp |
+++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp |
@@ -28,73 +28,72 @@ bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range, Vector<CSSP |
return false; |
ASSERT(range.peek().type() == CommaToken); |
range.consume(); |
- return resolveVariableReferencesFromTokens(range, result); |
+ return resolveTokenRange(range, result); |
} |
-bool CSSVariableResolver::resolveVariableTokensRecursive(CSSParserTokenRange range, |
- Vector<CSSParserToken>& result) |
+CSSVariableData* CSSVariableResolver::valueForCustomProperty(AtomicString name) |
+{ |
+ if (m_variablesSeen.contains(name)) { |
+ m_cycleStartPoints.add(name); |
+ return nullptr; |
+ } |
+ |
+ if (!m_styleVariableData) |
+ return nullptr; |
+ CSSVariableData* variableData = m_styleVariableData->getVariable(name); |
+ if (!variableData) |
+ return nullptr; |
+ if (!variableData->needsVariableResolution()) |
+ return variableData; |
+ RefPtr<CSSVariableData> newVariableData = resolveCustomProperty(name, *variableData); |
+ m_styleVariableData->setVariable(name, newVariableData); |
+ return newVariableData.get(); |
+} |
+ |
+PassRefPtr<CSSVariableData> CSSVariableResolver::resolveCustomProperty(AtomicString name, const CSSVariableData& variableData) |
+{ |
+ ASSERT(variableData.needsVariableResolution()); |
+ |
+ Vector<CSSParserToken> tokens; |
+ m_variablesSeen.add(name); |
+ bool success = resolveTokenRange(variableData.tokens(), tokens); |
+ m_variablesSeen.remove(name); |
+ |
+ // The old variable data holds onto the backing string the new resolved CSSVariableData |
+ // relies on. Ensure it will live beyond us overwriting the RefPtr in StyleVariableData. |
+ ASSERT(variableData.refCount() > 1); |
+ |
+ if (!success || !m_cycleStartPoints.isEmpty()) { |
+ m_cycleStartPoints.remove(name); |
+ return nullptr; |
+ } |
+ return CSSVariableData::createResolved(tokens, variableData); |
+} |
+ |
+bool CSSVariableResolver::resolveVariableReference(CSSParserTokenRange range, Vector<CSSParserToken>& result) |
{ |
- Vector<CSSParserToken> trash; |
range.consumeWhitespace(); |
ASSERT(range.peek().type() == IdentToken); |
AtomicString variableName = range.consumeIncludingWhitespace().value(); |
ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); |
- // Cycle detection. |
- if (m_variablesSeen.contains(variableName)) { |
- m_cycleStartPoints.add(variableName); |
- resolveFallback(range, trash); |
- return false; |
- } |
- |
- CSSVariableData* variableData = m_styleVariableData ? m_styleVariableData->getVariable(variableName) : nullptr; |
- if (variableData) { |
- Vector<CSSParserToken> tokens; |
- if (variableData->needsVariableResolution()) { |
- m_variablesSeen.add(variableName); |
- bool referenceValid = resolveVariableReferencesFromTokens(variableData->tokens(), tokens); |
- m_variablesSeen.remove(variableName); |
- |
- // The old variable data holds onto the backing string the new resolved CSSVariableData |
- // relies on. Ensure it will live beyond us overwriting the RefPtr in StyleVariableData. |
- ASSERT(variableData->refCount() > 1); |
- |
- if (!referenceValid || !m_cycleStartPoints.isEmpty()) { |
- m_styleVariableData->setVariable(variableName, nullptr); |
- m_cycleStartPoints.remove(variableName); |
- if (!m_cycleStartPoints.isEmpty()) { |
- resolveFallback(range, trash); |
- return false; |
- } |
- return resolveFallback(range, result); |
- } |
- |
- m_styleVariableData->setVariable(variableName, CSSVariableData::createResolved(tokens, variableData)); |
- } else { |
- tokens = variableData->tokens(); |
- } |
+ CSSVariableData* variableData = valueForCustomProperty(variableName); |
+ if (!variableData) |
+ return resolveFallback(range, result); |
- ASSERT(!tokens.isEmpty()); |
- // Check that loops are not induced by the fallback. |
- resolveFallback(range, trash); |
- if (m_cycleStartPoints.isEmpty()) { |
- // It's OK if the fallback fails to resolve - we're not actually taking it. |
- result.appendVector(tokens); |
- return true; |
- } |
- return false; |
- } |
- |
- return resolveFallback(range, result); |
+ result.appendVector(variableData->tokens()); |
+ Vector<CSSParserToken> trash; |
+ resolveFallback(range, trash); |
+ return true; |
} |
-bool CSSVariableResolver::resolveVariableReferencesFromTokens(CSSParserTokenRange range, |
+bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range, |
Vector<CSSParserToken>& result) |
{ |
bool success = true; |
while (!range.atEnd()) { |
if (range.peek().functionId() == CSSValueVar) { |
- success &= resolveVariableTokensRecursive(range.consumeBlock(), result); |
+ success &= resolveVariableReference(range.consumeBlock(), result); |
} else { |
result.append(range.consume()); |
} |
@@ -108,7 +107,7 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSVariableResolver::resolveVariableReferences( |
CSSVariableResolver resolver(styleVariableData); |
Vector<CSSParserToken> tokens; |
- if (!resolver.resolveVariableReferencesFromTokens(value.variableDataValue()->tokens(), tokens)) |
+ if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens)) |
return cssValuePool().createUnsetValue(); |
CSSParserContext context(HTMLStandardMode, nullptr); |
@@ -122,12 +121,10 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSVariableResolver::resolveVariableReferences( |
void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value) |
{ |
- |
- // TODO(leviw): This should be a stack |
CSSVariableResolver resolver(state.style()->variables()); |
Vector<CSSParserToken> tokens; |
- if (resolver.resolveVariableReferencesFromTokens(value.variableDataValue()->tokens(), tokens)) { |
+ if (resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens)) { |
CSSParserContext context(HTMLStandardMode, 0); |
WillBeHeapVector<CSSProperty, 256> parsedProperties; |
@@ -156,16 +153,10 @@ void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable |
if (!variables) |
return; |
+ CSSVariableResolver resolver(variables); |
for (auto& variable : variables->m_data) { |
- if (!variable.value || !variable.value->needsVariableResolution()) |
- continue; |
- Vector<CSSParserToken> resolvedTokens; |
- |
- CSSVariableResolver resolver(variables, variable.key); |
- if (resolver.resolveVariableReferencesFromTokens(variable.value->tokens(), resolvedTokens)) |
- variable.value = CSSVariableData::createResolved(resolvedTokens, variable.value); |
- else |
- variable.value = nullptr; |
+ if (variable.value && variable.value->needsVariableResolution()) |
+ variable.value = resolver.resolveCustomProperty(variable.key, *variable.value); |
} |
} |
@@ -174,10 +165,4 @@ CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData) |
{ |
} |
-CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData, AtomicString& variable) |
- : m_styleVariableData(styleVariableData) |
-{ |
- m_variablesSeen.add(variable); |
-} |
- |
} // namespace blink |