Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/css/resolver/CSSVariableResolver.h" | 5 #include "core/css/resolver/CSSVariableResolver.h" |
| 6 | 6 |
| 7 #include "core/CSSPropertyNames.h" | 7 #include "core/CSSPropertyNames.h" |
| 8 #include "core/CSSValueKeywords.h" | 8 #include "core/CSSValueKeywords.h" |
| 9 #include "core/StyleBuilderFunctions.h" | 9 #include "core/StyleBuilderFunctions.h" |
| 10 #include "core/StylePropertyShorthand.h" | 10 #include "core/StylePropertyShorthand.h" |
| 11 #include "core/css/CSSPendingSubstitutionValue.h" | 11 #include "core/css/CSSPendingSubstitutionValue.h" |
| 12 #include "core/css/CSSUnsetValue.h" | 12 #include "core/css/CSSUnsetValue.h" |
| 13 #include "core/css/CSSVariableData.h" | 13 #include "core/css/CSSVariableData.h" |
| 14 #include "core/css/CSSVariableReferenceValue.h" | 14 #include "core/css/CSSVariableReferenceValue.h" |
| 15 #include "core/css/PropertyRegistry.h" | 15 #include "core/css/PropertyRegistry.h" |
| 16 #include "core/css/parser/CSSParserToken.h" | 16 #include "core/css/parser/CSSParserToken.h" |
| 17 #include "core/css/parser/CSSParserTokenRange.h" | 17 #include "core/css/parser/CSSParserTokenRange.h" |
| 18 #include "core/css/parser/CSSPropertyParser.h" | 18 #include "core/css/parser/CSSPropertyParser.h" |
| 19 #include "core/css/resolver/StyleBuilder.h" | 19 #include "core/css/resolver/StyleBuilder.h" |
| 20 #include "core/css/resolver/StyleBuilderConverter.h" | 20 #include "core/css/resolver/StyleBuilderConverter.h" |
| 21 #include "core/css/resolver/StyleResolverState.h" | 21 #include "core/css/resolver/StyleResolverState.h" |
| 22 #include "core/style/StyleInheritedVariables.h" | 22 #include "core/style/StyleInheritedVariables.h" |
| 23 #include "core/style/StyleNonInheritedVariables.h" | 23 #include "core/style/StyleNonInheritedVariables.h" |
| 24 #include "wtf/Vector.h" | 24 #include "wtf/Vector.h" |
| 25 | 25 |
| 26 namespace blink { | 26 namespace blink { |
| 27 | 27 |
| 28 bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range, | 28 bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range, |
| 29 Vector<CSSParserToken>& result) { | 29 bool omitAnimationTainted, |
| 30 Vector<CSSParserToken>& result, | |
| 31 bool& resultIsAnimationTainted) { | |
| 30 if (range.atEnd()) | 32 if (range.atEnd()) |
| 31 return false; | 33 return false; |
| 32 ASSERT(range.peek().type() == CommaToken); | 34 ASSERT(range.peek().type() == CommaToken); |
| 33 range.consume(); | 35 range.consume(); |
| 34 return resolveTokenRange(range, result); | 36 return resolveTokenRange(range, omitAnimationTainted, result, |
| 37 resultIsAnimationTainted); | |
| 35 } | 38 } |
| 36 | 39 |
| 37 CSSVariableData* CSSVariableResolver::valueForCustomProperty( | 40 CSSVariableData* CSSVariableResolver::valueForCustomProperty( |
| 38 AtomicString name) { | 41 AtomicString name) { |
| 39 if (m_variablesSeen.contains(name)) { | 42 if (m_variablesSeen.contains(name)) { |
| 40 m_cycleStartPoints.add(name); | 43 m_cycleStartPoints.add(name); |
| 41 return nullptr; | 44 return nullptr; |
| 42 } | 45 } |
| 43 | 46 |
| 44 DCHECK(m_registry || !RuntimeEnabledFeatures::cssVariables2Enabled()); | 47 DCHECK(m_registry || !RuntimeEnabledFeatures::cssVariables2Enabled()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 if (!newVariableData) | 86 if (!newVariableData) |
| 84 return registration->initialVariableData(); | 87 return registration->initialVariableData(); |
| 85 return newVariableData.get(); | 88 return newVariableData.get(); |
| 86 } | 89 } |
| 87 | 90 |
| 88 PassRefPtr<CSSVariableData> CSSVariableResolver::resolveCustomProperty( | 91 PassRefPtr<CSSVariableData> CSSVariableResolver::resolveCustomProperty( |
| 89 AtomicString name, | 92 AtomicString name, |
| 90 const CSSVariableData& variableData) { | 93 const CSSVariableData& variableData) { |
| 91 ASSERT(variableData.needsVariableResolution()); | 94 ASSERT(variableData.needsVariableResolution()); |
| 92 | 95 |
| 96 bool omitAnimationTainted = false; | |
| 97 bool isAnimationTainted = variableData.isAnimationTainted(); | |
| 93 Vector<CSSParserToken> tokens; | 98 Vector<CSSParserToken> tokens; |
| 94 m_variablesSeen.add(name); | 99 m_variablesSeen.add(name); |
| 95 bool success = resolveTokenRange(variableData.tokens(), tokens); | 100 bool success = resolveTokenRange(variableData.tokens(), omitAnimationTainted, |
| 101 tokens, isAnimationTainted); | |
| 96 m_variablesSeen.remove(name); | 102 m_variablesSeen.remove(name); |
| 97 | 103 |
| 98 // The old variable data holds onto the backing string the new resolved CSSVar iableData | 104 // The old variable data holds onto the backing string the new resolved CSSVar iableData |
| 99 // relies on. Ensure it will live beyond us overwriting the RefPtr in StyleInh eritedVariables. | 105 // relies on. Ensure it will live beyond us overwriting the RefPtr in StyleInh eritedVariables. |
| 100 ASSERT(variableData.refCount() > 1); | 106 ASSERT(variableData.refCount() > 1); |
| 101 | 107 |
| 102 if (!success || !m_cycleStartPoints.isEmpty()) { | 108 if (!success || !m_cycleStartPoints.isEmpty()) { |
| 103 m_cycleStartPoints.remove(name); | 109 m_cycleStartPoints.remove(name); |
| 104 return nullptr; | 110 return nullptr; |
| 105 } | 111 } |
| 106 return CSSVariableData::createResolved(tokens, variableData); | 112 return CSSVariableData::createResolved(tokens, variableData, |
| 113 isAnimationTainted); | |
| 107 } | 114 } |
| 108 | 115 |
| 109 bool CSSVariableResolver::resolveVariableReference( | 116 bool CSSVariableResolver::resolveVariableReference( |
| 110 CSSParserTokenRange range, | 117 CSSParserTokenRange range, |
| 111 Vector<CSSParserToken>& result) { | 118 bool omitAnimationTainted, |
| 119 Vector<CSSParserToken>& result, | |
| 120 bool& resultIsAnimationTainted) { | |
| 112 range.consumeWhitespace(); | 121 range.consumeWhitespace(); |
| 113 ASSERT(range.peek().type() == IdentToken); | 122 ASSERT(range.peek().type() == IdentToken); |
| 114 AtomicString variableName = | 123 AtomicString variableName = |
| 115 range.consumeIncludingWhitespace().value().toAtomicString(); | 124 range.consumeIncludingWhitespace().value().toAtomicString(); |
| 116 ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); | 125 ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); |
| 117 | 126 |
| 118 CSSVariableData* variableData = valueForCustomProperty(variableName); | 127 CSSVariableData* variableData = valueForCustomProperty(variableName); |
| 119 if (!variableData) | 128 if (!variableData) { |
| 120 return resolveFallback(range, result); | 129 return resolveFallback(range, omitAnimationTainted, result, |
| 130 resultIsAnimationTainted); | |
| 131 } | |
| 121 | 132 |
| 122 result.appendVector(variableData->tokens()); | 133 if (!omitAnimationTainted || !variableData->isAnimationTainted()) { |
|
alancutter (OOO until 2018)
2016/10/05 07:46:40
Negate this and return so it reads better and does
alancutter (OOO until 2018)
2016/10/06 01:25:32
Done.
| |
| 134 result.appendVector(variableData->tokens()); | |
| 135 resultIsAnimationTainted |= variableData->isAnimationTainted(); | |
| 136 } else { | |
| 137 // TODO(alancutter): Append the registered initial custom property value. | |
|
alancutter (OOO until 2018)
2016/10/05 07:46:40
This should be calling resolveFallback instead of
alancutter (OOO until 2018)
2016/10/06 01:25:32
Done.
| |
| 138 } | |
| 139 | |
| 123 Vector<CSSParserToken> trash; | 140 Vector<CSSParserToken> trash; |
| 124 resolveFallback(range, trash); | 141 bool trashIsAnimationTainted; |
| 142 resolveFallback(range, omitAnimationTainted, trash, trashIsAnimationTainted); | |
| 125 return true; | 143 return true; |
| 126 } | 144 } |
| 127 | 145 |
| 128 void CSSVariableResolver::resolveApplyAtRule(CSSParserTokenRange& range, | 146 void CSSVariableResolver::resolveApplyAtRule(CSSParserTokenRange& range, |
| 129 Vector<CSSParserToken>& result) { | 147 Vector<CSSParserToken>& result) { |
| 130 DCHECK(range.peek().type() == AtKeywordToken && | 148 DCHECK(range.peek().type() == AtKeywordToken && |
| 131 equalIgnoringASCIICase(range.peek().value(), "apply")); | 149 equalIgnoringASCIICase(range.peek().value(), "apply")); |
| 132 range.consumeIncludingWhitespace(); | 150 range.consumeIncludingWhitespace(); |
| 133 const CSSParserToken& variableName = range.consumeIncludingWhitespace(); | 151 const CSSParserToken& variableName = range.consumeIncludingWhitespace(); |
| 134 // TODO(timloh): Should we actually be consuming this? | 152 // TODO(timloh): Should we actually be consuming this? |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 146 return; | 164 return; |
| 147 CSSParserTokenRange ruleContents = rule.consumeBlock(); | 165 CSSParserTokenRange ruleContents = rule.consumeBlock(); |
| 148 rule.consumeWhitespace(); | 166 rule.consumeWhitespace(); |
| 149 if (!rule.atEnd()) | 167 if (!rule.atEnd()) |
| 150 return; | 168 return; |
| 151 | 169 |
| 152 result.appendRange(ruleContents.begin(), ruleContents.end()); | 170 result.appendRange(ruleContents.begin(), ruleContents.end()); |
| 153 } | 171 } |
| 154 | 172 |
| 155 bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range, | 173 bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range, |
| 156 Vector<CSSParserToken>& result) { | 174 bool omitAnimationTainted, |
| 175 Vector<CSSParserToken>& result, | |
| 176 bool& resultIsAnimationTainted) { | |
| 157 bool success = true; | 177 bool success = true; |
| 158 while (!range.atEnd()) { | 178 while (!range.atEnd()) { |
| 159 if (range.peek().functionId() == CSSValueVar) { | 179 if (range.peek().functionId() == CSSValueVar) { |
| 160 success &= resolveVariableReference(range.consumeBlock(), result); | 180 success &= |
| 181 resolveVariableReference(range.consumeBlock(), omitAnimationTainted, | |
| 182 result, resultIsAnimationTainted); | |
| 161 } else if (range.peek().type() == AtKeywordToken && | 183 } else if (range.peek().type() == AtKeywordToken && |
| 162 equalIgnoringASCIICase(range.peek().value(), "apply") && | 184 equalIgnoringASCIICase(range.peek().value(), "apply") && |
| 163 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) { | 185 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) { |
| 164 resolveApplyAtRule(range, result); | 186 resolveApplyAtRule(range, result); |
| 165 } else { | 187 } else { |
| 166 result.append(range.consume()); | 188 result.append(range.consume()); |
| 167 } | 189 } |
| 168 } | 190 } |
| 169 return success; | 191 return success; |
| 170 } | 192 } |
| 171 | 193 |
| 172 const CSSValue* CSSVariableResolver::resolveVariableReferences( | 194 const CSSValue* CSSVariableResolver::resolveVariableReferences( |
| 173 const StyleResolverState& state, | 195 const StyleResolverState& state, |
| 174 CSSPropertyID id, | 196 CSSPropertyID id, |
| 175 const CSSValue& value) { | 197 const CSSValue& value, |
| 198 bool omitAnimationTainted) { | |
| 176 ASSERT(!isShorthandProperty(id)); | 199 ASSERT(!isShorthandProperty(id)); |
| 177 | 200 |
| 178 if (value.isPendingSubstitutionValue()) | 201 if (value.isPendingSubstitutionValue()) { |
| 179 return resolvePendingSubstitutions(state, id, | 202 return resolvePendingSubstitutions( |
| 180 toCSSPendingSubstitutionValue(value)); | 203 state, id, toCSSPendingSubstitutionValue(value), omitAnimationTainted); |
| 204 } | |
| 181 | 205 |
| 182 if (value.isVariableReferenceValue()) | 206 if (value.isVariableReferenceValue()) { |
| 183 return resolveVariableReferences(state, id, | 207 return resolveVariableReferences( |
| 184 toCSSVariableReferenceValue(value)); | 208 state, id, toCSSVariableReferenceValue(value), omitAnimationTainted); |
| 209 } | |
| 185 | 210 |
| 186 NOTREACHED(); | 211 NOTREACHED(); |
| 187 return nullptr; | 212 return nullptr; |
| 188 } | 213 } |
| 189 | 214 |
| 190 const CSSValue* CSSVariableResolver::resolveVariableReferences( | 215 const CSSValue* CSSVariableResolver::resolveVariableReferences( |
| 191 const StyleResolverState& state, | 216 const StyleResolverState& state, |
| 192 CSSPropertyID id, | 217 CSSPropertyID id, |
| 193 const CSSVariableReferenceValue& value) { | 218 const CSSVariableReferenceValue& value, |
| 219 bool omitAnimationTainted) { | |
| 194 CSSVariableResolver resolver(state); | 220 CSSVariableResolver resolver(state); |
| 195 Vector<CSSParserToken> tokens; | 221 Vector<CSSParserToken> tokens; |
| 196 if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens)) | 222 bool isAnimationTainted = false; |
| 223 if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(), | |
| 224 omitAnimationTainted, tokens, | |
| 225 isAnimationTainted)) | |
| 197 return CSSUnsetValue::create(); | 226 return CSSUnsetValue::create(); |
| 198 const CSSValue* result = | 227 const CSSValue* result = |
| 199 CSSPropertyParser::parseSingleValue(id, tokens, strictCSSParserContext()); | 228 CSSPropertyParser::parseSingleValue(id, tokens, strictCSSParserContext()); |
| 200 if (!result) | 229 if (!result) |
| 201 return CSSUnsetValue::create(); | 230 return CSSUnsetValue::create(); |
| 202 return result; | 231 return result; |
| 203 } | 232 } |
| 204 | 233 |
| 205 const CSSValue* CSSVariableResolver::resolvePendingSubstitutions( | 234 const CSSValue* CSSVariableResolver::resolvePendingSubstitutions( |
| 206 const StyleResolverState& state, | 235 const StyleResolverState& state, |
| 207 CSSPropertyID id, | 236 CSSPropertyID id, |
| 208 const CSSPendingSubstitutionValue& pendingValue) { | 237 const CSSPendingSubstitutionValue& pendingValue, |
| 238 bool omitAnimationTainted) { | |
| 209 // Longhands from shorthand references follow this path. | 239 // Longhands from shorthand references follow this path. |
| 210 HeapHashMap<CSSPropertyID, Member<const CSSValue>>& propertyCache = | 240 HeapHashMap<CSSPropertyID, Member<const CSSValue>>& propertyCache = |
| 211 state.parsedPropertiesForPendingSubstitutionCache(pendingValue); | 241 state.parsedPropertiesForPendingSubstitutionCache(pendingValue); |
| 212 | 242 |
| 213 const CSSValue* value = propertyCache.get(id); | 243 const CSSValue* value = propertyCache.get(id); |
| 214 if (!value) { | 244 if (!value) { |
| 215 // TODO(timloh): We shouldn't retry this for all longhands if the shorthand ends up invalid | 245 // TODO(timloh): We shouldn't retry this for all longhands if the shorthand ends up invalid |
| 216 CSSVariableReferenceValue* shorthandValue = pendingValue.shorthandValue(); | 246 CSSVariableReferenceValue* shorthandValue = pendingValue.shorthandValue(); |
| 217 CSSPropertyID shorthandPropertyId = pendingValue.shorthandPropertyId(); | 247 CSSPropertyID shorthandPropertyId = pendingValue.shorthandPropertyId(); |
| 218 | 248 |
| 219 CSSVariableResolver resolver(state); | 249 CSSVariableResolver resolver(state); |
| 220 | 250 |
| 221 Vector<CSSParserToken> tokens; | 251 Vector<CSSParserToken> tokens; |
| 252 bool isAnimationTainted = false; | |
| 222 if (resolver.resolveTokenRange( | 253 if (resolver.resolveTokenRange( |
| 223 shorthandValue->variableDataValue()->tokens(), tokens)) { | 254 shorthandValue->variableDataValue()->tokens(), omitAnimationTainted, |
| 255 tokens, isAnimationTainted)) { | |
| 224 CSSParserContext context(HTMLStandardMode, 0); | 256 CSSParserContext context(HTMLStandardMode, 0); |
| 225 | 257 |
| 226 HeapVector<CSSProperty, 256> parsedProperties; | 258 HeapVector<CSSProperty, 256> parsedProperties; |
| 227 | 259 |
| 228 if (CSSPropertyParser::parseValue( | 260 if (CSSPropertyParser::parseValue( |
| 229 shorthandPropertyId, false, CSSParserTokenRange(tokens), context, | 261 shorthandPropertyId, false, CSSParserTokenRange(tokens), context, |
| 230 parsedProperties, StyleRule::RuleType::Style)) { | 262 parsedProperties, StyleRule::RuleType::Style)) { |
| 231 unsigned parsedPropertiesCount = parsedProperties.size(); | 263 unsigned parsedPropertiesCount = parsedProperties.size(); |
| 232 for (unsigned i = 0; i < parsedPropertiesCount; ++i) { | 264 for (unsigned i = 0; i < parsedPropertiesCount; ++i) { |
| 233 propertyCache.set(parsedProperties[i].id(), | 265 propertyCache.set(parsedProperties[i].id(), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 : m_styleResolverState(state), | 300 : m_styleResolverState(state), |
| 269 m_inheritedVariables(state.style()->inheritedVariables()), | 301 m_inheritedVariables(state.style()->inheritedVariables()), |
| 270 m_nonInheritedVariables(state.style()->nonInheritedVariables()), | 302 m_nonInheritedVariables(state.style()->nonInheritedVariables()), |
| 271 m_registry(state.document().propertyRegistry()) {} | 303 m_registry(state.document().propertyRegistry()) {} |
| 272 | 304 |
| 273 DEFINE_TRACE(CSSVariableResolver) { | 305 DEFINE_TRACE(CSSVariableResolver) { |
| 274 visitor->trace(m_registry); | 306 visitor->trace(m_registry); |
| 275 } | 307 } |
| 276 | 308 |
| 277 } // namespace blink | 309 } // namespace blink |
| OLD | NEW |