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