1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All
6 * rights reserved.
7 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
8 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
9 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
10 * (http://www.torchmobile.com/)
11 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
12 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
13 * Copyright (C) 2012 Google Inc. All rights reserved.
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Library General Public
17 * License as published by the Free Software Foundation; either
18 * version 2 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Library General Public License for more details.
24 *
25 * You should have received a copy of the GNU Library General Public License
26 * along with this library; see the file COPYING.LIB. If not, write to
27 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 * Boston, MA 02110-1301, USA.
29 */
30
31 #include "third_party/blink/renderer/core/css/rule_set.h"
32
33 #include <type_traits>
34
35 #include "third_party/blink/renderer/core/css/css_font_selector.h"
36 #include "third_party/blink/renderer/core/css/css_selector.h"
37 #include "third_party/blink/renderer/core/css/css_selector_list.h"
38 #include "third_party/blink/renderer/core/css/selector_filter.h"
39 #include "third_party/blink/renderer/core/css/style_rule_import.h"
40 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
41 #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
42 #include "third_party/blink/renderer/core/html/track/text_track_cue.h"
43 #include "third_party/blink/renderer/core/html_names.h"
44 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
45 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
46
47 namespace blink {
48
DetermineValidPropertyFilter(const AddRuleFlags add_rule_flags,const CSSSelector & selector)49 static inline ValidPropertyFilter DetermineValidPropertyFilter(
50 const AddRuleFlags add_rule_flags,
51 const CSSSelector& selector) {
52 for (const CSSSelector* component = &selector; component;
53 component = component->TagHistory()) {
54 if (component->Match() == CSSSelector::kPseudoElement &&
55 component->Value() == TextTrackCue::CueShadowPseudoId()) {
56 return ValidPropertyFilter::kCue;
57 }
58 switch (component->GetPseudoType()) {
59 case CSSSelector::kPseudoCue:
60 return ValidPropertyFilter::kCue;
61 case CSSSelector::kPseudoFirstLetter:
62 return ValidPropertyFilter::kFirstLetter;
63 case CSSSelector::kPseudoMarker:
64 return ValidPropertyFilter::kMarker;
65 case CSSSelector::kPseudoSelection:
66 case CSSSelector::kPseudoTargetText:
67 return ValidPropertyFilter::kHighlight;
68 default:
69 break;
70 }
71 }
72 return ValidPropertyFilter::kNoFilter;
73 }
74
DetermineLinkMatchType(const AddRuleFlags add_rule_flags,const CSSSelector & selector)75 static unsigned DetermineLinkMatchType(const AddRuleFlags add_rule_flags,
76 const CSSSelector& selector) {
77 if (selector.HasLinkOrVisited()) {
78 return (add_rule_flags & kRuleIsVisitedDependent)
79 ? CSSSelector::kMatchVisited
80 : CSSSelector::kMatchLink;
81 }
82 return CSSSelector::kMatchAll;
83 }
84
MaybeCreate(StyleRule * rule,unsigned selector_index,unsigned position,AddRuleFlags add_rule_flags)85 RuleData* RuleData::MaybeCreate(StyleRule* rule,
86 unsigned selector_index,
87 unsigned position,
88 AddRuleFlags add_rule_flags) {
89 // The selector index field in RuleData is only 13 bits so we can't support
90 // selectors at index 8192 or beyond.
91 // See https://crbug.com/804179
92 if (selector_index >= (1 << RuleData::kSelectorIndexBits))
93 return nullptr;
94 if (position >= (1 << RuleData::kPositionBits))
95 return nullptr;
96 return MakeGarbageCollected<RuleData>(rule, selector_index, position,
97 add_rule_flags);
98 }
99
RuleData(StyleRule * rule,unsigned selector_index,unsigned position,AddRuleFlags add_rule_flags)100 RuleData::RuleData(StyleRule* rule,
101 unsigned selector_index,
102 unsigned position,
103 AddRuleFlags add_rule_flags)
104 : rule_(rule),
105 selector_index_(selector_index),
106 position_(position),
107 specificity_(Selector().Specificity()),
108 link_match_type_(DetermineLinkMatchType(add_rule_flags, Selector())),
109 has_document_security_origin_(add_rule_flags &
110 kRuleHasDocumentSecurityOrigin),
111 valid_property_filter_(
112 static_cast<std::underlying_type_t<ValidPropertyFilter>>(
113 DetermineValidPropertyFilter(add_rule_flags, Selector()))),
114 descendant_selector_identifier_hashes_() {
115 SelectorFilter::CollectIdentifierHashes(
116 Selector(), descendant_selector_identifier_hashes_,
117 kMaximumIdentifierCount);
118 }
119
AddToRuleSet(const AtomicString & key,PendingRuleMap & map,const RuleData * rule_data)120 void RuleSet::AddToRuleSet(const AtomicString& key,
121 PendingRuleMap& map,
122 const RuleData* rule_data) {
123 Member<HeapLinkedStack<Member<const RuleData>>>& rules =
124 map.insert(key, nullptr).stored_value->value;
125 if (!rules)
126 rules = MakeGarbageCollected<HeapLinkedStack<Member<const RuleData>>>();
127 rules->Push(rule_data);
128 }
129
ExtractSelectorValues(const CSSSelector * selector,AtomicString & id,AtomicString & class_name,AtomicString & custom_pseudo_element_name,AtomicString & tag_name,AtomicString & part_name,CSSSelector::PseudoType & pseudo_type)130 static void ExtractSelectorValues(const CSSSelector* selector,
131 AtomicString& id,
132 AtomicString& class_name,
133 AtomicString& custom_pseudo_element_name,
134 AtomicString& tag_name,
135 AtomicString& part_name,
136 CSSSelector::PseudoType& pseudo_type) {
137 switch (selector->Match()) {
138 case CSSSelector::kId:
139 id = selector->Value();
140 break;
141 case CSSSelector::kClass:
142 class_name = selector->Value();
143 break;
144 case CSSSelector::kTag:
145 if (selector->TagQName().LocalName() !=
146 CSSSelector::UniversalSelectorAtom())
147 tag_name = selector->TagQName().LocalName();
148 break;
149 case CSSSelector::kPseudoClass:
150 case CSSSelector::kPseudoElement:
151 case CSSSelector::kPagePseudoClass:
152 // Must match the cases in RuleSet::FindBestRuleSetAndAdd.
153 switch (selector->GetPseudoType()) {
154 case CSSSelector::kPseudoCue:
155 case CSSSelector::kPseudoLink:
156 case CSSSelector::kPseudoVisited:
157 case CSSSelector::kPseudoWebkitAnyLink:
158 case CSSSelector::kPseudoAnyLink:
159 case CSSSelector::kPseudoFocus:
160 case CSSSelector::kPseudoPlaceholder:
161 case CSSSelector::kPseudoHost:
162 case CSSSelector::kPseudoHostContext:
163 case CSSSelector::kPseudoSpatialNavigationInterest:
164 pseudo_type = selector->GetPseudoType();
165 break;
166 case CSSSelector::kPseudoWebKitCustomElement:
167 case CSSSelector::kPseudoBlinkInternalElement:
168 custom_pseudo_element_name = selector->Value();
169 break;
170 case CSSSelector::kPseudoPart:
171 part_name = selector->Value();
172 break;
173 default:
174 break;
175 }
176 break;
177 default:
178 break;
179 }
180 }
181
FindBestRuleSetAndAdd(const CSSSelector & component,RuleData * rule_data)182 bool RuleSet::FindBestRuleSetAndAdd(const CSSSelector& component,
183 RuleData* rule_data) {
184 AtomicString id;
185 AtomicString class_name;
186 AtomicString custom_pseudo_element_name;
187 AtomicString tag_name;
188 AtomicString part_name;
189 CSSSelector::PseudoType pseudo_type = CSSSelector::kPseudoUnknown;
190
191 #ifndef NDEBUG
192 all_rules_.push_back(rule_data);
193 #endif
194
195 const CSSSelector* it = &component;
196 for (; it && it->Relation() == CSSSelector::kSubSelector;
197 it = it->TagHistory()) {
198 ExtractSelectorValues(it, id, class_name, custom_pseudo_element_name,
199 tag_name, part_name, pseudo_type);
200 }
201 if (it) {
202 ExtractSelectorValues(it, id, class_name, custom_pseudo_element_name,
203 tag_name, part_name, pseudo_type);
204 }
205
206 // Prefer rule sets in order of most likely to apply infrequently.
207 if (!id.IsEmpty()) {
208 AddToRuleSet(id, EnsurePendingRules()->id_rules, rule_data);
209 return true;
210 }
211
212 if (!class_name.IsEmpty()) {
213 AddToRuleSet(class_name, EnsurePendingRules()->class_rules, rule_data);
214 return true;
215 }
216
217 if (!custom_pseudo_element_name.IsEmpty()) {
218 // Custom pseudos come before ids and classes in the order of tagHistory,
219 // and have a relation of ShadowPseudo between them. Therefore we should
220 // never be a situation where ExtractSelectorValues finds id and
221 // className in addition to custom pseudo.
222 DCHECK(id.IsEmpty());
223 DCHECK(class_name.IsEmpty());
224 AddToRuleSet(custom_pseudo_element_name,
225 EnsurePendingRules()->shadow_pseudo_element_rules, rule_data);
226 return true;
227 }
228
229 if (!part_name.IsEmpty()) {
230 part_pseudo_rules_.push_back(rule_data);
231 return true;
232 }
233
234 switch (pseudo_type) {
235 case CSSSelector::kPseudoCue:
236 cue_pseudo_rules_.push_back(rule_data);
237 return true;
238 case CSSSelector::kPseudoLink:
239 case CSSSelector::kPseudoVisited:
240 case CSSSelector::kPseudoAnyLink:
241 case CSSSelector::kPseudoWebkitAnyLink:
242 link_pseudo_class_rules_.push_back(rule_data);
243 return true;
244 case CSSSelector::kPseudoSpatialNavigationInterest:
245 spatial_navigation_interest_class_rules_.push_back(rule_data);
246 return true;
247 case CSSSelector::kPseudoFocus:
248 focus_pseudo_class_rules_.push_back(rule_data);
249 return true;
250 case CSSSelector::kPseudoPlaceholder:
251 if (it->FollowsPart()) {
252 part_pseudo_rules_.push_back(rule_data);
253 } else {
254 AddToRuleSet(shadow_element_names::kPseudoInputPlaceholder,
255 EnsurePendingRules()->shadow_pseudo_element_rules,
256 rule_data);
257 }
258 return true;
259 case CSSSelector::kPseudoHost:
260 case CSSSelector::kPseudoHostContext:
261 shadow_host_rules_.push_back(rule_data);
262 return true;
263 default:
264 break;
265 }
266
267 if (!tag_name.IsEmpty()) {
268 AddToRuleSet(tag_name, EnsurePendingRules()->tag_rules, rule_data);
269 return true;
270 }
271
272 return false;
273 }
274
AddRule(StyleRule * rule,unsigned selector_index,AddRuleFlags add_rule_flags)275 void RuleSet::AddRule(StyleRule* rule,
276 unsigned selector_index,
277 AddRuleFlags add_rule_flags) {
278 RuleData* rule_data =
279 RuleData::MaybeCreate(rule, selector_index, rule_count_, add_rule_flags);
280 if (!rule_data) {
281 // This can happen if selector_index or position is out of range.
282 return;
283 }
284 ++rule_count_;
285 if (features_.CollectFeaturesFromRuleData(rule_data) ==
286 RuleFeatureSet::kSelectorNeverMatches)
287 return;
288
289 if (!FindBestRuleSetAndAdd(rule_data->Selector(), rule_data)) {
290 // If we didn't find a specialized map to stick it in, file under universal
291 // rules.
292 universal_rules_.push_back(rule_data);
293 }
294
295 // If the rule has CSSSelector::kMatchLink, it means that there is a :visited
296 // or :link pseudo-class somewhere in the selector. In those cases, we
297 // effectively split the rule into two: one which covers the situation
298 // where we are in an unvisited link (kMatchLink), and another which covers
299 // the visited link case (kMatchVisited).
300 if (rule_data->LinkMatchType() == CSSSelector::kMatchLink) {
301 RuleData* visited_dependent = RuleData::MaybeCreate(
302 rule, rule_data->SelectorIndex(), rule_data->GetPosition(),
303 add_rule_flags | kRuleIsVisitedDependent);
304 DCHECK(visited_dependent);
305 visited_dependent_rules_.push_back(visited_dependent);
306 }
307 }
308
AddPageRule(StyleRulePage * rule)309 void RuleSet::AddPageRule(StyleRulePage* rule) {
310 EnsurePendingRules(); // So that page_rules_.ShrinkToFit() gets called.
311 page_rules_.push_back(rule);
312 }
313
AddFontFaceRule(StyleRuleFontFace * rule)314 void RuleSet::AddFontFaceRule(StyleRuleFontFace* rule) {
315 EnsurePendingRules(); // So that font_face_rules_.ShrinkToFit() gets called.
316 font_face_rules_.push_back(rule);
317 }
318
AddKeyframesRule(StyleRuleKeyframes * rule)319 void RuleSet::AddKeyframesRule(StyleRuleKeyframes* rule) {
320 EnsurePendingRules(); // So that keyframes_rules_.ShrinkToFit() gets called.
321 keyframes_rules_.push_back(rule);
322 keyframes_rules_sorted_ = false;
323 }
324
SortKeyframesRulesIfNeeded()325 void RuleSet::SortKeyframesRulesIfNeeded() {
326 if (keyframes_rules_sorted_)
327 return;
328 // Sort keyframes rules by name, breaking ties with vendor prefixing.
329 // Since equal AtomicStrings always have the same impl, there's no need to
330 // actually compare the contents of two AtomicStrings. Comparing their impl
331 // addresses is enough.
332 std::stable_sort(
333 keyframes_rules_.begin(), keyframes_rules_.end(),
334 [](const StyleRuleKeyframes* lhs, const StyleRuleKeyframes* rhs) {
335 if (lhs->GetName() != rhs->GetName())
336 return lhs->GetName().Impl() < rhs->GetName().Impl();
337 if (lhs->IsVendorPrefixed() != rhs->IsVendorPrefixed())
338 return lhs->IsVendorPrefixed();
339 return false;
340 });
341 // Deduplicate rules, erase all but the last one for each animation name,
342 // since all the preceding ones are overridden.
343 auto boundary = std::unique(
344 keyframes_rules_.rbegin(), keyframes_rules_.rend(),
345 [](const StyleRuleKeyframes* lhs, const StyleRuleKeyframes* rhs) {
346 return lhs->GetName() == rhs->GetName();
347 });
348 keyframes_rules_.erase(keyframes_rules_.begin(), boundary.base());
349 keyframes_rules_.ShrinkToFit();
350 keyframes_rules_sorted_ = true;
351 }
352
KeyframeStylesForAnimation(const AtomicString & name)353 StyleRuleKeyframes* RuleSet::KeyframeStylesForAnimation(
354 const AtomicString& name) {
355 SortKeyframesRulesIfNeeded();
356 Member<StyleRuleKeyframes>* rule_iterator = std::lower_bound(
357 keyframes_rules_.begin(), keyframes_rules_.end(), name,
358 [](const StyleRuleKeyframes* rule, const AtomicString& name) {
359 return rule->GetName().Impl() < name.Impl();
360 });
361 if (rule_iterator != keyframes_rules_.end() &&
362 (*rule_iterator)->GetName() == name) {
363 return *rule_iterator;
364 }
365 return nullptr;
366 }
367
AddPropertyRule(StyleRuleProperty * rule)368 void RuleSet::AddPropertyRule(StyleRuleProperty* rule) {
369 EnsurePendingRules(); // So that property_rules_.ShrinkToFit() gets called.
370 property_rules_.push_back(rule);
371 }
372
AddScrollTimelineRule(StyleRuleScrollTimeline * rule)373 void RuleSet::AddScrollTimelineRule(StyleRuleScrollTimeline* rule) {
374 EnsurePendingRules(); // So that property_rules_.ShrinkToFit() gets called.
375 scroll_timeline_rules_.push_back(rule);
376 }
377
AddChildRules(const HeapVector<Member<StyleRuleBase>> & rules,const MediaQueryEvaluator & medium,AddRuleFlags add_rule_flags)378 void RuleSet::AddChildRules(const HeapVector<Member<StyleRuleBase>>& rules,
379 const MediaQueryEvaluator& medium,
380 AddRuleFlags add_rule_flags) {
381 for (unsigned i = 0; i < rules.size(); ++i) {
382 StyleRuleBase* rule = rules[i].Get();
383
384 if (auto* style_rule = DynamicTo<StyleRule>(rule)) {
385 const CSSSelectorList& selector_list = style_rule->SelectorList();
386 for (const CSSSelector* selector = selector_list.First(); selector;
387 selector = selector_list.Next(*selector)) {
388 wtf_size_t selector_index = selector_list.SelectorIndex(*selector);
389 if (selector->HasDeepCombinatorOrShadowPseudo()) {
390 deep_combinator_or_shadow_pseudo_rules_.push_back(
391 MinimalRuleData(style_rule, selector_index, add_rule_flags));
392 } else if (selector->HasContentPseudo()) {
393 content_pseudo_element_rules_.push_back(
394 MinimalRuleData(style_rule, selector_index, add_rule_flags));
395 } else if (selector->HasSlottedPseudo()) {
396 slotted_pseudo_element_rules_.push_back(
397 MinimalRuleData(style_rule, selector_index, add_rule_flags));
398 } else {
399 AddRule(style_rule, selector_index, add_rule_flags);
400 }
401 }
402 } else if (auto* page_rule = DynamicTo<StyleRulePage>(rule)) {
403 AddPageRule(page_rule);
404 } else if (auto* media_rule = DynamicTo<StyleRuleMedia>(rule)) {
405 if (MatchMediaForAddRules(medium, media_rule->MediaQueries()))
406 AddChildRules(media_rule->ChildRules(), medium, add_rule_flags);
407 } else if (auto* font_face_rule = DynamicTo<StyleRuleFontFace>(rule)) {
408 AddFontFaceRule(font_face_rule);
409 } else if (auto* keyframes_rule = DynamicTo<StyleRuleKeyframes>(rule)) {
410 AddKeyframesRule(keyframes_rule);
411 } else if (auto* property_rule = DynamicTo<StyleRuleProperty>(rule)) {
412 AddPropertyRule(property_rule);
413 } else if (auto* scroll_timeline_rule =
414 DynamicTo<StyleRuleScrollTimeline>(rule)) {
415 AddScrollTimelineRule(scroll_timeline_rule);
416 } else if (auto* supports_rule = DynamicTo<StyleRuleSupports>(rule)) {
417 if (supports_rule->ConditionIsSupported())
418 AddChildRules(supports_rule->ChildRules(), medium, add_rule_flags);
419 }
420 }
421 }
422
MatchMediaForAddRules(const MediaQueryEvaluator & evaluator,const MediaQuerySet * media_queries)423 bool RuleSet::MatchMediaForAddRules(const MediaQueryEvaluator& evaluator,
424 const MediaQuerySet* media_queries) {
425 if (!media_queries)
426 return true;
427 bool match_media = evaluator.Eval(
428 *media_queries, &features_.ViewportDependentMediaQueryResults(),
429 &features_.DeviceDependentMediaQueryResults());
430 media_query_set_results_.push_back(
431 MediaQuerySetResult(*media_queries, match_media));
432 return match_media;
433 }
434
AddRulesFromSheet(StyleSheetContents * sheet,const MediaQueryEvaluator & medium,AddRuleFlags add_rule_flags)435 void RuleSet::AddRulesFromSheet(StyleSheetContents* sheet,
436 const MediaQueryEvaluator& medium,
437 AddRuleFlags add_rule_flags) {
438 TRACE_EVENT0("blink", "RuleSet::addRulesFromSheet");
439
440 DCHECK(sheet);
441
442 const HeapVector<Member<StyleRuleImport>>& import_rules =
443 sheet->ImportRules();
444 for (unsigned i = 0; i < import_rules.size(); ++i) {
445 StyleRuleImport* import_rule = import_rules[i].Get();
446 if (import_rule->GetStyleSheet() &&
447 MatchMediaForAddRules(medium, import_rule->MediaQueries())) {
448 AddRulesFromSheet(import_rule->GetStyleSheet(), medium, add_rule_flags);
449 }
450 }
451
452 AddChildRules(sheet->ChildRules(), medium, add_rule_flags);
453 }
454
AddStyleRule(StyleRule * rule,AddRuleFlags add_rule_flags)455 void RuleSet::AddStyleRule(StyleRule* rule, AddRuleFlags add_rule_flags) {
456 for (wtf_size_t selector_index =
457 rule->SelectorList().SelectorIndex(*rule->SelectorList().First());
458 selector_index != kNotFound;
459 selector_index =
460 rule->SelectorList().IndexOfNextSelectorAfter(selector_index))
461 AddRule(rule, selector_index, add_rule_flags);
462 }
463
CompactPendingRules(PendingRuleMap & pending_map,CompactRuleMap & compact_map)464 void RuleSet::CompactPendingRules(PendingRuleMap& pending_map,
465 CompactRuleMap& compact_map) {
466 for (auto& item : pending_map) {
467 HeapLinkedStack<Member<const RuleData>>* pending_rules =
468 item.value.Release();
469 Member<HeapVector<Member<const RuleData>>>& rules =
470 compact_map.insert(item.key, nullptr).stored_value->value;
471 if (!rules) {
472 rules = MakeGarbageCollected<HeapVector<Member<const RuleData>>>();
473 rules->ReserveInitialCapacity(pending_rules->size());
474 } else {
475 rules->ReserveCapacity(pending_rules->size());
476 }
477 while (!pending_rules->IsEmpty()) {
478 rules->push_back(pending_rules->Peek());
479 pending_rules->Pop();
480 }
481 }
482 }
483
CompactRules()484 void RuleSet::CompactRules() {
485 DCHECK(pending_rules_);
486 PendingRuleMaps* pending_rules = pending_rules_.Release();
487 CompactPendingRules(pending_rules->id_rules, id_rules_);
488 CompactPendingRules(pending_rules->class_rules, class_rules_);
489 CompactPendingRules(pending_rules->tag_rules, tag_rules_);
490 CompactPendingRules(pending_rules->shadow_pseudo_element_rules,
491 shadow_pseudo_element_rules_);
492 link_pseudo_class_rules_.ShrinkToFit();
493 cue_pseudo_rules_.ShrinkToFit();
494 focus_pseudo_class_rules_.ShrinkToFit();
495 spatial_navigation_interest_class_rules_.ShrinkToFit();
496 universal_rules_.ShrinkToFit();
497 shadow_host_rules_.ShrinkToFit();
498 page_rules_.ShrinkToFit();
499 font_face_rules_.ShrinkToFit();
500 keyframes_rules_.ShrinkToFit();
501 property_rules_.ShrinkToFit();
502 deep_combinator_or_shadow_pseudo_rules_.ShrinkToFit();
503 part_pseudo_rules_.ShrinkToFit();
504 content_pseudo_element_rules_.ShrinkToFit();
505 slotted_pseudo_element_rules_.ShrinkToFit();
506 }
507
DidMediaQueryResultsChange(const MediaQueryEvaluator & evaluator) const508 bool RuleSet::DidMediaQueryResultsChange(
509 const MediaQueryEvaluator& evaluator) const {
510 return evaluator.DidResultsChange(media_query_set_results_);
511 }
512
Trace(Visitor * visitor) const513 void MinimalRuleData::Trace(Visitor* visitor) const {
514 visitor->Trace(rule_);
515 }
516
Trace(Visitor * visitor) const517 void RuleData::Trace(Visitor* visitor) const {
518 visitor->Trace(rule_);
519 }
520
Trace(Visitor * visitor) const521 void RuleSet::PendingRuleMaps::Trace(Visitor* visitor) const {
522 visitor->Trace(id_rules);
523 visitor->Trace(class_rules);
524 visitor->Trace(tag_rules);
525 visitor->Trace(shadow_pseudo_element_rules);
526 }
527
Trace(Visitor * visitor) const528 void RuleSet::Trace(Visitor* visitor) const {
529 visitor->Trace(id_rules_);
530 visitor->Trace(class_rules_);
531 visitor->Trace(tag_rules_);
532 visitor->Trace(shadow_pseudo_element_rules_);
533 visitor->Trace(link_pseudo_class_rules_);
534 visitor->Trace(cue_pseudo_rules_);
535 visitor->Trace(focus_pseudo_class_rules_);
536 visitor->Trace(spatial_navigation_interest_class_rules_);
537 visitor->Trace(universal_rules_);
538 visitor->Trace(shadow_host_rules_);
539 visitor->Trace(page_rules_);
540 visitor->Trace(font_face_rules_);
541 visitor->Trace(keyframes_rules_);
542 visitor->Trace(property_rules_);
543 visitor->Trace(scroll_timeline_rules_);
544 visitor->Trace(deep_combinator_or_shadow_pseudo_rules_);
545 visitor->Trace(part_pseudo_rules_);
546 visitor->Trace(visited_dependent_rules_);
547 visitor->Trace(content_pseudo_element_rules_);
548 visitor->Trace(slotted_pseudo_element_rules_);
549 visitor->Trace(pending_rules_);
550 #ifndef NDEBUG
551 visitor->Trace(all_rules_);
552 #endif
553 }
554
555 #ifndef NDEBUG
Show() const556 void RuleSet::Show() const {
557 for (const auto& rule : all_rules_)
558 rule->Selector().Show();
559 }
560 #endif
561
562 } // namespace blink
563