void CSSVariableResolver::resolveApplyAtRule(CSSParserTokenRange& range, Vector<CSSParserToken>& result) { ASSERT(range.peek().type() == AtKeywordToken && range.peek().valueEqualsIgnoringASCIICase("apply")); range.consumeIncludingWhitespace(); const CSSParserToken& variableName = range.consumeIncludingWhitespace(); // TODO(timloh): Should we actually be consuming this? if (range.peek().type() == SemicolonToken) range.consume(); CSSVariableData* variableData = valueForCustomProperty(variableName.value()); if (!variableData) return; // Invalid custom property CSSParserTokenRange rule = variableData->tokenRange(); rule.consumeWhitespace(); if (rule.peek().type() != LeftBraceToken) return; CSSParserTokenRange ruleContents = rule.consumeBlock(); rule.consumeWhitespace(); if (!rule.atEnd()) return; result.appendRange(ruleContents.begin(), ruleContents.end()); }
bool CSSVariableResolver::resolveVariableReference(CSSParserTokenRange range, Vector<CSSParserToken>& result) { range.consumeWhitespace(); ASSERT(range.peek().type() == IdentToken); AtomicString variableName = range.consumeIncludingWhitespace().value(); ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); CSSVariableData* variableData = valueForCustomProperty(variableName); if (!variableData) return resolveFallback(range, result); result.appendVector(variableData->tokens()); Vector<CSSParserToken> trash; resolveFallback(range, trash); return true; }
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 CSSVariableData::operator==(const CSSVariableData& other) const { return tokens() == other.tokens(); }