Example #1
0
bool CSSValueList::checkVariablesForCycles(CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
{
    for (unsigned i = 0; i < m_values.size(); i++) {
        auto* value = item(i);
        if (value->isVariableValue()) {
            auto& variableValue = downcast<CSSVariableValue>(*value);
            if (seenProperties.contains(variableValue.name()))
                return false;
            RefPtr<CSSValue> value = customProperties.get(variableValue.name());
            if (value && value->isVariableDependentValue() && !downcast<CSSVariableDependentValue>(*value).checkVariablesForCycles(variableValue.name(), customProperties, seenProperties, invalidProperties))
                return false;

            // Have to check the fallback values.
            auto* fallbackArgs = variableValue.fallbackArguments();
            if (!fallbackArgs || !fallbackArgs->length())
                continue;
            
            if (!fallbackArgs->checkVariablesForCycles(customProperties, seenProperties, invalidProperties))
                return false;
        } else if (value->isFunctionValue()) {
            auto& functionValue = downcast<CSSFunctionValue>(*value);
            auto* args = functionValue.arguments();
            if (args && !args->checkVariablesForCycles(customProperties, seenProperties, invalidProperties))
                return false;
        } else if (value->isValueList()) {
            auto& listValue = downcast<CSSValueList>(*value);
            if (!listValue.checkVariablesForCycles(customProperties, seenProperties, invalidProperties))
                return false;
        }
    }
    return true;
}
Example #2
0
bool CSSVariableData::checkVariablesForCyclesWithRange(CSSParserTokenRange range, CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
{
    while (!range.atEnd()) {
        if (range.peek().functionId() == CSSValueVar) {
            CSSParserTokenRange block = range.consumeBlock();
            
            block.consumeWhitespace();
            ASSERT(block.peek().type() == IdentToken);
            AtomicString variableName = block.consumeIncludingWhitespace().value().toAtomicString();
            ASSERT(block.atEnd() || block.peek().type() == CommaToken);
            if (seenProperties.contains(variableName))
                return false;

            RefPtr<CSSCustomPropertyValue> value = customProperties.get(variableName);
            if (value && value->containsVariables() && !value->checkVariablesForCycles(variableName, customProperties, seenProperties, invalidProperties))
                return false;

            if (range.peek().type() == CommaToken) {
                // Fallback.
                range.consume();
                return checkVariablesForCyclesWithRange(block, customProperties, seenProperties, invalidProperties);
            }
        } else
            range.consume();
    }
    return true;
}
Example #3
0
bool CSSVariableData::resolveVariableReference(const CustomPropertyValueMap& customProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result) const
{
    range.consumeWhitespace();
    ASSERT(range.peek().type() == IdentToken);
    AtomicString variableName = range.consumeIncludingWhitespace().value().toAtomicString();
    ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
    
    RefPtr<CSSCustomPropertyValue> property = customProperties.get(variableName);
    if (!property || !property->value())
        return resolveVariableFallback(customProperties, range, result);
    
    if (property->containsVariables()) {
        // FIXME: Avoid doing this work more than once.
        RefPtr<CSSVariableData> resolvedData = property->value()->resolveVariableReferences(customProperties);
        if (!resolvedData)
            return false;
        result.appendVector(resolvedData->tokens());
    } else
        result.appendVector(property->value()->tokens());
    
    return true;
}