Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Side by Side Diff: third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp

Issue 1694133002: Simplify CSS variables resolution logic [2 of 2] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
(...skipping 10 matching lines...) Expand all
21 #include "wtf/Vector.h" 21 #include "wtf/Vector.h"
22 22
23 namespace blink { 23 namespace blink {
24 24
25 bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range, Vector<CSSP arserToken>& result) 25 bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range, Vector<CSSP arserToken>& result)
26 { 26 {
27 if (range.atEnd()) 27 if (range.atEnd())
28 return false; 28 return false;
29 ASSERT(range.peek().type() == CommaToken); 29 ASSERT(range.peek().type() == CommaToken);
30 range.consume(); 30 range.consume();
31 return resolveVariableReferencesFromTokens(range, result); 31 return resolveTokenRange(range, result);
32 } 32 }
33 33
34 bool CSSVariableResolver::resolveVariableTokensRecursive(CSSParserTokenRange ran ge, 34 CSSVariableData* CSSVariableResolver::valueForCustomProperty(AtomicString name)
35 Vector<CSSParserToken>& result)
36 { 35 {
37 Vector<CSSParserToken> trash; 36 if (m_variablesSeen.contains(name)) {
37 m_cycleStartPoints.add(name);
38 return nullptr;
39 }
40
41 if (!m_styleVariableData)
42 return nullptr;
43 CSSVariableData* variableData = m_styleVariableData->getVariable(name);
44 if (!variableData)
45 return nullptr;
46 if (!variableData->needsVariableResolution())
47 return variableData;
48 RefPtr<CSSVariableData> newVariableData = resolveCustomProperty(name, *varia bleData);
49 m_styleVariableData->setVariable(name, newVariableData);
50 return newVariableData.get();
51 }
52
53 PassRefPtr<CSSVariableData> CSSVariableResolver::resolveCustomProperty(AtomicStr ing name, const CSSVariableData& variableData)
54 {
55 Vector<CSSParserToken> tokens;
shans 2016/02/17 04:04:15 ASSERT(variableData->needsVariableResolution());
56 m_variablesSeen.add(name);
57 bool success = resolveTokenRange(variableData.tokens(), tokens);
58 m_variablesSeen.remove(name);
59
60 // The old variable data holds onto the backing string the new resolved CSSV ariableData
61 // relies on. Ensure it will live beyond us overwriting the RefPtr in StyleV ariableData.
62 ASSERT(variableData.refCount() > 1);
63
64 if (!success || !m_cycleStartPoints.isEmpty()) {
65 m_cycleStartPoints.remove(name);
66 return nullptr;
67 }
68 return CSSVariableData::createResolved(tokens, variableData);
69 }
70
71 bool CSSVariableResolver::resolveVariableReference(CSSParserTokenRange range, Ve ctor<CSSParserToken>& result)
72 {
38 range.consumeWhitespace(); 73 range.consumeWhitespace();
39 ASSERT(range.peek().type() == IdentToken); 74 ASSERT(range.peek().type() == IdentToken);
40 AtomicString variableName = range.consumeIncludingWhitespace().value(); 75 AtomicString variableName = range.consumeIncludingWhitespace().value();
41 ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); 76 ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
42 77
43 // Cycle detection. 78 CSSVariableData* variableData = valueForCustomProperty(variableName);
44 if (m_variablesSeen.contains(variableName)) { 79 if (!variableData)
45 m_cycleStartPoints.add(variableName); 80 return resolveFallback(range, result);
46 resolveFallback(range, trash);
47 return false;
48 }
49 81
50 CSSVariableData* variableData = m_styleVariableData ? m_styleVariableData->g etVariable(variableName) : nullptr; 82 result.appendVector(variableData->tokens());
51 if (variableData) { 83 Vector<CSSParserToken> trash;
52 Vector<CSSParserToken> tokens; 84 resolveFallback(range, trash);
53 if (variableData->needsVariableResolution()) { 85 return true;
54 m_variablesSeen.add(variableName);
55 bool referenceValid = resolveVariableReferencesFromTokens(variableDa ta->tokens(), tokens);
56 m_variablesSeen.remove(variableName);
57
58 // The old variable data holds onto the backing string the new resol ved CSSVariableData
59 // relies on. Ensure it will live beyond us overwriting the RefPtr i n StyleVariableData.
60 ASSERT(variableData->refCount() > 1);
61
62 if (!referenceValid || !m_cycleStartPoints.isEmpty()) {
63 m_styleVariableData->setVariable(variableName, nullptr);
64 m_cycleStartPoints.remove(variableName);
65 if (!m_cycleStartPoints.isEmpty()) {
66 resolveFallback(range, trash);
67 return false;
68 }
69 return resolveFallback(range, result);
70 }
71
72 m_styleVariableData->setVariable(variableName, CSSVariableData::crea teResolved(tokens, variableData));
73 } else {
74 tokens = variableData->tokens();
75 }
76
77 ASSERT(!tokens.isEmpty());
78 // Check that loops are not induced by the fallback.
79 resolveFallback(range, trash);
80 if (m_cycleStartPoints.isEmpty()) {
81 // It's OK if the fallback fails to resolve - we're not actually tak ing it.
82 result.appendVector(tokens);
83 return true;
84 }
85 return false;
86 }
87
88 return resolveFallback(range, result);
89 } 86 }
90 87
91 bool CSSVariableResolver::resolveVariableReferencesFromTokens(CSSParserTokenRang e range, 88 bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range,
92 Vector<CSSParserToken>& result) 89 Vector<CSSParserToken>& result)
93 { 90 {
94 bool success = true; 91 bool success = true;
95 while (!range.atEnd()) { 92 while (!range.atEnd()) {
96 if (range.peek().functionId() == CSSValueVar) { 93 if (range.peek().functionId() == CSSValueVar) {
97 success &= resolveVariableTokensRecursive(range.consumeBlock(), resu lt); 94 success &= resolveVariableReference(range.consumeBlock(), result);
98 } else { 95 } else {
99 result.append(range.consume()); 96 result.append(range.consume());
100 } 97 }
101 } 98 }
102 return success; 99 return success;
103 } 100 }
104 101
105 PassRefPtrWillBeRawPtr<CSSValue> CSSVariableResolver::resolveVariableReferences( StyleVariableData* styleVariableData, CSSPropertyID id, const CSSVariableReferen ceValue& value) 102 PassRefPtrWillBeRawPtr<CSSValue> CSSVariableResolver::resolveVariableReferences( StyleVariableData* styleVariableData, CSSPropertyID id, const CSSVariableReferen ceValue& value)
106 { 103 {
107 ASSERT(!isShorthandProperty(id)); 104 ASSERT(!isShorthandProperty(id));
108 105
109 CSSVariableResolver resolver(styleVariableData); 106 CSSVariableResolver resolver(styleVariableData);
110 Vector<CSSParserToken> tokens; 107 Vector<CSSParserToken> tokens;
111 if (!resolver.resolveVariableReferencesFromTokens(value.variableDataValue()- >tokens(), tokens)) 108 if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens) )
112 return cssValuePool().createUnsetValue(); 109 return cssValuePool().createUnsetValue();
113 110
114 CSSParserContext context(HTMLStandardMode, nullptr); 111 CSSParserContext context(HTMLStandardMode, nullptr);
115 WillBeHeapVector<CSSProperty, 256> parsedProperties; 112 WillBeHeapVector<CSSProperty, 256> parsedProperties;
116 // TODO(timloh): This should be CSSParser::parseSingleValue and not need a v ector. 113 // TODO(timloh): This should be CSSParser::parseSingleValue and not need a v ector.
117 if (!CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), c ontext, parsedProperties, StyleRule::Type::Style)) 114 if (!CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), c ontext, parsedProperties, StyleRule::Type::Style))
118 return cssValuePool().createUnsetValue(); 115 return cssValuePool().createUnsetValue();
119 ASSERT(parsedProperties.size() == 1); 116 ASSERT(parsedProperties.size() == 1);
120 return parsedProperties[0].value(); 117 return parsedProperties[0].value();
121 } 118 }
122 119
123 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value) 120 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value)
124 { 121 {
125
126 // TODO(leviw): This should be a stack
127 CSSVariableResolver resolver(state.style()->variables()); 122 CSSVariableResolver resolver(state.style()->variables());
128 123
129 Vector<CSSParserToken> tokens; 124 Vector<CSSParserToken> tokens;
130 if (resolver.resolveVariableReferencesFromTokens(value.variableDataValue()-> tokens(), tokens)) { 125 if (resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens)) {
131 CSSParserContext context(HTMLStandardMode, 0); 126 CSSParserContext context(HTMLStandardMode, 0);
132 127
133 WillBeHeapVector<CSSProperty, 256> parsedProperties; 128 WillBeHeapVector<CSSProperty, 256> parsedProperties;
134 129
135 if (CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens) , context, parsedProperties, StyleRule::Type::Style)) { 130 if (CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens) , context, parsedProperties, StyleRule::Type::Style)) {
136 unsigned parsedPropertiesCount = parsedProperties.size(); 131 unsigned parsedPropertiesCount = parsedProperties.size();
137 for (unsigned i = 0; i < parsedPropertiesCount; ++i) 132 for (unsigned i = 0; i < parsedPropertiesCount; ++i)
138 StyleBuilder::applyProperty(parsedProperties[i].id(), state, par sedProperties[i].value()); 133 StyleBuilder::applyProperty(parsedProperties[i].id(), state, par sedProperties[i].value());
139 return; 134 return;
140 } 135 }
141 } 136 }
142 137
143 RefPtrWillBeRawPtr<CSSUnsetValue> unset = cssValuePool().createUnsetValue(); 138 RefPtrWillBeRawPtr<CSSUnsetValue> unset = cssValuePool().createUnsetValue();
144 if (isShorthandProperty(id)) { 139 if (isShorthandProperty(id)) {
145 StylePropertyShorthand shorthand = shorthandForProperty(id); 140 StylePropertyShorthand shorthand = shorthandForProperty(id);
146 for (unsigned i = 0; i < shorthand.length(); i++) 141 for (unsigned i = 0; i < shorthand.length(); i++)
147 StyleBuilder::applyProperty(shorthand.properties()[i], state, unset. get()); 142 StyleBuilder::applyProperty(shorthand.properties()[i], state, unset. get());
148 return; 143 return;
149 } 144 }
150 145
151 StyleBuilder::applyProperty(id, state, unset.get()); 146 StyleBuilder::applyProperty(id, state, unset.get());
152 } 147 }
153 148
154 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable s) 149 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable s)
155 { 150 {
156 if (!variables) 151 if (!variables)
157 return; 152 return;
158 153
154 CSSVariableResolver resolver(variables);
159 for (auto& variable : variables->m_data) { 155 for (auto& variable : variables->m_data) {
160 if (!variable.value || !variable.value->needsVariableResolution()) 156 if (variable.value && variable.value->needsVariableResolution())
161 continue; 157 variable.value = resolver.resolveCustomProperty(variable.key, *varia ble.value);
162 Vector<CSSParserToken> resolvedTokens;
163
164 CSSVariableResolver resolver(variables, variable.key);
165 if (resolver.resolveVariableReferencesFromTokens(variable.value->tokens( ), resolvedTokens))
166 variable.value = CSSVariableData::createResolved(resolvedTokens, var iable.value);
167 else
168 variable.value = nullptr;
169 } 158 }
170 } 159 }
171 160
172 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData) 161 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData)
173 : m_styleVariableData(styleVariableData) 162 : m_styleVariableData(styleVariableData)
174 { 163 {
175 } 164 }
176 165
177 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData, A tomicString& variable)
178 : m_styleVariableData(styleVariableData)
179 {
180 m_variablesSeen.add(variable);
181 }
182
183 } // namespace blink 166 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698