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

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: split up 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
« no previous file with comments | « third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
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 m_cycleStartPoints.remove(variableName);
86 return false;
87 }
88
89 return resolveFallback(range, result);
90 } 86 }
91 87
92 bool CSSVariableResolver::resolveVariableReferencesFromTokens(CSSParserTokenRang e range, 88 bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range,
93 Vector<CSSParserToken>& result) 89 Vector<CSSParserToken>& result)
94 { 90 {
95 bool success = true; 91 bool success = true;
96 while (!range.atEnd()) { 92 while (!range.atEnd()) {
97 if (range.peek().functionId() == CSSValueVar) { 93 if (range.peek().functionId() == CSSValueVar) {
98 success &= resolveVariableTokensRecursive(range.consumeBlock(), resu lt); 94 success &= resolveVariableReference(range.consumeBlock(), result);
99 } else { 95 } else {
100 result.append(range.consume()); 96 result.append(range.consume());
101 } 97 }
102 } 98 }
103 return success; 99 return success;
104 } 100 }
105 101
106 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)
107 { 103 {
108 ASSERT(!isShorthandProperty(id)); 104 ASSERT(!isShorthandProperty(id));
109 105
110 CSSVariableResolver resolver(styleVariableData); 106 CSSVariableResolver resolver(styleVariableData);
111 Vector<CSSParserToken> tokens; 107 Vector<CSSParserToken> tokens;
112 if (!resolver.resolveVariableReferencesFromTokens(value.variableDataValue()- >tokens(), tokens)) 108 if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens) )
113 return cssValuePool().createUnsetValue(); 109 return cssValuePool().createUnsetValue();
114 110
115 CSSParserContext context(HTMLStandardMode, nullptr); 111 CSSParserContext context(HTMLStandardMode, nullptr);
116 WillBeHeapVector<CSSProperty, 256> parsedProperties; 112 WillBeHeapVector<CSSProperty, 256> parsedProperties;
117 // 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.
118 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))
119 return cssValuePool().createUnsetValue(); 115 return cssValuePool().createUnsetValue();
120 ASSERT(parsedProperties.size() == 1); 116 ASSERT(parsedProperties.size() == 1);
121 return parsedProperties[0].value(); 117 return parsedProperties[0].value();
122 } 118 }
123 119
124 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value) 120 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value)
125 { 121 {
126
127 // TODO(leviw): This should be a stack
Timothy Loh 2016/02/16 03:34:56 I assume this means to unroll the recursion into i
128 CSSVariableResolver resolver(state.style()->variables()); 122 CSSVariableResolver resolver(state.style()->variables());
129 123
130 Vector<CSSParserToken> tokens; 124 Vector<CSSParserToken> tokens;
131 if (resolver.resolveVariableReferencesFromTokens(value.variableDataValue()-> tokens(), tokens)) { 125 if (resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens)) {
132 CSSParserContext context(HTMLStandardMode, 0); 126 CSSParserContext context(HTMLStandardMode, 0);
133 127
134 WillBeHeapVector<CSSProperty, 256> parsedProperties; 128 WillBeHeapVector<CSSProperty, 256> parsedProperties;
135 129
136 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)) {
137 unsigned parsedPropertiesCount = parsedProperties.size(); 131 unsigned parsedPropertiesCount = parsedProperties.size();
138 for (unsigned i = 0; i < parsedPropertiesCount; ++i) 132 for (unsigned i = 0; i < parsedPropertiesCount; ++i)
139 StyleBuilder::applyProperty(parsedProperties[i].id(), state, par sedProperties[i].value()); 133 StyleBuilder::applyProperty(parsedProperties[i].id(), state, par sedProperties[i].value());
140 return; 134 return;
141 } 135 }
142 } 136 }
143 137
144 RefPtrWillBeRawPtr<CSSUnsetValue> unset = cssValuePool().createUnsetValue(); 138 RefPtrWillBeRawPtr<CSSUnsetValue> unset = cssValuePool().createUnsetValue();
145 if (isShorthandProperty(id)) { 139 if (isShorthandProperty(id)) {
146 StylePropertyShorthand shorthand = shorthandForProperty(id); 140 StylePropertyShorthand shorthand = shorthandForProperty(id);
147 for (unsigned i = 0; i < shorthand.length(); i++) 141 for (unsigned i = 0; i < shorthand.length(); i++)
148 StyleBuilder::applyProperty(shorthand.properties()[i], state, unset. get()); 142 StyleBuilder::applyProperty(shorthand.properties()[i], state, unset. get());
149 return; 143 return;
150 } 144 }
151 145
152 StyleBuilder::applyProperty(id, state, unset.get()); 146 StyleBuilder::applyProperty(id, state, unset.get());
153 } 147 }
154 148
155 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable s) 149 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable s)
156 { 150 {
157 if (!variables) 151 if (!variables)
158 return; 152 return;
159 153
154 CSSVariableResolver resolver(variables);
160 for (auto& variable : variables->m_data) { 155 for (auto& variable : variables->m_data) {
161 if (!variable.value || !variable.value->needsVariableResolution()) 156 if (variable.value && variable.value->needsVariableResolution())
162 continue; 157 variable.value = resolver.resolveCustomProperty(variable.key, *varia ble.value);
163 Vector<CSSParserToken> resolvedTokens;
164
165 CSSVariableResolver resolver(variables, variable.key);
166 if (resolver.resolveVariableReferencesFromTokens(variable.value->tokens( ), resolvedTokens))
167 variable.value = CSSVariableData::createResolved(resolvedTokens, var iable.value);
168 else
169 variable.value = nullptr;
170 } 158 }
171 } 159 }
172 160
173 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData) 161 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData)
174 : m_styleVariableData(styleVariableData) 162 : m_styleVariableData(styleVariableData)
175 { 163 {
176 } 164 }
177 165
178 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData, A tomicString& variable)
179 : m_styleVariableData(styleVariableData)
180 {
181 m_variablesSeen.add(variable);
182 }
183
184 } // namespace blink 166 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698