RefPtr<CSSValue> CSSParser::parseValueWithVariableReferences(CSSPropertyID propID, const CSSValue& value, const CustomPropertyValueMap& customProperties, TextDirection direction, WritingMode writingMode) { if (value.isPendingSubstitutionValue()) { // FIXME: Should have a resolvedShorthands cache to stop this from being done // over and over for each longhand value. const CSSPendingSubstitutionValue& pendingSubstitution = downcast<CSSPendingSubstitutionValue>(value); CSSPropertyID shorthandID = pendingSubstitution.shorthandPropertyId(); if (CSSProperty::isDirectionAwareProperty(shorthandID)) shorthandID = CSSProperty::resolveDirectionAwareProperty(shorthandID, direction, writingMode); CSSVariableReferenceValue* shorthandValue = pendingSubstitution.shorthandValue(); const CSSVariableData* variableData = shorthandValue->variableDataValue(); ASSERT(variableData); Vector<CSSParserToken> resolvedTokens; if (!variableData->resolveTokenRange(customProperties, variableData->tokens(), resolvedTokens)) return nullptr; ParsedPropertyVector parsedProperties; if (!CSSPropertyParser::parseValue(shorthandID, false, resolvedTokens, m_context, nullptr, parsedProperties, StyleRule::Style)) return nullptr; for (auto& property : parsedProperties) { if (property.id() == propID) return property.value(); } return nullptr; } if (value.isVariableReferenceValue()) { const CSSVariableReferenceValue& valueWithReferences = downcast<CSSVariableReferenceValue>(value); const CSSVariableData* variableData = valueWithReferences.variableDataValue(); ASSERT(variableData); Vector<CSSParserToken> resolvedTokens; if (!variableData->resolveTokenRange(customProperties, variableData->tokens(), resolvedTokens)) return nullptr; return CSSPropertyParser::parseSingleValue(propID, resolvedTokens, m_context, nullptr); } return nullptr; }
static bool computationallyIndependent(const CSSValue& value) { DCHECK(!value.isCSSWideKeyword()); if (value.isVariableReferenceValue()) return !toCSSVariableReferenceValue(value) .variableDataValue() ->needsVariableResolution(); if (value.isValueList()) { for (const CSSValue* innerValue : toCSSValueList(value)) { if (!computationallyIndependent(*innerValue)) return false; } return true; } if (value.isPrimitiveValue()) { const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value); if (!primitiveValue.isLength() && !primitiveValue.isCalculatedPercentageWithLength()) return true; CSSPrimitiveValue::CSSLengthArray lengthArray; primitiveValue.accumulateLengthArray(lengthArray); for (size_t i = 0; i < lengthArray.values.size(); i++) { if (lengthArray.typeFlags.get(i) && i != CSSPrimitiveValue::UnitTypePixels && i != CSSPrimitiveValue::UnitTypePercentage) return false; } return true; } // TODO(timloh): Images and transform-function values can also contain // lengths. return true; }