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

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

Issue 2901213005: Ensure string data is kept alive as long as there are CSSVariableData tokens pointing to it (Closed)
Patch Set: comment Created 3 years, 6 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"
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/css/resolver/StyleResolverStats.h" 22 #include "core/css/resolver/StyleResolverStats.h"
23 #include "core/dom/StyleEngine.h" 23 #include "core/dom/StyleEngine.h"
24 #include "core/style/StyleInheritedVariables.h" 24 #include "core/style/StyleInheritedVariables.h"
25 #include "core/style/StyleNonInheritedVariables.h" 25 #include "core/style/StyleNonInheritedVariables.h"
26 #include "platform/wtf/Vector.h" 26 #include "platform/wtf/Vector.h"
27 27
28 namespace blink { 28 namespace blink {
29 29
30 bool CSSVariableResolver::ResolveFallback(CSSParserTokenRange range, 30 bool CSSVariableResolver::ResolveFallback(
31 bool disallow_animation_tainted, 31 CSSParserTokenRange range,
32 Vector<CSSParserToken>& result, 32 bool disallow_animation_tainted,
33 bool& result_is_animation_tainted) { 33 Vector<CSSParserToken>& result,
34 Vector<String>& result_backing_strings,
35 bool& result_is_animation_tainted) {
34 if (range.AtEnd()) 36 if (range.AtEnd())
35 return false; 37 return false;
36 DCHECK_EQ(range.Peek().GetType(), kCommaToken); 38 DCHECK_EQ(range.Peek().GetType(), kCommaToken);
37 range.Consume(); 39 range.Consume();
38 return ResolveTokenRange(range, disallow_animation_tainted, result, 40 return ResolveTokenRange(range, disallow_animation_tainted, result,
39 result_is_animation_tainted); 41 result_backing_strings, result_is_animation_tainted);
40 } 42 }
41 43
42 CSSVariableData* CSSVariableResolver::ValueForCustomProperty( 44 CSSVariableData* CSSVariableResolver::ValueForCustomProperty(
43 AtomicString name) { 45 AtomicString name) {
44 if (variables_seen_.Contains(name)) { 46 if (variables_seen_.Contains(name)) {
45 cycle_start_points_.insert(name); 47 cycle_start_points_.insert(name);
46 return nullptr; 48 return nullptr;
47 } 49 }
48 50
49 DCHECK(registry_ || !RuntimeEnabledFeatures::cssVariables2Enabled()); 51 DCHECK(registry_ || !RuntimeEnabledFeatures::cssVariables2Enabled());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 } 91 }
90 92
91 PassRefPtr<CSSVariableData> CSSVariableResolver::ResolveCustomProperty( 93 PassRefPtr<CSSVariableData> CSSVariableResolver::ResolveCustomProperty(
92 AtomicString name, 94 AtomicString name,
93 const CSSVariableData& variable_data) { 95 const CSSVariableData& variable_data) {
94 DCHECK(variable_data.NeedsVariableResolution()); 96 DCHECK(variable_data.NeedsVariableResolution());
95 97
96 bool disallow_animation_tainted = false; 98 bool disallow_animation_tainted = false;
97 bool is_animation_tainted = variable_data.IsAnimationTainted(); 99 bool is_animation_tainted = variable_data.IsAnimationTainted();
98 Vector<CSSParserToken> tokens; 100 Vector<CSSParserToken> tokens;
101 Vector<String> backing_strings;
102 backing_strings.AppendVector(variable_data.BackingStrings());
99 variables_seen_.insert(name); 103 variables_seen_.insert(name);
100 bool success = 104 bool success =
101 ResolveTokenRange(variable_data.Tokens(), disallow_animation_tainted, 105 ResolveTokenRange(variable_data.Tokens(), disallow_animation_tainted,
102 tokens, is_animation_tainted); 106 tokens, backing_strings, is_animation_tainted);
103 variables_seen_.erase(name); 107 variables_seen_.erase(name);
104 108
105 // The old variable data holds onto the backing string the new resolved
106 // CSSVariableData relies on. Ensure it will live beyond us overwriting the
107 // RefPtr in StyleInheritedVariables.
108 DCHECK_GT(variable_data.RefCount(), 1);
109
110 if (!success || !cycle_start_points_.IsEmpty()) { 109 if (!success || !cycle_start_points_.IsEmpty()) {
111 cycle_start_points_.erase(name); 110 cycle_start_points_.erase(name);
112 return nullptr; 111 return nullptr;
113 } 112 }
114 return CSSVariableData::CreateResolved(tokens, variable_data, 113 return CSSVariableData::CreateResolved(tokens, std::move(backing_strings),
115 is_animation_tainted); 114 is_animation_tainted);
116 } 115 }
117 116
118 bool CSSVariableResolver::ResolveVariableReference( 117 bool CSSVariableResolver::ResolveVariableReference(
119 CSSParserTokenRange range, 118 CSSParserTokenRange range,
120 bool disallow_animation_tainted, 119 bool disallow_animation_tainted,
121 Vector<CSSParserToken>& result, 120 Vector<CSSParserToken>& result,
121 Vector<String>& result_backing_strings,
122 bool& result_is_animation_tainted) { 122 bool& result_is_animation_tainted) {
123 range.ConsumeWhitespace(); 123 range.ConsumeWhitespace();
124 DCHECK_EQ(range.Peek().GetType(), kIdentToken); 124 DCHECK_EQ(range.Peek().GetType(), kIdentToken);
125 AtomicString variable_name = 125 AtomicString variable_name =
126 range.ConsumeIncludingWhitespace().Value().ToAtomicString(); 126 range.ConsumeIncludingWhitespace().Value().ToAtomicString();
127 DCHECK(range.AtEnd() || (range.Peek().GetType() == kCommaToken)); 127 DCHECK(range.AtEnd() || (range.Peek().GetType() == kCommaToken));
128 128
129 CSSVariableData* variable_data = ValueForCustomProperty(variable_name); 129 CSSVariableData* variable_data = ValueForCustomProperty(variable_name);
130 if (!variable_data || 130 if (!variable_data ||
131 (disallow_animation_tainted && variable_data->IsAnimationTainted())) { 131 (disallow_animation_tainted && variable_data->IsAnimationTainted())) {
132 // TODO(alancutter): Append the registered initial custom property value if 132 // TODO(alancutter): Append the registered initial custom property value if
133 // we are disallowing an animation tainted value. 133 // we are disallowing an animation tainted value.
134 return ResolveFallback(range, disallow_animation_tainted, result, 134 return ResolveFallback(range, disallow_animation_tainted, result,
135 result_is_animation_tainted); 135 result_backing_strings, result_is_animation_tainted);
136 } 136 }
137 137
138 result.AppendVector(variable_data->Tokens()); 138 result.AppendVector(variable_data->Tokens());
139 // TODO(alancutter): Avoid adding backing strings multiple times in a row.
140 result_backing_strings.AppendVector(variable_data->BackingStrings());
139 result_is_animation_tainted |= variable_data->IsAnimationTainted(); 141 result_is_animation_tainted |= variable_data->IsAnimationTainted();
140 142
141 Vector<CSSParserToken> trash; 143 Vector<CSSParserToken> trash;
144 Vector<String> trash_backing_strings;
142 bool trash_is_animation_tainted; 145 bool trash_is_animation_tainted;
143 ResolveFallback(range, disallow_animation_tainted, trash, 146 ResolveFallback(range, disallow_animation_tainted, trash,
144 trash_is_animation_tainted); 147 trash_backing_strings, trash_is_animation_tainted);
145 return true; 148 return true;
146 } 149 }
147 150
148 void CSSVariableResolver::ResolveApplyAtRule(CSSParserTokenRange& range, 151 void CSSVariableResolver::ResolveApplyAtRule(
149 Vector<CSSParserToken>& result) { 152 CSSParserTokenRange& range,
153 Vector<CSSParserToken>& result,
154 Vector<String>& result_backing_strings) {
150 DCHECK(range.Peek().GetType() == kAtKeywordToken && 155 DCHECK(range.Peek().GetType() == kAtKeywordToken &&
151 EqualIgnoringASCIICase(range.Peek().Value(), "apply")); 156 EqualIgnoringASCIICase(range.Peek().Value(), "apply"));
152 range.ConsumeIncludingWhitespace(); 157 range.ConsumeIncludingWhitespace();
153 const CSSParserToken& variable_name = range.ConsumeIncludingWhitespace(); 158 const CSSParserToken& variable_name = range.ConsumeIncludingWhitespace();
154 // TODO(timloh): Should we actually be consuming this? 159 // TODO(timloh): Should we actually be consuming this?
155 if (range.Peek().GetType() == kSemicolonToken) 160 if (range.Peek().GetType() == kSemicolonToken)
156 range.Consume(); 161 range.Consume();
157 162
158 CSSVariableData* variable_data = 163 CSSVariableData* variable_data =
159 ValueForCustomProperty(variable_name.Value().ToAtomicString()); 164 ValueForCustomProperty(variable_name.Value().ToAtomicString());
160 if (!variable_data) 165 if (!variable_data)
161 return; // Invalid custom property 166 return; // Invalid custom property
162 167
163 CSSParserTokenRange rule = variable_data->TokenRange(); 168 CSSParserTokenRange rule = variable_data->TokenRange();
164 rule.ConsumeWhitespace(); 169 rule.ConsumeWhitespace();
165 if (rule.Peek().GetType() != kLeftBraceToken) 170 if (rule.Peek().GetType() != kLeftBraceToken)
166 return; 171 return;
167 CSSParserTokenRange rule_contents = rule.ConsumeBlock(); 172 CSSParserTokenRange rule_contents = rule.ConsumeBlock();
168 rule.ConsumeWhitespace(); 173 rule.ConsumeWhitespace();
169 if (!rule.AtEnd()) 174 if (!rule.AtEnd())
170 return; 175 return;
171 176
172 result.AppendRange(rule_contents.begin(), rule_contents.end()); 177 result.AppendRange(rule_contents.begin(), rule_contents.end());
178 result_backing_strings.AppendVector(variable_data->BackingStrings());
173 } 179 }
174 180
175 bool CSSVariableResolver::ResolveTokenRange(CSSParserTokenRange range, 181 bool CSSVariableResolver::ResolveTokenRange(
176 bool disallow_animation_tainted, 182 CSSParserTokenRange range,
177 Vector<CSSParserToken>& result, 183 bool disallow_animation_tainted,
178 bool& result_is_animation_tainted) { 184 Vector<CSSParserToken>& result,
185 Vector<String>& result_backing_strings,
186 bool& result_is_animation_tainted) {
179 bool success = true; 187 bool success = true;
180 while (!range.AtEnd()) { 188 while (!range.AtEnd()) {
181 if (range.Peek().FunctionId() == CSSValueVar) { 189 if (range.Peek().FunctionId() == CSSValueVar) {
182 success &= ResolveVariableReference(range.ConsumeBlock(), 190 success &= ResolveVariableReference(
183 disallow_animation_tainted, result, 191 range.ConsumeBlock(), disallow_animation_tainted, result,
184 result_is_animation_tainted); 192 result_backing_strings, result_is_animation_tainted);
185 } else if (range.Peek().GetType() == kAtKeywordToken && 193 } else if (range.Peek().GetType() == kAtKeywordToken &&
186 EqualIgnoringASCIICase(range.Peek().Value(), "apply") && 194 EqualIgnoringASCIICase(range.Peek().Value(), "apply") &&
187 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) { 195 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) {
188 ResolveApplyAtRule(range, result); 196 ResolveApplyAtRule(range, result, result_backing_strings);
189 } else { 197 } else {
190 result.push_back(range.Consume()); 198 result.push_back(range.Consume());
191 } 199 }
192 } 200 }
193 return success; 201 return success;
194 } 202 }
195 203
196 const CSSValue* CSSVariableResolver::ResolveVariableReferences( 204 const CSSValue* CSSVariableResolver::ResolveVariableReferences(
197 const StyleResolverState& state, 205 const StyleResolverState& state,
198 CSSPropertyID id, 206 CSSPropertyID id,
(...skipping 17 matching lines...) Expand all
216 return nullptr; 224 return nullptr;
217 } 225 }
218 226
219 const CSSValue* CSSVariableResolver::ResolveVariableReferences( 227 const CSSValue* CSSVariableResolver::ResolveVariableReferences(
220 const StyleResolverState& state, 228 const StyleResolverState& state,
221 CSSPropertyID id, 229 CSSPropertyID id,
222 const CSSVariableReferenceValue& value, 230 const CSSVariableReferenceValue& value,
223 bool disallow_animation_tainted) { 231 bool disallow_animation_tainted) {
224 CSSVariableResolver resolver(state); 232 CSSVariableResolver resolver(state);
225 Vector<CSSParserToken> tokens; 233 Vector<CSSParserToken> tokens;
234 Vector<String> backing_strings;
226 bool is_animation_tainted = false; 235 bool is_animation_tainted = false;
227 if (!resolver.ResolveTokenRange(value.VariableDataValue()->Tokens(), 236 if (!resolver.ResolveTokenRange(value.VariableDataValue()->Tokens(),
228 disallow_animation_tainted, tokens, 237 disallow_animation_tainted, tokens,
229 is_animation_tainted)) 238 backing_strings, is_animation_tainted))
230 return CSSUnsetValue::Create(); 239 return CSSUnsetValue::Create();
231 const CSSValue* result = 240 const CSSValue* result =
232 CSSPropertyParser::ParseSingleValue(id, tokens, value.ParserContext()); 241 CSSPropertyParser::ParseSingleValue(id, tokens, value.ParserContext());
233 if (!result) 242 if (!result)
234 return CSSUnsetValue::Create(); 243 return CSSUnsetValue::Create();
235 return result; 244 return result;
236 } 245 }
237 246
238 const CSSValue* CSSVariableResolver::ResolvePendingSubstitutions( 247 const CSSValue* CSSVariableResolver::ResolvePendingSubstitutions(
239 const StyleResolverState& state, 248 const StyleResolverState& state,
240 CSSPropertyID id, 249 CSSPropertyID id,
241 const CSSPendingSubstitutionValue& pending_value, 250 const CSSPendingSubstitutionValue& pending_value,
242 bool disallow_animation_tainted) { 251 bool disallow_animation_tainted) {
243 // Longhands from shorthand references follow this path. 252 // Longhands from shorthand references follow this path.
244 HeapHashMap<CSSPropertyID, Member<const CSSValue>>& property_cache = 253 HeapHashMap<CSSPropertyID, Member<const CSSValue>>& property_cache =
245 state.ParsedPropertiesForPendingSubstitutionCache(pending_value); 254 state.ParsedPropertiesForPendingSubstitutionCache(pending_value);
246 255
247 const CSSValue* value = property_cache.at(id); 256 const CSSValue* value = property_cache.at(id);
248 if (!value) { 257 if (!value) {
249 // TODO(timloh): We shouldn't retry this for all longhands if the shorthand 258 // TODO(timloh): We shouldn't retry this for all longhands if the shorthand
250 // ends up invalid. 259 // ends up invalid.
251 CSSVariableReferenceValue* shorthand_value = pending_value.ShorthandValue(); 260 CSSVariableReferenceValue* shorthand_value = pending_value.ShorthandValue();
252 CSSPropertyID shorthand_property_id = pending_value.ShorthandPropertyId(); 261 CSSPropertyID shorthand_property_id = pending_value.ShorthandPropertyId();
253 262
254 CSSVariableResolver resolver(state); 263 CSSVariableResolver resolver(state);
255 264
256 Vector<CSSParserToken> tokens; 265 Vector<CSSParserToken> tokens;
266 Vector<String> backing_strings;
257 bool is_animation_tainted = false; 267 bool is_animation_tainted = false;
258 if (resolver.ResolveTokenRange( 268 if (resolver.ResolveTokenRange(
259 shorthand_value->VariableDataValue()->Tokens(), 269 shorthand_value->VariableDataValue()->Tokens(),
260 disallow_animation_tainted, tokens, is_animation_tainted)) { 270 disallow_animation_tainted, tokens, backing_strings,
261 271 is_animation_tainted)) {
262 HeapVector<CSSProperty, 256> parsed_properties; 272 HeapVector<CSSProperty, 256> parsed_properties;
263 273
264 if (CSSPropertyParser::ParseValue( 274 if (CSSPropertyParser::ParseValue(
265 shorthand_property_id, false, CSSParserTokenRange(tokens), 275 shorthand_property_id, false, CSSParserTokenRange(tokens),
266 shorthand_value->ParserContext(), parsed_properties, 276 shorthand_value->ParserContext(), parsed_properties,
267 StyleRule::RuleType::kStyle)) { 277 StyleRule::RuleType::kStyle)) {
268 unsigned parsed_properties_count = parsed_properties.size(); 278 unsigned parsed_properties_count = parsed_properties.size();
269 for (unsigned i = 0; i < parsed_properties_count; ++i) { 279 for (unsigned i = 0; i < parsed_properties_count; ++i) {
270 property_cache.Set(parsed_properties[i].Id(), 280 property_cache.Set(parsed_properties[i].Id(),
271 parsed_properties[i].Value()); 281 parsed_properties[i].Value());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 } 344 }
335 } 345 }
336 } 346 }
337 347
338 CSSVariableResolver::CSSVariableResolver(const StyleResolverState& state) 348 CSSVariableResolver::CSSVariableResolver(const StyleResolverState& state)
339 : inherited_variables_(state.Style()->InheritedVariables()), 349 : inherited_variables_(state.Style()->InheritedVariables()),
340 non_inherited_variables_(state.Style()->NonInheritedVariables()), 350 non_inherited_variables_(state.Style()->NonInheritedVariables()),
341 registry_(state.GetDocument().GetPropertyRegistry()) {} 351 registry_(state.GetDocument().GetPropertyRegistry()) {}
342 352
343 } // namespace blink 353 } // 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