Backed out 5 changesets (bug 1731541) for causing multiple wpt failures. CLOSED TREE
[gecko.git] / servo / components / style / stylist.rs
blob2b365bfbf6a5932757584cc36844c02a14d0c68f
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
5 //! Selector matching.
7 use crate::applicable_declarations::{
8     ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority,
9 };
10 use crate::context::{CascadeInputs, QuirksMode};
11 use crate::dom::TElement;
12 #[cfg(feature = "gecko")]
13 use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
14 use crate::invalidation::element::invalidation_map::{
15     note_selector_for_invalidation, InvalidationMap, RelativeSelectorInvalidationMap,
17 use crate::invalidation::media_queries::{
18     EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
20 use crate::invalidation::stylesheets::RuleChangeKind;
21 use crate::media_queries::Device;
22 use crate::properties::{self, CascadeMode, ComputedValues, FirstLineReparenting};
23 use crate::properties::{AnimationDeclarations, PropertyDeclarationBlock};
24 use crate::properties_and_values::registry::{ScriptRegistry as CustomPropertyScriptRegistry, PropertyRegistration};
25 use crate::rule_cache::{RuleCache, RuleCacheConditions};
26 use crate::rule_collector::RuleCollector;
27 use crate::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
28 use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
29 use crate::selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap};
30 use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
31 use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
32 use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
33 use crate::stylesheets::container_rule::ContainerCondition;
34 use crate::stylesheets::import_rule::ImportLayer;
35 use crate::stylesheets::keyframes_rule::KeyframesAnimation;
36 use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
37 #[cfg(feature = "gecko")]
38 use crate::stylesheets::{
39     CounterStyleRule, FontFaceRule, FontFeatureValuesRule, FontPaletteValuesRule,
41 use crate::stylesheets::{
42     CssRule, EffectiveRulesIterator, Origin, OriginSet, PerOrigin, PerOriginIter,
43     PagePseudoClassFlags, PageRule,
45 use crate::stylesheets::{StyleRule, StylesheetContents, StylesheetInDocument};
46 use crate::AllocErr;
47 use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
48 use dom::{DocumentState, ElementState};
49 use fxhash::FxHashMap;
50 use malloc_size_of::MallocSizeOf;
51 #[cfg(feature = "gecko")]
52 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
53 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
54 use selectors::bloom::BloomFilter;
55 use selectors::matching::{
56     matches_selector, MatchingContext, MatchingMode, NeedsSelectorFlags, SelectorCaches,
58 use selectors::matching::{MatchingForInvalidation, VisitedHandlingMode};
59 use selectors::parser::{
60     ArcSelectorList, AncestorHashes, Combinator, Component, Selector, SelectorIter, SelectorList,
62 use selectors::visitor::{SelectorListKind, SelectorVisitor};
63 use servo_arc::{Arc, ArcBorrow};
64 use smallbitvec::SmallBitVec;
65 use smallvec::SmallVec;
66 use std::borrow::Cow;
67 use std::cmp::Ordering;
68 use std::hash::{Hash, Hasher};
69 use std::sync::Mutex;
70 use std::{mem, ops};
72 /// The type of the stylesheets that the stylist contains.
73 #[cfg(feature = "servo")]
74 pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
76 /// The type of the stylesheets that the stylist contains.
77 #[cfg(feature = "gecko")]
78 pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
80 #[derive(Debug, Clone)]
81 struct StylesheetContentsPtr(Arc<StylesheetContents>);
83 impl PartialEq for StylesheetContentsPtr {
84     #[inline]
85     fn eq(&self, other: &Self) -> bool {
86         Arc::ptr_eq(&self.0, &other.0)
87     }
90 impl Eq for StylesheetContentsPtr {}
92 impl Hash for StylesheetContentsPtr {
93     fn hash<H: Hasher>(&self, state: &mut H) {
94         let contents: &StylesheetContents = &*self.0;
95         (contents as *const StylesheetContents).hash(state)
96     }
99 type StyleSheetContentList = Vec<StylesheetContentsPtr>;
101 /// A key in the cascade data cache.
102 #[derive(Debug, Hash, Default, PartialEq, Eq)]
103 struct CascadeDataCacheKey {
104     media_query_results: Vec<MediaListKey>,
105     contents: StyleSheetContentList,
108 unsafe impl Send for CascadeDataCacheKey {}
109 unsafe impl Sync for CascadeDataCacheKey {}
111 trait CascadeDataCacheEntry: Sized {
112     /// Returns a reference to the cascade data.
113     fn cascade_data(&self) -> &CascadeData;
114     /// Rebuilds the cascade data for the new stylesheet collection. The
115     /// collection is guaranteed to be dirty.
116     fn rebuild<S>(
117         device: &Device,
118         quirks_mode: QuirksMode,
119         collection: SheetCollectionFlusher<S>,
120         guard: &SharedRwLockReadGuard,
121         old_entry: &Self,
122     ) -> Result<Arc<Self>, AllocErr>
123     where
124         S: StylesheetInDocument + PartialEq + 'static;
125     /// Measures heap memory usage.
126     #[cfg(feature = "gecko")]
127     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
130 struct CascadeDataCache<Entry> {
131     entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
134 impl<Entry> CascadeDataCache<Entry>
135 where
136     Entry: CascadeDataCacheEntry,
138     fn new() -> Self {
139         Self {
140             entries: Default::default(),
141         }
142     }
144     fn len(&self) -> usize {
145         self.entries.len()
146     }
148     // FIXME(emilio): This may need to be keyed on quirks-mode too, though for
149     // UA sheets there aren't class / id selectors on those sheets, usually, so
150     // it's probably ok... For the other cache the quirks mode shouldn't differ
151     // so also should be fine.
152     fn lookup<'a, S>(
153         &'a mut self,
154         device: &Device,
155         quirks_mode: QuirksMode,
156         collection: SheetCollectionFlusher<S>,
157         guard: &SharedRwLockReadGuard,
158         old_entry: &Entry,
159     ) -> Result<Option<Arc<Entry>>, AllocErr>
160     where
161         S: StylesheetInDocument + PartialEq + 'static,
162     {
163         use std::collections::hash_map::Entry as HashMapEntry;
164         debug!("StyleSheetCache::lookup({})", self.len());
166         if !collection.dirty() {
167             return Ok(None);
168         }
170         let mut key = CascadeDataCacheKey::default();
171         for sheet in collection.sheets() {
172             CascadeData::collect_applicable_media_query_results_into(
173                 device,
174                 sheet,
175                 guard,
176                 &mut key.media_query_results,
177                 &mut key.contents,
178             )
179         }
181         let new_entry;
182         match self.entries.entry(key) {
183             HashMapEntry::Vacant(e) => {
184                 debug!("> Picking the slow path (not in the cache)");
185                 new_entry = Entry::rebuild(device, quirks_mode, collection, guard, old_entry)?;
186                 e.insert(new_entry.clone());
187             },
188             HashMapEntry::Occupied(mut e) => {
189                 // Avoid reusing our old entry (this can happen if we get
190                 // invalidated due to CSSOM mutations and our old stylesheet
191                 // contents were already unique, for example).
192                 if !std::ptr::eq(&**e.get(), old_entry) {
193                     if log_enabled!(log::Level::Debug) {
194                         debug!("cache hit for:");
195                         for sheet in collection.sheets() {
196                             debug!(" > {:?}", sheet);
197                         }
198                     }
199                     // The line below ensures the "committed" bit is updated
200                     // properly.
201                     collection.each(|_, _| true);
202                     return Ok(Some(e.get().clone()));
203                 }
205                 debug!("> Picking the slow path due to same entry as old");
206                 new_entry = Entry::rebuild(device, quirks_mode, collection, guard, old_entry)?;
207                 e.insert(new_entry.clone());
208             },
209         }
211         Ok(Some(new_entry))
212     }
214     /// Returns all the cascade datas that are not being used (that is, that are
215     /// held alive just by this cache).
216     ///
217     /// We return them instead of dropping in place because some of them may
218     /// keep alive some other documents (like the SVG documents kept alive by
219     /// URL references), and thus we don't want to drop them while locking the
220     /// cache to not deadlock.
221     fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
222         let mut unused = SmallVec::new();
223         self.entries.retain(|_key, value| {
224             // is_unique() returns false for static references, but we never
225             // have static references to UserAgentCascadeDatas.  If we did, it
226             // may not make sense to put them in the cache in the first place.
227             if !value.is_unique() {
228                 return true;
229             }
230             unused.push(value.clone());
231             false
232         });
233         unused
234     }
236     fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
237         mem::take(&mut self.entries)
238     }
240     #[cfg(feature = "gecko")]
241     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
242         sizes.mOther += self.entries.shallow_size_of(ops);
243         for (_key, arc) in self.entries.iter() {
244             // These are primary Arc references that can be measured
245             // unconditionally.
246             sizes.mOther += arc.unconditional_shallow_size_of(ops);
247             arc.add_size_of(ops, sizes);
248         }
249     }
252 /// Measure heap usage of UA_CASCADE_DATA_CACHE.
253 #[cfg(feature = "gecko")]
254 pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
255     UA_CASCADE_DATA_CACHE
256         .lock()
257         .unwrap()
258         .add_size_of(ops, sizes);
261 lazy_static! {
262     /// A cache of computed user-agent data, to be shared across documents.
263     static ref UA_CASCADE_DATA_CACHE: Mutex<UserAgentCascadeDataCache> =
264         Mutex::new(UserAgentCascadeDataCache::new());
267 impl CascadeDataCacheEntry for UserAgentCascadeData {
268     fn cascade_data(&self) -> &CascadeData {
269         &self.cascade_data
270     }
272     fn rebuild<S>(
273         device: &Device,
274         quirks_mode: QuirksMode,
275         collection: SheetCollectionFlusher<S>,
276         guard: &SharedRwLockReadGuard,
277         _old: &Self,
278     ) -> Result<Arc<Self>, AllocErr>
279     where
280         S: StylesheetInDocument + PartialEq + 'static,
281     {
282         // TODO: Maybe we should support incremental rebuilds, though they seem
283         // uncommon and rebuild() doesn't deal with
284         // precomputed_pseudo_element_decls for now so...
285         let mut new_data = Self {
286             cascade_data: CascadeData::new(),
287             precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
288         };
290         for sheet in collection.sheets() {
291             new_data.cascade_data.add_stylesheet(
292                 device,
293                 quirks_mode,
294                 sheet,
295                 guard,
296                 SheetRebuildKind::Full,
297                 Some(&mut new_data.precomputed_pseudo_element_decls),
298             )?;
299         }
301         new_data.cascade_data.did_finish_rebuild();
303         Ok(Arc::new(new_data))
304     }
306     #[cfg(feature = "gecko")]
307     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
308         self.cascade_data.add_size_of(ops, sizes);
309         sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
310     }
313 type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
315 type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
317 #[derive(Default)]
318 struct UserAgentCascadeData {
319     cascade_data: CascadeData,
321     /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
322     ///
323     /// These are eagerly computed once, and then used to resolve the new
324     /// computed values on the fly on layout.
325     ///
326     /// These are only filled from UA stylesheets.
327     precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
330 lazy_static! {
331     /// The empty UA cascade data for un-filled stylists.
332     static ref EMPTY_UA_CASCADE_DATA: Arc<UserAgentCascadeData> = {
333         let arc = Arc::new(UserAgentCascadeData::default());
334         arc.mark_as_intentionally_leaked();
335         arc
336     };
339 /// All the computed information for all the stylesheets that apply to the
340 /// document.
341 #[derive(MallocSizeOf)]
342 pub struct DocumentCascadeData {
343     #[ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache or empty"]
344     user_agent: Arc<UserAgentCascadeData>,
345     user: CascadeData,
346     author: CascadeData,
347     per_origin: PerOrigin<()>,
350 impl Default for DocumentCascadeData {
351     fn default() -> Self {
352         Self {
353             user_agent: EMPTY_UA_CASCADE_DATA.clone(),
354             user: Default::default(),
355             author: Default::default(),
356             per_origin: Default::default(),
357         }
358     }
361 /// An iterator over the cascade data of a given document.
362 pub struct DocumentCascadeDataIter<'a> {
363     iter: PerOriginIter<'a, ()>,
364     cascade_data: &'a DocumentCascadeData,
367 impl<'a> Iterator for DocumentCascadeDataIter<'a> {
368     type Item = (&'a CascadeData, Origin);
370     fn next(&mut self) -> Option<Self::Item> {
371         let (_, origin) = self.iter.next()?;
372         Some((self.cascade_data.borrow_for_origin(origin), origin))
373     }
376 impl DocumentCascadeData {
377     /// Borrows the cascade data for a given origin.
378     #[inline]
379     pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
380         match origin {
381             Origin::UserAgent => &self.user_agent.cascade_data,
382             Origin::Author => &self.author,
383             Origin::User => &self.user,
384         }
385     }
387     fn iter_origins(&self) -> DocumentCascadeDataIter {
388         DocumentCascadeDataIter {
389             iter: self.per_origin.iter_origins(),
390             cascade_data: self,
391         }
392     }
394     fn iter_origins_rev(&self) -> DocumentCascadeDataIter {
395         DocumentCascadeDataIter {
396             iter: self.per_origin.iter_origins_rev(),
397             cascade_data: self,
398         }
399     }
401     /// Rebuild the cascade data for the given document stylesheets, and
402     /// optionally with a set of user agent stylesheets.  Returns Err(..)
403     /// to signify OOM.
404     fn rebuild<'a, S>(
405         &mut self,
406         device: &Device,
407         quirks_mode: QuirksMode,
408         mut flusher: DocumentStylesheetFlusher<'a, S>,
409         guards: &StylesheetGuards,
410     ) -> Result<(), AllocErr>
411     where
412         S: StylesheetInDocument + PartialEq + 'static,
413     {
414         // First do UA sheets.
415         {
416             let origin_flusher = flusher.flush_origin(Origin::UserAgent);
417             // Dirty check is just a minor optimization (no need to grab the
418             // lock if nothing has changed).
419             if origin_flusher.dirty() {
420                 let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
421                 let new_data = ua_cache.lookup(
422                     device,
423                     quirks_mode,
424                     origin_flusher,
425                     guards.ua_or_user,
426                     &self.user_agent,
427                 )?;
428                 if let Some(new_data) = new_data {
429                     self.user_agent = new_data;
430                 }
431                 let _unused_entries = ua_cache.take_unused();
432                 // See the comments in take_unused() as for why the following
433                 // line.
434                 std::mem::drop(ua_cache);
435             }
436         }
438         // Now do the user sheets.
439         self.user.rebuild(
440             device,
441             quirks_mode,
442             flusher.flush_origin(Origin::User),
443             guards.ua_or_user,
444         )?;
446         // And now the author sheets.
447         self.author.rebuild(
448             device,
449             quirks_mode,
450             flusher.flush_origin(Origin::Author),
451             guards.author,
452         )?;
454         Ok(())
455     }
457     /// Measures heap usage.
458     #[cfg(feature = "gecko")]
459     pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
460         self.user.add_size_of(ops, sizes);
461         self.author.add_size_of(ops, sizes);
462     }
465 /// Whether author styles are enabled.
467 /// This is used to support Gecko.
468 #[allow(missing_docs)]
469 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
470 pub enum AuthorStylesEnabled {
471     Yes,
472     No,
475 /// A wrapper over a DocumentStylesheetSet that can be `Sync`, since it's only
476 /// used and exposed via mutable methods in the `Stylist`.
477 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
478 struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
479 // Read above to see why this is fine.
480 unsafe impl Sync for StylistStylesheetSet {}
482 impl StylistStylesheetSet {
483     fn new() -> Self {
484         StylistStylesheetSet(DocumentStylesheetSet::new())
485     }
488 impl ops::Deref for StylistStylesheetSet {
489     type Target = DocumentStylesheetSet<StylistSheet>;
491     fn deref(&self) -> &Self::Target {
492         &self.0
493     }
496 impl ops::DerefMut for StylistStylesheetSet {
497     fn deref_mut(&mut self) -> &mut Self::Target {
498         &mut self.0
499     }
502 /// This structure holds all the selectors and device characteristics
503 /// for a given document. The selectors are converted into `Rule`s
504 /// and sorted into `SelectorMap`s keyed off stylesheet origin and
505 /// pseudo-element (see `CascadeData`).
507 /// This structure is effectively created once per pipeline, in the
508 /// LayoutThread corresponding to that pipeline.
509 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
510 pub struct Stylist {
511     /// Device that the stylist is currently evaluating against.
512     ///
513     /// This field deserves a bigger comment due to the different use that Gecko
514     /// and Servo give to it (that we should eventually unify).
515     ///
516     /// With Gecko, the device is never changed. Gecko manually tracks whether
517     /// the device data should be reconstructed, and "resets" the state of the
518     /// device.
519     ///
520     /// On Servo, on the other hand, the device is a really cheap representation
521     /// that is recreated each time some constraint changes and calling
522     /// `set_device`.
523     device: Device,
525     /// The list of stylesheets.
526     stylesheets: StylistStylesheetSet,
528     /// A cache of CascadeDatas for AuthorStylesheetSets (i.e., shadow DOM).
529     author_data_cache: CascadeDataCache<CascadeData>,
531     /// If true, the quirks-mode stylesheet is applied.
532     #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
533     quirks_mode: QuirksMode,
535     /// Selector maps for all of the style sheets in the stylist, after
536     /// evalutaing media rules against the current device, split out per
537     /// cascade level.
538     cascade_data: DocumentCascadeData,
540     /// Whether author styles are enabled.
541     author_styles_enabled: AuthorStylesEnabled,
543     /// The rule tree, that stores the results of selector matching.
544     rule_tree: RuleTree,
546     /// The set of registered custom properties from script.
547     /// <https://drafts.css-houdini.org/css-properties-values-api-1/#dom-window-registeredpropertyset-slot>
548     script_custom_properties: CustomPropertyScriptRegistry,
550     /// The total number of times the stylist has been rebuilt.
551     num_rebuilds: usize,
554 /// What cascade levels to include when styling elements.
555 #[derive(Clone, Copy, PartialEq)]
556 pub enum RuleInclusion {
557     /// Include rules for style sheets at all cascade levels.  This is the
558     /// normal rule inclusion mode.
559     All,
560     /// Only include rules from UA and user level sheets.  Used to implement
561     /// `getDefaultComputedStyle`.
562     DefaultOnly,
565 #[cfg(feature = "gecko")]
566 impl From<StyleRuleInclusion> for RuleInclusion {
567     fn from(value: StyleRuleInclusion) -> Self {
568         match value {
569             StyleRuleInclusion::All => RuleInclusion::All,
570             StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
571         }
572     }
575 enum AncestorSelectorList<'a> {
576     Borrowed(&'a SelectorList<SelectorImpl>),
577     Shared(ArcSelectorList<SelectorImpl>),
580 impl<'a> AncestorSelectorList<'a> {
581     fn into_shared(&mut self) -> &ArcSelectorList<SelectorImpl> {
582         if let Self::Borrowed(ref b) = *self {
583             let shared = b.to_shared();
584             *self = Self::Shared(shared);
585         }
586         match *self {
587             Self::Shared(ref shared) => return shared,
588             Self::Borrowed(..) => unsafe { debug_unreachable!() },
589         }
590     }
593 /// A struct containing state from ancestor rules like @layer / @import /
594 /// @container / nesting.
595 struct ContainingRuleState<'a> {
596     layer_name: LayerName,
597     layer_id: LayerId,
598     container_condition_id: ContainerConditionId,
599     ancestor_selector_lists: SmallVec<[AncestorSelectorList<'a>; 2]>,
602 impl<'a> Default for ContainingRuleState<'a> {
603     fn default() -> Self {
604         Self {
605             layer_name: LayerName::new_empty(),
606             layer_id: LayerId::root(),
607             container_condition_id: ContainerConditionId::none(),
608             ancestor_selector_lists: Default::default(),
609         }
610     }
613 struct SavedContainingRuleState {
614     ancestor_selector_lists_len: usize,
615     layer_name_len: usize,
616     layer_id: LayerId,
617     container_condition_id: ContainerConditionId,
620 impl<'a> ContainingRuleState<'a> {
621     fn save(&self) -> SavedContainingRuleState {
622         SavedContainingRuleState {
623             ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
624             layer_name_len: self.layer_name.0.len(),
625             layer_id: self.layer_id,
626             container_condition_id: self.container_condition_id,
627         }
628     }
630     fn restore(&mut self, saved: &SavedContainingRuleState) {
631         debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
632         debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
633         self.ancestor_selector_lists
634             .truncate(saved.ancestor_selector_lists_len);
635         self.layer_name.0.truncate(saved.layer_name_len);
636         self.layer_id = saved.layer_id;
637         self.container_condition_id = saved.container_condition_id;
638     }
641 impl Stylist {
642     /// Construct a new `Stylist`, using given `Device` and `QuirksMode`.
643     /// If more members are added here, think about whether they should
644     /// be reset in clear().
645     #[inline]
646     pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
647         Self {
648             device,
649             quirks_mode,
650             stylesheets: StylistStylesheetSet::new(),
651             author_data_cache: CascadeDataCache::new(),
652             cascade_data: Default::default(),
653             author_styles_enabled: AuthorStylesEnabled::Yes,
654             rule_tree: RuleTree::new(),
655             script_custom_properties: Default::default(),
656             num_rebuilds: 0,
657         }
658     }
660     /// Returns the document cascade data.
661     #[inline]
662     pub fn cascade_data(&self) -> &DocumentCascadeData {
663         &self.cascade_data
664     }
666     /// Returns whether author styles are enabled or not.
667     #[inline]
668     pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
669         self.author_styles_enabled
670     }
672     /// Iterate through all the cascade datas from the document.
673     #[inline]
674     pub fn iter_origins(&self) -> DocumentCascadeDataIter {
675         self.cascade_data.iter_origins()
676     }
678     /// Does what the name says, to prevent author_data_cache to grow without
679     /// bound.
680     pub fn remove_unique_author_data_cache_entries(&mut self) {
681         self.author_data_cache.take_unused();
682     }
684     /// Returns the custom property registration for this property's name.
685     /// https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
686     pub fn get_custom_property_registration(&self, name: &Atom) -> Option<&PropertyRegistration> {
687         if let Some(registration) = self.custom_property_script_registry().get(name) {
688             return Some(registration);
689         }
690         for (data, _) in self.iter_origins() {
691             if let Some(registration) = data.custom_property_registrations.get(name) {
692                 return Some(registration);
693             }
694         }
695         None
696     }
699     /// Rebuilds (if needed) the CascadeData given a sheet collection.
700     pub fn rebuild_author_data<S>(
701         &mut self,
702         old_data: &CascadeData,
703         collection: SheetCollectionFlusher<S>,
704         guard: &SharedRwLockReadGuard,
705     ) -> Result<Option<Arc<CascadeData>>, AllocErr>
706     where
707         S: StylesheetInDocument + PartialEq + 'static,
708     {
709         self.author_data_cache
710             .lookup(&self.device, self.quirks_mode, collection, guard, old_data)
711     }
713     /// Iterate over the extra data in origin order.
714     #[inline]
715     pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator {
716         ExtraStyleDataIterator(self.cascade_data.iter_origins())
717     }
719     /// Iterate over the extra data in reverse origin order.
720     #[inline]
721     pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator {
722         ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
723     }
725     /// Returns the number of selectors.
726     pub fn num_selectors(&self) -> usize {
727         self.cascade_data
728             .iter_origins()
729             .map(|(d, _)| d.num_selectors)
730             .sum()
731     }
733     /// Returns the number of declarations.
734     pub fn num_declarations(&self) -> usize {
735         self.cascade_data
736             .iter_origins()
737             .map(|(d, _)| d.num_declarations)
738             .sum()
739     }
741     /// Returns the number of times the stylist has been rebuilt.
742     pub fn num_rebuilds(&self) -> usize {
743         self.num_rebuilds
744     }
746     /// Returns the number of revalidation_selectors.
747     pub fn num_revalidation_selectors(&self) -> usize {
748         self.cascade_data
749             .iter_origins()
750             .map(|(data, _)| data.selectors_for_cache_revalidation.len())
751             .sum()
752     }
754     /// Returns the number of entries in invalidation maps.
755     pub fn num_invalidations(&self) -> usize {
756         self.cascade_data
757             .iter_origins()
758             .map(|(data, _)| {
759                 data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
760             })
761             .sum()
762     }
764     /// Returns whether the given DocumentState bit is relied upon by a selector
765     /// of some rule.
766     pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
767         self.cascade_data
768             .iter_origins()
769             .any(|(d, _)| d.document_state_dependencies.intersects(state))
770     }
772     /// Flush the list of stylesheets if they changed, ensuring the stylist is
773     /// up-to-date.
774     pub fn flush<E>(
775         &mut self,
776         guards: &StylesheetGuards,
777         document_element: Option<E>,
778         snapshots: Option<&SnapshotMap>,
779     ) -> bool
780     where
781         E: TElement,
782     {
783         if !self.stylesheets.has_changed() {
784             return false;
785         }
787         self.num_rebuilds += 1;
789         let flusher = self.stylesheets.flush(document_element, snapshots);
791         let had_invalidations = flusher.had_invalidations();
793         self.cascade_data
794             .rebuild(&self.device, self.quirks_mode, flusher, guards)
795             .unwrap_or_else(|_| warn!("OOM in Stylist::flush"));
797         had_invalidations
798     }
800     /// Insert a given stylesheet before another stylesheet in the document.
801     pub fn insert_stylesheet_before(
802         &mut self,
803         sheet: StylistSheet,
804         before_sheet: StylistSheet,
805         guard: &SharedRwLockReadGuard,
806     ) {
807         self.stylesheets
808             .insert_stylesheet_before(Some(&self.device), sheet, before_sheet, guard)
809     }
811     /// Marks a given stylesheet origin as dirty, due to, for example, changes
812     /// in the declarations that affect a given rule.
813     ///
814     /// FIXME(emilio): Eventually it'd be nice for this to become more
815     /// fine-grained.
816     pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
817         self.stylesheets.force_dirty(origins)
818     }
820     /// Sets whether author style is enabled or not.
821     pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
822         self.author_styles_enabled = enabled;
823     }
825     /// Returns whether we've recorded any stylesheet change so far.
826     pub fn stylesheets_have_changed(&self) -> bool {
827         self.stylesheets.has_changed()
828     }
830     /// Appends a new stylesheet to the current set.
831     pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
832         self.stylesheets
833             .append_stylesheet(Some(&self.device), sheet, guard)
834     }
836     /// Remove a given stylesheet to the current set.
837     pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
838         self.stylesheets
839             .remove_stylesheet(Some(&self.device), sheet, guard)
840     }
842     /// Notify of a change of a given rule.
843     pub fn rule_changed(
844         &mut self,
845         sheet: &StylistSheet,
846         rule: &CssRule,
847         guard: &SharedRwLockReadGuard,
848         change_kind: RuleChangeKind,
849     ) {
850         self.stylesheets
851             .rule_changed(Some(&self.device), sheet, rule, guard, change_kind)
852     }
854     /// Appends a new stylesheet to the current set.
855     #[inline]
856     pub fn sheet_count(&self, origin: Origin) -> usize {
857         self.stylesheets.sheet_count(origin)
858     }
860     /// Appends a new stylesheet to the current set.
861     #[inline]
862     pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
863         self.stylesheets.get(origin, index)
864     }
866     /// Returns whether for any of the applicable style rule data a given
867     /// condition is true.
868     pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
869     where
870         E: TElement,
871         F: FnMut(&CascadeData) -> bool,
872     {
873         if f(&self.cascade_data.user_agent.cascade_data) {
874             return true;
875         }
877         let mut maybe = false;
879         let doc_author_rules_apply =
880             element.each_applicable_non_document_style_rule_data(|data, _| {
881                 maybe = maybe || f(&*data);
882             });
884         if maybe || f(&self.cascade_data.user) {
885             return true;
886         }
888         doc_author_rules_apply && f(&self.cascade_data.author)
889     }
891     /// Execute callback for all applicable style rule data.
892     pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
893     where
894         E: TElement + 'a,
895         F: FnMut(&'a CascadeData, Option<E>),
896     {
897         f(&self.cascade_data.user_agent.cascade_data, None);
898         element.each_applicable_non_document_style_rule_data(|data, scope| {
899             f(data, Some(scope));
900         });
901         f(&self.cascade_data.user, None);
902         f(&self.cascade_data.author, None);
903     }
905     /// Computes the style for a given "precomputed" pseudo-element, taking the
906     /// universal rules and applying them.
907     pub fn precomputed_values_for_pseudo<E>(
908         &self,
909         guards: &StylesheetGuards,
910         pseudo: &PseudoElement,
911         parent: Option<&ComputedValues>,
912     ) -> Arc<ComputedValues>
913     where
914         E: TElement,
915     {
916         debug_assert!(pseudo.is_precomputed());
918         let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
920         self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
921     }
923     /// Computes the style for a given "precomputed" pseudo-element with
924     /// given rule node.
925     ///
926     /// TODO(emilio): The type parameter could go away with a void type
927     /// implementing TElement.
928     pub fn precomputed_values_for_pseudo_with_rule_node<E>(
929         &self,
930         guards: &StylesheetGuards,
931         pseudo: &PseudoElement,
932         parent: Option<&ComputedValues>,
933         rules: StrongRuleNode,
934     ) -> Arc<ComputedValues>
935     where
936         E: TElement,
937     {
938         self.compute_pseudo_element_style_with_inputs::<E>(
939             CascadeInputs {
940                 rules: Some(rules),
941                 visited_rules: None,
942                 flags: Default::default(),
943             },
944             pseudo,
945             guards,
946             /* originating_element_style */ None,
947             parent,
948             /* element */ None,
949         )
950     }
952     /// Returns the rule node for a given precomputed pseudo-element.
953     ///
954     /// If we want to include extra declarations to this precomputed
955     /// pseudo-element, we can provide a vector of ApplicableDeclarationBlocks
956     /// to extra_declarations. This is useful for @page rules.
957     pub fn rule_node_for_precomputed_pseudo(
958         &self,
959         guards: &StylesheetGuards,
960         pseudo: &PseudoElement,
961         mut extra_declarations: Vec<ApplicableDeclarationBlock>,
962     ) -> StrongRuleNode {
963         let mut declarations_with_extra;
964         let declarations = match self
965             .cascade_data
966             .user_agent
967             .precomputed_pseudo_element_decls
968             .get(pseudo)
969         {
970             Some(declarations) => {
971                 if !extra_declarations.is_empty() {
972                     declarations_with_extra = declarations.clone();
973                     declarations_with_extra.append(&mut extra_declarations);
974                     &*declarations_with_extra
975                 } else {
976                     &**declarations
977                 }
978             },
979             None => &[],
980         };
982         self.rule_tree.insert_ordered_rules_with_important(
983             declarations.into_iter().map(|a| a.clone().for_rule_tree()),
984             guards,
985         )
986     }
988     /// Returns the style for an anonymous box of the given type.
989     ///
990     /// TODO(emilio): The type parameter could go away with a void type
991     /// implementing TElement.
992     #[cfg(feature = "servo")]
993     pub fn style_for_anonymous<E>(
994         &self,
995         guards: &StylesheetGuards,
996         pseudo: &PseudoElement,
997         parent_style: &ComputedValues,
998     ) -> Arc<ComputedValues>
999     where
1000         E: TElement,
1001     {
1002         self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1003     }
1005     /// Computes a pseudo-element style lazily during layout.
1006     ///
1007     /// This can only be done for a certain set of pseudo-elements, like
1008     /// :selection.
1009     ///
1010     /// Check the documentation on lazy pseudo-elements in
1011     /// docs/components/style.md
1012     pub fn lazily_compute_pseudo_element_style<E>(
1013         &self,
1014         guards: &StylesheetGuards,
1015         element: E,
1016         pseudo: &PseudoElement,
1017         rule_inclusion: RuleInclusion,
1018         originating_element_style: &ComputedValues,
1019         parent_style: &Arc<ComputedValues>,
1020         is_probe: bool,
1021         matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1022     ) -> Option<Arc<ComputedValues>>
1023     where
1024         E: TElement,
1025     {
1026         let cascade_inputs = self.lazy_pseudo_rules(
1027             guards,
1028             element,
1029             originating_element_style,
1030             parent_style,
1031             pseudo,
1032             is_probe,
1033             rule_inclusion,
1034             matching_fn,
1035         )?;
1037         Some(self.compute_pseudo_element_style_with_inputs(
1038             cascade_inputs,
1039             pseudo,
1040             guards,
1041             Some(originating_element_style),
1042             Some(parent_style),
1043             Some(element),
1044         ))
1045     }
1047     /// Computes a pseudo-element style lazily using the given CascadeInputs.
1048     /// This can be used for truly lazy pseudo-elements or to avoid redoing
1049     /// selector matching for eager pseudo-elements when we need to recompute
1050     /// their style with a new parent style.
1051     pub fn compute_pseudo_element_style_with_inputs<E>(
1052         &self,
1053         inputs: CascadeInputs,
1054         pseudo: &PseudoElement,
1055         guards: &StylesheetGuards,
1056         originating_element_style: Option<&ComputedValues>,
1057         parent_style: Option<&ComputedValues>,
1058         element: Option<E>,
1059     ) -> Arc<ComputedValues>
1060     where
1061         E: TElement,
1062     {
1063         // FIXME(emilio): The lack of layout_parent_style here could be
1064         // worrying, but we're probably dropping the display fixup for
1065         // pseudos other than before and after, so it's probably ok.
1066         //
1067         // (Though the flags don't indicate so!)
1068         //
1069         // It'd be fine to assert that this isn't called with a parent style
1070         // where display contents is in effect, but in practice this is hard to
1071         // do for stuff like :-moz-fieldset-content with a
1072         // <fieldset style="display: contents">. That is, the computed value of
1073         // display for the fieldset is "contents", even though it's not the used
1074         // value, so we don't need to adjust in a different way anyway.
1075         self.cascade_style_and_visited(
1076             element,
1077             Some(pseudo),
1078             inputs,
1079             guards,
1080             originating_element_style,
1081             parent_style,
1082             parent_style,
1083             FirstLineReparenting::No,
1084             /* rule_cache = */ None,
1085             &mut RuleCacheConditions::default(),
1086         )
1087     }
1089     /// Computes a style using the given CascadeInputs.  This can be used to
1090     /// compute a style any time we know what rules apply and just need to use
1091     /// the given parent styles.
1092     ///
1093     /// parent_style is the style to inherit from for properties affected by
1094     /// first-line ancestors.
1095     ///
1096     /// parent_style_ignoring_first_line is the style to inherit from for
1097     /// properties not affected by first-line ancestors.
1098     ///
1099     /// layout_parent_style is the style used for some property fixups.  It's
1100     /// the style of the nearest ancestor with a layout box.
1101     pub fn cascade_style_and_visited<E>(
1102         &self,
1103         element: Option<E>,
1104         pseudo: Option<&PseudoElement>,
1105         inputs: CascadeInputs,
1106         guards: &StylesheetGuards,
1107         originating_element_style: Option<&ComputedValues>,
1108         parent_style: Option<&ComputedValues>,
1109         layout_parent_style: Option<&ComputedValues>,
1110         first_line_reparenting: FirstLineReparenting,
1111         rule_cache: Option<&RuleCache>,
1112         rule_cache_conditions: &mut RuleCacheConditions,
1113     ) -> Arc<ComputedValues>
1114     where
1115         E: TElement,
1116     {
1117         debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1119         // We need to compute visited values if we have visited rules or if our
1120         // parent has visited values.
1121         let visited_rules = match inputs.visited_rules.as_ref() {
1122             Some(rules) => Some(rules),
1123             None => {
1124                 if parent_style.and_then(|s| s.visited_style()).is_some() {
1125                     Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1126                 } else {
1127                     None
1128                 }
1129             },
1130         };
1132         // Read the comment on `precomputed_values_for_pseudo` to see why it's
1133         // difficult to assert that display: contents nodes never arrive here
1134         // (tl;dr: It doesn't apply for replaced elements and such, but the
1135         // computed value is still "contents").
1136         //
1137         // FIXME(emilio): We should assert that it holds if pseudo.is_none()!
1138         properties::cascade::<E>(
1139             &self,
1140             pseudo,
1141             inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1142             guards,
1143             originating_element_style,
1144             parent_style,
1145             layout_parent_style,
1146             first_line_reparenting,
1147             visited_rules,
1148             inputs.flags,
1149             rule_cache,
1150             rule_cache_conditions,
1151             element,
1152         )
1153     }
1155     /// Computes the cascade inputs for a lazily-cascaded pseudo-element.
1156     ///
1157     /// See the documentation on lazy pseudo-elements in
1158     /// docs/components/style.md
1159     fn lazy_pseudo_rules<E>(
1160         &self,
1161         guards: &StylesheetGuards,
1162         element: E,
1163         originating_element_style: &ComputedValues,
1164         parent_style: &Arc<ComputedValues>,
1165         pseudo: &PseudoElement,
1166         is_probe: bool,
1167         rule_inclusion: RuleInclusion,
1168         matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1169     ) -> Option<CascadeInputs>
1170     where
1171         E: TElement,
1172     {
1173         debug_assert!(pseudo.is_lazy());
1175         let mut selector_caches = SelectorCaches::default();
1176         // No need to bother setting the selector flags when we're computing
1177         // default styles.
1178         let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
1179             NeedsSelectorFlags::No
1180         } else {
1181             NeedsSelectorFlags::Yes
1182         };
1184         let mut declarations = ApplicableDeclarationList::new();
1185         let mut matching_context = MatchingContext::<'_, E::Impl>::new(
1186             MatchingMode::ForStatelessPseudoElement,
1187             None,
1188             &mut selector_caches,
1189             self.quirks_mode,
1190             needs_selector_flags,
1191             MatchingForInvalidation::No,
1192         );
1194         matching_context.pseudo_element_matching_fn = matching_fn;
1195         matching_context.extra_data.originating_element_style = Some(originating_element_style);
1197         self.push_applicable_declarations(
1198             element,
1199             Some(&pseudo),
1200             None,
1201             None,
1202             /* animation_declarations = */ Default::default(),
1203             rule_inclusion,
1204             &mut declarations,
1205             &mut matching_context,
1206         );
1208         if declarations.is_empty() && is_probe {
1209             return None;
1210         }
1212         let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1214         let mut visited_rules = None;
1215         if parent_style.visited_style().is_some() {
1216             let mut declarations = ApplicableDeclarationList::new();
1217             let mut selector_caches = SelectorCaches::default();
1219             let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
1220                 MatchingMode::ForStatelessPseudoElement,
1221                 None,
1222                 &mut selector_caches,
1223                 VisitedHandlingMode::RelevantLinkVisited,
1224                 self.quirks_mode,
1225                 needs_selector_flags,
1226                 MatchingForInvalidation::No,
1227             );
1228             matching_context.pseudo_element_matching_fn = matching_fn;
1229             matching_context.extra_data.originating_element_style = Some(originating_element_style);
1231             self.push_applicable_declarations(
1232                 element,
1233                 Some(&pseudo),
1234                 None,
1235                 None,
1236                 /* animation_declarations = */ Default::default(),
1237                 rule_inclusion,
1238                 &mut declarations,
1239                 &mut matching_context,
1240             );
1241             if !declarations.is_empty() {
1242                 let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1243                     declarations.drain(..).map(|a| a.for_rule_tree()),
1244                     guards,
1245                 );
1246                 if rule_node != *self.rule_tree.root() {
1247                     visited_rules = Some(rule_node);
1248                 }
1249             }
1250         }
1252         Some(CascadeInputs {
1253             rules: Some(rules),
1254             visited_rules,
1255             flags: matching_context.extra_data.cascade_input_flags,
1256         })
1257     }
1259     /// Set a given device, which may change the styles that apply to the
1260     /// document.
1261     ///
1262     /// Returns the sheet origins that were actually affected.
1263     ///
1264     /// This means that we may need to rebuild style data even if the
1265     /// stylesheets haven't changed.
1266     ///
1267     /// Also, the device that arrives here may need to take the viewport rules
1268     /// into account.
1269     pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
1270         self.device = device;
1271         self.media_features_change_changed_style(guards, &self.device)
1272     }
1274     /// Returns whether, given a media feature change, any previously-applicable
1275     /// style has become non-applicable, or vice-versa for each origin, using
1276     /// `device`.
1277     pub fn media_features_change_changed_style(
1278         &self,
1279         guards: &StylesheetGuards,
1280         device: &Device,
1281     ) -> OriginSet {
1282         debug!("Stylist::media_features_change_changed_style {:?}", device);
1284         let mut origins = OriginSet::empty();
1285         let stylesheets = self.stylesheets.iter();
1287         for (stylesheet, origin) in stylesheets {
1288             if origins.contains(origin.into()) {
1289                 continue;
1290             }
1292             let guard = guards.for_origin(origin);
1293             let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1295             let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1296                 stylesheet,
1297                 guard,
1298                 device,
1299                 self.quirks_mode,
1300             );
1302             if affected_changed {
1303                 origins |= origin;
1304             }
1305         }
1307         origins
1308     }
1310     /// Returns the Quirks Mode of the document.
1311     pub fn quirks_mode(&self) -> QuirksMode {
1312         self.quirks_mode
1313     }
1315     /// Sets the quirks mode of the document.
1316     pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1317         if self.quirks_mode == quirks_mode {
1318             return;
1319         }
1320         self.quirks_mode = quirks_mode;
1321         self.force_stylesheet_origins_dirty(OriginSet::all());
1322     }
1324     /// Returns the applicable CSS declarations for the given element.
1325     pub fn push_applicable_declarations<E>(
1326         &self,
1327         element: E,
1328         pseudo_element: Option<&PseudoElement>,
1329         style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1330         smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1331         animation_declarations: AnimationDeclarations,
1332         rule_inclusion: RuleInclusion,
1333         applicable_declarations: &mut ApplicableDeclarationList,
1334         context: &mut MatchingContext<E::Impl>,
1335     ) where
1336         E: TElement,
1337     {
1338         RuleCollector::new(
1339             self,
1340             element,
1341             pseudo_element,
1342             style_attribute,
1343             smil_override,
1344             animation_declarations,
1345             rule_inclusion,
1346             applicable_declarations,
1347             context,
1348         )
1349         .collect_all();
1350     }
1352     /// Given an id, returns whether there might be any rules for that id in any
1353     /// of our rule maps.
1354     #[inline]
1355     pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1356     where
1357         E: TElement,
1358     {
1359         // If id needs to be compared case-insensitively, the logic below
1360         // wouldn't work. Just conservatively assume it may have such rules.
1361         match self.quirks_mode().classes_and_ids_case_sensitivity() {
1362             CaseSensitivity::AsciiCaseInsensitive => return true,
1363             CaseSensitivity::CaseSensitive => {},
1364         }
1366         self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1367     }
1369     /// Returns the registered `@keyframes` animation for the specified name.
1370     #[inline]
1371     pub fn get_animation<'a, E>(&'a self, name: &Atom, element: E) -> Option<&'a KeyframesAnimation>
1372     where
1373         E: TElement + 'a,
1374     {
1375         macro_rules! try_find_in {
1376             ($data:expr) => {
1377                 if let Some(animation) = $data.animations.get(name) {
1378                     return Some(animation);
1379                 }
1380             };
1381         }
1383         // NOTE(emilio): This is a best-effort thing, the right fix is a bit TBD because it
1384         // involves "recording" which tree the name came from, see [1][2].
1385         //
1386         // [1]: https://github.com/w3c/csswg-drafts/issues/1995
1387         // [2]: https://bugzil.la/1458189
1388         let mut animation = None;
1389         let doc_rules_apply = element.each_applicable_non_document_style_rule_data(|data, _host| {
1390             if animation.is_none() {
1391                 animation = data.animations.get(name);
1392             }
1393         });
1395         if animation.is_some() {
1396             return animation;
1397         }
1399         if doc_rules_apply {
1400             try_find_in!(self.cascade_data.author);
1401         }
1402         try_find_in!(self.cascade_data.user);
1403         try_find_in!(self.cascade_data.user_agent.cascade_data);
1405         None
1406     }
1408     /// Computes the match results of a given element against the set of
1409     /// revalidation selectors.
1410     pub fn match_revalidation_selectors<E>(
1411         &self,
1412         element: E,
1413         bloom: Option<&BloomFilter>,
1414         selector_caches: &mut SelectorCaches,
1415         needs_selector_flags: NeedsSelectorFlags,
1416     ) -> SmallBitVec
1417     where
1418         E: TElement,
1419     {
1420         // NB: `MatchingMode` doesn't really matter, given we don't share style
1421         // between pseudos.
1422         let mut matching_context = MatchingContext::new(
1423             MatchingMode::Normal,
1424             bloom,
1425             selector_caches,
1426             self.quirks_mode,
1427             needs_selector_flags,
1428             MatchingForInvalidation::No,
1429         );
1431         // Note that, by the time we're revalidating, we're guaranteed that the
1432         // candidate and the entry have the same id, classes, and local name.
1433         // This means we're guaranteed to get the same rulehash buckets for all
1434         // the lookups, which means that the bitvecs are comparable. We verify
1435         // this in the caller by asserting that the bitvecs are same-length.
1436         let mut results = SmallBitVec::new();
1438         let matches_document_rules =
1439             element.each_applicable_non_document_style_rule_data(|data, host| {
1440                 matching_context.with_shadow_host(Some(host), |matching_context| {
1441                     data.selectors_for_cache_revalidation.lookup(
1442                         element,
1443                         self.quirks_mode,
1444                         |selector_and_hashes| {
1445                             results.push(matches_selector(
1446                                 &selector_and_hashes.selector,
1447                                 selector_and_hashes.selector_offset,
1448                                 Some(&selector_and_hashes.hashes),
1449                                 &element,
1450                                 matching_context,
1451                             ));
1452                             true
1453                         },
1454                     );
1455                 })
1456             });
1458         for (data, origin) in self.cascade_data.iter_origins() {
1459             if origin == Origin::Author && !matches_document_rules {
1460                 continue;
1461             }
1463             data.selectors_for_cache_revalidation.lookup(
1464                 element,
1465                 self.quirks_mode,
1466                 |selector_and_hashes| {
1467                     results.push(matches_selector(
1468                         &selector_and_hashes.selector,
1469                         selector_and_hashes.selector_offset,
1470                         Some(&selector_and_hashes.hashes),
1471                         &element,
1472                         &mut matching_context,
1473                     ));
1474                     true
1475                 },
1476             );
1477         }
1479         results
1480     }
1482     /// Computes styles for a given declaration with parent_style.
1483     ///
1484     /// FIXME(emilio): the lack of pseudo / cascade flags look quite dubious,
1485     /// hopefully this is only used for some canvas font stuff.
1486     ///
1487     /// TODO(emilio): The type parameter can go away when
1488     /// https://github.com/rust-lang/rust/issues/35121 is fixed.
1489     pub fn compute_for_declarations<E>(
1490         &self,
1491         guards: &StylesheetGuards,
1492         parent_style: &ComputedValues,
1493         declarations: Arc<Locked<PropertyDeclarationBlock>>,
1494     ) -> Arc<ComputedValues>
1495     where
1496         E: TElement,
1497     {
1498         let block = declarations.read_with(guards.author);
1500         // We don't bother inserting these declarations in the rule tree, since
1501         // it'd be quite useless and slow.
1502         //
1503         // TODO(emilio): Now that we fixed bug 1493420, we should consider
1504         // reversing this as it shouldn't be slow anymore, and should avoid
1505         // generating two instantiations of apply_declarations.
1506         properties::apply_declarations::<E, _>(
1507             &self,
1508             /* pseudo = */ None,
1509             self.rule_tree.root(),
1510             guards,
1511             block.declaration_importance_iter().map(|(declaration, _)| {
1512                 (
1513                     declaration,
1514                     CascadePriority::new(
1515                         CascadeLevel::same_tree_author_normal(),
1516                         LayerOrder::root(),
1517                     ),
1518                 )
1519             }),
1520             /* originating_element_style */ None,
1521             Some(parent_style),
1522             Some(parent_style),
1523             FirstLineReparenting::No,
1524             CascadeMode::Unvisited {
1525                 visited_rules: None,
1526             },
1527             Default::default(),
1528             /* rule_cache = */ None,
1529             &mut Default::default(),
1530             /* element = */ None,
1531         )
1532     }
1534     /// Accessor for a shared reference to the device.
1535     #[inline]
1536     pub fn device(&self) -> &Device {
1537         &self.device
1538     }
1540     /// Accessor for a mutable reference to the device.
1541     #[inline]
1542     pub fn device_mut(&mut self) -> &mut Device {
1543         &mut self.device
1544     }
1546     /// Accessor for a shared reference to the rule tree.
1547     #[inline]
1548     pub fn rule_tree(&self) -> &RuleTree {
1549         &self.rule_tree
1550     }
1552     /// Returns the script-registered custom property registry.
1553     #[inline]
1554     pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
1555         &self.script_custom_properties
1556     }
1558     /// Returns the script-registered custom property registry, as a mutable ref.
1559     #[inline]
1560     pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
1561         &mut self.script_custom_properties
1562     }
1564     /// Measures heap usage.
1565     #[cfg(feature = "gecko")]
1566     pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
1567         self.cascade_data.add_size_of(ops, sizes);
1568         self.author_data_cache.add_size_of(ops, sizes);
1569         sizes.mRuleTree += self.rule_tree.size_of(ops);
1571         // We may measure other fields in the future if DMD says it's worth it.
1572     }
1574     /// Shutdown the static data that this module stores.
1575     pub fn shutdown() {
1576         let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
1577     }
1580 /// A vector that is sorted in layer order.
1581 #[derive(Clone, Debug, Deref, MallocSizeOf)]
1582 pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
1583 impl<T> Default for LayerOrderedVec<T> {
1584     fn default() -> Self {
1585         Self(Default::default())
1586     }
1589 /// A map that is sorted in layer order.
1590 #[derive(Clone, Debug, Deref, MallocSizeOf)]
1591 pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
1592 impl<T> Default for LayerOrderedMap<T> {
1593     fn default() -> Self {
1594         Self(Default::default())
1595     }
1598 impl<T: 'static> LayerOrderedVec<T> {
1599     fn clear(&mut self) {
1600         self.0.clear();
1601     }
1602     fn push(&mut self, v: T, id: LayerId) {
1603         self.0.push((v, id));
1604     }
1605     fn sort(&mut self, layers: &[CascadeLayer]) {
1606         self.0
1607             .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
1608     }
1611 impl<T: 'static> LayerOrderedMap<T> {
1612     fn shrink_if_needed(&mut self) {
1613         self.0.shrink_if_needed();
1614     }
1615     fn clear(&mut self) {
1616         self.0.clear();
1617     }
1618     fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
1619         self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
1620     }
1621     fn try_insert_with(
1622         &mut self,
1623         name: Atom,
1624         v: T,
1625         id: LayerId,
1626         cmp: impl Fn(&T, &T) -> Ordering,
1627     ) -> Result<(), AllocErr> {
1628         self.0.try_reserve(1)?;
1629         let vec = self.0.entry(name).or_default();
1630         if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
1631             if *last_id == id {
1632                 if cmp(&val, &v) != Ordering::Greater {
1633                     *val = v;
1634                 }
1635                 return Ok(());
1636             }
1637         }
1638         vec.push((v, id));
1639         Ok(())
1640     }
1641     fn sort(&mut self, layers: &[CascadeLayer]) {
1642         self.sort_with(layers, |_, _| Ordering::Equal)
1643     }
1644     fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
1645         for (_, v) in self.0.iter_mut() {
1646             v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
1647                 let order1 = layers[id1.0 as usize].order;
1648                 let order2 = layers[id2.0 as usize].order;
1649                 order1.cmp(&order2).then_with(|| cmp(v1, v2))
1650             })
1651         }
1652     }
1653     /// Get an entry on the LayerOrderedMap by name.
1654     pub fn get(&self, name: &Atom) -> Option<&T> {
1655         let vec = self.0.get(name)?;
1656         Some(&vec.last()?.0)
1657     }
1660 /// Wrapper to allow better tracking of memory usage by page rule lists.
1662 /// This includes the layer ID for use with the named page table.
1663 #[derive(Clone, Debug, MallocSizeOf)]
1664 pub struct PageRuleData {
1665     /// Layer ID for sorting page rules after matching.
1666     pub layer: LayerId,
1667     /// Page rule
1668     #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
1669     pub rule: Arc<Locked<PageRule>>,
1672 /// Stores page rules indexed by page names.
1673 #[derive(Clone, Debug, Default, MallocSizeOf)]
1674 pub struct PageRuleMap {
1675     /// Page rules, indexed by page name. An empty atom indicates no page name.
1676     pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
1679 impl PageRuleMap {
1680     #[inline]
1681     fn clear(&mut self) {
1682         self.rules.clear();
1683     }
1685     /// Uses page-name and pseudo-classes to match all applicable
1686     /// page-rules and append them to the matched_rules vec.
1687     /// This will ensure correct rule order for cascading.
1688     pub fn match_and_append_rules(
1689         &self,
1690         matched_rules: &mut Vec<ApplicableDeclarationBlock>,
1691         origin: Origin,
1692         guards: &StylesheetGuards,
1693         cascade_data: &DocumentCascadeData,
1694         name: &Option<Atom>,
1695         pseudos: PagePseudoClassFlags,
1696     ) {
1697         let level = match origin {
1698             Origin::UserAgent => CascadeLevel::UANormal,
1699             Origin::User => CascadeLevel::UserNormal,
1700             Origin::Author => CascadeLevel::same_tree_author_normal(),
1701         };
1702         let cascade_data = cascade_data.borrow_for_origin(origin);
1703         let start = matched_rules.len();
1705         self.match_and_add_rules(matched_rules, level, guards, cascade_data, &atom!(""), pseudos);
1706         if let Some(name) = name {
1707             self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
1708         }
1710         // Because page-rules do not have source location information stored,
1711         // use stable sort to ensure source locations are preserved.
1712         matched_rules[start..].sort_by_key(|block| {
1713             (block.layer_order(), block.specificity, block.source_order())
1714         });
1715     }
1717     fn match_and_add_rules(
1718         &self,
1719         extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
1720         level: CascadeLevel,
1721         guards: &StylesheetGuards,
1722         cascade_data: &CascadeData,
1723         name: &Atom,
1724         pseudos: PagePseudoClassFlags,
1725     ) {
1726         let rules = match self.rules.get(name) {
1727             Some(rules) => rules,
1728             None => return,
1729         };
1730         for data in rules.iter() {
1731             let rule = data.rule.read_with(level.guard(&guards));
1732             let specificity = match rule.match_specificity(pseudos) {
1733                 Some(specificity) => specificity,
1734                 None => continue,
1735             };
1736             let block = rule.block.clone();
1737             extra_declarations.push(ApplicableDeclarationBlock::new(
1738                 StyleSource::from_declarations(block),
1739                 0,
1740                 level,
1741                 specificity,
1742                 cascade_data.layer_order_for(data.layer),
1743             ));
1744         }
1745     }
1748 impl MallocShallowSizeOf for PageRuleMap {
1749     fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1750         self.rules.shallow_size_of(ops)
1751     }
1754 /// This struct holds data which users of Stylist may want to extract
1755 /// from stylesheets which can be done at the same time as updating.
1756 #[derive(Clone, Debug, Default)]
1757 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
1758 pub struct ExtraStyleData {
1759     /// A list of effective font-face rules and their origin.
1760     #[cfg(feature = "gecko")]
1761     pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
1763     /// A list of effective font-feature-values rules.
1764     #[cfg(feature = "gecko")]
1765     pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
1767     /// A list of effective font-palette-values rules.
1768     #[cfg(feature = "gecko")]
1769     pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
1771     /// A map of effective counter-style rules.
1772     #[cfg(feature = "gecko")]
1773     pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
1775     /// A map of effective page rules.
1776     #[cfg(feature = "gecko")]
1777     pub pages: PageRuleMap,
1780 #[cfg(feature = "gecko")]
1781 impl ExtraStyleData {
1782     /// Add the given @font-face rule.
1783     fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
1784         self.font_faces.push(rule.clone(), layer);
1785     }
1787     /// Add the given @font-feature-values rule.
1788     fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
1789         self.font_feature_values.push(rule.clone(), layer);
1790     }
1792     /// Add the given @font-palette-values rule.
1793     fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
1794         self.font_palette_values.push(rule.clone(), layer);
1795     }
1797     /// Add the given @counter-style rule.
1798     fn add_counter_style(
1799         &mut self,
1800         guard: &SharedRwLockReadGuard,
1801         rule: &Arc<Locked<CounterStyleRule>>,
1802         layer: LayerId,
1803     ) -> Result<(), AllocErr> {
1804         let name = rule.read_with(guard).name().0.clone();
1805         self.counter_styles.try_insert(name, rule.clone(), layer)
1806     }
1808     /// Add the given @page rule.
1809     fn add_page(
1810         &mut self,
1811         guard: &SharedRwLockReadGuard,
1812         rule: &Arc<Locked<PageRule>>,
1813         layer: LayerId,
1814     ) -> Result<(), AllocErr> {
1815         let page_rule = rule.read_with(guard);
1816         let mut add_rule = |name| {
1817             let vec = self.pages.rules.entry(name).or_default();
1818             vec.push(PageRuleData{layer, rule: rule.clone()});
1819         };
1820         if page_rule.selectors.0.is_empty() {
1821             add_rule(atom!(""));
1822         } else {
1823             for selector in page_rule.selectors.as_slice() {
1824                 add_rule(selector.name.0.clone());
1825             }
1826         }
1827         Ok(())
1828     }
1830     fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
1831         self.font_faces.sort(layers);
1832         self.font_feature_values.sort(layers);
1833         self.font_palette_values.sort(layers);
1834         self.counter_styles.sort(layers);
1835     }
1837     fn clear(&mut self) {
1838         #[cfg(feature = "gecko")]
1839         {
1840             self.font_faces.clear();
1841             self.font_feature_values.clear();
1842             self.font_palette_values.clear();
1843             self.counter_styles.clear();
1844             self.pages.clear();
1845         }
1846     }
1849 // Don't let a prefixed keyframes animation override
1850 // a non-prefixed one.
1851 fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
1852     if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
1853         Ordering::Equal
1854     } else if v2.vendor_prefix.is_some() {
1855         Ordering::Greater
1856     } else {
1857         Ordering::Less
1858     }
1861 /// An iterator over the different ExtraStyleData.
1862 pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
1864 impl<'a> Iterator for ExtraStyleDataIterator<'a> {
1865     type Item = (&'a ExtraStyleData, Origin);
1867     fn next(&mut self) -> Option<Self::Item> {
1868         self.0.next().map(|d| (&d.0.extra_data, d.1))
1869     }
1872 #[cfg(feature = "gecko")]
1873 impl MallocSizeOf for ExtraStyleData {
1874     /// Measure heap usage.
1875     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1876         let mut n = 0;
1877         n += self.font_faces.shallow_size_of(ops);
1878         n += self.font_feature_values.shallow_size_of(ops);
1879         n += self.font_palette_values.shallow_size_of(ops);
1880         n += self.counter_styles.shallow_size_of(ops);
1881         n += self.pages.shallow_size_of(ops);
1882         n
1883     }
1886 /// SelectorMapEntry implementation for use in our revalidation selector map.
1887 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
1888 #[derive(Clone, Debug)]
1889 struct RevalidationSelectorAndHashes {
1890     #[cfg_attr(
1891         feature = "gecko",
1892         ignore_malloc_size_of = "CssRules have primary refs, we measure there"
1893     )]
1894     selector: Selector<SelectorImpl>,
1895     selector_offset: usize,
1896     hashes: AncestorHashes,
1899 impl RevalidationSelectorAndHashes {
1900     fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
1901         let selector_offset = {
1902             // We basically want to check whether the first combinator is a
1903             // pseudo-element combinator.  If it is, we want to use the offset
1904             // one past it.  Otherwise, our offset is 0.
1905             let mut index = 0;
1906             let mut iter = selector.iter();
1908             // First skip over the first ComplexSelector.
1909             //
1910             // We can't check what sort of what combinator we have until we do
1911             // that.
1912             for _ in &mut iter {
1913                 index += 1; // Simple selector
1914             }
1916             match iter.next_sequence() {
1917                 Some(Combinator::PseudoElement) => index + 1, // +1 for the combinator
1918                 _ => 0,
1919             }
1920         };
1922         RevalidationSelectorAndHashes {
1923             selector,
1924             selector_offset,
1925             hashes,
1926         }
1927     }
1930 impl SelectorMapEntry for RevalidationSelectorAndHashes {
1931     fn selector(&self) -> SelectorIter<SelectorImpl> {
1932         self.selector.iter_from(self.selector_offset)
1933     }
1936 /// A selector visitor implementation that collects all the state the Stylist
1937 /// cares about a selector.
1938 struct StylistSelectorVisitor<'a> {
1939     /// Whether we've past the rightmost compound selector, not counting
1940     /// pseudo-elements.
1941     passed_rightmost_selector: bool,
1943     /// Whether the selector needs revalidation for the style sharing cache.
1944     needs_revalidation: &'a mut bool,
1946     /// Flags for which selector list-containing components the visitor is
1947     /// inside of, if any
1948     in_selector_list_of: SelectorListKind,
1950     /// The filter with all the id's getting referenced from rightmost
1951     /// selectors.
1952     mapped_ids: &'a mut PrecomputedHashSet<Atom>,
1954     /// The filter with the IDs getting referenced from the selector list of
1955     /// :nth-child(... of <selector list>) selectors.
1956     nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
1958     /// The filter with the local names of attributes there are selectors for.
1959     attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
1961     /// The filter with the classes getting referenced from the selector list of
1962     /// :nth-child(... of <selector list>) selectors.
1963     nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
1965     /// The filter with the local names of attributes there are selectors for
1966     /// within the selector list of :nth-child(... of <selector list>)
1967     /// selectors.
1968     nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
1970     /// All the states selectors in the page reference.
1971     state_dependencies: &'a mut ElementState,
1973     /// All the state selectors in the page reference within the selector list
1974     /// of :nth-child(... of <selector list>) selectors.
1975     nth_of_state_dependencies: &'a mut ElementState,
1977     /// All the document states selectors in the page reference.
1978     document_state_dependencies: &'a mut DocumentState,
1981 fn component_needs_revalidation(
1982     c: &Component<SelectorImpl>,
1983     passed_rightmost_selector: bool,
1984 ) -> bool {
1985     match *c {
1986         Component::ID(_) => {
1987             // TODO(emilio): This could also check that the ID is not already in
1988             // the rule hash. In that case, we could avoid making this a
1989             // revalidation selector too.
1990             //
1991             // See https://bugzilla.mozilla.org/show_bug.cgi?id=1369611
1992             passed_rightmost_selector
1993         },
1994         Component::AttributeInNoNamespaceExists { .. } |
1995         Component::AttributeInNoNamespace { .. } |
1996         Component::AttributeOther(_) |
1997         Component::Empty |
1998         Component::Nth(_) |
1999         Component::NthOf(_) => true,
2000         Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2001         _ => false,
2002     }
2005 impl<'a> StylistSelectorVisitor<'a> {
2006     fn visit_nested_selector(
2007         &mut self,
2008         in_selector_list_of: SelectorListKind,
2009         selector: &Selector<SelectorImpl>
2010     ) {
2011         let old_passed_rightmost_selector = self.passed_rightmost_selector;
2012         let old_in_selector_list_of = self.in_selector_list_of;
2014         self.passed_rightmost_selector = false;
2015         self.in_selector_list_of = in_selector_list_of;
2016         let _ret = selector.visit(self);
2017         debug_assert!(_ret, "We never return false");
2019         self.passed_rightmost_selector = old_passed_rightmost_selector;
2020         self.in_selector_list_of = old_in_selector_list_of;
2021     }
2024 impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2025     type Impl = SelectorImpl;
2027     fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2028         *self.needs_revalidation =
2029             *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2031         // NOTE(emilio): this call happens before we visit any of the simple
2032         // selectors in the next ComplexSelector, so we can use this to skip
2033         // looking at them.
2034         self.passed_rightmost_selector = self.passed_rightmost_selector ||
2035             !matches!(combinator, None | Some(Combinator::PseudoElement));
2037         true
2038     }
2040     fn visit_selector_list(
2041         &mut self,
2042         list_kind: SelectorListKind,
2043         list: &[Selector<Self::Impl>],
2044     ) -> bool {
2045         let in_selector_list_of = self.in_selector_list_of | list_kind;
2046         for selector in list {
2047             self.visit_nested_selector(in_selector_list_of, selector);
2048         }
2049         true
2050     }
2052     fn visit_relative_selector_list(
2053         &mut self,
2054         list: &[selectors::parser::RelativeSelector<Self::Impl>],
2055     ) -> bool {
2056         let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2057         for selector in list {
2058             self.visit_nested_selector(in_selector_list_of, &selector.selector);
2059         }
2060         true
2061     }
2063     fn visit_attribute_selector(
2064         &mut self,
2065         _ns: &NamespaceConstraint<&Namespace>,
2066         name: &LocalName,
2067         lower_name: &LocalName,
2068     ) -> bool {
2069         if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2070             self.nth_of_attribute_dependencies.insert(name.clone());
2071             if name != lower_name {
2072                 self.nth_of_attribute_dependencies
2073                     .insert(lower_name.clone());
2074             }
2075         }
2077         self.attribute_dependencies.insert(name.clone());
2078         if name != lower_name {
2079             self.attribute_dependencies.insert(lower_name.clone());
2080         }
2082         true
2083     }
2085     fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2086         *self.needs_revalidation = *self.needs_revalidation ||
2087             component_needs_revalidation(s, self.passed_rightmost_selector);
2089         match *s {
2090             Component::NonTSPseudoClass(ref p) => {
2091                 self.state_dependencies.insert(p.state_flag());
2092                 self.document_state_dependencies
2093                     .insert(p.document_state_flag());
2095                 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2096                     self.nth_of_state_dependencies.insert(p.state_flag());
2097                 }
2098             },
2099             Component::ID(ref id) => {
2100                 // We want to stop storing mapped ids as soon as we've moved off
2101                 // the rightmost ComplexSelector that is not a pseudo-element.
2102                 //
2103                 // That can be detected by a visit_complex_selector call with a
2104                 // combinator other than None and PseudoElement.
2105                 //
2106                 // Importantly, this call happens before we visit any of the
2107                 // simple selectors in that ComplexSelector.
2108                 //
2109                 // NOTE(emilio): See the comment regarding on when this may
2110                 // break in visit_complex_selector.
2111                 if !self.passed_rightmost_selector {
2112                     self.mapped_ids.insert(id.0.clone());
2113                 }
2115                 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2116                     self.nth_of_mapped_ids.insert(id.0.clone());
2117                 }
2118             },
2119             Component::Class(ref class)
2120                 if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2121             {
2122                 self.nth_of_class_dependencies.insert(class.0.clone());
2123             },
2124             _ => {},
2125         }
2127         true
2128     }
2131 /// A set of rules for element and pseudo-elements.
2132 #[derive(Clone, Debug, Default, MallocSizeOf)]
2133 struct GenericElementAndPseudoRules<Map> {
2134     /// Rules from stylesheets at this `CascadeData`'s origin.
2135     element_map: Map,
2137     /// Rules from stylesheets at this `CascadeData`'s origin that correspond
2138     /// to a given pseudo-element.
2139     ///
2140     /// FIXME(emilio): There are a bunch of wasted entries here in practice.
2141     /// Figure out a good way to do a `PerNonAnonBox` and `PerAnonBox` (for
2142     /// `precomputed_values_for_pseudo`) without duplicating a lot of code.
2143     pseudos_map: PerPseudoElementMap<Box<Map>>,
2146 impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2147     #[inline(always)]
2148     fn for_insertion(&mut self, pseudo_element: Option<&PseudoElement>) -> &mut Map {
2149         debug_assert!(
2150             pseudo_element.map_or(true, |pseudo| {
2151                 !pseudo.is_precomputed() && !pseudo.is_unknown_webkit_pseudo_element()
2152             }),
2153             "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2154              and unknown webkit pseudos should be discarded before getting here"
2155         );
2157         match pseudo_element {
2158             None => &mut self.element_map,
2159             Some(pseudo) => self
2160                 .pseudos_map
2161                 .get_or_insert_with(pseudo, || Box::new(Default::default())),
2162         }
2163     }
2165     #[inline]
2166     fn rules(&self, pseudo: Option<&PseudoElement>) -> Option<&Map> {
2167         match pseudo {
2168             Some(pseudo) => self.pseudos_map.get(pseudo).map(|p| &**p),
2169             None => Some(&self.element_map),
2170         }
2171     }
2173     /// Measures heap usage.
2174     #[cfg(feature = "gecko")]
2175     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2176         sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2178         for elem in self.pseudos_map.iter() {
2179             if let Some(ref elem) = *elem {
2180                 sizes.mElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops);
2181             }
2182         }
2183     }
2186 type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2187 type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2188 type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2190 impl ElementAndPseudoRules {
2191     // TODO(emilio): Should we retain storage of these?
2192     fn clear(&mut self) {
2193         self.element_map.clear();
2194         self.pseudos_map.clear();
2195     }
2197     fn shrink_if_needed(&mut self) {
2198         self.element_map.shrink_if_needed();
2199         for pseudo in self.pseudos_map.iter_mut() {
2200             if let Some(ref mut pseudo) = pseudo {
2201                 pseudo.shrink_if_needed();
2202             }
2203         }
2204     }
2207 impl PartElementAndPseudoRules {
2208     // TODO(emilio): Should we retain storage of these?
2209     fn clear(&mut self) {
2210         self.element_map.clear();
2211         self.pseudos_map.clear();
2212     }
2215 /// The id of a given layer, a sequentially-increasing identifier.
2216 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2217 pub struct LayerId(u16);
2219 impl LayerId {
2220     /// The id of the root layer.
2221     pub const fn root() -> Self {
2222         Self(0)
2223     }
2226 #[derive(Clone, Debug, MallocSizeOf)]
2227 struct CascadeLayer {
2228     id: LayerId,
2229     order: LayerOrder,
2230     children: Vec<LayerId>,
2233 impl CascadeLayer {
2234     const fn root() -> Self {
2235         Self {
2236             id: LayerId::root(),
2237             order: LayerOrder::root(),
2238             children: vec![],
2239         }
2240     }
2243 /// The id of a given container condition, a sequentially-increasing identifier
2244 /// for a given style set.
2245 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2246 pub struct ContainerConditionId(u16);
2248 impl ContainerConditionId {
2249     /// A special id that represents no container rule all.
2250     pub const fn none() -> Self {
2251         Self(0)
2252     }
2255 #[derive(Clone, Debug, MallocSizeOf)]
2256 struct ContainerConditionReference {
2257     parent: ContainerConditionId,
2258     #[ignore_malloc_size_of = "Arc"]
2259     condition: Option<Arc<ContainerCondition>>,
2262 impl ContainerConditionReference {
2263     const fn none() -> Self {
2264         Self {
2265             parent: ContainerConditionId::none(),
2266             condition: None,
2267         }
2268     }
2271 /// Data resulting from performing the CSS cascade that is specific to a given
2272 /// origin.
2274 /// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
2275 /// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
2276 #[derive(Debug, Clone, MallocSizeOf)]
2277 pub struct CascadeData {
2278     /// The data coming from normal style rules that apply to elements at this
2279     /// cascade level.
2280     normal_rules: ElementAndPseudoRules,
2282     /// The `:host` pseudo rules that are the rightmost selector (without
2283     /// accounting for pseudo-elements).
2284     host_rules: Option<Box<ElementAndPseudoRules>>,
2286     /// The data coming from ::slotted() pseudo-element rules.
2287     ///
2288     /// We need to store them separately because an element needs to match
2289     /// ::slotted() pseudo-element rules in different shadow roots.
2290     ///
2291     /// In particular, we need to go through all the style data in all the
2292     /// containing style scopes starting from the closest assigned slot.
2293     slotted_rules: Option<Box<ElementAndPseudoRules>>,
2295     /// The data coming from ::part() pseudo-element rules.
2296     ///
2297     /// We need to store them separately because an element needs to match
2298     /// ::part() pseudo-element rules in different shadow roots.
2299     part_rules: Option<Box<PartElementAndPseudoRules>>,
2301     /// The invalidation map for these rules.
2302     invalidation_map: InvalidationMap,
2304     /// The relative selector equivalent of the invalidation map.
2305     relative_selector_invalidation_map: RelativeSelectorInvalidationMap,
2307     /// The attribute local names that appear in attribute selectors.  Used
2308     /// to avoid taking element snapshots when an irrelevant attribute changes.
2309     /// (We don't bother storing the namespace, since namespaced attributes are
2310     /// rare.)
2311     attribute_dependencies: PrecomputedHashSet<LocalName>,
2313     /// The classes that appear in the selector list of
2314     /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
2315     /// an element when an irrelevant class changes.
2316     nth_of_class_dependencies: PrecomputedHashSet<Atom>,
2318     /// The attributes that appear in the selector list of
2319     /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
2320     /// an element when an irrelevant attribute changes.
2321     nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
2323     /// The element state bits that are relied on by selectors.  Like
2324     /// `attribute_dependencies`, this is used to avoid taking element snapshots
2325     /// when an irrelevant element state bit changes.
2326     state_dependencies: ElementState,
2328     /// The element state bits that are relied on by selectors that appear in
2329     /// the selector list of :nth-child(... of <selector list>).
2330     nth_of_state_dependencies: ElementState,
2332     /// The document state bits that are relied on by selectors.  This is used
2333     /// to tell whether we need to restyle the entire document when a document
2334     /// state bit changes.
2335     document_state_dependencies: DocumentState,
2337     /// The ids that appear in the rightmost complex selector of selectors (and
2338     /// hence in our selector maps).  Used to determine when sharing styles is
2339     /// safe: we disallow style sharing for elements whose id matches this
2340     /// filter, and hence might be in one of our selector maps.
2341     mapped_ids: PrecomputedHashSet<Atom>,
2343     /// The IDs that appear in the selector list of
2344     /// :nth-child(... of <selector list>). Used to avoid restyling siblings
2345     /// of an element when an irrelevant ID changes.
2346     nth_of_mapped_ids: PrecomputedHashSet<Atom>,
2348     /// Selectors that require explicit cache revalidation (i.e. which depend
2349     /// on state that is not otherwise visible to the cache, like attributes or
2350     /// tree-structural state like child index and pseudos).
2351     #[ignore_malloc_size_of = "Arc"]
2352     selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
2354     /// A map with all the animations at this `CascadeData`'s origin, indexed
2355     /// by name.
2356     animations: LayerOrderedMap<KeyframesAnimation>,
2358     /// A map with all the layer-ordered registrations from style at this `CascadeData`'s origin,
2359     /// indexed by name.
2360     custom_property_registrations: LayerOrderedMap<PropertyRegistration>,
2362     /// A map from cascade layer name to layer order.
2363     layer_id: FxHashMap<LayerName, LayerId>,
2365     /// The list of cascade layers, indexed by their layer id.
2366     layers: SmallVec<[CascadeLayer; 1]>,
2368     /// The list of container conditions, indexed by their id.
2369     container_conditions: SmallVec<[ContainerConditionReference; 1]>,
2371     /// Effective media query results cached from the last rebuild.
2372     effective_media_query_results: EffectiveMediaQueryResults,
2374     /// Extra data, like different kinds of rules, etc.
2375     extra_data: ExtraStyleData,
2377     /// A monotonically increasing counter to represent the order on which a
2378     /// style rule appears in a stylesheet, needed to sort them by source order.
2379     rules_source_order: u32,
2381     /// The total number of selectors.
2382     num_selectors: usize,
2384     /// The total number of declarations.
2385     num_declarations: usize,
2388 impl CascadeData {
2389     /// Creates an empty `CascadeData`.
2390     pub fn new() -> Self {
2391         Self {
2392             normal_rules: ElementAndPseudoRules::default(),
2393             host_rules: None,
2394             slotted_rules: None,
2395             part_rules: None,
2396             invalidation_map: InvalidationMap::new(),
2397             relative_selector_invalidation_map: RelativeSelectorInvalidationMap::new(),
2398             nth_of_mapped_ids: PrecomputedHashSet::default(),
2399             nth_of_class_dependencies: PrecomputedHashSet::default(),
2400             nth_of_attribute_dependencies: PrecomputedHashSet::default(),
2401             nth_of_state_dependencies: ElementState::empty(),
2402             attribute_dependencies: PrecomputedHashSet::default(),
2403             state_dependencies: ElementState::empty(),
2404             document_state_dependencies: DocumentState::empty(),
2405             mapped_ids: PrecomputedHashSet::default(),
2406             // NOTE: We disable attribute bucketing for revalidation because we
2407             // rely on the buckets to match, but we don't want to just not share
2408             // style across elements with different attributes.
2409             //
2410             // An alternative to this would be to perform a style sharing check
2411             // like may_match_different_id_rules which would check that the
2412             // attribute buckets match on all scopes. But that seems
2413             // somewhat gnarly.
2414             selectors_for_cache_revalidation: SelectorMap::new_without_attribute_bucketing(),
2415             animations: Default::default(),
2416             custom_property_registrations: Default::default(),
2417             layer_id: Default::default(),
2418             layers: smallvec::smallvec![CascadeLayer::root()],
2419             container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
2420             extra_data: ExtraStyleData::default(),
2421             effective_media_query_results: EffectiveMediaQueryResults::new(),
2422             rules_source_order: 0,
2423             num_selectors: 0,
2424             num_declarations: 0,
2425         }
2426     }
2428     /// Rebuild the cascade data from a given SheetCollection, incrementally if
2429     /// possible.
2430     pub fn rebuild<'a, S>(
2431         &mut self,
2432         device: &Device,
2433         quirks_mode: QuirksMode,
2434         collection: SheetCollectionFlusher<S>,
2435         guard: &SharedRwLockReadGuard,
2436     ) -> Result<(), AllocErr>
2437     where
2438         S: StylesheetInDocument + PartialEq + 'static,
2439     {
2440         if !collection.dirty() {
2441             return Ok(());
2442         }
2444         let validity = collection.data_validity();
2446         match validity {
2447             DataValidity::Valid => {},
2448             DataValidity::CascadeInvalid => self.clear_cascade_data(),
2449             DataValidity::FullyInvalid => self.clear(),
2450         }
2452         let mut result = Ok(());
2454         collection.each(|stylesheet, rebuild_kind| {
2455             result = self.add_stylesheet(
2456                 device,
2457                 quirks_mode,
2458                 stylesheet,
2459                 guard,
2460                 rebuild_kind,
2461                 /* precomputed_pseudo_element_decls = */ None,
2462             );
2463             result.is_ok()
2464         });
2466         self.did_finish_rebuild();
2468         result
2469     }
2471     /// Returns the invalidation map.
2472     pub fn invalidation_map(&self) -> &InvalidationMap {
2473         &self.invalidation_map
2474     }
2476     /// Returns the relative selector invalidation map.
2477     pub fn relative_selector_invalidation_map(&self) -> &RelativeSelectorInvalidationMap {
2478         &self.relative_selector_invalidation_map
2479     }
2481     /// Returns whether the given ElementState bit is relied upon by a selector
2482     /// of some rule.
2483     #[inline]
2484     pub fn has_state_dependency(&self, state: ElementState) -> bool {
2485         self.state_dependencies.intersects(state)
2486     }
2488     /// Returns whether the given ElementState bit is relied upon by a selector
2489     /// of some rule in the selector list of :nth-child(... of <selector list>).
2490     #[inline]
2491     pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
2492         self.nth_of_state_dependencies.intersects(state)
2493     }
2495     /// Returns whether the given attribute might appear in an attribute
2496     /// selector of some rule.
2497     #[inline]
2498     pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
2499         self.attribute_dependencies.contains(local_name)
2500     }
2502     /// Returns whether the given ID might appear in an ID selector in the
2503     /// selector list of :nth-child(... of <selector list>).
2504     #[inline]
2505     pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
2506         self.nth_of_mapped_ids.contains(id)
2507     }
2509     /// Returns whether the given class might appear in a class selector in the
2510     /// selector list of :nth-child(... of <selector list>).
2511     #[inline]
2512     pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
2513         self.nth_of_class_dependencies.contains(class)
2514     }
2516     /// Returns whether the given attribute might appear in an attribute
2517     /// selector in the selector list of :nth-child(... of <selector list>).
2518     #[inline]
2519     pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
2520         self.nth_of_attribute_dependencies.contains(local_name)
2521     }
2523     /// Returns the normal rule map for a given pseudo-element.
2524     #[inline]
2525     pub fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
2526         self.normal_rules.rules(pseudo)
2527     }
2529     /// Returns the host pseudo rule map for a given pseudo-element.
2530     #[inline]
2531     pub fn host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
2532         self.host_rules.as_ref().and_then(|d| d.rules(pseudo))
2533     }
2535     /// Whether there's any host rule that could match in this scope.
2536     pub fn any_host_rules(&self) -> bool {
2537         self.host_rules.is_some()
2538     }
2540     /// Returns the slotted rule map for a given pseudo-element.
2541     #[inline]
2542     pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
2543         self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo))
2544     }
2546     /// Whether there's any ::slotted rule that could match in this scope.
2547     pub fn any_slotted_rule(&self) -> bool {
2548         self.slotted_rules.is_some()
2549     }
2551     /// Returns the parts rule map for a given pseudo-element.
2552     #[inline]
2553     pub fn part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap> {
2554         self.part_rules.as_ref().and_then(|d| d.rules(pseudo))
2555     }
2557     /// Whether there's any ::part rule that could match in this scope.
2558     pub fn any_part_rule(&self) -> bool {
2559         self.part_rules.is_some()
2560     }
2562     #[inline]
2563     fn layer_order_for(&self, id: LayerId) -> LayerOrder {
2564         self.layers[id.0 as usize].order
2565     }
2567     pub(crate) fn container_condition_matches<E>(
2568         &self,
2569         mut id: ContainerConditionId,
2570         stylist: &Stylist,
2571         element: E,
2572         context: &mut MatchingContext<E::Impl>,
2573     ) -> bool
2574     where
2575         E: TElement,
2576     {
2577         loop {
2578             let condition_ref = &self.container_conditions[id.0 as usize];
2579             let condition = match condition_ref.condition {
2580                 None => return true,
2581                 Some(ref c) => c,
2582             };
2583             let matches = condition
2584                 .matches(
2585                     stylist,
2586                     element,
2587                     context.extra_data.originating_element_style,
2588                     &mut context.extra_data.cascade_input_flags,
2589                 )
2590                 .to_bool(/* unknown = */ false);
2591             if !matches {
2592                 return false;
2593             }
2594             id = condition_ref.parent;
2595         }
2596     }
2598     fn did_finish_rebuild(&mut self) {
2599         self.shrink_maps_if_needed();
2600         self.compute_layer_order();
2601     }
2603     fn shrink_maps_if_needed(&mut self) {
2604         self.normal_rules.shrink_if_needed();
2605         if let Some(ref mut host_rules) = self.host_rules {
2606             host_rules.shrink_if_needed();
2607         }
2608         if let Some(ref mut slotted_rules) = self.slotted_rules {
2609             slotted_rules.shrink_if_needed();
2610         }
2611         self.animations.shrink_if_needed();
2612         self.custom_property_registrations.shrink_if_needed();
2613         self.invalidation_map.shrink_if_needed();
2614         self.relative_selector_invalidation_map.shrink_if_needed();
2615         self.attribute_dependencies.shrink_if_needed();
2616         self.nth_of_attribute_dependencies.shrink_if_needed();
2617         self.nth_of_class_dependencies.shrink_if_needed();
2618         self.nth_of_mapped_ids.shrink_if_needed();
2619         self.mapped_ids.shrink_if_needed();
2620         self.layer_id.shrink_if_needed();
2621         self.selectors_for_cache_revalidation.shrink_if_needed();
2622     }
2624     fn compute_layer_order(&mut self) {
2625         debug_assert_ne!(
2626             self.layers.len(),
2627             0,
2628             "There should be at least the root layer!"
2629         );
2630         if self.layers.len() == 1 {
2631             return; // Nothing to do
2632         }
2633         let (first, remaining) = self.layers.split_at_mut(1);
2634         let root = &mut first[0];
2635         let mut order = LayerOrder::first();
2636         compute_layer_order_for_subtree(root, remaining, &mut order);
2638         // NOTE(emilio): This is a bit trickier than it should to avoid having
2639         // to clone() around layer indices.
2640         fn compute_layer_order_for_subtree(
2641             parent: &mut CascadeLayer,
2642             remaining_layers: &mut [CascadeLayer],
2643             order: &mut LayerOrder,
2644         ) {
2645             for child in parent.children.iter() {
2646                 debug_assert!(
2647                     parent.id < *child,
2648                     "Children are always registered after parents"
2649                 );
2650                 let child_index = (child.0 - parent.id.0 - 1) as usize;
2651                 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
2652                 let child = &mut first[child_index];
2653                 compute_layer_order_for_subtree(child, remaining, order);
2654             }
2656             if parent.id != LayerId::root() {
2657                 parent.order = *order;
2658                 order.inc();
2659             }
2660         }
2661         self.extra_data.sort_by_layer(&self.layers);
2662         self.animations
2663             .sort_with(&self.layers, compare_keyframes_in_same_layer);
2664         self.custom_property_registrations.sort(&self.layers)
2665     }
2667     /// Collects all the applicable media query results into `results`.
2668     ///
2669     /// This duplicates part of the logic in `add_stylesheet`, which is
2670     /// a bit unfortunate.
2671     ///
2672     /// FIXME(emilio): With a bit of smartness in
2673     /// `media_feature_affected_matches`, we could convert
2674     /// `EffectiveMediaQueryResults` into a vector without too much effort.
2675     fn collect_applicable_media_query_results_into<S>(
2676         device: &Device,
2677         stylesheet: &S,
2678         guard: &SharedRwLockReadGuard,
2679         results: &mut Vec<MediaListKey>,
2680         contents_list: &mut StyleSheetContentList,
2681     ) where
2682         S: StylesheetInDocument + 'static,
2683     {
2684         if !stylesheet.enabled() || !stylesheet.is_effective_for_device(device, guard) {
2685             return;
2686         }
2688         debug!(" + {:?}", stylesheet);
2689         let contents = stylesheet.contents();
2690         results.push(contents.to_media_list_key());
2692         // Safety: StyleSheetContents are reference-counted with Arc.
2693         contents_list.push(StylesheetContentsPtr(unsafe {
2694             Arc::from_raw_addrefed(contents)
2695         }));
2697         for rule in stylesheet.effective_rules(device, guard) {
2698             match *rule {
2699                 CssRule::Import(ref lock) => {
2700                     let import_rule = lock.read_with(guard);
2701                     debug!(" + {:?}", import_rule.stylesheet.media(guard));
2702                     results.push(import_rule.to_media_list_key());
2703                 },
2704                 CssRule::Media(ref media_rule) => {
2705                     debug!(" + {:?}", media_rule.media_queries.read_with(guard));
2706                     results.push(media_rule.to_media_list_key());
2707                 },
2708                 _ => {},
2709             }
2710         }
2711     }
2713     fn add_rule_list<'a, S>(
2714         &mut self,
2715         rules: std::slice::Iter<'a, CssRule>,
2716         device: &'a Device,
2717         quirks_mode: QuirksMode,
2718         stylesheet: &S,
2719         guard: &'a SharedRwLockReadGuard,
2720         rebuild_kind: SheetRebuildKind,
2721         containing_rule_state: &mut ContainingRuleState<'a>,
2722         mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
2723     ) -> Result<(), AllocErr>
2724     where
2725         S: StylesheetInDocument + 'static,
2726     {
2727         for rule in rules {
2728             // Handle leaf rules first, as those are by far the most common
2729             // ones, and are always effective, so we can skip some checks.
2730             let mut handled = true;
2731             let mut selectors_for_nested_rules = None;
2732             match *rule {
2733                 CssRule::Style(ref locked) => {
2734                     let style_rule = locked.read_with(guard);
2735                     self.num_declarations += style_rule.block.read_with(&guard).len();
2737                     let has_nested_rules = style_rule.rules.is_some();
2738                     let mut ancestor_selectors = containing_rule_state.ancestor_selector_lists.last_mut();
2739                     if has_nested_rules {
2740                         selectors_for_nested_rules = Some(if ancestor_selectors.is_some() {
2741                             Cow::Owned(SelectorList(Default::default()))
2742                         } else {
2743                             Cow::Borrowed(&style_rule.selectors)
2744                         });
2745                     }
2747                     for selector in &style_rule.selectors.0 {
2748                         self.num_selectors += 1;
2750                         let pseudo_element = selector.pseudo_element();
2751                         if let Some(pseudo) = pseudo_element {
2752                             if pseudo.is_precomputed() {
2753                                 debug_assert!(selector.is_universal());
2754                                 debug_assert!(ancestor_selectors.is_none());
2755                                 debug_assert!(!has_nested_rules);
2756                                 debug_assert_eq!(stylesheet.contents().origin, Origin::UserAgent);
2757                                 debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
2759                                 precomputed_pseudo_element_decls
2760                                     .as_mut()
2761                                     .expect("Expected precomputed declarations for the UA level")
2762                                     .get_or_insert_with(pseudo, Vec::new)
2763                                     .push(ApplicableDeclarationBlock::new(
2764                                         StyleSource::from_rule(locked.clone()),
2765                                         self.rules_source_order,
2766                                         CascadeLevel::UANormal,
2767                                         selector.specificity(),
2768                                         LayerOrder::root(),
2769                                     ));
2770                                 continue;
2771                             }
2772                             if pseudo.is_unknown_webkit_pseudo_element() {
2773                                 continue;
2774                             }
2775                         }
2777                         let selector = match ancestor_selectors {
2778                             Some(ref mut s) => selector.replace_parent_selector(&s.into_shared()),
2779                             None => selector.clone(),
2780                         };
2782                         let hashes = AncestorHashes::new(&selector, quirks_mode);
2784                         let rule = Rule::new(
2785                             selector,
2786                             hashes,
2787                             locked.clone(),
2788                             self.rules_source_order,
2789                             containing_rule_state.layer_id,
2790                             containing_rule_state.container_condition_id,
2791                         );
2793                         if let Some(Cow::Owned(ref mut nested_selectors)) =
2794                             selectors_for_nested_rules
2795                         {
2796                             nested_selectors.0.push(rule.selector.clone())
2797                         }
2799                         if rebuild_kind.should_rebuild_invalidation() {
2800                             note_selector_for_invalidation(
2801                                 &rule.selector,
2802                                 quirks_mode,
2803                                 &mut self.invalidation_map,
2804                                 &mut self.relative_selector_invalidation_map,
2805                             )?;
2806                             let mut needs_revalidation = false;
2807                             let mut visitor = StylistSelectorVisitor {
2808                                 needs_revalidation: &mut needs_revalidation,
2809                                 passed_rightmost_selector: false,
2810                                 in_selector_list_of: SelectorListKind::default(),
2811                                 mapped_ids: &mut self.mapped_ids,
2812                                 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
2813                                 attribute_dependencies: &mut self.attribute_dependencies,
2814                                 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
2815                                 nth_of_attribute_dependencies: &mut self
2816                                     .nth_of_attribute_dependencies,
2817                                 state_dependencies: &mut self.state_dependencies,
2818                                 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
2819                                 document_state_dependencies: &mut self.document_state_dependencies,
2820                             };
2821                             rule.selector.visit(&mut visitor);
2823                             if needs_revalidation {
2824                                 self.selectors_for_cache_revalidation.insert(
2825                                     RevalidationSelectorAndHashes::new(
2826                                         rule.selector.clone(),
2827                                         rule.hashes.clone(),
2828                                     ),
2829                                     quirks_mode,
2830                                 )?;
2831                             }
2832                         }
2834                         // Part is special, since given it doesn't have any
2835                         // selectors inside, it's not worth using a whole
2836                         // SelectorMap for it.
2837                         if let Some(parts) = rule.selector.parts() {
2838                             // ::part() has all semantics, so we just need to
2839                             // put any of them in the selector map.
2840                             //
2841                             // We choose the last one quite arbitrarily,
2842                             // expecting it's slightly more likely to be more
2843                             // specific.
2844                             let map = self
2845                                 .part_rules
2846                                 .get_or_insert_with(|| Box::new(Default::default()))
2847                                 .for_insertion(pseudo_element);
2848                             map.try_reserve(1)?;
2849                             let vec = map.entry(parts.last().unwrap().clone().0).or_default();
2850                             vec.try_reserve(1)?;
2851                             vec.push(rule);
2852                         } else {
2853                             // NOTE(emilio): It's fine to look at :host and then at
2854                             // ::slotted(..), since :host::slotted(..) could never
2855                             // possibly match, as <slot> is not a valid shadow host.
2856                             let rules = if rule
2857                                 .selector
2858                                 .is_featureless_host_selector_or_pseudo_element()
2859                             {
2860                                 self.host_rules
2861                                     .get_or_insert_with(|| Box::new(Default::default()))
2862                             } else if rule.selector.is_slotted() {
2863                                 self.slotted_rules
2864                                     .get_or_insert_with(|| Box::new(Default::default()))
2865                             } else {
2866                                 &mut self.normal_rules
2867                             }
2868                             .for_insertion(pseudo_element);
2869                             rules.insert(rule, quirks_mode)?;
2870                         }
2871                     }
2872                     self.rules_source_order += 1;
2873                     handled = !has_nested_rules;
2874                 },
2875                 CssRule::Keyframes(ref keyframes_rule) => {
2876                     debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
2877                     let keyframes_rule = keyframes_rule.read_with(guard);
2878                     let name = keyframes_rule.name.as_atom().clone();
2879                     let animation = KeyframesAnimation::from_keyframes(
2880                         &keyframes_rule.keyframes,
2881                         keyframes_rule.vendor_prefix.clone(),
2882                         guard,
2883                     );
2884                     self.animations.try_insert_with(
2885                         name,
2886                         animation,
2887                         containing_rule_state.layer_id,
2888                         compare_keyframes_in_same_layer,
2889                     )?;
2890                 },
2891                 CssRule::Property(ref rule) => {
2892                     let url_data = stylesheet.contents().url_data.read();
2893                     if let Ok(registration) = rule.to_valid_registration(&url_data) {
2894                         self.custom_property_registrations.try_insert(
2895                             rule.name.0.clone(),
2896                             registration,
2897                             containing_rule_state.layer_id,
2898                         )?;
2899                     }
2900                 },
2901                 #[cfg(feature = "gecko")]
2902                 CssRule::FontFace(ref rule) => {
2903                     // NOTE(emilio): We don't care about container_condition_id
2904                     // because:
2905                     //
2906                     //     Global, name-defining at-rules such as @keyframes or
2907                     //     @font-face or @layer that are defined inside container
2908                     //     queries are not constrained by the container query
2909                     //     conditions.
2910                     //
2911                     // https://drafts.csswg.org/css-contain-3/#container-rule
2912                     // (Same elsewhere)
2913                     self.extra_data
2914                         .add_font_face(rule, containing_rule_state.layer_id);
2915                 },
2916                 #[cfg(feature = "gecko")]
2917                 CssRule::FontFeatureValues(ref rule) => {
2918                     self.extra_data
2919                         .add_font_feature_values(rule, containing_rule_state.layer_id);
2920                 },
2921                 #[cfg(feature = "gecko")]
2922                 CssRule::FontPaletteValues(ref rule) => {
2923                     self.extra_data
2924                         .add_font_palette_values(rule, containing_rule_state.layer_id);
2925                 },
2926                 #[cfg(feature = "gecko")]
2927                 CssRule::CounterStyle(ref rule) => {
2928                     self.extra_data.add_counter_style(
2929                         guard,
2930                         rule,
2931                         containing_rule_state.layer_id,
2932                     )?;
2933                 },
2934                 #[cfg(feature = "gecko")]
2935                 CssRule::Page(ref rule) => {
2936                     self.extra_data
2937                         .add_page(guard, rule, containing_rule_state.layer_id)?;
2938                 },
2939                 _ => {
2940                     handled = false;
2941                 },
2942             }
2944             if handled {
2945                 // Assert that there are no children, and that the rule is
2946                 // effective.
2947                 if cfg!(debug_assertions) {
2948                     let mut effective = false;
2949                     let children = EffectiveRulesIterator::children(
2950                         rule,
2951                         device,
2952                         quirks_mode,
2953                         guard,
2954                         &mut effective,
2955                     );
2956                     debug_assert!(children.is_none());
2957                     debug_assert!(effective);
2958                 }
2959                 continue;
2960             }
2962             let mut effective = false;
2963             let children =
2964                 EffectiveRulesIterator::children(rule, device, quirks_mode, guard, &mut effective);
2966             if !effective {
2967                 continue;
2968             }
2970             fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
2971                 // TODO: Measure what's more common / expensive, if
2972                 // layer.clone() or the double hash lookup in the insert
2973                 // case.
2974                 if let Some(id) = data.layer_id.get(layer) {
2975                     return *id;
2976                 }
2977                 let id = LayerId(data.layers.len() as u16);
2979                 let parent_layer_id = if layer.layer_names().len() > 1 {
2980                     let mut parent = layer.clone();
2981                     parent.0.pop();
2983                     *data
2984                         .layer_id
2985                         .get_mut(&parent)
2986                         .expect("Parent layers should be registered before child layers")
2987                 } else {
2988                     LayerId::root()
2989                 };
2991                 data.layers[parent_layer_id.0 as usize].children.push(id);
2992                 data.layers.push(CascadeLayer {
2993                     id,
2994                     // NOTE(emilio): Order is evaluated after rebuild in
2995                     // compute_layer_order.
2996                     order: LayerOrder::first(),
2997                     children: vec![],
2998                 });
3000                 data.layer_id.insert(layer.clone(), id);
3002                 id
3003             }
3005             fn maybe_register_layers(
3006                 data: &mut CascadeData,
3007                 name: Option<&LayerName>,
3008                 containing_rule_state: &mut ContainingRuleState,
3009             ) {
3010                 let anon_name;
3011                 let name = match name {
3012                     Some(name) => name,
3013                     None => {
3014                         anon_name = LayerName::new_anonymous();
3015                         &anon_name
3016                     },
3017                 };
3018                 for name in name.layer_names() {
3019                     containing_rule_state.layer_name.0.push(name.clone());
3020                     containing_rule_state.layer_id =
3021                         maybe_register_layer(data, &containing_rule_state.layer_name);
3022                 }
3023                 debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
3024             }
3026             let saved_containing_rule_state = containing_rule_state.save();
3027             match *rule {
3028                 CssRule::Import(ref lock) => {
3029                     let import_rule = lock.read_with(guard);
3030                     if rebuild_kind.should_rebuild_invalidation() {
3031                         self.effective_media_query_results
3032                             .saw_effective(import_rule);
3033                     }
3034                     match import_rule.layer {
3035                         ImportLayer::Named(ref name) => {
3036                             maybe_register_layers(self, Some(name), containing_rule_state)
3037                         },
3038                         ImportLayer::Anonymous => {
3039                             maybe_register_layers(self, None, containing_rule_state)
3040                         },
3041                         ImportLayer::None => {},
3042                     }
3043                 },
3044                 CssRule::Media(ref media_rule) => {
3045                     if rebuild_kind.should_rebuild_invalidation() {
3046                         self.effective_media_query_results
3047                             .saw_effective(&**media_rule);
3048                     }
3049                 },
3050                 CssRule::LayerBlock(ref rule) => {
3051                     maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
3052                 },
3053                 CssRule::LayerStatement(ref rule) => {
3054                     for name in &*rule.names {
3055                         maybe_register_layers(self, Some(name), containing_rule_state);
3056                         // Register each layer individually.
3057                         containing_rule_state.restore(&saved_containing_rule_state);
3058                     }
3059                 },
3060                 CssRule::Style(..) => {
3061                     if let Some(ref mut s) = selectors_for_nested_rules {
3062                         containing_rule_state.ancestor_selector_lists.push(match s {
3063                             Cow::Owned(ref mut list) => AncestorSelectorList::Shared(list.into_shared()),
3064                             Cow::Borrowed(ref b) => AncestorSelectorList::Borrowed(b),
3065                         });
3066                     }
3067                 },
3068                 CssRule::Container(ref rule) => {
3069                     let id = ContainerConditionId(self.container_conditions.len() as u16);
3070                     self.container_conditions.push(ContainerConditionReference {
3071                         parent: containing_rule_state.container_condition_id,
3072                         condition: Some(rule.condition.clone()),
3073                     });
3074                     containing_rule_state.container_condition_id = id;
3075                 },
3076                 // We don't care about any other rule.
3077                 _ => {},
3078             }
3080             if let Some(children) = children {
3081                 self.add_rule_list(
3082                     children,
3083                     device,
3084                     quirks_mode,
3085                     stylesheet,
3086                     guard,
3087                     rebuild_kind,
3088                     containing_rule_state,
3089                     precomputed_pseudo_element_decls.as_deref_mut(),
3090                 )?;
3091             }
3093             containing_rule_state.restore(&saved_containing_rule_state);
3094         }
3096         Ok(())
3097     }
3099     // Returns Err(..) to signify OOM
3100     fn add_stylesheet<S>(
3101         &mut self,
3102         device: &Device,
3103         quirks_mode: QuirksMode,
3104         stylesheet: &S,
3105         guard: &SharedRwLockReadGuard,
3106         rebuild_kind: SheetRebuildKind,
3107         mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3108     ) -> Result<(), AllocErr>
3109     where
3110         S: StylesheetInDocument + 'static,
3111     {
3112         if !stylesheet.enabled() || !stylesheet.is_effective_for_device(device, guard) {
3113             return Ok(());
3114         }
3116         let contents = stylesheet.contents();
3118         if rebuild_kind.should_rebuild_invalidation() {
3119             self.effective_media_query_results.saw_effective(contents);
3120         }
3122         let mut state = ContainingRuleState::default();
3123         self.add_rule_list(
3124             contents.rules(guard).iter(),
3125             device,
3126             quirks_mode,
3127             stylesheet,
3128             guard,
3129             rebuild_kind,
3130             &mut state,
3131             precomputed_pseudo_element_decls.as_deref_mut(),
3132         )?;
3134         Ok(())
3135     }
3137     /// Returns whether all the media-feature affected values matched before and
3138     /// match now in the given stylesheet.
3139     pub fn media_feature_affected_matches<S>(
3140         &self,
3141         stylesheet: &S,
3142         guard: &SharedRwLockReadGuard,
3143         device: &Device,
3144         quirks_mode: QuirksMode,
3145     ) -> bool
3146     where
3147         S: StylesheetInDocument + 'static,
3148     {
3149         use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
3151         let effective_now = stylesheet.is_effective_for_device(device, guard);
3153         let effective_then = self
3154             .effective_media_query_results
3155             .was_effective(stylesheet.contents());
3157         if effective_now != effective_then {
3158             debug!(
3159                 " > Stylesheet {:?} changed -> {}, {}",
3160                 stylesheet.media(guard),
3161                 effective_then,
3162                 effective_now
3163             );
3164             return false;
3165         }
3167         if !effective_now {
3168             return true;
3169         }
3171         let mut iter = stylesheet.iter_rules::<PotentiallyEffectiveMediaRules>(device, guard);
3173         while let Some(rule) = iter.next() {
3174             match *rule {
3175                 CssRule::Style(..) |
3176                 CssRule::Namespace(..) |
3177                 CssRule::FontFace(..) |
3178                 CssRule::Container(..) |
3179                 CssRule::CounterStyle(..) |
3180                 CssRule::Supports(..) |
3181                 CssRule::Keyframes(..) |
3182                 CssRule::Page(..) |
3183                 CssRule::Property(..) |
3184                 CssRule::Document(..) |
3185                 CssRule::LayerBlock(..) |
3186                 CssRule::LayerStatement(..) |
3187                 CssRule::FontPaletteValues(..) |
3188                 CssRule::FontFeatureValues(..) => {
3189                     // Not affected by device changes.
3190                     continue;
3191                 },
3192                 CssRule::Import(ref lock) => {
3193                     let import_rule = lock.read_with(guard);
3194                     let effective_now = match import_rule.stylesheet.media(guard) {
3195                         Some(m) => m.evaluate(device, quirks_mode),
3196                         None => true,
3197                     };
3198                     let effective_then = self
3199                         .effective_media_query_results
3200                         .was_effective(import_rule);
3201                     if effective_now != effective_then {
3202                         debug!(
3203                             " > @import rule {:?} changed {} -> {}",
3204                             import_rule.stylesheet.media(guard),
3205                             effective_then,
3206                             effective_now
3207                         );
3208                         return false;
3209                     }
3211                     if !effective_now {
3212                         iter.skip_children();
3213                     }
3214                 },
3215                 CssRule::Media(ref media_rule) => {
3216                     let mq = media_rule.media_queries.read_with(guard);
3217                     let effective_now = mq.evaluate(device, quirks_mode);
3218                     let effective_then = self
3219                         .effective_media_query_results
3220                         .was_effective(&**media_rule);
3222                     if effective_now != effective_then {
3223                         debug!(
3224                             " > @media rule {:?} changed {} -> {}",
3225                             mq, effective_then, effective_now
3226                         );
3227                         return false;
3228                     }
3230                     if !effective_now {
3231                         iter.skip_children();
3232                     }
3233                 },
3234             }
3235         }
3237         true
3238     }
3240     /// Returns the custom properties map.
3241     pub fn custom_property_registrations(&self) -> &LayerOrderedMap<PropertyRegistration> {
3242         &self.custom_property_registrations
3243     }
3245     /// Clears the cascade data, but not the invalidation data.
3246     fn clear_cascade_data(&mut self) {
3247         self.normal_rules.clear();
3248         if let Some(ref mut slotted_rules) = self.slotted_rules {
3249             slotted_rules.clear();
3250         }
3251         if let Some(ref mut part_rules) = self.part_rules {
3252             part_rules.clear();
3253         }
3254         if let Some(ref mut host_rules) = self.host_rules {
3255             host_rules.clear();
3256         }
3257         self.animations.clear();
3258         self.custom_property_registrations.clear();
3259         self.layer_id.clear();
3260         self.layers.clear();
3261         self.layers.push(CascadeLayer::root());
3262         self.container_conditions.clear();
3263         self.container_conditions
3264             .push(ContainerConditionReference::none());
3265         self.extra_data.clear();
3266         self.rules_source_order = 0;
3267         self.num_selectors = 0;
3268         self.num_declarations = 0;
3269     }
3271     fn clear(&mut self) {
3272         self.clear_cascade_data();
3273         self.invalidation_map.clear();
3274         self.relative_selector_invalidation_map.clear();
3275         self.attribute_dependencies.clear();
3276         self.nth_of_attribute_dependencies.clear();
3277         self.nth_of_class_dependencies.clear();
3278         self.state_dependencies = ElementState::empty();
3279         self.nth_of_state_dependencies = ElementState::empty();
3280         self.document_state_dependencies = DocumentState::empty();
3281         self.mapped_ids.clear();
3282         self.nth_of_mapped_ids.clear();
3283         self.selectors_for_cache_revalidation.clear();
3284         self.effective_media_query_results.clear();
3285     }
3288 impl CascadeDataCacheEntry for CascadeData {
3289     fn cascade_data(&self) -> &CascadeData {
3290         self
3291     }
3293     fn rebuild<S>(
3294         device: &Device,
3295         quirks_mode: QuirksMode,
3296         collection: SheetCollectionFlusher<S>,
3297         guard: &SharedRwLockReadGuard,
3298         old: &Self,
3299     ) -> Result<Arc<Self>, AllocErr>
3300     where
3301         S: StylesheetInDocument + PartialEq + 'static,
3302     {
3303         debug_assert!(collection.dirty(), "We surely need to do something?");
3304         // If we're doing a full rebuild anyways, don't bother cloning the data.
3305         let mut updatable_entry = match collection.data_validity() {
3306             DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
3307             DataValidity::FullyInvalid => Self::new(),
3308         };
3309         updatable_entry.rebuild(device, quirks_mode, collection, guard)?;
3310         Ok(Arc::new(updatable_entry))
3311     }
3313     #[cfg(feature = "gecko")]
3314     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
3315         self.normal_rules.add_size_of(ops, sizes);
3316         if let Some(ref slotted_rules) = self.slotted_rules {
3317             slotted_rules.add_size_of(ops, sizes);
3318         }
3319         if let Some(ref part_rules) = self.part_rules {
3320             part_rules.add_size_of(ops, sizes);
3321         }
3322         if let Some(ref host_rules) = self.host_rules {
3323             host_rules.add_size_of(ops, sizes);
3324         }
3325         sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
3326         sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
3327         sizes.mOther += self.animations.size_of(ops);
3328         sizes.mOther += self.effective_media_query_results.size_of(ops);
3329         sizes.mOther += self.extra_data.size_of(ops);
3330     }
3333 impl Default for CascadeData {
3334     fn default() -> Self {
3335         CascadeData::new()
3336     }
3339 /// A rule, that wraps a style rule, but represents a single selector of the
3340 /// rule.
3341 #[derive(Clone, Debug, MallocSizeOf)]
3342 pub struct Rule {
3343     /// The selector this struct represents. We store this and the
3344     /// any_{important,normal} booleans inline in the Rule to avoid
3345     /// pointer-chasing when gathering applicable declarations, which
3346     /// can ruin performance when there are a lot of rules.
3347     #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
3348     pub selector: Selector<SelectorImpl>,
3350     /// The ancestor hashes associated with the selector.
3351     pub hashes: AncestorHashes,
3353     /// The source order this style rule appears in. Note that we only use
3354     /// three bytes to store this value in ApplicableDeclarationsBlock, so
3355     /// we could repurpose that storage here if we needed to.
3356     pub source_order: u32,
3358     /// The current layer id of this style rule.
3359     pub layer_id: LayerId,
3361     /// The current @container rule id.
3362     pub container_condition_id: ContainerConditionId,
3364     /// The actual style rule.
3365     #[cfg_attr(
3366         feature = "gecko",
3367         ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."
3368     )]
3369     #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
3370     pub style_rule: Arc<Locked<StyleRule>>,
3373 impl SelectorMapEntry for Rule {
3374     fn selector(&self) -> SelectorIter<SelectorImpl> {
3375         self.selector.iter()
3376     }
3379 impl Rule {
3380     /// Returns the specificity of the rule.
3381     pub fn specificity(&self) -> u32 {
3382         self.selector.specificity()
3383     }
3385     /// Turns this rule into an `ApplicableDeclarationBlock` for the given
3386     /// cascade level.
3387     pub fn to_applicable_declaration_block(
3388         &self,
3389         level: CascadeLevel,
3390         cascade_data: &CascadeData,
3391     ) -> ApplicableDeclarationBlock {
3392         let source = StyleSource::from_rule(self.style_rule.clone());
3393         ApplicableDeclarationBlock::new(
3394             source,
3395             self.source_order,
3396             level,
3397             self.specificity(),
3398             cascade_data.layer_order_for(self.layer_id),
3399         )
3400     }
3402     /// Creates a new Rule.
3403     pub fn new(
3404         selector: Selector<SelectorImpl>,
3405         hashes: AncestorHashes,
3406         style_rule: Arc<Locked<StyleRule>>,
3407         source_order: u32,
3408         layer_id: LayerId,
3409         container_condition_id: ContainerConditionId,
3410     ) -> Self {
3411         Rule {
3412             selector,
3413             hashes,
3414             style_rule,
3415             source_order,
3416             layer_id,
3417             container_condition_id,
3418         }
3419     }
3422 // The size of this is critical to performance on the bloom-basic
3423 // microbenchmark.
3424 // When iterating over a large Rule array, we want to be able to fast-reject
3425 // selectors (with the inline hashes) with as few cache misses as possible.
3426 size_of_test!(Rule, 40);
3428 /// A function to be able to test the revalidation stuff.
3429 pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
3430     let mut needs_revalidation = false;
3431     let mut mapped_ids = Default::default();
3432     let mut nth_of_mapped_ids = Default::default();
3433     let mut attribute_dependencies = Default::default();
3434     let mut nth_of_class_dependencies = Default::default();
3435     let mut nth_of_attribute_dependencies = Default::default();
3436     let mut state_dependencies = ElementState::empty();
3437     let mut nth_of_state_dependencies = ElementState::empty();
3438     let mut document_state_dependencies = DocumentState::empty();
3439     let mut visitor = StylistSelectorVisitor {
3440         passed_rightmost_selector: false,
3441         needs_revalidation: &mut needs_revalidation,
3442         in_selector_list_of: SelectorListKind::default(),
3443         mapped_ids: &mut mapped_ids,
3444         nth_of_mapped_ids: &mut nth_of_mapped_ids,
3445         attribute_dependencies: &mut attribute_dependencies,
3446         nth_of_class_dependencies: &mut nth_of_class_dependencies,
3447         nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
3448         state_dependencies: &mut state_dependencies,
3449         nth_of_state_dependencies: &mut nth_of_state_dependencies,
3450         document_state_dependencies: &mut document_state_dependencies,
3451     };
3452     s.visit(&mut visitor);
3453     needs_revalidation