tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

stylist.rs (180025B)


      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/. */
      4 
      5 //! Selector matching.
      6 
      7 use crate::applicable_declarations::{
      8    ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
      9 };
     10 use crate::computed_value_flags::ComputedValueFlags;
     11 use crate::context::{CascadeInputs, QuirksMode};
     12 use crate::custom_properties::ComputedCustomProperties;
     13 use crate::derives::*;
     14 use crate::dom::TElement;
     15 #[cfg(feature = "gecko")]
     16 use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
     17 use crate::invalidation::element::invalidation_map::{
     18    note_selector_for_invalidation, AdditionalRelativeSelectorInvalidationMap, Dependency,
     19    DependencyInvalidationKind, InvalidationMap, ScopeDependencyInvalidationKind,
     20 };
     21 use crate::invalidation::media_queries::{
     22    EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
     23 };
     24 use crate::invalidation::stylesheets::{RuleChangeKind, StylesheetInvalidationSet};
     25 use crate::media_queries::Device;
     26 use crate::properties::{
     27    self, AnimationDeclarations, CascadeMode, ComputedValues, FirstLineReparenting,
     28    PropertyDeclarationBlock, StyleBuilder,
     29 };
     30 use crate::properties_and_values::registry::{
     31    PropertyRegistration, PropertyRegistrationData, ScriptRegistry as CustomPropertyScriptRegistry,
     32 };
     33 use crate::rule_cache::{RuleCache, RuleCacheConditions};
     34 use crate::rule_collector::RuleCollector;
     35 use crate::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
     36 use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
     37 use crate::selector_parser::{NonTSPseudoClass, PerPseudoElementMap, PseudoElement, SelectorImpl};
     38 use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
     39 use crate::sharing::{RevalidationResult, ScopeRevalidationResult};
     40 use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
     41 use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
     42 use crate::stylesheets::container_rule::ContainerCondition;
     43 use crate::stylesheets::import_rule::ImportLayer;
     44 use crate::stylesheets::keyframes_rule::KeyframesAnimation;
     45 use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
     46 use crate::stylesheets::scope_rule::{
     47    collect_scope_roots, element_is_outside_of_scope, scope_selector_list_is_trivial,
     48    ImplicitScopeRoot, ScopeRootCandidate, ScopeSubjectMap, ScopeTarget,
     49 };
     50 use crate::stylesheets::{
     51    CounterStyleRule, CssRule, CssRuleRef, EffectiveRulesIterator, FontFaceRule,
     52    FontFeatureValuesRule, FontPaletteValuesRule, Origin, OriginSet, PagePseudoClassFlags,
     53    PageRule, PerOrigin, PerOriginIter, PositionTryRule, StylesheetContents, StylesheetInDocument,
     54 };
     55 use crate::stylesheets::{CustomMediaEvaluator, CustomMediaMap};
     56 use crate::values::specified::position::PositionTryFallbacksItem;
     57 use crate::values::specified::position::PositionTryFallbacksTryTactic;
     58 use crate::values::{computed, AtomIdent};
     59 use crate::AllocErr;
     60 use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
     61 use dom::{DocumentState, ElementState};
     62 #[cfg(feature = "gecko")]
     63 use malloc_size_of::MallocUnconditionalShallowSizeOf;
     64 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
     65 use rustc_hash::FxHashMap;
     66 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
     67 use selectors::bloom::BloomFilter;
     68 use selectors::matching::{
     69    matches_selector, selector_may_match, MatchingContext, MatchingMode, NeedsSelectorFlags,
     70    SelectorCaches,
     71 };
     72 use selectors::matching::{MatchingForInvalidation, VisitedHandlingMode};
     73 use selectors::parser::{
     74    AncestorHashes, Combinator, Component, MatchesFeaturelessHost, Selector, SelectorIter,
     75    SelectorList,
     76 };
     77 use selectors::visitor::{SelectorListKind, SelectorVisitor};
     78 use servo_arc::{Arc, ArcBorrow, ThinArc};
     79 use smallvec::SmallVec;
     80 use std::cmp::Ordering;
     81 use std::hash::{Hash, Hasher};
     82 use std::mem;
     83 use std::sync::{LazyLock, Mutex};
     84 
     85 /// The type of the stylesheets that the stylist contains.
     86 #[cfg(feature = "servo")]
     87 pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
     88 
     89 /// The type of the stylesheets that the stylist contains.
     90 #[cfg(feature = "gecko")]
     91 pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
     92 
     93 #[derive(Debug, Clone)]
     94 struct StylesheetContentsPtr(Arc<StylesheetContents>);
     95 
     96 impl PartialEq for StylesheetContentsPtr {
     97    #[inline]
     98    fn eq(&self, other: &Self) -> bool {
     99        Arc::ptr_eq(&self.0, &other.0)
    100    }
    101 }
    102 
    103 impl Eq for StylesheetContentsPtr {}
    104 
    105 impl Hash for StylesheetContentsPtr {
    106    fn hash<H: Hasher>(&self, state: &mut H) {
    107        let contents: &StylesheetContents = &*self.0;
    108        (contents as *const StylesheetContents).hash(state)
    109    }
    110 }
    111 
    112 type StyleSheetContentList = Vec<StylesheetContentsPtr>;
    113 
    114 /// The @position-try rules that have changed.
    115 #[derive(Default, Debug, MallocSizeOf)]
    116 pub struct CascadeDataDifference {
    117    /// The set of changed @position-try rule names.
    118    pub changed_position_try_names: PrecomputedHashSet<Atom>,
    119 }
    120 
    121 impl CascadeDataDifference {
    122    /// Merges another difference into `self`.
    123    pub fn merge_with(&mut self, other: Self) {
    124        self.changed_position_try_names
    125            .extend(other.changed_position_try_names.into_iter())
    126    }
    127 
    128    /// Returns whether we're empty.
    129    pub fn is_empty(&self) -> bool {
    130        self.changed_position_try_names.is_empty()
    131    }
    132 
    133    fn update(&mut self, old_data: &PositionTryMap, new_data: &PositionTryMap) {
    134        let mut any_different_key = false;
    135        let different_len = old_data.len() != new_data.len();
    136        for (name, rules) in old_data.iter() {
    137            let changed = match new_data.get(name) {
    138                Some(new_rule) => !Arc::ptr_eq(&rules.last().unwrap().0, new_rule),
    139                None => {
    140                    any_different_key = true;
    141                    true
    142                },
    143            };
    144            if changed {
    145                self.changed_position_try_names.insert(name.clone());
    146            }
    147        }
    148 
    149        if any_different_key || different_len {
    150            for name in new_data.keys() {
    151                // If the key exists in both, we've already checked it above.
    152                if !old_data.contains_key(name) {
    153                    self.changed_position_try_names.insert(name.clone());
    154                }
    155            }
    156        }
    157    }
    158 }
    159 
    160 /// A key in the cascade data cache.
    161 #[derive(Debug, Hash, Default, PartialEq, Eq)]
    162 struct CascadeDataCacheKey {
    163    media_query_results: Vec<MediaListKey>,
    164    contents: StyleSheetContentList,
    165 }
    166 
    167 unsafe impl Send for CascadeDataCacheKey {}
    168 unsafe impl Sync for CascadeDataCacheKey {}
    169 
    170 trait CascadeDataCacheEntry: Sized {
    171    /// Rebuilds the cascade data for the new stylesheet collection. The
    172    /// collection is guaranteed to be dirty.
    173    fn rebuild<S>(
    174        device: &Device,
    175        quirks_mode: QuirksMode,
    176        collection: SheetCollectionFlusher<S>,
    177        guard: &SharedRwLockReadGuard,
    178        old_entry: &Self,
    179        difference: &mut CascadeDataDifference,
    180    ) -> Result<Arc<Self>, AllocErr>
    181    where
    182        S: StylesheetInDocument + PartialEq + 'static;
    183    /// Measures heap memory usage.
    184    #[cfg(feature = "gecko")]
    185    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
    186 }
    187 
    188 struct CascadeDataCache<Entry> {
    189    entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
    190 }
    191 
    192 impl<Entry> CascadeDataCache<Entry>
    193 where
    194    Entry: CascadeDataCacheEntry,
    195 {
    196    fn new() -> Self {
    197        Self {
    198            entries: Default::default(),
    199        }
    200    }
    201 
    202    fn len(&self) -> usize {
    203        self.entries.len()
    204    }
    205 
    206    // FIXME(emilio): This may need to be keyed on quirks-mode too, though for
    207    // UA sheets there aren't class / id selectors on those sheets, usually, so
    208    // it's probably ok... For the other cache the quirks mode shouldn't differ
    209    // so also should be fine.
    210    fn lookup<'a, S>(
    211        &'a mut self,
    212        device: &Device,
    213        quirks_mode: QuirksMode,
    214        collection: SheetCollectionFlusher<S>,
    215        guard: &SharedRwLockReadGuard,
    216        old_entry: &Entry,
    217        difference: &mut CascadeDataDifference,
    218    ) -> Result<Option<Arc<Entry>>, AllocErr>
    219    where
    220        S: StylesheetInDocument + PartialEq + 'static,
    221    {
    222        use std::collections::hash_map::Entry as HashMapEntry;
    223        debug!("StyleSheetCache::lookup({})", self.len());
    224 
    225        if !collection.dirty() {
    226            return Ok(None);
    227        }
    228 
    229        let mut key = CascadeDataCacheKey::default();
    230        let mut custom_media_map = CustomMediaMap::default();
    231        for sheet in collection.sheets() {
    232            CascadeData::collect_applicable_media_query_results_into(
    233                device,
    234                sheet,
    235                guard,
    236                &mut key.media_query_results,
    237                &mut key.contents,
    238                &mut custom_media_map,
    239            )
    240        }
    241 
    242        let new_entry;
    243        match self.entries.entry(key) {
    244            HashMapEntry::Vacant(e) => {
    245                debug!("> Picking the slow path (not in the cache)");
    246                new_entry = Entry::rebuild(
    247                    device,
    248                    quirks_mode,
    249                    collection,
    250                    guard,
    251                    old_entry,
    252                    difference,
    253                )?;
    254                e.insert(new_entry.clone());
    255            },
    256            HashMapEntry::Occupied(mut e) => {
    257                // Avoid reusing our old entry (this can happen if we get
    258                // invalidated due to CSSOM mutations and our old stylesheet
    259                // contents were already unique, for example).
    260                if !std::ptr::eq(&**e.get(), old_entry) {
    261                    if log_enabled!(log::Level::Debug) {
    262                        debug!("cache hit for:");
    263                        for sheet in collection.sheets() {
    264                            debug!(" > {:?}", sheet);
    265                        }
    266                    }
    267                    // The line below ensures the "committed" bit is updated
    268                    // properly.
    269                    collection.each(|_, _, _| true);
    270                    return Ok(Some(e.get().clone()));
    271                }
    272 
    273                debug!("> Picking the slow path due to same entry as old");
    274                new_entry = Entry::rebuild(
    275                    device,
    276                    quirks_mode,
    277                    collection,
    278                    guard,
    279                    old_entry,
    280                    difference,
    281                )?;
    282                e.insert(new_entry.clone());
    283            },
    284        }
    285 
    286        Ok(Some(new_entry))
    287    }
    288 
    289    /// Returns all the cascade datas that are not being used (that is, that are
    290    /// held alive just by this cache).
    291    ///
    292    /// We return them instead of dropping in place because some of them may
    293    /// keep alive some other documents (like the SVG documents kept alive by
    294    /// URL references), and thus we don't want to drop them while locking the
    295    /// cache to not deadlock.
    296    fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
    297        let mut unused = SmallVec::new();
    298        self.entries.retain(|_key, value| {
    299            // is_unique() returns false for static references, but we never
    300            // have static references to UserAgentCascadeDatas.  If we did, it
    301            // may not make sense to put them in the cache in the first place.
    302            if !value.is_unique() {
    303                return true;
    304            }
    305            unused.push(value.clone());
    306            false
    307        });
    308        unused
    309    }
    310 
    311    fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
    312        mem::take(&mut self.entries)
    313    }
    314 
    315    #[cfg(feature = "gecko")]
    316    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
    317        sizes.mOther += self.entries.shallow_size_of(ops);
    318        for (_key, arc) in self.entries.iter() {
    319            // These are primary Arc references that can be measured
    320            // unconditionally.
    321            sizes.mOther += arc.unconditional_shallow_size_of(ops);
    322            arc.add_size_of(ops, sizes);
    323        }
    324    }
    325 }
    326 
    327 /// Measure heap usage of UA_CASCADE_DATA_CACHE.
    328 #[cfg(feature = "gecko")]
    329 pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
    330    UA_CASCADE_DATA_CACHE
    331        .lock()
    332        .unwrap()
    333        .add_size_of(ops, sizes);
    334 }
    335 
    336 /// A cache of computed user-agent data, to be shared across documents.
    337 static UA_CASCADE_DATA_CACHE: LazyLock<Mutex<UserAgentCascadeDataCache>> =
    338    LazyLock::new(|| Mutex::new(UserAgentCascadeDataCache::new()));
    339 
    340 impl CascadeDataCacheEntry for UserAgentCascadeData {
    341    fn rebuild<S>(
    342        device: &Device,
    343        quirks_mode: QuirksMode,
    344        collection: SheetCollectionFlusher<S>,
    345        guard: &SharedRwLockReadGuard,
    346        old: &Self,
    347        difference: &mut CascadeDataDifference,
    348    ) -> Result<Arc<Self>, AllocErr>
    349    where
    350        S: StylesheetInDocument + PartialEq + 'static,
    351    {
    352        // TODO: Maybe we should support incremental rebuilds, though they seem uncommon and
    353        // rebuild() doesn't deal with precomputed_pseudo_element_decls for now so...
    354        let mut new_data = servo_arc::UniqueArc::new(Self {
    355            cascade_data: CascadeData::new(),
    356            precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
    357        });
    358 
    359        for (index, sheet) in collection.sheets().enumerate() {
    360            let new_data = &mut *new_data;
    361            new_data.cascade_data.add_stylesheet(
    362                device,
    363                quirks_mode,
    364                sheet,
    365                index,
    366                guard,
    367                SheetRebuildKind::Full,
    368                Some(&mut new_data.precomputed_pseudo_element_decls),
    369                None,
    370            )?;
    371        }
    372 
    373        new_data.cascade_data.did_finish_rebuild();
    374        difference.update(
    375            &old.cascade_data.extra_data.position_try_rules,
    376            &new_data.cascade_data.extra_data.position_try_rules,
    377        );
    378 
    379        Ok(new_data.shareable())
    380    }
    381 
    382    #[cfg(feature = "gecko")]
    383    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
    384        self.cascade_data.add_size_of(ops, sizes);
    385        sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
    386    }
    387 }
    388 
    389 type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
    390 
    391 type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
    392 
    393 #[derive(Default)]
    394 struct UserAgentCascadeData {
    395    cascade_data: CascadeData,
    396 
    397    /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
    398    ///
    399    /// These are eagerly computed once, and then used to resolve the new
    400    /// computed values on the fly on layout.
    401    ///
    402    /// These are only filled from UA stylesheets.
    403    precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
    404 }
    405 
    406 /// The empty UA cascade data for un-filled stylists.
    407 static EMPTY_UA_CASCADE_DATA: LazyLock<Arc<UserAgentCascadeData>> = LazyLock::new(|| {
    408    let arc = Arc::new(UserAgentCascadeData::default());
    409    arc.mark_as_intentionally_leaked();
    410    arc
    411 });
    412 
    413 /// All the computed information for all the stylesheets that apply to the
    414 /// document.
    415 #[derive(MallocSizeOf)]
    416 pub struct DocumentCascadeData {
    417    #[ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache or empty"]
    418    user_agent: Arc<UserAgentCascadeData>,
    419    user: CascadeData,
    420    author: CascadeData,
    421    per_origin: PerOrigin<()>,
    422 }
    423 
    424 impl Default for DocumentCascadeData {
    425    fn default() -> Self {
    426        Self {
    427            user_agent: EMPTY_UA_CASCADE_DATA.clone(),
    428            user: Default::default(),
    429            author: Default::default(),
    430            per_origin: Default::default(),
    431        }
    432    }
    433 }
    434 
    435 /// An iterator over the cascade data of a given document.
    436 pub struct DocumentCascadeDataIter<'a> {
    437    iter: PerOriginIter<'a, ()>,
    438    cascade_data: &'a DocumentCascadeData,
    439 }
    440 
    441 impl<'a> Iterator for DocumentCascadeDataIter<'a> {
    442    type Item = (&'a CascadeData, Origin);
    443 
    444    fn next(&mut self) -> Option<Self::Item> {
    445        let (_, origin) = self.iter.next()?;
    446        Some((self.cascade_data.borrow_for_origin(origin), origin))
    447    }
    448 }
    449 
    450 impl DocumentCascadeData {
    451    /// Borrows the cascade data for a given origin.
    452    #[inline]
    453    pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
    454        match origin {
    455            Origin::UserAgent => &self.user_agent.cascade_data,
    456            Origin::Author => &self.author,
    457            Origin::User => &self.user,
    458        }
    459    }
    460 
    461    fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
    462        DocumentCascadeDataIter {
    463            iter: self.per_origin.iter_origins(),
    464            cascade_data: self,
    465        }
    466    }
    467 
    468    fn iter_origins_rev(&self) -> DocumentCascadeDataIter<'_> {
    469        DocumentCascadeDataIter {
    470            iter: self.per_origin.iter_origins_rev(),
    471            cascade_data: self,
    472        }
    473    }
    474 
    475    fn custom_media_for_sheet(
    476        &self,
    477        s: &StylistSheet,
    478        guard: &SharedRwLockReadGuard,
    479    ) -> &CustomMediaMap {
    480        let origin = s.contents(guard).origin;
    481        &self.borrow_for_origin(origin).custom_media
    482    }
    483 
    484    /// Rebuild the cascade data for the given document stylesheets, and
    485    /// optionally with a set of user agent stylesheets.  Returns Err(..)
    486    /// to signify OOM.
    487    fn rebuild<'a, S>(
    488        &mut self,
    489        device: &Device,
    490        quirks_mode: QuirksMode,
    491        mut flusher: DocumentStylesheetFlusher<'a, S>,
    492        guards: &StylesheetGuards,
    493        difference: &mut CascadeDataDifference,
    494    ) -> Result<(), AllocErr>
    495    where
    496        S: StylesheetInDocument + PartialEq + 'static,
    497    {
    498        // First do UA sheets.
    499        {
    500            let origin_flusher = flusher.flush_origin(Origin::UserAgent);
    501            // Dirty check is just a minor optimization (no need to grab the
    502            // lock if nothing has changed).
    503            if origin_flusher.dirty() {
    504                let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
    505                let new_data = ua_cache.lookup(
    506                    device,
    507                    quirks_mode,
    508                    origin_flusher,
    509                    guards.ua_or_user,
    510                    &self.user_agent,
    511                    difference,
    512                )?;
    513                if let Some(new_data) = new_data {
    514                    self.user_agent = new_data;
    515                }
    516                let _unused_entries = ua_cache.take_unused();
    517                // See the comments in take_unused() as for why the following line.
    518                std::mem::drop(ua_cache);
    519            }
    520        }
    521 
    522        // Now do the user sheets.
    523        self.user.rebuild(
    524            device,
    525            quirks_mode,
    526            flusher.flush_origin(Origin::User),
    527            guards.ua_or_user,
    528            difference,
    529        )?;
    530 
    531        // And now the author sheets.
    532        self.author.rebuild(
    533            device,
    534            quirks_mode,
    535            flusher.flush_origin(Origin::Author),
    536            guards.author,
    537            difference,
    538        )?;
    539 
    540        Ok(())
    541    }
    542 
    543    /// Measures heap usage.
    544    #[cfg(feature = "gecko")]
    545    pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
    546        self.user.add_size_of(ops, sizes);
    547        self.author.add_size_of(ops, sizes);
    548    }
    549 }
    550 
    551 /// Whether author styles are enabled.
    552 ///
    553 /// This is used to support Gecko.
    554 #[allow(missing_docs)]
    555 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
    556 pub enum AuthorStylesEnabled {
    557    Yes,
    558    No,
    559 }
    560 
    561 /// A wrapper over a DocumentStylesheetSet that can be `Sync`, since it's only
    562 /// used and exposed via mutable methods in the `Stylist`.
    563 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
    564 #[derive(Deref, DerefMut)]
    565 struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
    566 // Read above to see why this is fine.
    567 unsafe impl Sync for StylistStylesheetSet {}
    568 
    569 impl StylistStylesheetSet {
    570    fn new() -> Self {
    571        StylistStylesheetSet(DocumentStylesheetSet::new())
    572    }
    573 }
    574 
    575 /// This structure holds all the selectors and device characteristics
    576 /// for a given document. The selectors are converted into `Rule`s
    577 /// and sorted into `SelectorMap`s keyed off stylesheet origin and
    578 /// pseudo-element (see `CascadeData`).
    579 ///
    580 /// This structure is effectively created once per pipeline, in the
    581 /// LayoutThread corresponding to that pipeline.
    582 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
    583 pub struct Stylist {
    584    /// Device that the stylist is currently evaluating against.
    585    ///
    586    /// This field deserves a bigger comment due to the different use that Gecko
    587    /// and Servo give to it (that we should eventually unify).
    588    ///
    589    /// With Gecko, the device is never changed. Gecko manually tracks whether
    590    /// the device data should be reconstructed, and "resets" the state of the
    591    /// device.
    592    ///
    593    /// On Servo, on the other hand, the device is a really cheap representation
    594    /// that is recreated each time some constraint changes and calling
    595    /// `set_device`.
    596    device: Device,
    597 
    598    /// The list of stylesheets.
    599    stylesheets: StylistStylesheetSet,
    600 
    601    /// A cache of CascadeDatas for AuthorStylesheetSets (i.e., shadow DOM).
    602    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "XXX: how to handle this?")]
    603    author_data_cache: CascadeDataCache<CascadeData>,
    604 
    605    /// If true, the quirks-mode stylesheet is applied.
    606    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
    607    quirks_mode: QuirksMode,
    608 
    609    /// Selector maps for all of the style sheets in the stylist, after
    610    /// evalutaing media rules against the current device, split out per
    611    /// cascade level.
    612    cascade_data: DocumentCascadeData,
    613 
    614    /// Whether author styles are enabled.
    615    author_styles_enabled: AuthorStylesEnabled,
    616 
    617    /// The rule tree, that stores the results of selector matching.
    618    rule_tree: RuleTree,
    619 
    620    /// The set of registered custom properties from script.
    621    /// <https://drafts.css-houdini.org/css-properties-values-api-1/#dom-window-registeredpropertyset-slot>
    622    script_custom_properties: CustomPropertyScriptRegistry,
    623 
    624    /// Initial values for registered custom properties.
    625    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
    626    initial_values_for_custom_properties: ComputedCustomProperties,
    627 
    628    /// Flags set from computing registered custom property initial values.
    629    initial_values_for_custom_properties_flags: ComputedValueFlags,
    630 
    631    /// The total number of times the stylist has been rebuilt.
    632    num_rebuilds: usize,
    633 }
    634 
    635 /// What cascade levels to include when styling elements.
    636 #[derive(Clone, Copy, PartialEq)]
    637 pub enum RuleInclusion {
    638    /// Include rules for style sheets at all cascade levels.  This is the
    639    /// normal rule inclusion mode.
    640    All,
    641    /// Only include rules from UA and user level sheets.  Used to implement
    642    /// `getDefaultComputedStyle`.
    643    DefaultOnly,
    644 }
    645 
    646 #[cfg(feature = "gecko")]
    647 impl From<StyleRuleInclusion> for RuleInclusion {
    648    fn from(value: StyleRuleInclusion) -> Self {
    649        match value {
    650            StyleRuleInclusion::All => RuleInclusion::All,
    651            StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
    652        }
    653    }
    654 }
    655 
    656 /// `:scope` selector, depending on the use case, can match a shadow host.
    657 /// If used outside of `@scope`, it cannot possibly match the host.
    658 /// Even when inside of `@scope`, it's conditional if the selector will
    659 /// match the shadow host.
    660 #[derive(Clone, Copy, Eq, PartialEq)]
    661 enum ScopeMatchesShadowHost {
    662    NotApplicable,
    663    No,
    664    Yes,
    665 }
    666 
    667 impl Default for ScopeMatchesShadowHost {
    668    fn default() -> Self {
    669        Self::NotApplicable
    670    }
    671 }
    672 
    673 impl ScopeMatchesShadowHost {
    674    fn nest_for_scope(&mut self, matches_shadow_host: bool) {
    675        match *self {
    676            Self::NotApplicable => {
    677                // We're at the outermost `@scope`.
    678                *self = if matches_shadow_host {
    679                    Self::Yes
    680                } else {
    681                    Self::No
    682                };
    683            },
    684            Self::Yes if !matches_shadow_host => {
    685                // Inner `@scope` will not be able to match the shadow host.
    686                *self = Self::No;
    687            },
    688            _ => (),
    689        }
    690    }
    691 }
    692 
    693 /// Nested declarations have effectively two behaviors:
    694 ///  * Inside style rules (where they behave as the containing selector).
    695 ///  * Inside @scope (where they behave as :where(:scope)).
    696 /// It is a bit unfortunate ideally we wouldn't need this, because scope also pushes to the
    697 /// ancestor_selector_lists, but the behavior isn't quite the same as wrapping in `&`, see
    698 /// https://github.com/w3c/csswg-drafts/issues/10431
    699 #[derive(Copy, Clone)]
    700 enum NestedDeclarationsContext {
    701    Style,
    702    Scope,
    703 }
    704 
    705 /// A struct containing state related to scope rules
    706 struct ContainingScopeRuleState {
    707    id: ScopeConditionId,
    708    inner_dependencies: Vec<Dependency>,
    709    matches_shadow_host: ScopeMatchesShadowHost,
    710 }
    711 
    712 impl Default for ContainingScopeRuleState {
    713    fn default() -> Self {
    714        Self {
    715            id: ScopeConditionId::none(),
    716            inner_dependencies: Vec::new(),
    717            matches_shadow_host: Default::default(),
    718        }
    719    }
    720 }
    721 
    722 impl ContainingScopeRuleState {
    723    fn save(&self) -> SavedContainingScopeRuleState {
    724        SavedContainingScopeRuleState {
    725            id: self.id,
    726            matches_shadow_host: self.matches_shadow_host,
    727            inner_dependencies_len: self.inner_dependencies.len(),
    728        }
    729    }
    730 
    731    fn restore(
    732        &mut self,
    733        saved: &SavedContainingScopeRuleState,
    734    ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
    735        debug_assert!(self.inner_dependencies.len() >= saved.inner_dependencies_len);
    736 
    737        if self.id == saved.id {
    738            return None;
    739        }
    740 
    741        let scope_id = self.id;
    742        let inner_deps = self
    743            .inner_dependencies
    744            .drain(saved.inner_dependencies_len..)
    745            .collect();
    746 
    747        self.id = saved.id;
    748        self.matches_shadow_host = saved.matches_shadow_host;
    749 
    750        Some((inner_deps, scope_id))
    751    }
    752 }
    753 
    754 struct SavedContainingScopeRuleState {
    755    id: ScopeConditionId,
    756    matches_shadow_host: ScopeMatchesShadowHost,
    757    inner_dependencies_len: usize,
    758 }
    759 
    760 /// A struct containing state from ancestor rules like @layer / @import /
    761 /// @container / nesting / @scope.
    762 struct ContainingRuleState {
    763    layer_name: LayerName,
    764    layer_id: LayerId,
    765    container_condition_id: ContainerConditionId,
    766    in_starting_style: bool,
    767    containing_scope_rule_state: ContainingScopeRuleState,
    768    ancestor_selector_lists: SmallVec<[SelectorList<SelectorImpl>; 2]>,
    769    nested_declarations_context: NestedDeclarationsContext,
    770 }
    771 
    772 impl Default for ContainingRuleState {
    773    fn default() -> Self {
    774        Self {
    775            layer_name: LayerName::new_empty(),
    776            layer_id: LayerId::root(),
    777            container_condition_id: ContainerConditionId::none(),
    778            in_starting_style: false,
    779            ancestor_selector_lists: Default::default(),
    780            containing_scope_rule_state: Default::default(),
    781            nested_declarations_context: NestedDeclarationsContext::Style,
    782        }
    783    }
    784 }
    785 
    786 struct SavedContainingRuleState {
    787    ancestor_selector_lists_len: usize,
    788    layer_name_len: usize,
    789    layer_id: LayerId,
    790    container_condition_id: ContainerConditionId,
    791    in_starting_style: bool,
    792    saved_containing_scope_rule_state: SavedContainingScopeRuleState,
    793    nested_declarations_context: NestedDeclarationsContext,
    794 }
    795 
    796 impl ContainingRuleState {
    797    fn save(&self) -> SavedContainingRuleState {
    798        SavedContainingRuleState {
    799            ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
    800            layer_name_len: self.layer_name.0.len(),
    801            layer_id: self.layer_id,
    802            container_condition_id: self.container_condition_id,
    803            in_starting_style: self.in_starting_style,
    804            saved_containing_scope_rule_state: self.containing_scope_rule_state.save(),
    805            nested_declarations_context: self.nested_declarations_context,
    806        }
    807    }
    808 
    809    fn restore(
    810        &mut self,
    811        saved: &SavedContainingRuleState,
    812    ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
    813        debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
    814        debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
    815 
    816        self.ancestor_selector_lists
    817            .truncate(saved.ancestor_selector_lists_len);
    818        self.layer_name.0.truncate(saved.layer_name_len);
    819        self.layer_id = saved.layer_id;
    820        self.container_condition_id = saved.container_condition_id;
    821        self.in_starting_style = saved.in_starting_style;
    822        self.nested_declarations_context = saved.nested_declarations_context;
    823 
    824        self.containing_scope_rule_state
    825            .restore(&saved.saved_containing_scope_rule_state)
    826    }
    827 
    828    fn scope_is_effective(&self) -> bool {
    829        self.containing_scope_rule_state.id != ScopeConditionId::none()
    830    }
    831 }
    832 
    833 type ReplacedSelectors = SmallVec<[Selector<SelectorImpl>; 4]>;
    834 
    835 impl Stylist {
    836    /// Construct a new `Stylist`, using given `Device` and `QuirksMode`.
    837    /// If more members are added here, think about whether they should
    838    /// be reset in clear().
    839    #[inline]
    840    pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
    841        Self {
    842            device,
    843            quirks_mode,
    844            stylesheets: StylistStylesheetSet::new(),
    845            author_data_cache: CascadeDataCache::new(),
    846            cascade_data: Default::default(),
    847            author_styles_enabled: AuthorStylesEnabled::Yes,
    848            rule_tree: RuleTree::new(),
    849            script_custom_properties: Default::default(),
    850            initial_values_for_custom_properties: Default::default(),
    851            initial_values_for_custom_properties_flags: Default::default(),
    852            num_rebuilds: 0,
    853        }
    854    }
    855 
    856    /// Returns the document cascade data.
    857    #[inline]
    858    pub fn cascade_data(&self) -> &DocumentCascadeData {
    859        &self.cascade_data
    860    }
    861 
    862    /// Returns whether author styles are enabled or not.
    863    #[inline]
    864    pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
    865        self.author_styles_enabled
    866    }
    867 
    868    /// Iterate through all the cascade datas from the document.
    869    #[inline]
    870    pub fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
    871        self.cascade_data.iter_origins()
    872    }
    873 
    874    /// Does what the name says, to prevent author_data_cache to grow without
    875    /// bound.
    876    pub fn remove_unique_author_data_cache_entries(&mut self) {
    877        self.author_data_cache.take_unused();
    878    }
    879 
    880    /// Returns the custom property registration for this property's name.
    881    /// https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
    882    pub fn get_custom_property_registration(&self, name: &Atom) -> &PropertyRegistrationData {
    883        if let Some(registration) = self.custom_property_script_registry().get(name) {
    884            return &registration.data;
    885        }
    886        for (data, _) in self.iter_origins() {
    887            if let Some(registration) = data.custom_property_registrations.get(name) {
    888                return &registration.data;
    889            }
    890        }
    891        PropertyRegistrationData::unregistered()
    892    }
    893 
    894    /// Returns custom properties with their registered initial values.
    895    pub fn get_custom_property_initial_values(&self) -> &ComputedCustomProperties {
    896        &self.initial_values_for_custom_properties
    897    }
    898 
    899    /// Returns flags set from computing the registered custom property initial values.
    900    pub fn get_custom_property_initial_values_flags(&self) -> ComputedValueFlags {
    901        self.initial_values_for_custom_properties_flags
    902    }
    903 
    904    /// Rebuild custom properties with their registered initial values.
    905    /// https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
    906    pub fn rebuild_initial_values_for_custom_properties(&mut self) {
    907        let mut initial_values = ComputedCustomProperties::default();
    908        let initial_values_flags;
    909        {
    910            let mut seen_names = PrecomputedHashSet::default();
    911            let mut rule_cache_conditions = RuleCacheConditions::default();
    912            let context = computed::Context::new_for_initial_at_property_value(
    913                self,
    914                &mut rule_cache_conditions,
    915            );
    916 
    917            for (k, v) in self.custom_property_script_registry().properties().iter() {
    918                seen_names.insert(k.clone());
    919                let Ok(value) = v.compute_initial_value(&context) else {
    920                    continue;
    921                };
    922                let map = if v.inherits() {
    923                    &mut initial_values.inherited
    924                } else {
    925                    &mut initial_values.non_inherited
    926                };
    927                map.insert(k, value);
    928            }
    929            for (data, _) in self.iter_origins() {
    930                for (k, v) in data.custom_property_registrations.iter() {
    931                    if seen_names.insert(k.clone()) {
    932                        let last_value = &v.last().unwrap().0;
    933                        let Ok(value) = last_value.compute_initial_value(&context) else {
    934                            continue;
    935                        };
    936                        let map = if last_value.inherits() {
    937                            &mut initial_values.inherited
    938                        } else {
    939                            &mut initial_values.non_inherited
    940                        };
    941                        map.insert(k, value);
    942                    }
    943                }
    944            }
    945            initial_values_flags = context.builder.flags();
    946        }
    947        self.initial_values_for_custom_properties_flags = initial_values_flags;
    948        self.initial_values_for_custom_properties = initial_values;
    949    }
    950 
    951    /// Rebuilds (if needed) the CascadeData given a sheet collection.
    952    pub fn rebuild_author_data<S>(
    953        &mut self,
    954        old_data: &CascadeData,
    955        collection: SheetCollectionFlusher<S>,
    956        guard: &SharedRwLockReadGuard,
    957        difference: &mut CascadeDataDifference,
    958    ) -> Result<Option<Arc<CascadeData>>, AllocErr>
    959    where
    960        S: StylesheetInDocument + PartialEq + 'static,
    961    {
    962        self.author_data_cache.lookup(
    963            &self.device,
    964            self.quirks_mode,
    965            collection,
    966            guard,
    967            old_data,
    968            difference,
    969        )
    970    }
    971 
    972    /// Iterate over the extra data in origin order.
    973    #[inline]
    974    pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator<'_> {
    975        ExtraStyleDataIterator(self.cascade_data.iter_origins())
    976    }
    977 
    978    /// Iterate over the extra data in reverse origin order.
    979    #[inline]
    980    pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator<'_> {
    981        ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
    982    }
    983 
    984    /// Returns the number of selectors.
    985    pub fn num_selectors(&self) -> usize {
    986        self.cascade_data
    987            .iter_origins()
    988            .map(|(d, _)| d.num_selectors)
    989            .sum()
    990    }
    991 
    992    /// Returns the number of declarations.
    993    pub fn num_declarations(&self) -> usize {
    994        self.cascade_data
    995            .iter_origins()
    996            .map(|(d, _)| d.num_declarations)
    997            .sum()
    998    }
    999 
   1000    /// Returns the number of times the stylist has been rebuilt.
   1001    pub fn num_rebuilds(&self) -> usize {
   1002        self.num_rebuilds
   1003    }
   1004 
   1005    /// Returns the number of revalidation_selectors.
   1006    pub fn num_revalidation_selectors(&self) -> usize {
   1007        self.cascade_data
   1008            .iter_origins()
   1009            .map(|(data, _)| data.selectors_for_cache_revalidation.len())
   1010            .sum()
   1011    }
   1012 
   1013    /// Returns the number of entries in invalidation maps.
   1014    pub fn num_invalidations(&self) -> usize {
   1015        self.cascade_data
   1016            .iter_origins()
   1017            .map(|(data, _)| {
   1018                data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
   1019            })
   1020            .sum()
   1021    }
   1022 
   1023    /// Returns whether the given DocumentState bit is relied upon by a selector
   1024    /// of some rule.
   1025    pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
   1026        self.cascade_data
   1027            .iter_origins()
   1028            .any(|(d, _)| d.document_state_dependencies.intersects(state))
   1029    }
   1030 
   1031    /// Flush the list of stylesheets if they changed, ensuring the stylist is
   1032    /// up-to-date.
   1033    pub fn flush(&mut self, guards: &StylesheetGuards) -> StylesheetInvalidationSet {
   1034        if !self.stylesheets.has_changed() {
   1035            return Default::default();
   1036        }
   1037 
   1038        self.num_rebuilds += 1;
   1039 
   1040        let (flusher, mut invalidations) = self.stylesheets.flush();
   1041 
   1042        self.cascade_data
   1043            .rebuild(
   1044                &self.device,
   1045                self.quirks_mode,
   1046                flusher,
   1047                guards,
   1048                &mut invalidations.cascade_data_difference,
   1049            )
   1050            .unwrap_or_else(|_| {
   1051                warn!("OOM in Stylist::flush");
   1052            });
   1053 
   1054        self.rebuild_initial_values_for_custom_properties();
   1055        invalidations
   1056    }
   1057 
   1058    /// Marks a given stylesheet origin as dirty, due to, for example, changes
   1059    /// in the declarations that affect a given rule.
   1060    ///
   1061    /// FIXME(emilio): Eventually it'd be nice for this to become more
   1062    /// fine-grained.
   1063    pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
   1064        self.stylesheets.force_dirty(origins)
   1065    }
   1066 
   1067    /// Sets whether author style is enabled or not.
   1068    pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
   1069        self.author_styles_enabled = enabled;
   1070    }
   1071 
   1072    /// Returns whether we've recorded any stylesheet change so far.
   1073    pub fn stylesheets_have_changed(&self) -> bool {
   1074        self.stylesheets.has_changed()
   1075    }
   1076 
   1077    /// Insert a given stylesheet before another stylesheet in the document.
   1078    pub fn insert_stylesheet_before(
   1079        &mut self,
   1080        sheet: StylistSheet,
   1081        before_sheet: StylistSheet,
   1082        guard: &SharedRwLockReadGuard,
   1083    ) {
   1084        let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
   1085        self.stylesheets.insert_stylesheet_before(
   1086            Some(&self.device),
   1087            custom_media,
   1088            sheet,
   1089            before_sheet,
   1090            guard,
   1091        )
   1092    }
   1093 
   1094    /// Appends a new stylesheet to the current set.
   1095    pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
   1096        let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
   1097        self.stylesheets
   1098            .append_stylesheet(Some(&self.device), custom_media, sheet, guard)
   1099    }
   1100 
   1101    /// Remove a given stylesheet to the current set.
   1102    pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
   1103        let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
   1104        self.stylesheets
   1105            .remove_stylesheet(Some(&self.device), custom_media, sheet, guard)
   1106    }
   1107 
   1108    /// Notify of a change of a given rule.
   1109    pub fn rule_changed(
   1110        &mut self,
   1111        sheet: &StylistSheet,
   1112        rule: &CssRule,
   1113        guard: &SharedRwLockReadGuard,
   1114        change_kind: RuleChangeKind,
   1115        ancestors: &[CssRuleRef],
   1116    ) {
   1117        let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
   1118        self.stylesheets.rule_changed(
   1119            Some(&self.device),
   1120            custom_media,
   1121            sheet,
   1122            rule,
   1123            guard,
   1124            change_kind,
   1125            ancestors,
   1126        )
   1127    }
   1128 
   1129    /// Get the total stylesheet count for a given origin.
   1130    #[inline]
   1131    pub fn sheet_count(&self, origin: Origin) -> usize {
   1132        self.stylesheets.sheet_count(origin)
   1133    }
   1134 
   1135    /// Get the index-th stylesheet for a given origin.
   1136    #[inline]
   1137    pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
   1138        self.stylesheets.get(origin, index)
   1139    }
   1140 
   1141    /// Returns whether for any of the applicable style rule data a given
   1142    /// condition is true.
   1143    pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
   1144    where
   1145        E: TElement,
   1146        F: FnMut(&CascadeData) -> bool,
   1147    {
   1148        if f(&self.cascade_data.user_agent.cascade_data) {
   1149            return true;
   1150        }
   1151 
   1152        let mut maybe = false;
   1153 
   1154        let doc_author_rules_apply =
   1155            element.each_applicable_non_document_style_rule_data(|data, _| {
   1156                maybe = maybe || f(&*data);
   1157            });
   1158 
   1159        if maybe || f(&self.cascade_data.user) {
   1160            return true;
   1161        }
   1162 
   1163        doc_author_rules_apply && f(&self.cascade_data.author)
   1164    }
   1165 
   1166    /// Execute callback for all applicable style rule data.
   1167    pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
   1168    where
   1169        E: TElement + 'a,
   1170        F: FnMut(&'a CascadeData, Option<E>),
   1171    {
   1172        f(&self.cascade_data.user_agent.cascade_data, None);
   1173        element.each_applicable_non_document_style_rule_data(|data, scope| {
   1174            f(data, Some(scope));
   1175        });
   1176        f(&self.cascade_data.user, None);
   1177        f(&self.cascade_data.author, None);
   1178    }
   1179 
   1180    /// Computes the style for a given "precomputed" pseudo-element, taking the
   1181    /// universal rules and applying them.
   1182    pub fn precomputed_values_for_pseudo<E>(
   1183        &self,
   1184        guards: &StylesheetGuards,
   1185        pseudo: &PseudoElement,
   1186        parent: Option<&ComputedValues>,
   1187    ) -> Arc<ComputedValues>
   1188    where
   1189        E: TElement,
   1190    {
   1191        debug_assert!(pseudo.is_precomputed());
   1192 
   1193        let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
   1194 
   1195        self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
   1196    }
   1197 
   1198    /// Computes the style for a given "precomputed" pseudo-element with
   1199    /// given rule node.
   1200    ///
   1201    /// TODO(emilio): The type parameter could go away with a void type
   1202    /// implementing TElement.
   1203    pub fn precomputed_values_for_pseudo_with_rule_node<E>(
   1204        &self,
   1205        guards: &StylesheetGuards,
   1206        pseudo: &PseudoElement,
   1207        parent: Option<&ComputedValues>,
   1208        rules: StrongRuleNode,
   1209    ) -> Arc<ComputedValues>
   1210    where
   1211        E: TElement,
   1212    {
   1213        self.compute_pseudo_element_style_with_inputs::<E>(
   1214            CascadeInputs {
   1215                rules: Some(rules),
   1216                visited_rules: None,
   1217                flags: Default::default(),
   1218            },
   1219            pseudo,
   1220            guards,
   1221            parent,
   1222            /* element */ None,
   1223        )
   1224    }
   1225 
   1226    /// Returns the rule node for a given precomputed pseudo-element.
   1227    ///
   1228    /// If we want to include extra declarations to this precomputed
   1229    /// pseudo-element, we can provide a vector of ApplicableDeclarationBlocks
   1230    /// to extra_declarations. This is useful for @page rules.
   1231    pub fn rule_node_for_precomputed_pseudo(
   1232        &self,
   1233        guards: &StylesheetGuards,
   1234        pseudo: &PseudoElement,
   1235        mut extra_declarations: Vec<ApplicableDeclarationBlock>,
   1236    ) -> StrongRuleNode {
   1237        let mut declarations_with_extra;
   1238        let declarations = match self
   1239            .cascade_data
   1240            .user_agent
   1241            .precomputed_pseudo_element_decls
   1242            .get(pseudo)
   1243        {
   1244            Some(declarations) => {
   1245                if !extra_declarations.is_empty() {
   1246                    declarations_with_extra = declarations.clone();
   1247                    declarations_with_extra.append(&mut extra_declarations);
   1248                    &*declarations_with_extra
   1249                } else {
   1250                    &**declarations
   1251                }
   1252            },
   1253            None => &[],
   1254        };
   1255 
   1256        self.rule_tree.insert_ordered_rules_with_important(
   1257            declarations.into_iter().map(|a| a.clone().for_rule_tree()),
   1258            guards,
   1259        )
   1260    }
   1261 
   1262    /// Returns the style for an anonymous box of the given type.
   1263    ///
   1264    /// TODO(emilio): The type parameter could go away with a void type
   1265    /// implementing TElement.
   1266    #[cfg(feature = "servo")]
   1267    pub fn style_for_anonymous<E>(
   1268        &self,
   1269        guards: &StylesheetGuards,
   1270        pseudo: &PseudoElement,
   1271        parent_style: &ComputedValues,
   1272    ) -> Arc<ComputedValues>
   1273    where
   1274        E: TElement,
   1275    {
   1276        self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
   1277    }
   1278 
   1279    /// Computes a pseudo-element style lazily during layout.
   1280    ///
   1281    /// This can only be done for a certain set of pseudo-elements, like
   1282    /// :selection.
   1283    ///
   1284    /// Check the documentation on lazy pseudo-elements in
   1285    /// docs/components/style.md
   1286    pub fn lazily_compute_pseudo_element_style<E>(
   1287        &self,
   1288        guards: &StylesheetGuards,
   1289        element: E,
   1290        pseudo: &PseudoElement,
   1291        rule_inclusion: RuleInclusion,
   1292        originating_element_style: &ComputedValues,
   1293        is_probe: bool,
   1294        matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
   1295    ) -> Option<Arc<ComputedValues>>
   1296    where
   1297        E: TElement,
   1298    {
   1299        let cascade_inputs = self.lazy_pseudo_rules(
   1300            guards,
   1301            element,
   1302            originating_element_style,
   1303            pseudo,
   1304            is_probe,
   1305            rule_inclusion,
   1306            matching_fn,
   1307        )?;
   1308 
   1309        Some(self.compute_pseudo_element_style_with_inputs(
   1310            cascade_inputs,
   1311            pseudo,
   1312            guards,
   1313            Some(originating_element_style),
   1314            Some(element),
   1315        ))
   1316    }
   1317 
   1318    /// Computes a pseudo-element style lazily using the given CascadeInputs.
   1319    /// This can be used for truly lazy pseudo-elements or to avoid redoing
   1320    /// selector matching for eager pseudo-elements when we need to recompute
   1321    /// their style with a new parent style.
   1322    pub fn compute_pseudo_element_style_with_inputs<E>(
   1323        &self,
   1324        inputs: CascadeInputs,
   1325        pseudo: &PseudoElement,
   1326        guards: &StylesheetGuards,
   1327        parent_style: Option<&ComputedValues>,
   1328        element: Option<E>,
   1329    ) -> Arc<ComputedValues>
   1330    where
   1331        E: TElement,
   1332    {
   1333        // FIXME(emilio): The lack of layout_parent_style here could be
   1334        // worrying, but we're probably dropping the display fixup for
   1335        // pseudos other than before and after, so it's probably ok.
   1336        //
   1337        // (Though the flags don't indicate so!)
   1338        //
   1339        // It'd be fine to assert that this isn't called with a parent style
   1340        // where display contents is in effect, but in practice this is hard to
   1341        // do for stuff like :-moz-fieldset-content with a
   1342        // <fieldset style="display: contents">. That is, the computed value of
   1343        // display for the fieldset is "contents", even though it's not the used
   1344        // value, so we don't need to adjust in a different way anyway.
   1345        self.cascade_style_and_visited(
   1346            element,
   1347            Some(pseudo),
   1348            inputs,
   1349            guards,
   1350            parent_style,
   1351            parent_style,
   1352            FirstLineReparenting::No,
   1353            &PositionTryFallbacksTryTactic::default(),
   1354            /* rule_cache = */ None,
   1355            &mut RuleCacheConditions::default(),
   1356        )
   1357    }
   1358 
   1359    /// Computes a fallback style lazily given the current and parent styles, and name.
   1360    pub fn resolve_position_try<E>(
   1361        &self,
   1362        style: &ComputedValues,
   1363        guards: &StylesheetGuards,
   1364        element: E,
   1365        fallback_item: &PositionTryFallbacksItem,
   1366    ) -> Option<Arc<ComputedValues>>
   1367    where
   1368        E: TElement,
   1369    {
   1370        let name_and_try_tactic = match *fallback_item {
   1371            PositionTryFallbacksItem::PositionArea(area) => {
   1372                // We don't bother passing the parent_style argument here since
   1373                // we probably don't need it. If we do, we could wrap this up in
   1374                // a style_resolver::with_default_parent_styles call, as below.
   1375                let mut builder =
   1376                    StyleBuilder::for_derived_style(&self.device, Some(self), style, None);
   1377                builder.mutate_position().set_position_area(area);
   1378                return Some(builder.build());
   1379            },
   1380            PositionTryFallbacksItem::IdentAndOrTactic(ref name_and_try_tactic) => {
   1381                name_and_try_tactic
   1382            },
   1383        };
   1384 
   1385        let fallback_rule = if !name_and_try_tactic.ident.is_empty() {
   1386            Some(self.lookup_position_try(&name_and_try_tactic.ident.0, element)?)
   1387        } else {
   1388            None
   1389        };
   1390        let fallback_block = fallback_rule
   1391            .as_ref()
   1392            .map(|r| &r.read_with(guards.author).block);
   1393        let pseudo = style
   1394            .pseudo()
   1395            .or_else(|| element.implemented_pseudo_element());
   1396        let inputs = {
   1397            let mut inputs = CascadeInputs::new_from_style(style);
   1398            // @position-try doesn't care about any :visited-dependent property.
   1399            inputs.visited_rules = None;
   1400            let rules = inputs.rules.as_ref().unwrap_or(self.rule_tree.root());
   1401            let mut important_rules_changed = false;
   1402            if let Some(fallback_block) = fallback_block {
   1403                let new_rules = self.rule_tree.update_rule_at_level(
   1404                    CascadeLevel::PositionFallback,
   1405                    LayerOrder::root(),
   1406                    Some(fallback_block.borrow_arc()),
   1407                    rules,
   1408                    guards,
   1409                    &mut important_rules_changed,
   1410                );
   1411                if new_rules.is_some() {
   1412                    inputs.rules = new_rules;
   1413                } else {
   1414                    // This will return an identical style to `style`. We could consider optimizing
   1415                    // this a bit more but for now just perform the cascade, this can only happen with
   1416                    // the same position-try name repeated multiple times anyways.
   1417                }
   1418            }
   1419            inputs
   1420        };
   1421        crate::style_resolver::with_default_parent_styles(
   1422            element,
   1423            |parent_style, layout_parent_style| {
   1424                Some(self.cascade_style_and_visited(
   1425                    Some(element),
   1426                    pseudo.as_ref(),
   1427                    inputs,
   1428                    guards,
   1429                    parent_style,
   1430                    layout_parent_style,
   1431                    FirstLineReparenting::No,
   1432                    &name_and_try_tactic.try_tactic,
   1433                    /* rule_cache = */ None,
   1434                    &mut RuleCacheConditions::default(),
   1435                ))
   1436            },
   1437        )
   1438    }
   1439 
   1440    /// Computes a style using the given CascadeInputs.  This can be used to
   1441    /// compute a style any time we know what rules apply and just need to use
   1442    /// the given parent styles.
   1443    ///
   1444    /// parent_style is the style to inherit from for properties affected by
   1445    /// first-line ancestors.
   1446    ///
   1447    /// parent_style_ignoring_first_line is the style to inherit from for
   1448    /// properties not affected by first-line ancestors.
   1449    ///
   1450    /// layout_parent_style is the style used for some property fixups.  It's
   1451    /// the style of the nearest ancestor with a layout box.
   1452    pub fn cascade_style_and_visited<E>(
   1453        &self,
   1454        element: Option<E>,
   1455        pseudo: Option<&PseudoElement>,
   1456        inputs: CascadeInputs,
   1457        guards: &StylesheetGuards,
   1458        parent_style: Option<&ComputedValues>,
   1459        layout_parent_style: Option<&ComputedValues>,
   1460        first_line_reparenting: FirstLineReparenting,
   1461        try_tactic: &PositionTryFallbacksTryTactic,
   1462        rule_cache: Option<&RuleCache>,
   1463        rule_cache_conditions: &mut RuleCacheConditions,
   1464    ) -> Arc<ComputedValues>
   1465    where
   1466        E: TElement,
   1467    {
   1468        debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
   1469 
   1470        // We need to compute visited values if we have visited rules or if our
   1471        // parent has visited values.
   1472        let visited_rules = match inputs.visited_rules.as_ref() {
   1473            Some(rules) => Some(rules),
   1474            None => {
   1475                if parent_style.and_then(|s| s.visited_style()).is_some() {
   1476                    Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
   1477                } else {
   1478                    None
   1479                }
   1480            },
   1481        };
   1482 
   1483        let mut implemented_pseudo = None;
   1484        // Read the comment on `precomputed_values_for_pseudo` to see why it's
   1485        // difficult to assert that display: contents nodes never arrive here
   1486        // (tl;dr: It doesn't apply for replaced elements and such, but the
   1487        // computed value is still "contents").
   1488        //
   1489        // FIXME(emilio): We should assert that it holds if pseudo.is_none()!
   1490        properties::cascade::<E>(
   1491            &self,
   1492            pseudo.or_else(|| {
   1493                implemented_pseudo = element.unwrap().implemented_pseudo_element();
   1494                implemented_pseudo.as_ref()
   1495            }),
   1496            inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
   1497            guards,
   1498            parent_style,
   1499            layout_parent_style,
   1500            first_line_reparenting,
   1501            try_tactic,
   1502            visited_rules,
   1503            inputs.flags,
   1504            rule_cache,
   1505            rule_cache_conditions,
   1506            element,
   1507        )
   1508    }
   1509 
   1510    /// Computes the cascade inputs for a lazily-cascaded pseudo-element.
   1511    ///
   1512    /// See the documentation on lazy pseudo-elements in
   1513    /// docs/components/style.md
   1514    fn lazy_pseudo_rules<E>(
   1515        &self,
   1516        guards: &StylesheetGuards,
   1517        element: E,
   1518        originating_element_style: &ComputedValues,
   1519        pseudo: &PseudoElement,
   1520        is_probe: bool,
   1521        rule_inclusion: RuleInclusion,
   1522        matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
   1523    ) -> Option<CascadeInputs>
   1524    where
   1525        E: TElement,
   1526    {
   1527        debug_assert!(pseudo.is_lazy());
   1528 
   1529        let mut selector_caches = SelectorCaches::default();
   1530        // No need to bother setting the selector flags when we're computing
   1531        // default styles.
   1532        let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
   1533            NeedsSelectorFlags::No
   1534        } else {
   1535            NeedsSelectorFlags::Yes
   1536        };
   1537 
   1538        let mut declarations = ApplicableDeclarationList::new();
   1539        let mut matching_context = MatchingContext::<'_, E::Impl>::new(
   1540            MatchingMode::ForStatelessPseudoElement,
   1541            None,
   1542            &mut selector_caches,
   1543            self.quirks_mode,
   1544            needs_selector_flags,
   1545            MatchingForInvalidation::No,
   1546        );
   1547 
   1548        matching_context.pseudo_element_matching_fn = matching_fn;
   1549        matching_context.extra_data.originating_element_style = Some(originating_element_style);
   1550 
   1551        self.push_applicable_declarations(
   1552            element,
   1553            Some(&pseudo),
   1554            None,
   1555            None,
   1556            /* animation_declarations = */ Default::default(),
   1557            rule_inclusion,
   1558            &mut declarations,
   1559            &mut matching_context,
   1560        );
   1561 
   1562        if declarations.is_empty() && is_probe {
   1563            return None;
   1564        }
   1565 
   1566        let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
   1567 
   1568        let mut visited_rules = None;
   1569        if originating_element_style.visited_style().is_some() {
   1570            let mut declarations = ApplicableDeclarationList::new();
   1571            let mut selector_caches = SelectorCaches::default();
   1572 
   1573            let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
   1574                MatchingMode::ForStatelessPseudoElement,
   1575                None,
   1576                &mut selector_caches,
   1577                VisitedHandlingMode::RelevantLinkVisited,
   1578                selectors::matching::IncludeStartingStyle::No,
   1579                self.quirks_mode,
   1580                needs_selector_flags,
   1581                MatchingForInvalidation::No,
   1582            );
   1583            matching_context.pseudo_element_matching_fn = matching_fn;
   1584            matching_context.extra_data.originating_element_style = Some(originating_element_style);
   1585 
   1586            self.push_applicable_declarations(
   1587                element,
   1588                Some(&pseudo),
   1589                None,
   1590                None,
   1591                /* animation_declarations = */ Default::default(),
   1592                rule_inclusion,
   1593                &mut declarations,
   1594                &mut matching_context,
   1595            );
   1596            if !declarations.is_empty() {
   1597                let rule_node = self.rule_tree.insert_ordered_rules_with_important(
   1598                    declarations.drain(..).map(|a| a.for_rule_tree()),
   1599                    guards,
   1600                );
   1601                if rule_node != *self.rule_tree.root() {
   1602                    visited_rules = Some(rule_node);
   1603                }
   1604            }
   1605        }
   1606 
   1607        Some(CascadeInputs {
   1608            rules: Some(rules),
   1609            visited_rules,
   1610            flags: matching_context.extra_data.cascade_input_flags,
   1611        })
   1612    }
   1613 
   1614    /// Set a given device, which may change the styles that apply to the
   1615    /// document.
   1616    ///
   1617    /// Returns the sheet origins that were actually affected.
   1618    ///
   1619    /// This means that we may need to rebuild style data even if the
   1620    /// stylesheets haven't changed.
   1621    ///
   1622    /// Also, the device that arrives here may need to take the viewport rules
   1623    /// into account.
   1624    pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
   1625        self.device = device;
   1626        self.media_features_change_changed_style(guards, &self.device)
   1627    }
   1628 
   1629    /// Returns whether, given a media feature change, any previously-applicable
   1630    /// style has become non-applicable, or vice-versa for each origin, using
   1631    /// `device`.
   1632    pub fn media_features_change_changed_style(
   1633        &self,
   1634        guards: &StylesheetGuards,
   1635        device: &Device,
   1636    ) -> OriginSet {
   1637        debug!("Stylist::media_features_change_changed_style {:?}", device);
   1638 
   1639        let mut origins = OriginSet::empty();
   1640        let stylesheets = self.stylesheets.iter();
   1641 
   1642        for (stylesheet, origin) in stylesheets {
   1643            if origins.contains(origin.into()) {
   1644                continue;
   1645            }
   1646 
   1647            let guard = guards.for_origin(origin);
   1648            let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
   1649 
   1650            let affected_changed = !origin_cascade_data.media_feature_affected_matches(
   1651                stylesheet,
   1652                guard,
   1653                device,
   1654                self.quirks_mode,
   1655            );
   1656 
   1657            if affected_changed {
   1658                origins |= origin;
   1659            }
   1660        }
   1661 
   1662        origins
   1663    }
   1664 
   1665    /// Returns the Quirks Mode of the document.
   1666    pub fn quirks_mode(&self) -> QuirksMode {
   1667        self.quirks_mode
   1668    }
   1669 
   1670    /// Sets the quirks mode of the document.
   1671    pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
   1672        if self.quirks_mode == quirks_mode {
   1673            return;
   1674        }
   1675        self.quirks_mode = quirks_mode;
   1676        self.force_stylesheet_origins_dirty(OriginSet::all());
   1677    }
   1678 
   1679    /// Returns the applicable CSS declarations for the given element.
   1680    pub fn push_applicable_declarations<E>(
   1681        &self,
   1682        element: E,
   1683        pseudo_element: Option<&PseudoElement>,
   1684        style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
   1685        smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
   1686        animation_declarations: AnimationDeclarations,
   1687        rule_inclusion: RuleInclusion,
   1688        applicable_declarations: &mut ApplicableDeclarationList,
   1689        context: &mut MatchingContext<E::Impl>,
   1690    ) where
   1691        E: TElement,
   1692    {
   1693        let mut cur = element;
   1694        let mut pseudos = SmallVec::new();
   1695        if let Some(pseudo) = pseudo_element {
   1696            pseudos.push(pseudo.clone());
   1697        }
   1698        while let Some(p) = cur.implemented_pseudo_element() {
   1699            pseudos.push(p);
   1700            let Some(parent_pseudo) = cur.pseudo_element_originating_element() else {
   1701                break;
   1702            };
   1703            cur = parent_pseudo;
   1704        }
   1705        RuleCollector::new(
   1706            self,
   1707            element,
   1708            pseudos,
   1709            style_attribute,
   1710            smil_override,
   1711            animation_declarations,
   1712            rule_inclusion,
   1713            applicable_declarations,
   1714            context,
   1715        )
   1716        .collect_all();
   1717    }
   1718 
   1719    /// Given an id, returns whether there might be any rules for that id in any
   1720    /// of our rule maps.
   1721    #[inline]
   1722    pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
   1723    where
   1724        E: TElement,
   1725    {
   1726        // If id needs to be compared case-insensitively, the logic below
   1727        // wouldn't work. Just conservatively assume it may have such rules.
   1728        match self.quirks_mode().classes_and_ids_case_sensitivity() {
   1729            CaseSensitivity::AsciiCaseInsensitive => return true,
   1730            CaseSensitivity::CaseSensitive => {},
   1731        }
   1732 
   1733        self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
   1734    }
   1735 
   1736    /// Looks up a CascadeData-dependent rule for a given element.
   1737    ///
   1738    /// NOTE(emilio): This is a best-effort thing, the right fix is a bit TBD because it involves
   1739    /// "recording" which tree the name came from, see [1][2].
   1740    ///
   1741    /// [1]: https://github.com/w3c/csswg-drafts/issues/1995
   1742    /// [2]: https://bugzil.la/1458189
   1743    #[inline]
   1744    fn lookup_element_dependent_at_rule<'a, T, F, E>(
   1745        &'a self,
   1746        element: E,
   1747        find_in: F,
   1748    ) -> Option<&'a T>
   1749    where
   1750        E: TElement + 'a,
   1751        F: Fn(&'a CascadeData) -> Option<&'a T>,
   1752    {
   1753        macro_rules! try_find_in {
   1754            ($data:expr) => {
   1755                if let Some(thing) = find_in(&$data) {
   1756                    return Some(thing);
   1757                }
   1758            };
   1759        }
   1760 
   1761        let mut result = None;
   1762        let doc_rules_apply =
   1763            element.each_applicable_non_document_style_rule_data(|data, _host| {
   1764                if result.is_none() {
   1765                    result = find_in(data);
   1766                }
   1767            });
   1768 
   1769        if result.is_some() {
   1770            return result;
   1771        }
   1772 
   1773        if doc_rules_apply {
   1774            try_find_in!(self.cascade_data.author);
   1775        }
   1776        try_find_in!(self.cascade_data.user);
   1777        try_find_in!(self.cascade_data.user_agent.cascade_data);
   1778 
   1779        None
   1780    }
   1781 
   1782    /// Returns the registered `@keyframes` animation for the specified name.
   1783    #[inline]
   1784    pub fn lookup_keyframes<'a, E>(
   1785        &'a self,
   1786        name: &Atom,
   1787        element: E,
   1788    ) -> Option<&'a KeyframesAnimation>
   1789    where
   1790        E: TElement + 'a,
   1791    {
   1792        self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
   1793    }
   1794 
   1795    /// Returns the registered `@position-try-rule` animation for the specified name.
   1796    #[inline]
   1797    #[cfg(feature = "gecko")]
   1798    fn lookup_position_try<'a, E>(
   1799        &'a self,
   1800        name: &Atom,
   1801        element: E,
   1802    ) -> Option<&'a Arc<Locked<PositionTryRule>>>
   1803    where
   1804        E: TElement + 'a,
   1805    {
   1806        self.lookup_element_dependent_at_rule(element, |data| {
   1807            data.extra_data.position_try_rules.get(name)
   1808        })
   1809    }
   1810 
   1811    /// Computes the match results of a given element against the set of
   1812    /// revalidation selectors.
   1813    pub fn match_revalidation_selectors<E>(
   1814        &self,
   1815        element: E,
   1816        bloom: Option<&BloomFilter>,
   1817        selector_caches: &mut SelectorCaches,
   1818        needs_selector_flags: NeedsSelectorFlags,
   1819    ) -> RevalidationResult
   1820    where
   1821        E: TElement,
   1822    {
   1823        // NB: `MatchingMode` doesn't really matter, given we don't share style
   1824        // between pseudos.
   1825        let mut matching_context = MatchingContext::new(
   1826            MatchingMode::Normal,
   1827            bloom,
   1828            selector_caches,
   1829            self.quirks_mode,
   1830            needs_selector_flags,
   1831            MatchingForInvalidation::No,
   1832        );
   1833 
   1834        // Note that, by the time we're revalidating, we're guaranteed that the
   1835        // candidate and the entry have the same id, classes, and local name.
   1836        // This means we're guaranteed to get the same rulehash buckets for all
   1837        // the lookups, which means that the bitvecs are comparable. We verify
   1838        // this in the caller by asserting that the bitvecs are same-length.
   1839        let mut result = RevalidationResult::default();
   1840        let mut relevant_attributes = &mut result.relevant_attributes;
   1841        let selectors_matched = &mut result.selectors_matched;
   1842 
   1843        let matches_document_rules =
   1844            element.each_applicable_non_document_style_rule_data(|data, host| {
   1845                matching_context.with_shadow_host(Some(host), |matching_context| {
   1846                    data.selectors_for_cache_revalidation.lookup(
   1847                        element,
   1848                        self.quirks_mode,
   1849                        Some(&mut relevant_attributes),
   1850                        |selector_and_hashes| {
   1851                            selectors_matched.push(matches_selector(
   1852                                &selector_and_hashes.selector,
   1853                                selector_and_hashes.selector_offset,
   1854                                Some(&selector_and_hashes.hashes),
   1855                                &element,
   1856                                matching_context,
   1857                            ));
   1858                            true
   1859                        },
   1860                    );
   1861                })
   1862            });
   1863 
   1864        for (data, origin) in self.cascade_data.iter_origins() {
   1865            if origin == Origin::Author && !matches_document_rules {
   1866                continue;
   1867            }
   1868 
   1869            data.selectors_for_cache_revalidation.lookup(
   1870                element,
   1871                self.quirks_mode,
   1872                Some(&mut relevant_attributes),
   1873                |selector_and_hashes| {
   1874                    selectors_matched.push(matches_selector(
   1875                        &selector_and_hashes.selector,
   1876                        selector_and_hashes.selector_offset,
   1877                        Some(&selector_and_hashes.hashes),
   1878                        &element,
   1879                        &mut matching_context,
   1880                    ));
   1881                    true
   1882                },
   1883            );
   1884        }
   1885 
   1886        result
   1887    }
   1888 
   1889    /// Computes currently active scopes for the given element for revalidation purposes.
   1890    pub fn revalidate_scopes<E: TElement>(
   1891        &self,
   1892        element: &E,
   1893        selector_caches: &mut SelectorCaches,
   1894        needs_selector_flags: NeedsSelectorFlags,
   1895    ) -> ScopeRevalidationResult {
   1896        let mut matching_context = MatchingContext::new(
   1897            MatchingMode::Normal,
   1898            None,
   1899            selector_caches,
   1900            self.quirks_mode,
   1901            needs_selector_flags,
   1902            MatchingForInvalidation::No,
   1903        );
   1904 
   1905        let mut result = ScopeRevalidationResult::default();
   1906        let matches_document_rules =
   1907            element.each_applicable_non_document_style_rule_data(|data, host| {
   1908                matching_context.with_shadow_host(Some(host), |matching_context| {
   1909                    data.revalidate_scopes(element, matching_context, &mut result);
   1910                })
   1911            });
   1912 
   1913        for (data, origin) in self.cascade_data.iter_origins() {
   1914            if origin == Origin::Author && !matches_document_rules {
   1915                continue;
   1916            }
   1917 
   1918            data.revalidate_scopes(element, &mut matching_context, &mut result);
   1919        }
   1920 
   1921        result
   1922    }
   1923 
   1924    /// Computes styles for a given declaration with parent_style.
   1925    ///
   1926    /// FIXME(emilio): the lack of pseudo / cascade flags look quite dubious,
   1927    /// hopefully this is only used for some canvas font stuff.
   1928    ///
   1929    /// TODO(emilio): The type parameter can go away when
   1930    /// https://github.com/rust-lang/rust/issues/35121 is fixed.
   1931    pub fn compute_for_declarations<E>(
   1932        &self,
   1933        guards: &StylesheetGuards,
   1934        parent_style: &ComputedValues,
   1935        declarations: Arc<Locked<PropertyDeclarationBlock>>,
   1936    ) -> Arc<ComputedValues>
   1937    where
   1938        E: TElement,
   1939    {
   1940        let block = declarations.read_with(guards.author);
   1941 
   1942        // We don't bother inserting these declarations in the rule tree, since
   1943        // it'd be quite useless and slow.
   1944        //
   1945        // TODO(emilio): Now that we fixed bug 1493420, we should consider
   1946        // reversing this as it shouldn't be slow anymore, and should avoid
   1947        // generating two instantiations of apply_declarations.
   1948        properties::apply_declarations::<E, _>(
   1949            &self,
   1950            /* pseudo = */ None,
   1951            self.rule_tree.root(),
   1952            guards,
   1953            block.declaration_importance_iter().map(|(declaration, _)| {
   1954                (
   1955                    declaration,
   1956                    CascadePriority::new(
   1957                        CascadeLevel::same_tree_author_normal(),
   1958                        LayerOrder::root(),
   1959                    ),
   1960                )
   1961            }),
   1962            Some(parent_style),
   1963            Some(parent_style),
   1964            FirstLineReparenting::No,
   1965            &PositionTryFallbacksTryTactic::default(),
   1966            CascadeMode::Unvisited {
   1967                visited_rules: None,
   1968            },
   1969            Default::default(),
   1970            /* rule_cache = */ None,
   1971            &mut Default::default(),
   1972            /* element = */ None,
   1973        )
   1974    }
   1975 
   1976    /// Accessor for a shared reference to the device.
   1977    #[inline]
   1978    pub fn device(&self) -> &Device {
   1979        &self.device
   1980    }
   1981 
   1982    /// Accessor for a mutable reference to the device.
   1983    #[inline]
   1984    pub fn device_mut(&mut self) -> &mut Device {
   1985        &mut self.device
   1986    }
   1987 
   1988    /// Accessor for a shared reference to the rule tree.
   1989    #[inline]
   1990    pub fn rule_tree(&self) -> &RuleTree {
   1991        &self.rule_tree
   1992    }
   1993 
   1994    /// Returns the script-registered custom property registry.
   1995    #[inline]
   1996    pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
   1997        &self.script_custom_properties
   1998    }
   1999 
   2000    /// Returns the script-registered custom property registry, as a mutable ref.
   2001    #[inline]
   2002    pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
   2003        &mut self.script_custom_properties
   2004    }
   2005 
   2006    /// Measures heap usage.
   2007    #[cfg(feature = "gecko")]
   2008    pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
   2009        self.cascade_data.add_size_of(ops, sizes);
   2010        self.author_data_cache.add_size_of(ops, sizes);
   2011        sizes.mRuleTree += self.rule_tree.size_of(ops);
   2012 
   2013        // We may measure other fields in the future if DMD says it's worth it.
   2014    }
   2015 
   2016    /// Shutdown the static data that this module stores.
   2017    pub fn shutdown() {
   2018        let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
   2019    }
   2020 }
   2021 
   2022 /// A vector that is sorted in layer order.
   2023 #[derive(Clone, Debug, Deref, MallocSizeOf)]
   2024 pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
   2025 impl<T> Default for LayerOrderedVec<T> {
   2026    fn default() -> Self {
   2027        Self(Default::default())
   2028    }
   2029 }
   2030 
   2031 /// A map that is sorted in layer order.
   2032 #[derive(Clone, Debug, Deref, MallocSizeOf)]
   2033 pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
   2034 impl<T> Default for LayerOrderedMap<T> {
   2035    fn default() -> Self {
   2036        Self(Default::default())
   2037    }
   2038 }
   2039 
   2040 #[cfg(feature = "gecko")]
   2041 impl<T: 'static> LayerOrderedVec<T> {
   2042    fn clear(&mut self) {
   2043        self.0.clear();
   2044    }
   2045    fn push(&mut self, v: T, id: LayerId) {
   2046        self.0.push((v, id));
   2047    }
   2048    fn sort(&mut self, layers: &[CascadeLayer]) {
   2049        self.0
   2050            .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
   2051    }
   2052 }
   2053 
   2054 impl<T: 'static> LayerOrderedMap<T> {
   2055    fn shrink_if_needed(&mut self) {
   2056        self.0.shrink_if_needed();
   2057    }
   2058    fn clear(&mut self) {
   2059        self.0.clear();
   2060    }
   2061    fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
   2062        self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
   2063    }
   2064    fn try_insert_with(
   2065        &mut self,
   2066        name: Atom,
   2067        v: T,
   2068        id: LayerId,
   2069        cmp: impl Fn(&T, &T) -> Ordering,
   2070    ) -> Result<(), AllocErr> {
   2071        self.0.try_reserve(1)?;
   2072        let vec = self.0.entry(name).or_default();
   2073        if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
   2074            if *last_id == id {
   2075                if cmp(&val, &v) != Ordering::Greater {
   2076                    *val = v;
   2077                }
   2078                return Ok(());
   2079            }
   2080        }
   2081        vec.push((v, id));
   2082        Ok(())
   2083    }
   2084    fn sort(&mut self, layers: &[CascadeLayer]) {
   2085        self.sort_with(layers, |_, _| Ordering::Equal)
   2086    }
   2087    fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
   2088        for (_, v) in self.0.iter_mut() {
   2089            v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
   2090                let order1 = layers[id1.0 as usize].order;
   2091                let order2 = layers[id2.0 as usize].order;
   2092                order1.cmp(&order2).then_with(|| cmp(v1, v2))
   2093            })
   2094        }
   2095    }
   2096    /// Get an entry on the LayerOrderedMap by name.
   2097    pub fn get(&self, name: &Atom) -> Option<&T> {
   2098        let vec = self.0.get(name)?;
   2099        Some(&vec.last()?.0)
   2100    }
   2101 }
   2102 
   2103 /// Wrapper to allow better tracking of memory usage by page rule lists.
   2104 ///
   2105 /// This includes the layer ID for use with the named page table.
   2106 #[derive(Clone, Debug, MallocSizeOf)]
   2107 pub struct PageRuleData {
   2108    /// Layer ID for sorting page rules after matching.
   2109    pub layer: LayerId,
   2110    /// Page rule
   2111    #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
   2112    pub rule: Arc<Locked<PageRule>>,
   2113 }
   2114 
   2115 /// Stores page rules indexed by page names.
   2116 #[derive(Clone, Debug, Default, MallocSizeOf)]
   2117 pub struct PageRuleMap {
   2118    /// Page rules, indexed by page name. An empty atom indicates no page name.
   2119    pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
   2120 }
   2121 
   2122 impl PageRuleMap {
   2123    #[inline]
   2124    fn clear(&mut self) {
   2125        self.rules.clear();
   2126    }
   2127 
   2128    /// Uses page-name and pseudo-classes to match all applicable
   2129    /// page-rules and append them to the matched_rules vec.
   2130    /// This will ensure correct rule order for cascading.
   2131    pub fn match_and_append_rules(
   2132        &self,
   2133        matched_rules: &mut Vec<ApplicableDeclarationBlock>,
   2134        origin: Origin,
   2135        guards: &StylesheetGuards,
   2136        cascade_data: &DocumentCascadeData,
   2137        name: &Option<Atom>,
   2138        pseudos: PagePseudoClassFlags,
   2139    ) {
   2140        let level = match origin {
   2141            Origin::UserAgent => CascadeLevel::UANormal,
   2142            Origin::User => CascadeLevel::UserNormal,
   2143            Origin::Author => CascadeLevel::same_tree_author_normal(),
   2144        };
   2145        let cascade_data = cascade_data.borrow_for_origin(origin);
   2146        let start = matched_rules.len();
   2147 
   2148        self.match_and_add_rules(
   2149            matched_rules,
   2150            level,
   2151            guards,
   2152            cascade_data,
   2153            &atom!(""),
   2154            pseudos,
   2155        );
   2156        if let Some(name) = name {
   2157            self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
   2158        }
   2159 
   2160        // Because page-rules do not have source location information stored,
   2161        // use stable sort to ensure source locations are preserved.
   2162        matched_rules[start..].sort_by_key(|block| block.sort_key());
   2163    }
   2164 
   2165    fn match_and_add_rules(
   2166        &self,
   2167        extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
   2168        level: CascadeLevel,
   2169        guards: &StylesheetGuards,
   2170        cascade_data: &CascadeData,
   2171        name: &Atom,
   2172        pseudos: PagePseudoClassFlags,
   2173    ) {
   2174        let rules = match self.rules.get(name) {
   2175            Some(rules) => rules,
   2176            None => return,
   2177        };
   2178        for data in rules.iter() {
   2179            let rule = data.rule.read_with(level.guard(&guards));
   2180            let specificity = match rule.match_specificity(pseudos) {
   2181                Some(specificity) => specificity,
   2182                None => continue,
   2183            };
   2184            let block = rule.block.clone();
   2185            extra_declarations.push(ApplicableDeclarationBlock::new(
   2186                StyleSource::from_declarations(block),
   2187                0,
   2188                level,
   2189                specificity,
   2190                cascade_data.layer_order_for(data.layer),
   2191                ScopeProximity::infinity(), // Page rule can't have nested rules anyway.
   2192            ));
   2193        }
   2194    }
   2195 }
   2196 
   2197 impl MallocShallowSizeOf for PageRuleMap {
   2198    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
   2199        self.rules.shallow_size_of(ops)
   2200    }
   2201 }
   2202 
   2203 type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
   2204 
   2205 /// This struct holds data which users of Stylist may want to extract from stylesheets which can be
   2206 /// done at the same time as updating.
   2207 #[derive(Clone, Debug, Default)]
   2208 pub struct ExtraStyleData {
   2209    /// A list of effective font-face rules and their origin.
   2210    pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
   2211 
   2212    /// A list of effective font-feature-values rules.
   2213    pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
   2214 
   2215    /// A list of effective font-palette-values rules.
   2216    pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
   2217 
   2218    /// A map of effective counter-style rules.
   2219    pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
   2220 
   2221    /// A map of effective @position-try rules.
   2222    pub position_try_rules: PositionTryMap,
   2223 
   2224    /// A map of effective page rules.
   2225    pub pages: PageRuleMap,
   2226 }
   2227 
   2228 impl ExtraStyleData {
   2229    /// Add the given @font-face rule.
   2230    fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
   2231        self.font_faces.push(rule.clone(), layer);
   2232    }
   2233 
   2234    /// Add the given @font-feature-values rule.
   2235    fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
   2236        self.font_feature_values.push(rule.clone(), layer);
   2237    }
   2238 
   2239    /// Add the given @font-palette-values rule.
   2240    fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
   2241        self.font_palette_values.push(rule.clone(), layer);
   2242    }
   2243 
   2244    /// Add the given @counter-style rule.
   2245    fn add_counter_style(
   2246        &mut self,
   2247        guard: &SharedRwLockReadGuard,
   2248        rule: &Arc<Locked<CounterStyleRule>>,
   2249        layer: LayerId,
   2250    ) -> Result<(), AllocErr> {
   2251        let name = rule.read_with(guard).name().0.clone();
   2252        self.counter_styles.try_insert(name, rule.clone(), layer)
   2253    }
   2254 
   2255    /// Add the given @position-try rule.
   2256    fn add_position_try(
   2257        &mut self,
   2258        name: Atom,
   2259        rule: Arc<Locked<PositionTryRule>>,
   2260        layer: LayerId,
   2261    ) -> Result<(), AllocErr> {
   2262        self.position_try_rules.try_insert(name, rule, layer)
   2263    }
   2264 
   2265    /// Add the given @page rule.
   2266    fn add_page(
   2267        &mut self,
   2268        guard: &SharedRwLockReadGuard,
   2269        rule: &Arc<Locked<PageRule>>,
   2270        layer: LayerId,
   2271    ) -> Result<(), AllocErr> {
   2272        let page_rule = rule.read_with(guard);
   2273        let mut add_rule = |name| {
   2274            let vec = self.pages.rules.entry(name).or_default();
   2275            vec.push(PageRuleData {
   2276                layer,
   2277                rule: rule.clone(),
   2278            });
   2279        };
   2280        if page_rule.selectors.0.is_empty() {
   2281            add_rule(atom!(""));
   2282        } else {
   2283            for selector in page_rule.selectors.as_slice() {
   2284                add_rule(selector.name.0.clone());
   2285            }
   2286        }
   2287        Ok(())
   2288    }
   2289 
   2290    fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
   2291        self.font_faces.sort(layers);
   2292        self.font_feature_values.sort(layers);
   2293        self.font_palette_values.sort(layers);
   2294        self.counter_styles.sort(layers);
   2295        self.position_try_rules.sort(layers);
   2296    }
   2297 
   2298    fn clear(&mut self) {
   2299        self.font_faces.clear();
   2300        self.font_feature_values.clear();
   2301        self.font_palette_values.clear();
   2302        self.counter_styles.clear();
   2303        self.position_try_rules.clear();
   2304        self.pages.clear();
   2305    }
   2306 }
   2307 
   2308 // Don't let a prefixed keyframes animation override
   2309 // a non-prefixed one.
   2310 fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
   2311    if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
   2312        Ordering::Equal
   2313    } else if v2.vendor_prefix.is_some() {
   2314        Ordering::Greater
   2315    } else {
   2316        Ordering::Less
   2317    }
   2318 }
   2319 
   2320 /// An iterator over the different ExtraStyleData.
   2321 pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
   2322 
   2323 impl<'a> Iterator for ExtraStyleDataIterator<'a> {
   2324    type Item = (&'a ExtraStyleData, Origin);
   2325 
   2326    fn next(&mut self) -> Option<Self::Item> {
   2327        self.0.next().map(|d| (&d.0.extra_data, d.1))
   2328    }
   2329 }
   2330 
   2331 impl MallocSizeOf for ExtraStyleData {
   2332    /// Measure heap usage.
   2333    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
   2334        let mut n = 0;
   2335        n += self.font_faces.shallow_size_of(ops);
   2336        n += self.font_feature_values.shallow_size_of(ops);
   2337        n += self.font_palette_values.shallow_size_of(ops);
   2338        n += self.counter_styles.shallow_size_of(ops);
   2339        n += self.position_try_rules.shallow_size_of(ops);
   2340        n += self.pages.shallow_size_of(ops);
   2341        n
   2342    }
   2343 }
   2344 
   2345 /// SelectorMapEntry implementation for use in our revalidation selector map.
   2346 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
   2347 #[derive(Clone, Debug)]
   2348 struct RevalidationSelectorAndHashes {
   2349    #[cfg_attr(
   2350        feature = "gecko",
   2351        ignore_malloc_size_of = "CssRules have primary refs, we measure there"
   2352    )]
   2353    selector: Selector<SelectorImpl>,
   2354    selector_offset: usize,
   2355    hashes: AncestorHashes,
   2356 }
   2357 
   2358 impl RevalidationSelectorAndHashes {
   2359    fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
   2360        let selector_offset = {
   2361            // We basically want to check whether the first combinator is a
   2362            // pseudo-element combinator.  If it is, we want to use the offset
   2363            // one past it.  Otherwise, our offset is 0.
   2364            let mut index = 0;
   2365            let mut iter = selector.iter();
   2366 
   2367            // First skip over the first ComplexSelector.
   2368            //
   2369            // We can't check what sort of what combinator we have until we do
   2370            // that.
   2371            for _ in &mut iter {
   2372                index += 1; // Simple selector
   2373            }
   2374 
   2375            match iter.next_sequence() {
   2376                Some(Combinator::PseudoElement) => index + 1, // +1 for the combinator
   2377                _ => 0,
   2378            }
   2379        };
   2380 
   2381        RevalidationSelectorAndHashes {
   2382            selector,
   2383            selector_offset,
   2384            hashes,
   2385        }
   2386    }
   2387 }
   2388 
   2389 impl SelectorMapEntry for RevalidationSelectorAndHashes {
   2390    fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
   2391        self.selector.iter_from(self.selector_offset)
   2392    }
   2393 }
   2394 
   2395 /// A selector visitor implementation that collects all the state the Stylist
   2396 /// cares about a selector.
   2397 struct StylistSelectorVisitor<'a> {
   2398    /// Whether we've past the rightmost compound selector, not counting
   2399    /// pseudo-elements.
   2400    passed_rightmost_selector: bool,
   2401 
   2402    /// Whether the selector needs revalidation for the style sharing cache.
   2403    needs_revalidation: &'a mut bool,
   2404 
   2405    /// Flags for which selector list-containing components the visitor is
   2406    /// inside of, if any
   2407    in_selector_list_of: SelectorListKind,
   2408 
   2409    /// The filter with all the id's getting referenced from rightmost
   2410    /// selectors.
   2411    mapped_ids: &'a mut PrecomputedHashSet<Atom>,
   2412 
   2413    /// The filter with the IDs getting referenced from the selector list of
   2414    /// :nth-child(... of <selector list>) selectors.
   2415    nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
   2416 
   2417    /// The filter with the local names of attributes there are selectors for.
   2418    attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
   2419 
   2420    /// The filter with the classes getting referenced from the selector list of
   2421    /// :nth-child(... of <selector list>) selectors.
   2422    nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
   2423 
   2424    /// The filter with the local names of attributes there are selectors for
   2425    /// within the selector list of :nth-child(... of <selector list>)
   2426    /// selectors.
   2427    nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
   2428 
   2429    /// The filter with the local names of custom states in selectors for
   2430    /// within the selector list of :nth-child(... of <selector list>)
   2431    /// selectors.
   2432    nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
   2433 
   2434    /// All the states selectors in the page reference.
   2435    state_dependencies: &'a mut ElementState,
   2436 
   2437    /// All the state selectors in the page reference within the selector list
   2438    /// of :nth-child(... of <selector list>) selectors.
   2439    nth_of_state_dependencies: &'a mut ElementState,
   2440 
   2441    /// All the document states selectors in the page reference.
   2442    document_state_dependencies: &'a mut DocumentState,
   2443 }
   2444 
   2445 fn component_needs_revalidation(
   2446    c: &Component<SelectorImpl>,
   2447    passed_rightmost_selector: bool,
   2448 ) -> bool {
   2449    match *c {
   2450        Component::ID(_) => {
   2451            // TODO(emilio): This could also check that the ID is not already in
   2452            // the rule hash. In that case, we could avoid making this a
   2453            // revalidation selector too.
   2454            //
   2455            // See https://bugzilla.mozilla.org/show_bug.cgi?id=1369611
   2456            passed_rightmost_selector
   2457        },
   2458        Component::AttributeInNoNamespaceExists { .. }
   2459        | Component::AttributeInNoNamespace { .. }
   2460        | Component::AttributeOther(_)
   2461        | Component::Empty
   2462        | Component::Nth(_)
   2463        | Component::NthOf(_)
   2464        | Component::Has(_) => true,
   2465        Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
   2466        _ => false,
   2467    }
   2468 }
   2469 
   2470 impl<'a> StylistSelectorVisitor<'a> {
   2471    fn visit_nested_selector(
   2472        &mut self,
   2473        in_selector_list_of: SelectorListKind,
   2474        selector: &Selector<SelectorImpl>,
   2475    ) {
   2476        let old_passed_rightmost_selector = self.passed_rightmost_selector;
   2477        let old_in_selector_list_of = self.in_selector_list_of;
   2478 
   2479        self.passed_rightmost_selector = false;
   2480        self.in_selector_list_of = in_selector_list_of;
   2481        let _ret = selector.visit(self);
   2482        debug_assert!(_ret, "We never return false");
   2483 
   2484        self.passed_rightmost_selector = old_passed_rightmost_selector;
   2485        self.in_selector_list_of = old_in_selector_list_of;
   2486    }
   2487 }
   2488 
   2489 impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
   2490    type Impl = SelectorImpl;
   2491 
   2492    fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
   2493        *self.needs_revalidation =
   2494            *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
   2495 
   2496        // NOTE(emilio): this call happens before we visit any of the simple
   2497        // selectors in the next ComplexSelector, so we can use this to skip
   2498        // looking at them.
   2499        self.passed_rightmost_selector = self.passed_rightmost_selector
   2500            || !matches!(combinator, None | Some(Combinator::PseudoElement));
   2501 
   2502        true
   2503    }
   2504 
   2505    fn visit_selector_list(
   2506        &mut self,
   2507        list_kind: SelectorListKind,
   2508        list: &[Selector<Self::Impl>],
   2509    ) -> bool {
   2510        let in_selector_list_of = self.in_selector_list_of | list_kind;
   2511        for selector in list {
   2512            self.visit_nested_selector(in_selector_list_of, selector);
   2513        }
   2514        true
   2515    }
   2516 
   2517    fn visit_relative_selector_list(
   2518        &mut self,
   2519        list: &[selectors::parser::RelativeSelector<Self::Impl>],
   2520    ) -> bool {
   2521        let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
   2522        for selector in list {
   2523            self.visit_nested_selector(in_selector_list_of, &selector.selector);
   2524        }
   2525        true
   2526    }
   2527 
   2528    fn visit_attribute_selector(
   2529        &mut self,
   2530        _ns: &NamespaceConstraint<&Namespace>,
   2531        name: &LocalName,
   2532        lower_name: &LocalName,
   2533    ) -> bool {
   2534        if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
   2535            self.nth_of_attribute_dependencies.insert(name.clone());
   2536            if name != lower_name {
   2537                self.nth_of_attribute_dependencies
   2538                    .insert(lower_name.clone());
   2539            }
   2540        }
   2541 
   2542        self.attribute_dependencies.insert(name.clone());
   2543        if name != lower_name {
   2544            self.attribute_dependencies.insert(lower_name.clone());
   2545        }
   2546 
   2547        true
   2548    }
   2549 
   2550    fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
   2551        *self.needs_revalidation = *self.needs_revalidation
   2552            || component_needs_revalidation(s, self.passed_rightmost_selector);
   2553 
   2554        match *s {
   2555            Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
   2556                // CustomStateSet is special cased as it is a functional pseudo
   2557                // class with unbounded inner values. This is different to
   2558                // other psuedo class like :emtpy or :dir() which can be packed
   2559                // into the ElementState bitflags. For CustomState, however,
   2560                // the state name should be checked for presence in the selector.
   2561                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
   2562                    self.nth_of_custom_state_dependencies.insert(name.0.clone());
   2563                }
   2564            },
   2565            Component::NonTSPseudoClass(ref p) => {
   2566                self.state_dependencies.insert(p.state_flag());
   2567                self.document_state_dependencies
   2568                    .insert(p.document_state_flag());
   2569 
   2570                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
   2571                    self.nth_of_state_dependencies.insert(p.state_flag());
   2572                }
   2573            },
   2574            Component::ID(ref id) => {
   2575                // We want to stop storing mapped ids as soon as we've moved off
   2576                // the rightmost ComplexSelector that is not a pseudo-element.
   2577                //
   2578                // That can be detected by a visit_complex_selector call with a
   2579                // combinator other than None and PseudoElement.
   2580                //
   2581                // Importantly, this call happens before we visit any of the
   2582                // simple selectors in that ComplexSelector.
   2583                //
   2584                // NOTE(emilio): See the comment regarding on when this may
   2585                // break in visit_complex_selector.
   2586                if !self.passed_rightmost_selector {
   2587                    self.mapped_ids.insert(id.0.clone());
   2588                }
   2589 
   2590                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
   2591                    self.nth_of_mapped_ids.insert(id.0.clone());
   2592                }
   2593            },
   2594            Component::Class(ref class)
   2595                if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
   2596            {
   2597                self.nth_of_class_dependencies.insert(class.0.clone());
   2598            },
   2599            _ => {},
   2600        }
   2601 
   2602        true
   2603    }
   2604 }
   2605 
   2606 /// A set of rules for element and pseudo-elements.
   2607 #[derive(Clone, Debug, Default, MallocSizeOf)]
   2608 struct GenericElementAndPseudoRules<Map> {
   2609    /// Rules from stylesheets at this `CascadeData`'s origin.
   2610    element_map: Map,
   2611 
   2612    /// Rules from stylesheets at this `CascadeData`'s origin that correspond
   2613    /// to a given pseudo-element.
   2614    ///
   2615    /// FIXME(emilio): There are a bunch of wasted entries here in practice.
   2616    /// Figure out a good way to do a `PerNonAnonBox` and `PerAnonBox` (for
   2617    /// `precomputed_values_for_pseudo`) without duplicating a lot of code.
   2618    pseudos_map: PerPseudoElementMap<Self>,
   2619 }
   2620 
   2621 impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
   2622    #[inline(always)]
   2623    fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
   2624        let mut current = self;
   2625        for &pseudo_element in pseudo_elements {
   2626            debug_assert!(
   2627                !pseudo_element.is_precomputed()
   2628                    && !pseudo_element.is_unknown_webkit_pseudo_element(),
   2629                "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
   2630                 and unknown webkit pseudos should be discarded before getting here"
   2631            );
   2632 
   2633            current = current
   2634                .pseudos_map
   2635                .get_or_insert_with(pseudo_element, Default::default);
   2636        }
   2637 
   2638        &mut current.element_map
   2639    }
   2640 
   2641    #[inline]
   2642    fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
   2643        let mut current = self;
   2644        for pseudo in pseudo_elements {
   2645            current = current.pseudos_map.get(&pseudo)?;
   2646        }
   2647        Some(&current.element_map)
   2648    }
   2649 
   2650    /// Measures heap usage.
   2651    #[cfg(feature = "gecko")]
   2652    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
   2653        sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
   2654 
   2655        for elem in self.pseudos_map.iter() {
   2656            sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
   2657        }
   2658    }
   2659 }
   2660 
   2661 type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
   2662 type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
   2663 type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
   2664 
   2665 impl ElementAndPseudoRules {
   2666    // TODO(emilio): Should we retain storage of these?
   2667    fn clear(&mut self) {
   2668        self.element_map.clear();
   2669        self.pseudos_map.clear();
   2670    }
   2671 
   2672    fn shrink_if_needed(&mut self) {
   2673        self.element_map.shrink_if_needed();
   2674        for pseudo in self.pseudos_map.iter_mut() {
   2675            pseudo.shrink_if_needed();
   2676        }
   2677    }
   2678 }
   2679 
   2680 impl PartElementAndPseudoRules {
   2681    // TODO(emilio): Should we retain storage of these?
   2682    fn clear(&mut self) {
   2683        self.element_map.clear();
   2684        self.pseudos_map.clear();
   2685    }
   2686 }
   2687 
   2688 /// The id of a given layer, a sequentially-increasing identifier.
   2689 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
   2690 pub struct LayerId(u16);
   2691 
   2692 impl LayerId {
   2693    /// The id of the root layer.
   2694    pub const fn root() -> Self {
   2695        Self(0)
   2696    }
   2697 }
   2698 
   2699 #[derive(Clone, Debug, MallocSizeOf)]
   2700 struct CascadeLayer {
   2701    id: LayerId,
   2702    order: LayerOrder,
   2703    children: Vec<LayerId>,
   2704 }
   2705 
   2706 impl CascadeLayer {
   2707    const fn root() -> Self {
   2708        Self {
   2709            id: LayerId::root(),
   2710            order: LayerOrder::root(),
   2711            children: vec![],
   2712        }
   2713    }
   2714 }
   2715 
   2716 /// The id of a given container condition, a sequentially-increasing identifier
   2717 /// for a given style set.
   2718 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
   2719 pub struct ContainerConditionId(u16);
   2720 
   2721 impl ContainerConditionId {
   2722    /// A special id that represents no container rule.
   2723    pub const fn none() -> Self {
   2724        Self(0)
   2725    }
   2726 }
   2727 
   2728 #[derive(Clone, Debug, MallocSizeOf)]
   2729 struct ContainerConditionReference {
   2730    parent: ContainerConditionId,
   2731    #[ignore_malloc_size_of = "Arc"]
   2732    condition: Option<Arc<ContainerCondition>>,
   2733 }
   2734 
   2735 impl ContainerConditionReference {
   2736    const fn none() -> Self {
   2737        Self {
   2738            parent: ContainerConditionId::none(),
   2739            condition: None,
   2740        }
   2741    }
   2742 }
   2743 
   2744 /// The id of a given scope condition, a sequentially-increasing identifier
   2745 /// for a given style set.
   2746 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
   2747 pub struct ScopeConditionId(u16);
   2748 
   2749 impl ScopeConditionId {
   2750    /// Construct a new scope condition id.
   2751    pub fn new(id: u16) -> Self {
   2752        Self(id)
   2753    }
   2754 
   2755    /// A special id that represents no scope rule.
   2756    pub const fn none() -> Self {
   2757        Self(0)
   2758    }
   2759 }
   2760 
   2761 /// Data required to process this scope condition.
   2762 #[derive(Clone, Debug, MallocSizeOf)]
   2763 pub struct ScopeConditionReference {
   2764    /// The ID of outer scope condition, `none()` otherwise.
   2765    parent: ScopeConditionId,
   2766    /// Start and end bounds of the scope. None implies sentinel data (i.e. Not a scope condition).
   2767    condition: Option<ScopeBoundsWithHashes>,
   2768    /// Implicit scope root of this scope condition, computed unconditionally,
   2769    /// even if the start bound may be Some.
   2770    #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
   2771    implicit_scope_root: StylistImplicitScopeRoot,
   2772    /// Is the condition trivial? See `ScopeBoundsWithHashes::is_trivial`.
   2773    is_trivial: bool,
   2774 }
   2775 
   2776 impl ScopeConditionReference {
   2777    /// Create a new scope condition.
   2778    pub fn new(
   2779        parent: ScopeConditionId,
   2780        condition: Option<ScopeBoundsWithHashes>,
   2781        implicit_scope_root: ImplicitScopeRoot,
   2782        is_trivial: bool,
   2783    ) -> Self {
   2784        Self {
   2785            parent,
   2786            condition,
   2787            implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
   2788            is_trivial,
   2789        }
   2790    }
   2791 
   2792    /// Create a sentinel scope condition.
   2793    pub const fn none() -> Self {
   2794        Self {
   2795            parent: ScopeConditionId::none(),
   2796            condition: None,
   2797            implicit_scope_root: StylistImplicitScopeRoot::default_const(),
   2798            is_trivial: true,
   2799        }
   2800    }
   2801 }
   2802 
   2803 /// All potential sscope root candidates.
   2804 pub struct ScopeRootCandidates {
   2805    /// List of scope root candidates.
   2806    pub candidates: Vec<ScopeRootCandidate>,
   2807    /// Is the scope condition matching these candidates trivial? See `ScopeBoundsWithHashes::is_trivial`.
   2808    pub is_trivial: bool,
   2809 }
   2810 
   2811 impl Default for ScopeRootCandidates {
   2812    fn default() -> Self {
   2813        Self {
   2814            candidates: vec![],
   2815            is_trivial: true,
   2816        }
   2817    }
   2818 }
   2819 
   2820 impl ScopeRootCandidates {
   2821    fn empty(is_trivial: bool) -> Self {
   2822        Self {
   2823            candidates: vec![],
   2824            is_trivial,
   2825        }
   2826    }
   2827 }
   2828 
   2829 /// Start and end bound of a scope, along with their selector hashes.
   2830 #[derive(Clone, Debug, MallocSizeOf)]
   2831 pub struct ScopeBoundWithHashes {
   2832    // TODO(dshin): With replaced parent selectors, these may be unique...
   2833    #[ignore_malloc_size_of = "Arc"]
   2834    selectors: SelectorList<SelectorImpl>,
   2835    hashes: SmallVec<[AncestorHashes; 1]>,
   2836 }
   2837 
   2838 impl ScopeBoundWithHashes {
   2839    fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
   2840        let mut hashes = SmallVec::with_capacity(selectors.len());
   2841        for selector in selectors.slice() {
   2842            hashes.push(AncestorHashes::new(selector, quirks_mode));
   2843        }
   2844        Self { selectors, hashes }
   2845    }
   2846 
   2847    fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
   2848        let hashes = selectors
   2849            .slice()
   2850            .iter()
   2851            .map(|_| AncestorHashes {
   2852                packed_hashes: [0, 0, 0],
   2853            })
   2854            .collect();
   2855        Self { selectors, hashes }
   2856    }
   2857 }
   2858 
   2859 /// Bounds for this scope, along with corresponding selector hashes.
   2860 #[derive(Clone, Debug, MallocSizeOf)]
   2861 pub struct ScopeBoundsWithHashes {
   2862    /// Start of the scope bound. If None, implies implicit scope root.
   2863    start: Option<ScopeBoundWithHashes>,
   2864    /// Optional end of the scope bound.
   2865    end: Option<ScopeBoundWithHashes>,
   2866 }
   2867 
   2868 impl ScopeBoundsWithHashes {
   2869    /// Create a new scope bound, hashing selectors for fast rejection.
   2870    fn new(
   2871        quirks_mode: QuirksMode,
   2872        start: Option<SelectorList<SelectorImpl>>,
   2873        end: Option<SelectorList<SelectorImpl>>,
   2874    ) -> Self {
   2875        Self {
   2876            start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
   2877            end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
   2878        }
   2879    }
   2880 
   2881    /// Create a new scope bound, but not hashing any selector.
   2882    pub fn new_no_hash(
   2883        start: Option<SelectorList<SelectorImpl>>,
   2884        end: Option<SelectorList<SelectorImpl>>,
   2885    ) -> Self {
   2886        Self {
   2887            start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
   2888            end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
   2889        }
   2890    }
   2891 
   2892    fn selectors_for<'a>(
   2893        bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
   2894    ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
   2895        bound_with_hashes
   2896            .map(|b| b.selectors.slice().iter())
   2897            .into_iter()
   2898            .flatten()
   2899    }
   2900 
   2901    fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
   2902        Self::selectors_for(self.start.as_ref())
   2903    }
   2904 
   2905    fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
   2906        Self::selectors_for(self.end.as_ref())
   2907    }
   2908 
   2909    fn is_trivial(&self) -> bool {
   2910        fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
   2911            bound.as_ref().map_or(default, |bound| {
   2912                scope_selector_list_is_trivial(&bound.selectors)
   2913            })
   2914        }
   2915 
   2916        // Given an implicit scope, we are unable to tell if the cousins share the same implicit root.
   2917        scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
   2918    }
   2919 }
   2920 
   2921 /// Find all scope conditions for a given condition ID, indexing into the given list of scope conditions.
   2922 pub fn scope_root_candidates<E>(
   2923    scope_conditions: &[ScopeConditionReference],
   2924    id: ScopeConditionId,
   2925    element: &E,
   2926    override_matches_shadow_host_for_part: bool,
   2927    scope_subject_map: &ScopeSubjectMap,
   2928    context: &mut MatchingContext<SelectorImpl>,
   2929 ) -> ScopeRootCandidates
   2930 where
   2931    E: TElement,
   2932 {
   2933    let condition_ref = &scope_conditions[id.0 as usize];
   2934    let bounds = match condition_ref.condition {
   2935        None => return ScopeRootCandidates::default(),
   2936        Some(ref c) => c,
   2937    };
   2938    // Make sure the parent scopes ara evaluated first. This runs a bit counter to normal
   2939    // selector matching where rightmost selectors match first. However, this avoids having
   2940    // to traverse through descendants (i.e. Avoids tree traversal vs linear traversal).
   2941    let outer_result = scope_root_candidates(
   2942        scope_conditions,
   2943        condition_ref.parent,
   2944        element,
   2945        override_matches_shadow_host_for_part,
   2946        scope_subject_map,
   2947        context,
   2948    );
   2949 
   2950    let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
   2951    let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
   2952    if !is_outermost_scope && outer_result.candidates.is_empty() {
   2953        return ScopeRootCandidates::empty(is_trivial);
   2954    }
   2955 
   2956    let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
   2957        if let Some(filter) = context.bloom_filter {
   2958            // Use the bloom filter here. If our ancestors do not have the right hashes,
   2959            // there's no point in traversing up. Besides, the filter is built for this depth,
   2960            // so the filter contains more data than it should, the further we go up the ancestor
   2961            // chain. It wouldn't generate wrong results, but makes the traversal even more pointless.
   2962            if !start
   2963                .hashes
   2964                .iter()
   2965                .any(|entry| selector_may_match(entry, filter))
   2966            {
   2967                return ScopeRootCandidates::empty(is_trivial);
   2968            }
   2969        }
   2970        (
   2971            ScopeTarget::Selector(&start.selectors),
   2972            scope_start_matches_shadow_host(&start.selectors),
   2973        )
   2974    } else {
   2975        let implicit_root = condition_ref.implicit_scope_root;
   2976        match implicit_root {
   2977            StylistImplicitScopeRoot::Normal(r) => (
   2978                ScopeTarget::Implicit(r.element(context.current_host.clone())),
   2979                r.matches_shadow_host(),
   2980            ),
   2981            StylistImplicitScopeRoot::Cached(index) => {
   2982                let host = context
   2983                    .current_host
   2984                    .expect("Cached implicit scope for light DOM implicit scope");
   2985                match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
   2986                    None => return ScopeRootCandidates::empty(is_trivial),
   2987                    Some(root) => (
   2988                        ScopeTarget::Implicit(root.element(context.current_host.clone())),
   2989                        root.matches_shadow_host(),
   2990                    ),
   2991                }
   2992            },
   2993        }
   2994    };
   2995    // For `::part`, we need to be able to reach the outer tree. Parts without the corresponding
   2996    // `exportparts` attribute will be rejected at the selector matching time.
   2997    let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
   2998 
   2999    let potential_scope_roots = if is_outermost_scope {
   3000        collect_scope_roots(
   3001            *element,
   3002            None,
   3003            context,
   3004            &root_target,
   3005            matches_shadow_host,
   3006            scope_subject_map,
   3007        )
   3008    } else {
   3009        let mut result = vec![];
   3010        for activation in outer_result.candidates {
   3011            let mut this_result = collect_scope_roots(
   3012                *element,
   3013                Some(activation.root),
   3014                context,
   3015                &root_target,
   3016                matches_shadow_host,
   3017                scope_subject_map,
   3018            );
   3019            result.append(&mut this_result);
   3020        }
   3021        result
   3022    };
   3023 
   3024    if potential_scope_roots.is_empty() {
   3025        return ScopeRootCandidates::empty(is_trivial);
   3026    }
   3027 
   3028    let candidates = if let Some(end) = bounds.end.as_ref() {
   3029        let mut result = vec![];
   3030        // If any scope-end selector matches, we're not in scope.
   3031        for scope_root in potential_scope_roots {
   3032            if end
   3033                .selectors
   3034                .slice()
   3035                .iter()
   3036                .zip(end.hashes.iter())
   3037                .all(|(selector, hashes)| {
   3038                    // Like checking for scope-start, use the bloom filter here.
   3039                    if let Some(filter) = context.bloom_filter {
   3040                        if !selector_may_match(hashes, filter) {
   3041                            // Selector this hash belongs to won't cause us to be out of this scope.
   3042                            return true;
   3043                        }
   3044                    }
   3045 
   3046                    !element_is_outside_of_scope(
   3047                        selector,
   3048                        *element,
   3049                        scope_root.root,
   3050                        context,
   3051                        matches_shadow_host,
   3052                    )
   3053                })
   3054            {
   3055                result.push(scope_root);
   3056            }
   3057        }
   3058        result
   3059    } else {
   3060        potential_scope_roots
   3061    };
   3062 
   3063    ScopeRootCandidates {
   3064        candidates,
   3065        is_trivial,
   3066    }
   3067 }
   3068 
   3069 /// Implicit scope root, which may or may not be cached (i.e. For shadow DOM author
   3070 /// styles that are cached and shared).
   3071 #[derive(Copy, Clone, Debug, MallocSizeOf)]
   3072 enum StylistImplicitScopeRoot {
   3073    Normal(ImplicitScopeRoot),
   3074    Cached(usize),
   3075 }
   3076 // Should be safe, only mutated through mutable methods in `Stylist`.
   3077 unsafe impl Sync for StylistImplicitScopeRoot {}
   3078 
   3079 impl StylistImplicitScopeRoot {
   3080    const fn default_const() -> Self {
   3081        // Use the "safest" fallback.
   3082        Self::Normal(ImplicitScopeRoot::DocumentElement)
   3083    }
   3084 }
   3085 
   3086 impl Default for StylistImplicitScopeRoot {
   3087    fn default() -> Self {
   3088        Self::default_const()
   3089    }
   3090 }
   3091 
   3092 /// Data resulting from performing the CSS cascade that is specific to a given
   3093 /// origin.
   3094 ///
   3095 /// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
   3096 /// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
   3097 #[derive(Debug, Clone, MallocSizeOf)]
   3098 pub struct CascadeData {
   3099    /// The data coming from normal style rules that apply to elements at this
   3100    /// cascade level.
   3101    normal_rules: ElementAndPseudoRules,
   3102 
   3103    /// The `:host` pseudo rules that are the rightmost selector (without
   3104    /// accounting for pseudo-elements), or `:scope` rules that may match
   3105    /// the featureless host.
   3106    featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
   3107 
   3108    /// The data coming from ::slotted() pseudo-element rules.
   3109    ///
   3110    /// We need to store them separately because an element needs to match
   3111    /// ::slotted() pseudo-element rules in different shadow roots.
   3112    ///
   3113    /// In particular, we need to go through all the style data in all the
   3114    /// containing style scopes starting from the closest assigned slot.
   3115    slotted_rules: Option<Box<ElementAndPseudoRules>>,
   3116 
   3117    /// The data coming from ::part() pseudo-element rules.
   3118    ///
   3119    /// We need to store them separately because an element needs to match
   3120    /// ::part() pseudo-element rules in different shadow roots.
   3121    part_rules: Option<Box<PartElementAndPseudoRules>>,
   3122 
   3123    /// The invalidation map for these rules.
   3124    invalidation_map: InvalidationMap,
   3125 
   3126    /// The relative selector equivalent of the invalidation map.
   3127    relative_selector_invalidation_map: InvalidationMap,
   3128 
   3129    additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
   3130 
   3131    /// The attribute local names that appear in attribute selectors.  Used
   3132    /// to avoid taking element snapshots when an irrelevant attribute changes.
   3133    /// (We don't bother storing the namespace, since namespaced attributes are
   3134    /// rare.)
   3135    attribute_dependencies: PrecomputedHashSet<LocalName>,
   3136 
   3137    /// The classes that appear in the selector list of
   3138    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
   3139    /// an element when an irrelevant class changes.
   3140    nth_of_class_dependencies: PrecomputedHashSet<Atom>,
   3141 
   3142    /// The attributes that appear in the selector list of
   3143    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
   3144    /// an element when an irrelevant attribute changes.
   3145    nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
   3146 
   3147    /// The custom states that appear in the selector list of
   3148    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
   3149    /// an element when an irrelevant custom state changes.
   3150    nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
   3151 
   3152    /// The element state bits that are relied on by selectors.  Like
   3153    /// `attribute_dependencies`, this is used to avoid taking element snapshots
   3154    /// when an irrelevant element state bit changes.
   3155    state_dependencies: ElementState,
   3156 
   3157    /// The element state bits that are relied on by selectors that appear in
   3158    /// the selector list of :nth-child(... of <selector list>).
   3159    nth_of_state_dependencies: ElementState,
   3160 
   3161    /// The document state bits that are relied on by selectors.  This is used
   3162    /// to tell whether we need to restyle the entire document when a document
   3163    /// state bit changes.
   3164    document_state_dependencies: DocumentState,
   3165 
   3166    /// The ids that appear in the rightmost complex selector of selectors (and
   3167    /// hence in our selector maps).  Used to determine when sharing styles is
   3168    /// safe: we disallow style sharing for elements whose id matches this
   3169    /// filter, and hence might be in one of our selector maps.
   3170    mapped_ids: PrecomputedHashSet<Atom>,
   3171 
   3172    /// The IDs that appear in the selector list of
   3173    /// :nth-child(... of <selector list>). Used to avoid restyling siblings
   3174    /// of an element when an irrelevant ID changes.
   3175    nth_of_mapped_ids: PrecomputedHashSet<Atom>,
   3176 
   3177    /// Selectors that require explicit cache revalidation (i.e. which depend
   3178    /// on state that is not otherwise visible to the cache, like attributes or
   3179    /// tree-structural state like child index and pseudos).
   3180    #[ignore_malloc_size_of = "Arc"]
   3181    selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
   3182 
   3183    /// A map with all the animations at this `CascadeData`'s origin, indexed
   3184    /// by name.
   3185    animations: LayerOrderedMap<KeyframesAnimation>,
   3186 
   3187    /// A map with all the layer-ordered registrations from style at this `CascadeData`'s origin,
   3188    /// indexed by name.
   3189    #[ignore_malloc_size_of = "Arc"]
   3190    custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
   3191 
   3192    /// Custom media query registrations.
   3193    custom_media: CustomMediaMap,
   3194 
   3195    /// A map from cascade layer name to layer order.
   3196    layer_id: FxHashMap<LayerName, LayerId>,
   3197 
   3198    /// The list of cascade layers, indexed by their layer id.
   3199    layers: SmallVec<[CascadeLayer; 1]>,
   3200 
   3201    /// The list of container conditions, indexed by their id.
   3202    container_conditions: SmallVec<[ContainerConditionReference; 1]>,
   3203 
   3204    /// The list of scope conditions, indexed by their id.
   3205    scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
   3206 
   3207    /// Map of unique selectors on scope start selectors' subjects.
   3208    scope_subject_map: ScopeSubjectMap,
   3209 
   3210    /// Effective media query results cached from the last rebuild.
   3211    effective_media_query_results: EffectiveMediaQueryResults,
   3212 
   3213    /// Extra data, like different kinds of rules, etc.
   3214    extra_data: ExtraStyleData,
   3215 
   3216    /// A monotonically increasing counter to represent the order on which a
   3217    /// style rule appears in a stylesheet, needed to sort them by source order.
   3218    rules_source_order: u32,
   3219 
   3220    /// The total number of selectors.
   3221    num_selectors: usize,
   3222 
   3223    /// The total number of declarations.
   3224    num_declarations: usize,
   3225 }
   3226 
   3227 static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
   3228    // Implicit scope, as per https://github.com/w3c/csswg-drafts/issues/10196
   3229    // Also, `&` is `:where(:scope)`, as per https://github.com/w3c/csswg-drafts/issues/9740
   3230    // ``:where(:scope)` effectively behaves the same as the implicit scope.
   3231    let list = SelectorList::implicit_scope();
   3232    list.mark_as_intentionally_leaked();
   3233    list
   3234 });
   3235 
   3236 fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
   3237    // TODO(emilio): Should we carry a MatchesFeaturelessHost rather than a bool around?
   3238    // Pre-existing behavior with multiple selectors matches this tho.
   3239    start
   3240        .slice()
   3241        .iter()
   3242        .any(|s| s.matches_featureless_host(true).may_match())
   3243 }
   3244 
   3245 /// Replace any occurrence of parent selector in the given selector with a implicit scope selector.
   3246 pub fn replace_parent_selector_with_implicit_scope(
   3247    selectors: &SelectorList<SelectorImpl>,
   3248 ) -> SelectorList<SelectorImpl> {
   3249    selectors.replace_parent_selector(&IMPLICIT_SCOPE)
   3250 }
   3251 
   3252 impl CascadeData {
   3253    /// Creates an empty `CascadeData`.
   3254    pub fn new() -> Self {
   3255        Self {
   3256            normal_rules: ElementAndPseudoRules::default(),
   3257            featureless_host_rules: None,
   3258            slotted_rules: None,
   3259            part_rules: None,
   3260            invalidation_map: InvalidationMap::new(),
   3261            relative_selector_invalidation_map: InvalidationMap::new(),
   3262            additional_relative_selector_invalidation_map:
   3263                AdditionalRelativeSelectorInvalidationMap::new(),
   3264            nth_of_mapped_ids: PrecomputedHashSet::default(),
   3265            nth_of_class_dependencies: PrecomputedHashSet::default(),
   3266            nth_of_attribute_dependencies: PrecomputedHashSet::default(),
   3267            nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
   3268            nth_of_state_dependencies: ElementState::empty(),
   3269            attribute_dependencies: PrecomputedHashSet::default(),
   3270            state_dependencies: ElementState::empty(),
   3271            document_state_dependencies: DocumentState::empty(),
   3272            mapped_ids: PrecomputedHashSet::default(),
   3273            selectors_for_cache_revalidation: SelectorMap::new(),
   3274            animations: Default::default(),
   3275            custom_property_registrations: Default::default(),
   3276            custom_media: Default::default(),
   3277            layer_id: Default::default(),
   3278            layers: smallvec::smallvec![CascadeLayer::root()],
   3279            container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
   3280            scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
   3281            scope_subject_map: Default::default(),
   3282            extra_data: ExtraStyleData::default(),
   3283            effective_media_query_results: EffectiveMediaQueryResults::new(),
   3284            rules_source_order: 0,
   3285            num_selectors: 0,
   3286            num_declarations: 0,
   3287        }
   3288    }
   3289 
   3290    /// Rebuild the cascade data from a given SheetCollection, incrementally if possible.
   3291    pub fn rebuild<'a, S>(
   3292        &mut self,
   3293        device: &Device,
   3294        quirks_mode: QuirksMode,
   3295        collection: SheetCollectionFlusher<S>,
   3296        guard: &SharedRwLockReadGuard,
   3297        difference: &mut CascadeDataDifference,
   3298    ) -> Result<(), AllocErr>
   3299    where
   3300        S: StylesheetInDocument + PartialEq + 'static,
   3301    {
   3302        if !collection.dirty() {
   3303            return Ok(());
   3304        }
   3305 
   3306        let validity = collection.data_validity();
   3307 
   3308        let mut old_position_try_data = LayerOrderedMap::default();
   3309        if validity != DataValidity::Valid {
   3310            old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
   3311            self.clear_cascade_data();
   3312            if validity == DataValidity::FullyInvalid {
   3313                self.clear_invalidation_data();
   3314            }
   3315        }
   3316 
   3317        let mut result = Ok(());
   3318 
   3319        collection.each(|index, stylesheet, rebuild_kind| {
   3320            result = self.add_stylesheet(
   3321                device,
   3322                quirks_mode,
   3323                stylesheet,
   3324                index,
   3325                guard,
   3326                rebuild_kind,
   3327                /* precomputed_pseudo_element_decls = */ None,
   3328                if validity == DataValidity::Valid {
   3329                    Some(difference)
   3330                } else {
   3331                    None
   3332                },
   3333            );
   3334            result.is_ok()
   3335        });
   3336 
   3337        self.did_finish_rebuild();
   3338 
   3339        // For DataValidity::Valid, we pass the difference down to `add_stylesheet` so that we
   3340        // populate it with new data. Otherwise we need to diff with the old data.
   3341        if validity != DataValidity::Valid {
   3342            difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
   3343        }
   3344 
   3345        result
   3346    }
   3347 
   3348    /// Returns the custom media query map.
   3349    pub fn custom_media_map(&self) -> &CustomMediaMap {
   3350        &self.custom_media
   3351    }
   3352 
   3353    /// Returns the invalidation map.
   3354    pub fn invalidation_map(&self) -> &InvalidationMap {
   3355        &self.invalidation_map
   3356    }
   3357 
   3358    /// Returns the relative selector invalidation map.
   3359    pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
   3360        &self.relative_selector_invalidation_map
   3361    }
   3362 
   3363    /// Returns the relative selector invalidation map data.
   3364    pub fn relative_invalidation_map_attributes(
   3365        &self,
   3366    ) -> &AdditionalRelativeSelectorInvalidationMap {
   3367        &self.additional_relative_selector_invalidation_map
   3368    }
   3369 
   3370    /// Returns whether the given ElementState bit is relied upon by a selector
   3371    /// of some rule.
   3372    #[inline]
   3373    pub fn has_state_dependency(&self, state: ElementState) -> bool {
   3374        self.state_dependencies.intersects(state)
   3375    }
   3376 
   3377    /// Returns whether the given Custom State is relied upon by a selector
   3378    /// of some rule in the selector list of :nth-child(... of <selector list>).
   3379    #[inline]
   3380    pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
   3381        self.nth_of_custom_state_dependencies.contains(state)
   3382    }
   3383 
   3384    /// Returns whether the given ElementState bit is relied upon by a selector
   3385    /// of some rule in the selector list of :nth-child(... of <selector list>).
   3386    #[inline]
   3387    pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
   3388        self.nth_of_state_dependencies.intersects(state)
   3389    }
   3390 
   3391    /// Returns whether the given attribute might appear in an attribute
   3392    /// selector of some rule.
   3393    #[inline]
   3394    pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
   3395        self.attribute_dependencies.contains(local_name)
   3396    }
   3397 
   3398    /// Returns whether the given ID might appear in an ID selector in the
   3399    /// selector list of :nth-child(... of <selector list>).
   3400    #[inline]
   3401    pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
   3402        self.nth_of_mapped_ids.contains(id)
   3403    }
   3404 
   3405    /// Returns whether the given class might appear in a class selector in the
   3406    /// selector list of :nth-child(... of <selector list>).
   3407    #[inline]
   3408    pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
   3409        self.nth_of_class_dependencies.contains(class)
   3410    }
   3411 
   3412    /// Returns whether the given attribute might appear in an attribute
   3413    /// selector in the selector list of :nth-child(... of <selector list>).
   3414    #[inline]
   3415    pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
   3416        self.nth_of_attribute_dependencies.contains(local_name)
   3417    }
   3418 
   3419    /// Returns the normal rule map for a given pseudo-element.
   3420    #[inline]
   3421    pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
   3422        self.normal_rules.rules(pseudo_elements)
   3423    }
   3424 
   3425    /// Returns the featureless pseudo rule map for a given pseudo-element.
   3426    #[inline]
   3427    pub fn featureless_host_rules(
   3428        &self,
   3429        pseudo_elements: &[PseudoElement],
   3430    ) -> Option<&SelectorMap<Rule>> {
   3431        self.featureless_host_rules
   3432            .as_ref()
   3433            .and_then(|d| d.rules(pseudo_elements))
   3434    }
   3435 
   3436    /// Whether there's any featureless rule that could match in this scope.
   3437    pub fn any_featureless_host_rules(&self) -> bool {
   3438        self.featureless_host_rules.is_some()
   3439    }
   3440 
   3441    /// Returns the slotted rule map for a given pseudo-element.
   3442    #[inline]
   3443    pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
   3444        self.slotted_rules
   3445            .as_ref()
   3446            .and_then(|d| d.rules(pseudo_elements))
   3447    }
   3448 
   3449    /// Whether there's any ::slotted rule that could match in this scope.
   3450    pub fn any_slotted_rule(&self) -> bool {
   3451        self.slotted_rules.is_some()
   3452    }
   3453 
   3454    /// Returns the parts rule map for a given pseudo-element.
   3455    #[inline]
   3456    pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
   3457        self.part_rules
   3458            .as_ref()
   3459            .and_then(|d| d.rules(pseudo_elements))
   3460    }
   3461 
   3462    /// Whether there's any ::part rule that could match in this scope.
   3463    pub fn any_part_rule(&self) -> bool {
   3464        self.part_rules.is_some()
   3465    }
   3466 
   3467    #[inline]
   3468    fn layer_order_for(&self, id: LayerId) -> LayerOrder {
   3469        self.layers[id.0 as usize].order
   3470    }
   3471 
   3472    pub(crate) fn container_condition_matches<E>(
   3473        &self,
   3474        mut id: ContainerConditionId,
   3475        stylist: &Stylist,
   3476        element: E,
   3477        context: &mut MatchingContext<E::Impl>,
   3478    ) -> bool
   3479    where
   3480        E: TElement,
   3481    {
   3482        loop {
   3483            let condition_ref = &self.container_conditions[id.0 as usize];
   3484            let condition = match condition_ref.condition {
   3485                None => return true,
   3486                Some(ref c) => c,
   3487            };
   3488            let matches = condition
   3489                .matches(
   3490                    stylist,
   3491                    element,
   3492                    context.extra_data.originating_element_style,
   3493                    &mut context.extra_data.cascade_input_flags,
   3494                )
   3495                .to_bool(/* unknown = */ false);
   3496            if !matches {
   3497                return false;
   3498            }
   3499            id = condition_ref.parent;
   3500        }
   3501    }
   3502 
   3503    pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
   3504        &self,
   3505        rule: &Rule,
   3506        element: E,
   3507        context: &mut MatchingContext<E::Impl>,
   3508    ) -> ScopeProximity {
   3509        context
   3510            .extra_data
   3511            .cascade_input_flags
   3512            .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
   3513 
   3514        // Whether the scope root matches a shadow host mostly olny depends on scope-intrinsic
   3515        // parameters (i.e. bounds/implicit scope) - except for the use of `::parts`, where
   3516        // matching crosses the shadow boundary.
   3517        let result = scope_root_candidates(
   3518            &self.scope_conditions,
   3519            rule.scope_condition_id,
   3520            &element,
   3521            rule.selector.is_part(),
   3522            &self.scope_subject_map,
   3523            context,
   3524        );
   3525        for candidate in result.candidates {
   3526            if context.nest_for_scope(Some(candidate.root), |context| {
   3527                matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
   3528            }) {
   3529                return candidate.proximity;
   3530            }
   3531        }
   3532        ScopeProximity::infinity()
   3533    }
   3534 
   3535    fn did_finish_rebuild(&mut self) {
   3536        self.shrink_maps_if_needed();
   3537        self.compute_layer_order();
   3538    }
   3539 
   3540    fn shrink_maps_if_needed(&mut self) {
   3541        self.normal_rules.shrink_if_needed();
   3542        if let Some(ref mut host_rules) = self.featureless_host_rules {
   3543            host_rules.shrink_if_needed();
   3544        }
   3545        if let Some(ref mut slotted_rules) = self.slotted_rules {
   3546            slotted_rules.shrink_if_needed();
   3547        }
   3548        self.animations.shrink_if_needed();
   3549        self.custom_property_registrations.shrink_if_needed();
   3550        self.invalidation_map.shrink_if_needed();
   3551        self.relative_selector_invalidation_map.shrink_if_needed();
   3552        self.additional_relative_selector_invalidation_map
   3553            .shrink_if_needed();
   3554        self.attribute_dependencies.shrink_if_needed();
   3555        self.nth_of_attribute_dependencies.shrink_if_needed();
   3556        self.nth_of_custom_state_dependencies.shrink_if_needed();
   3557        self.nth_of_class_dependencies.shrink_if_needed();
   3558        self.nth_of_mapped_ids.shrink_if_needed();
   3559        self.mapped_ids.shrink_if_needed();
   3560        self.layer_id.shrink_if_needed();
   3561        self.selectors_for_cache_revalidation.shrink_if_needed();
   3562        self.scope_subject_map.shrink_if_needed();
   3563    }
   3564 
   3565    fn compute_layer_order(&mut self) {
   3566        debug_assert_ne!(
   3567            self.layers.len(),
   3568            0,
   3569            "There should be at least the root layer!"
   3570        );
   3571        if self.layers.len() == 1 {
   3572            return; // Nothing to do
   3573        }
   3574        let (first, remaining) = self.layers.split_at_mut(1);
   3575        let root = &mut first[0];
   3576        let mut order = LayerOrder::first();
   3577        compute_layer_order_for_subtree(root, remaining, &mut order);
   3578 
   3579        // NOTE(emilio): This is a bit trickier than it should to avoid having
   3580        // to clone() around layer indices.
   3581        fn compute_layer_order_for_subtree(
   3582            parent: &mut CascadeLayer,
   3583            remaining_layers: &mut [CascadeLayer],
   3584            order: &mut LayerOrder,
   3585        ) {
   3586            for child in parent.children.iter() {
   3587                debug_assert!(
   3588                    parent.id < *child,
   3589                    "Children are always registered after parents"
   3590                );
   3591                let child_index = (child.0 - parent.id.0 - 1) as usize;
   3592                let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
   3593                let child = &mut first[child_index];
   3594                compute_layer_order_for_subtree(child, remaining, order);
   3595            }
   3596 
   3597            if parent.id != LayerId::root() {
   3598                parent.order = *order;
   3599                order.inc();
   3600            }
   3601        }
   3602        #[cfg(feature = "gecko")]
   3603        self.extra_data.sort_by_layer(&self.layers);
   3604        self.animations
   3605            .sort_with(&self.layers, compare_keyframes_in_same_layer);
   3606        self.custom_property_registrations.sort(&self.layers)
   3607    }
   3608 
   3609    /// Collects all the applicable media query results into `results`.
   3610    ///
   3611    /// This duplicates part of the logic in `add_stylesheet`, which is
   3612    /// a bit unfortunate.
   3613    ///
   3614    /// FIXME(emilio): With a bit of smartness in
   3615    /// `media_feature_affected_matches`, we could convert
   3616    /// `EffectiveMediaQueryResults` into a vector without too much effort.
   3617    fn collect_applicable_media_query_results_into<S>(
   3618        device: &Device,
   3619        stylesheet: &S,
   3620        guard: &SharedRwLockReadGuard,
   3621        results: &mut Vec<MediaListKey>,
   3622        contents_list: &mut StyleSheetContentList,
   3623        custom_media_map: &mut CustomMediaMap,
   3624    ) where
   3625        S: StylesheetInDocument + 'static,
   3626    {
   3627        if !stylesheet.enabled() {
   3628            return;
   3629        }
   3630        if !stylesheet.is_effective_for_device(device, &custom_media_map, guard) {
   3631            return;
   3632        }
   3633 
   3634        debug!(" + {:?}", stylesheet);
   3635        let contents = stylesheet.contents(guard);
   3636        results.push(contents.to_media_list_key());
   3637 
   3638        // Safety: StyleSheetContents are reference-counted with Arc.
   3639        contents_list.push(StylesheetContentsPtr(unsafe {
   3640            Arc::from_raw_addrefed(&*contents)
   3641        }));
   3642 
   3643        let mut iter = stylesheet
   3644            .contents(guard)
   3645            .effective_rules(device, custom_media_map, guard);
   3646        while let Some(rule) = iter.next() {
   3647            match *rule {
   3648                CssRule::CustomMedia(ref custom_media) => {
   3649                    iter.custom_media()
   3650                        .insert(custom_media.name.0.clone(), custom_media.condition.clone());
   3651                },
   3652                CssRule::Import(ref lock) => {
   3653                    let import_rule = lock.read_with(guard);
   3654                    debug!(" + {:?}", import_rule.stylesheet.media(guard));
   3655                    results.push(import_rule.to_media_list_key());
   3656                },
   3657                CssRule::Media(ref media_rule) => {
   3658                    debug!(" + {:?}", media_rule.media_queries.read_with(guard));
   3659                    results.push(media_rule.to_media_list_key());
   3660                },
   3661                _ => {},
   3662            }
   3663        }
   3664    }
   3665 
   3666    fn add_styles(
   3667        &mut self,
   3668        selectors: &SelectorList<SelectorImpl>,
   3669        declarations: &Arc<Locked<PropertyDeclarationBlock>>,
   3670        ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
   3671        containing_rule_state: &ContainingRuleState,
   3672        mut replaced_selectors: Option<&mut ReplacedSelectors>,
   3673        guard: &SharedRwLockReadGuard,
   3674        rebuild_kind: SheetRebuildKind,
   3675        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
   3676        quirks_mode: QuirksMode,
   3677        mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
   3678    ) -> Result<(), AllocErr> {
   3679        self.num_declarations += declarations.read_with(guard).len();
   3680        for selector in selectors.slice() {
   3681            self.num_selectors += 1;
   3682 
   3683            let pseudo_elements = selector.pseudo_elements();
   3684            let inner_pseudo_element = pseudo_elements.get(0);
   3685            if let Some(pseudo) = inner_pseudo_element {
   3686                if pseudo.is_precomputed() {
   3687                    debug_assert!(selector.is_universal());
   3688                    debug_assert!(ancestor_selectors.is_none());
   3689                    debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
   3690                    // Because we precompute pseudos, we cannot possibly calculate scope proximity.
   3691                    debug_assert!(!containing_rule_state.scope_is_effective());
   3692                    precomputed_pseudo_element_decls
   3693                        .as_mut()
   3694                        .expect("Expected precomputed declarations for the UA level")
   3695                        .get_or_insert_with(pseudo, Vec::new)
   3696                        .push(ApplicableDeclarationBlock::new(
   3697                            StyleSource::from_declarations(declarations.clone()),
   3698                            self.rules_source_order,
   3699                            CascadeLevel::UANormal,
   3700                            selector.specificity(),
   3701                            LayerOrder::root(),
   3702                            ScopeProximity::infinity(),
   3703                        ));
   3704                    continue;
   3705                }
   3706                if pseudo_elements
   3707                    .iter()
   3708                    .any(|p| p.is_unknown_webkit_pseudo_element())
   3709                {
   3710                    continue;
   3711                }
   3712            }
   3713 
   3714            debug_assert!(!pseudo_elements
   3715                .iter()
   3716                .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
   3717 
   3718            let selector = match ancestor_selectors {
   3719                Some(ref s) => selector.replace_parent_selector(&s),
   3720                None => selector.clone(),
   3721            };
   3722 
   3723            let hashes = AncestorHashes::new(&selector, quirks_mode);
   3724 
   3725            let rule = Rule::new(
   3726                selector,
   3727                hashes,
   3728                StyleSource::from_declarations(declarations.clone()),
   3729                self.rules_source_order,
   3730                containing_rule_state.layer_id,
   3731                containing_rule_state.container_condition_id,
   3732                containing_rule_state.in_starting_style,
   3733                containing_rule_state.containing_scope_rule_state.id,
   3734            );
   3735 
   3736            if let Some(ref mut replaced_selectors) = replaced_selectors {
   3737                replaced_selectors.push(rule.selector.clone())
   3738            }
   3739 
   3740            if rebuild_kind.should_rebuild_invalidation() {
   3741                let mut scope_dependencies = note_selector_for_invalidation(
   3742                    &rule.selector,
   3743                    quirks_mode,
   3744                    &mut self.invalidation_map,
   3745                    &mut self.relative_selector_invalidation_map,
   3746                    &mut self.additional_relative_selector_invalidation_map,
   3747                    None,
   3748                    None,
   3749                )?;
   3750                let mut needs_revalidation = false;
   3751                let mut visitor = StylistSelectorVisitor {
   3752                    needs_revalidation: &mut needs_revalidation,
   3753                    passed_rightmost_selector: false,
   3754                    in_selector_list_of: SelectorListKind::default(),
   3755                    mapped_ids: &mut self.mapped_ids,
   3756                    nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
   3757                    attribute_dependencies: &mut self.attribute_dependencies,
   3758                    nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
   3759                    nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
   3760                    nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
   3761                    state_dependencies: &mut self.state_dependencies,
   3762                    nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
   3763                    document_state_dependencies: &mut self.document_state_dependencies,
   3764                };
   3765                rule.selector.visit(&mut visitor);
   3766 
   3767                if needs_revalidation {
   3768                    self.selectors_for_cache_revalidation.insert(
   3769                        RevalidationSelectorAndHashes::new(
   3770                            rule.selector.clone(),
   3771                            rule.hashes.clone(),
   3772                        ),
   3773                        quirks_mode,
   3774                    )?;
   3775                }
   3776 
   3777                match (
   3778                    scope_dependencies.as_mut(),
   3779                    collected_scope_dependencies.as_mut(),
   3780                ) {
   3781                    (Some(inner_scope_deps), Some(scope_deps)) => {
   3782                        scope_deps.append(inner_scope_deps)
   3783                    },
   3784                    _ => {},
   3785                }
   3786            }
   3787 
   3788            // Part is special, since given it doesn't have any
   3789            // selectors inside, it's not worth using a whole
   3790            // SelectorMap for it.
   3791            if let Some(parts) = rule.selector.parts() {
   3792                // ::part() has all semantics, so we just need to
   3793                // put any of them in the selector map.
   3794                //
   3795                // We choose the last one quite arbitrarily,
   3796                // expecting it's slightly more likely to be more
   3797                // specific.
   3798                let map = self
   3799                    .part_rules
   3800                    .get_or_insert_with(|| Box::new(Default::default()))
   3801                    .for_insertion(&pseudo_elements);
   3802                map.try_reserve(1)?;
   3803                let vec = map.entry(parts.last().unwrap().clone().0).or_default();
   3804                vec.try_reserve(1)?;
   3805                vec.push(rule);
   3806            } else {
   3807                let scope_matches_shadow_host = containing_rule_state
   3808                    .containing_scope_rule_state
   3809                    .matches_shadow_host
   3810                    == ScopeMatchesShadowHost::Yes;
   3811                let matches_featureless_host_only = match rule
   3812                    .selector
   3813                    .matches_featureless_host(scope_matches_shadow_host)
   3814                {
   3815                    MatchesFeaturelessHost::Only => true,
   3816                    MatchesFeaturelessHost::Yes => {
   3817                        // We need to insert this in featureless_host_rules but also normal_rules.
   3818                        self.featureless_host_rules
   3819                            .get_or_insert_with(|| Box::new(Default::default()))
   3820                            .for_insertion(&pseudo_elements)
   3821                            .insert(rule.clone(), quirks_mode)?;
   3822                        false
   3823                    },
   3824                    MatchesFeaturelessHost::Never => false,
   3825                };
   3826 
   3827                // NOTE(emilio): It's fine to look at :host and then at
   3828                // ::slotted(..), since :host::slotted(..) could never
   3829                // possibly match, as <slot> is not a valid shadow host.
   3830                // :scope may match featureless shadow host if the scope
   3831                // root is the shadow root.
   3832                // See https://github.com/w3c/csswg-drafts/issues/9025
   3833                let rules = if matches_featureless_host_only {
   3834                    self.featureless_host_rules
   3835                        .get_or_insert_with(|| Box::new(Default::default()))
   3836                } else if rule.selector.is_slotted() {
   3837                    self.slotted_rules
   3838                        .get_or_insert_with(|| Box::new(Default::default()))
   3839                } else {
   3840                    &mut self.normal_rules
   3841                }
   3842                .for_insertion(&pseudo_elements);
   3843                rules.insert(rule, quirks_mode)?;
   3844            }
   3845        }
   3846        self.rules_source_order += 1;
   3847        Ok(())
   3848    }
   3849 
   3850    fn add_rule_list<S>(
   3851        &mut self,
   3852        rules: std::slice::Iter<CssRule>,
   3853        device: &Device,
   3854        quirks_mode: QuirksMode,
   3855        stylesheet: &S,
   3856        sheet_index: usize,
   3857        guard: &SharedRwLockReadGuard,
   3858        rebuild_kind: SheetRebuildKind,
   3859        containing_rule_state: &mut ContainingRuleState,
   3860        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
   3861        mut difference: Option<&mut CascadeDataDifference>,
   3862    ) -> Result<(), AllocErr>
   3863    where
   3864        S: StylesheetInDocument + 'static,
   3865    {
   3866        for rule in rules {
   3867            // Handle leaf rules first, as those are by far the most common
   3868            // ones, and are always effective, so we can skip some checks.
   3869            let mut handled = true;
   3870            let mut list_for_nested_rules = None;
   3871            match *rule {
   3872                CssRule::Style(ref locked) => {
   3873                    let style_rule = locked.read_with(guard);
   3874                    let has_nested_rules = style_rule.rules.is_some();
   3875                    let mut replaced_selectors = ReplacedSelectors::new();
   3876                    let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
   3877                    let collect_replaced_selectors =
   3878                        has_nested_rules && ancestor_selectors.is_some();
   3879                    let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
   3880                        .scope_is_effective()
   3881                        .then(|| Vec::new());
   3882                    self.add_styles(
   3883                        &style_rule.selectors,
   3884                        &style_rule.block,
   3885                        ancestor_selectors,
   3886                        containing_rule_state,
   3887                        if collect_replaced_selectors {
   3888                            Some(&mut replaced_selectors)
   3889                        } else {
   3890                            None
   3891                        },
   3892                        guard,
   3893                        rebuild_kind,
   3894                        precomputed_pseudo_element_decls.as_deref_mut(),
   3895                        quirks_mode,
   3896                        inner_dependencies.as_mut(),
   3897                    )?;
   3898                    if let Some(mut scope_dependencies) = inner_dependencies {
   3899                        containing_rule_state
   3900                            .containing_scope_rule_state
   3901                            .inner_dependencies
   3902                            .append(&mut scope_dependencies);
   3903                    }
   3904                    if has_nested_rules {
   3905                        handled = false;
   3906                        list_for_nested_rules = Some(if collect_replaced_selectors {
   3907                            SelectorList::from_iter(replaced_selectors.drain(..))
   3908                        } else {
   3909                            style_rule.selectors.clone()
   3910                        });
   3911                    }
   3912                },
   3913                CssRule::NestedDeclarations(ref rule) => {
   3914                    if let Some(ref ancestor_selectors) =
   3915                        containing_rule_state.ancestor_selector_lists.last()
   3916                    {
   3917                        let decls = &rule.read_with(guard).block;
   3918                        let selectors = match containing_rule_state.nested_declarations_context {
   3919                            NestedDeclarationsContext::Style => ancestor_selectors,
   3920                            NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
   3921                        };
   3922                        let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
   3923                            .scope_is_effective()
   3924                            .then(|| Vec::new());
   3925                        self.add_styles(
   3926                            selectors,
   3927                            decls,
   3928                            /* ancestor_selectors = */ None,
   3929                            containing_rule_state,
   3930                            /* replaced_selectors = */ None,
   3931                            guard,
   3932                            // We don't need to rebuild invalidation data, since our ancestor style
   3933                            // rule would've done this.
   3934                            SheetRebuildKind::CascadeOnly,
   3935                            precomputed_pseudo_element_decls.as_deref_mut(),
   3936                            quirks_mode,
   3937                            inner_dependencies.as_mut(),
   3938                        )?;
   3939                        if let Some(mut scope_dependencies) = inner_dependencies {
   3940                            containing_rule_state
   3941                                .containing_scope_rule_state
   3942                                .inner_dependencies
   3943                                .append(&mut scope_dependencies);
   3944                        }
   3945                    }
   3946                },
   3947                CssRule::Keyframes(ref keyframes_rule) => {
   3948                    debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
   3949                    let keyframes_rule = keyframes_rule.read_with(guard);
   3950                    let name = keyframes_rule.name.as_atom().clone();
   3951                    let animation = KeyframesAnimation::from_keyframes(
   3952                        &keyframes_rule.keyframes,
   3953                        keyframes_rule.vendor_prefix.clone(),
   3954                        guard,
   3955                    );
   3956                    self.animations.try_insert_with(
   3957                        name,
   3958                        animation,
   3959                        containing_rule_state.layer_id,
   3960                        compare_keyframes_in_same_layer,
   3961                    )?;
   3962                },
   3963                CssRule::Property(ref registration) => {
   3964                    self.custom_property_registrations.try_insert(
   3965                        registration.name.0.clone(),
   3966                        Arc::clone(registration),
   3967                        containing_rule_state.layer_id,
   3968                    )?;
   3969                },
   3970                CssRule::FontFace(ref rule) => {
   3971                    // NOTE(emilio): We don't care about container_condition_id
   3972                    // because:
   3973                    //
   3974                    //     Global, name-defining at-rules such as @keyframes or
   3975                    //     @font-face or @layer that are defined inside container
   3976                    //     queries are not constrained by the container query
   3977                    //     conditions.
   3978                    //
   3979                    // https://drafts.csswg.org/css-contain-3/#container-rule
   3980                    // (Same elsewhere)
   3981                    self.extra_data
   3982                        .add_font_face(rule, containing_rule_state.layer_id);
   3983                },
   3984                CssRule::FontFeatureValues(ref rule) => {
   3985                    self.extra_data
   3986                        .add_font_feature_values(rule, containing_rule_state.layer_id);
   3987                },
   3988                CssRule::FontPaletteValues(ref rule) => {
   3989                    self.extra_data
   3990                        .add_font_palette_values(rule, containing_rule_state.layer_id);
   3991                },
   3992                CssRule::CounterStyle(ref rule) => {
   3993                    self.extra_data.add_counter_style(
   3994                        guard,
   3995                        rule,
   3996                        containing_rule_state.layer_id,
   3997                    )?;
   3998                },
   3999                CssRule::PositionTry(ref rule) => {
   4000                    let name = rule.read_with(guard).name.0.clone();
   4001                    if let Some(ref mut difference) = difference {
   4002                        difference.changed_position_try_names.insert(name.clone());
   4003                    }
   4004                    self.extra_data.add_position_try(
   4005                        name,
   4006                        rule.clone(),
   4007                        containing_rule_state.layer_id,
   4008                    )?;
   4009                },
   4010                CssRule::Page(ref rule) => {
   4011                    self.extra_data
   4012                        .add_page(guard, rule, containing_rule_state.layer_id)?;
   4013                    handled = false;
   4014                },
   4015                _ => {
   4016                    handled = false;
   4017                },
   4018            }
   4019 
   4020            if handled {
   4021                // Assert that there are no children, and that the rule is
   4022                // effective.
   4023                if cfg!(debug_assertions) {
   4024                    let mut effective = false;
   4025                    let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
   4026                        rule,
   4027                        device,
   4028                        quirks_mode,
   4029                        &self.custom_media,
   4030                        guard,
   4031                        &mut effective,
   4032                    );
   4033                    debug_assert!(children.is_none());
   4034                    debug_assert!(effective);
   4035                }
   4036                continue;
   4037            }
   4038 
   4039            let mut effective = false;
   4040            let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
   4041                rule,
   4042                device,
   4043                quirks_mode,
   4044                &self.custom_media,
   4045                guard,
   4046                &mut effective,
   4047            );
   4048            if !effective {
   4049                continue;
   4050            }
   4051 
   4052            fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
   4053                // TODO: Measure what's more common / expensive, if
   4054                // layer.clone() or the double hash lookup in the insert
   4055                // case.
   4056                if let Some(id) = data.layer_id.get(layer) {
   4057                    return *id;
   4058                }
   4059                let id = LayerId(data.layers.len() as u16);
   4060 
   4061                let parent_layer_id = if layer.layer_names().len() > 1 {
   4062                    let mut parent = layer.clone();
   4063                    parent.0.pop();
   4064 
   4065                    *data
   4066                        .layer_id
   4067                        .get_mut(&parent)
   4068                        .expect("Parent layers should be registered before child layers")
   4069                } else {
   4070                    LayerId::root()
   4071                };
   4072 
   4073                data.layers[parent_layer_id.0 as usize].children.push(id);
   4074                data.layers.push(CascadeLayer {
   4075                    id,
   4076                    // NOTE(emilio): Order is evaluated after rebuild in
   4077                    // compute_layer_order.
   4078                    order: LayerOrder::first(),
   4079                    children: vec![],
   4080                });
   4081 
   4082                data.layer_id.insert(layer.clone(), id);
   4083 
   4084                id
   4085            }
   4086 
   4087            fn maybe_register_layers(
   4088                data: &mut CascadeData,
   4089                name: Option<&LayerName>,
   4090                containing_rule_state: &mut ContainingRuleState,
   4091            ) {
   4092                let anon_name;
   4093                let name = match name {
   4094                    Some(name) => name,
   4095                    None => {
   4096                        anon_name = LayerName::new_anonymous();
   4097                        &anon_name
   4098                    },
   4099                };
   4100                for name in name.layer_names() {
   4101                    containing_rule_state.layer_name.0.push(name.clone());
   4102                    containing_rule_state.layer_id =
   4103                        maybe_register_layer(data, &containing_rule_state.layer_name);
   4104                }
   4105                debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
   4106            }
   4107 
   4108            let saved_containing_rule_state = containing_rule_state.save();
   4109            match *rule {
   4110                CssRule::Import(ref lock) => {
   4111                    let import_rule = lock.read_with(guard);
   4112                    if rebuild_kind.should_rebuild_invalidation() {
   4113                        self.effective_media_query_results
   4114                            .saw_effective(import_rule);
   4115                    }
   4116                    match import_rule.layer {
   4117                        ImportLayer::Named(ref name) => {
   4118                            maybe_register_layers(self, Some(name), containing_rule_state)
   4119                        },
   4120                        ImportLayer::Anonymous => {
   4121                            maybe_register_layers(self, None, containing_rule_state)
   4122                        },
   4123                        ImportLayer::None => {},
   4124                    }
   4125                },
   4126                CssRule::Media(ref media_rule) => {
   4127                    if rebuild_kind.should_rebuild_invalidation() {
   4128                        self.effective_media_query_results
   4129                            .saw_effective(&**media_rule);
   4130                    }
   4131                },
   4132                CssRule::LayerBlock(ref rule) => {
   4133                    maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
   4134                },
   4135                CssRule::CustomMedia(ref custom_media) => {
   4136                    self.custom_media
   4137                        .insert(custom_media.name.0.clone(), custom_media.condition.clone());
   4138                },
   4139                CssRule::LayerStatement(ref rule) => {
   4140                    for name in &*rule.names {
   4141                        maybe_register_layers(self, Some(name), containing_rule_state);
   4142                        // Register each layer individually.
   4143                        containing_rule_state.restore(&saved_containing_rule_state);
   4144                    }
   4145                },
   4146                CssRule::Style(..) => {
   4147                    containing_rule_state.nested_declarations_context =
   4148                        NestedDeclarationsContext::Style;
   4149                    if let Some(s) = list_for_nested_rules {
   4150                        containing_rule_state.ancestor_selector_lists.push(s);
   4151                    }
   4152                },
   4153                CssRule::Container(ref rule) => {
   4154                    let id = ContainerConditionId(self.container_conditions.len() as u16);
   4155                    self.container_conditions.push(ContainerConditionReference {
   4156                        parent: containing_rule_state.container_condition_id,
   4157                        condition: Some(rule.condition.clone()),
   4158                    });
   4159                    containing_rule_state.container_condition_id = id;
   4160                },
   4161                CssRule::StartingStyle(..) => {
   4162                    containing_rule_state.in_starting_style = true;
   4163                },
   4164                CssRule::Scope(ref rule) => {
   4165                    containing_rule_state.nested_declarations_context =
   4166                        NestedDeclarationsContext::Scope;
   4167                    let id = ScopeConditionId(self.scope_conditions.len() as u16);
   4168                    let mut matches_shadow_host = false;
   4169                    let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
   4170                        matches_shadow_host = scope_start_matches_shadow_host(start);
   4171                        // Would be unused, but use the default as fallback.
   4172                        StylistImplicitScopeRoot::default()
   4173                    } else {
   4174                        // (Re)Moving stylesheets trigger a complete flush, so saving the implicit
   4175                        // root here should be safe.
   4176                        if let Some(root) = stylesheet.implicit_scope_root() {
   4177                            matches_shadow_host = root.matches_shadow_host();
   4178                            match root {
   4179                                ImplicitScopeRoot::InLightTree(_)
   4180                                | ImplicitScopeRoot::Constructed
   4181                                | ImplicitScopeRoot::DocumentElement => {
   4182                                    StylistImplicitScopeRoot::Normal(root)
   4183                                },
   4184                                ImplicitScopeRoot::ShadowHost(_)
   4185                                | ImplicitScopeRoot::InShadowTree(_) => {
   4186                                    // Style data can be shared between shadow trees, so we must
   4187                                    // query the implicit root for that specific tree.
   4188                                    // Shared stylesheet means shared sheet indices, so we can
   4189                                    // use that to locate the implicit root.
   4190                                    // Technically, this can also be applied to the light tree,
   4191                                    // but that requires also knowing about what cascade level we're at.
   4192                                    StylistImplicitScopeRoot::Cached(sheet_index)
   4193                                },
   4194                            }
   4195                        } else {
   4196                            // Could not find implicit scope root, but use the default as fallback.
   4197                            StylistImplicitScopeRoot::default()
   4198                        }
   4199                    };
   4200 
   4201                    let replaced =
   4202                        {
   4203                            let start = rule.bounds.start.as_ref().map(|selector| {
   4204                                match containing_rule_state.ancestor_selector_lists.last() {
   4205                                    Some(s) => selector.replace_parent_selector(s),
   4206                                    None => selector.clone(),
   4207                                }
   4208                            });
   4209                            let implicit_scope_selector = &*IMPLICIT_SCOPE;
   4210                            let end = rule.bounds.end.as_ref().map(|selector| {
   4211                                selector.replace_parent_selector(implicit_scope_selector)
   4212                            });
   4213                            containing_rule_state
   4214                                .ancestor_selector_lists
   4215                                .push(implicit_scope_selector.clone());
   4216                            ScopeBoundsWithHashes::new(quirks_mode, start, end)
   4217                        };
   4218 
   4219                    if let Some(selectors) = replaced.start.as_ref() {
   4220                        self.scope_subject_map
   4221                            .add_bound_start(&selectors.selectors, quirks_mode);
   4222                    }
   4223 
   4224                    let is_trivial = replaced.is_trivial();
   4225                    self.scope_conditions.push(ScopeConditionReference {
   4226                        parent: containing_rule_state.containing_scope_rule_state.id,
   4227                        condition: Some(replaced),
   4228                        implicit_scope_root,
   4229                        is_trivial,
   4230                    });
   4231 
   4232                    containing_rule_state
   4233                        .containing_scope_rule_state
   4234                        .matches_shadow_host
   4235                        .nest_for_scope(matches_shadow_host);
   4236                    containing_rule_state.containing_scope_rule_state.id = id;
   4237                    containing_rule_state
   4238                        .containing_scope_rule_state
   4239                        .inner_dependencies
   4240                        .reserve(children.iter().len());
   4241                },
   4242                // We don't care about any other rule.
   4243                _ => {},
   4244            }
   4245 
   4246            if let Some(children) = children {
   4247                self.add_rule_list(
   4248                    children,
   4249                    device,
   4250                    quirks_mode,
   4251                    stylesheet,
   4252                    sheet_index,
   4253                    guard,
   4254                    rebuild_kind,
   4255                    containing_rule_state,
   4256                    precomputed_pseudo_element_decls.as_deref_mut(),
   4257                    difference.as_deref_mut(),
   4258                )?;
   4259            }
   4260 
   4261            if let Some(scope_restore_data) =
   4262                containing_rule_state.restore(&saved_containing_rule_state)
   4263            {
   4264                let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
   4265                let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
   4266                if let Some(cond) = cur_scope.condition.as_ref() {
   4267                    let mut _unused = false;
   4268                    let visitor = StylistSelectorVisitor {
   4269                        needs_revalidation: &mut _unused,
   4270                        passed_rightmost_selector: true,
   4271                        in_selector_list_of: SelectorListKind::default(),
   4272                        mapped_ids: &mut self.mapped_ids,
   4273                        nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
   4274                        attribute_dependencies: &mut self.attribute_dependencies,
   4275                        nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
   4276                        nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
   4277                        nth_of_custom_state_dependencies: &mut self
   4278                            .nth_of_custom_state_dependencies,
   4279                        state_dependencies: &mut self.state_dependencies,
   4280                        nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
   4281                        document_state_dependencies: &mut self.document_state_dependencies,
   4282                    };
   4283 
   4284                    let dependency_vector = build_scope_dependencies(
   4285                        quirks_mode,
   4286                        cur_scope_inner_dependencies,
   4287                        visitor,
   4288                        cond,
   4289                        &mut self.invalidation_map,
   4290                        &mut self.relative_selector_invalidation_map,
   4291                        &mut self.additional_relative_selector_invalidation_map,
   4292                    )?;
   4293 
   4294                    containing_rule_state
   4295                        .containing_scope_rule_state
   4296                        .inner_dependencies
   4297                        .extend(dependency_vector);
   4298                }
   4299            }
   4300        }
   4301 
   4302        Ok(())
   4303    }
   4304 
   4305    // Returns Err(..) to signify OOM
   4306    fn add_stylesheet<S>(
   4307        &mut self,
   4308        device: &Device,
   4309        quirks_mode: QuirksMode,
   4310        stylesheet: &S,
   4311        sheet_index: usize,
   4312        guard: &SharedRwLockReadGuard,
   4313        rebuild_kind: SheetRebuildKind,
   4314        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
   4315        mut difference: Option<&mut CascadeDataDifference>,
   4316    ) -> Result<(), AllocErr>
   4317    where
   4318        S: StylesheetInDocument + 'static,
   4319    {
   4320        if !stylesheet.enabled() {
   4321            return Ok(());
   4322        }
   4323 
   4324        if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
   4325            return Ok(());
   4326        }
   4327 
   4328        let contents = stylesheet.contents(guard);
   4329        if rebuild_kind.should_rebuild_invalidation() {
   4330            self.effective_media_query_results.saw_effective(&*contents);
   4331        }
   4332 
   4333        let mut state = ContainingRuleState::default();
   4334        self.add_rule_list(
   4335            contents.rules(guard).iter(),
   4336            device,
   4337            quirks_mode,
   4338            stylesheet,
   4339            sheet_index,
   4340            guard,
   4341            rebuild_kind,
   4342            &mut state,
   4343            precomputed_pseudo_element_decls.as_deref_mut(),
   4344            difference.as_deref_mut(),
   4345        )?;
   4346 
   4347        Ok(())
   4348    }
   4349 
   4350    /// Returns whether all the media-feature affected values matched before and
   4351    /// match now in the given stylesheet.
   4352    pub fn media_feature_affected_matches<S>(
   4353        &self,
   4354        stylesheet: &S,
   4355        guard: &SharedRwLockReadGuard,
   4356        device: &Device,
   4357        quirks_mode: QuirksMode,
   4358    ) -> bool
   4359    where
   4360        S: StylesheetInDocument + 'static,
   4361    {
   4362        use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
   4363 
   4364        let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
   4365 
   4366        let contents = stylesheet.contents(guard);
   4367        let effective_then = self.effective_media_query_results.was_effective(contents);
   4368 
   4369        if effective_now != effective_then {
   4370            debug!(
   4371                " > Stylesheet {:?} changed -> {}, {}",
   4372                stylesheet.media(guard),
   4373                effective_then,
   4374                effective_now
   4375            );
   4376            return false;
   4377        }
   4378 
   4379        if !effective_now {
   4380            return true;
   4381        }
   4382 
   4383        // We don't need a custom media map for PotentiallyEffectiveMediaRules.
   4384        let custom_media = CustomMediaMap::default();
   4385        let mut iter =
   4386            contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
   4387        while let Some(rule) = iter.next() {
   4388            match *rule {
   4389                CssRule::Style(..)
   4390                | CssRule::NestedDeclarations(..)
   4391                | CssRule::Namespace(..)
   4392                | CssRule::FontFace(..)
   4393                | CssRule::Container(..)
   4394                | CssRule::CounterStyle(..)
   4395                | CssRule::Supports(..)
   4396                | CssRule::Keyframes(..)
   4397                | CssRule::Margin(..)
   4398                | CssRule::Page(..)
   4399                | CssRule::Property(..)
   4400                | CssRule::Document(..)
   4401                | CssRule::LayerBlock(..)
   4402                | CssRule::LayerStatement(..)
   4403                | CssRule::FontPaletteValues(..)
   4404                | CssRule::FontFeatureValues(..)
   4405                | CssRule::Scope(..)
   4406                | CssRule::StartingStyle(..)
   4407                | CssRule::CustomMedia(..)
   4408                | CssRule::PositionTry(..) => {
   4409                    // Not affected by device changes. @custom-media is handled by the potential
   4410                    // @media rules referencing it being handled.
   4411                    continue;
   4412                },
   4413                CssRule::Import(ref lock) => {
   4414                    let import_rule = lock.read_with(guard);
   4415                    let effective_now = match import_rule.stylesheet.media(guard) {
   4416                        Some(m) => m.evaluate(
   4417                            device,
   4418                            quirks_mode,
   4419                            &mut CustomMediaEvaluator::new(&self.custom_media, guard),
   4420                        ),
   4421                        None => true,
   4422                    };
   4423                    let effective_then = self
   4424                        .effective_media_query_results
   4425                        .was_effective(import_rule);
   4426                    if effective_now != effective_then {
   4427                        debug!(
   4428                            " > @import rule {:?} changed {} -> {}",
   4429                            import_rule.stylesheet.media(guard),
   4430                            effective_then,
   4431                            effective_now
   4432                        );
   4433                        return false;
   4434                    }
   4435 
   4436                    if !effective_now {
   4437                        iter.skip_children();
   4438                    }
   4439                },
   4440                CssRule::Media(ref media_rule) => {
   4441                    let mq = media_rule.media_queries.read_with(guard);
   4442                    let effective_now = mq.evaluate(
   4443                        device,
   4444                        quirks_mode,
   4445                        &mut CustomMediaEvaluator::new(&self.custom_media, guard),
   4446                    );
   4447                    let effective_then = self
   4448                        .effective_media_query_results
   4449                        .was_effective(&**media_rule);
   4450 
   4451                    if effective_now != effective_then {
   4452                        debug!(
   4453                            " > @media rule {:?} changed {} -> {}",
   4454                            mq, effective_then, effective_now
   4455                        );
   4456                        return false;
   4457                    }
   4458 
   4459                    if !effective_now {
   4460                        iter.skip_children();
   4461                    }
   4462                },
   4463            }
   4464        }
   4465 
   4466        true
   4467    }
   4468 
   4469    /// Returns the custom properties map.
   4470    pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
   4471        &self.custom_property_registrations
   4472    }
   4473 
   4474    fn revalidate_scopes<E: TElement>(
   4475        &self,
   4476        element: &E,
   4477        matching_context: &mut MatchingContext<E::Impl>,
   4478        result: &mut ScopeRevalidationResult,
   4479    ) {
   4480        // TODO(dshin): A scope block may not contain style rule for this element, but we don't keep
   4481        // track of that, so we check _all_ scope conditions. It's possible for two comparable elements
   4482        // to share scope & relevant styles rules, but also differ in scopes that do not contain style
   4483        // rules relevant to them. So while we can be certain that an identical result share scoped styles
   4484        // (Given that other sharing conditions are met), it is uncertain if elements with non-matching
   4485        // results do not.
   4486        for condition_id in 1..self.scope_conditions.len() {
   4487            let condition = &self.scope_conditions[condition_id];
   4488            let matches = if condition.is_trivial {
   4489                // Just ignore this condition - for style sharing candidates, guaranteed
   4490                // the same match result.
   4491                continue;
   4492            } else {
   4493                let result = scope_root_candidates(
   4494                    &self.scope_conditions,
   4495                    ScopeConditionId(condition_id as u16),
   4496                    element,
   4497                    // This should be ok since we aren't sharing styles across shadow boundaries.
   4498                    false,
   4499                    &self.scope_subject_map,
   4500                    matching_context,
   4501                );
   4502                !result.candidates.is_empty()
   4503            };
   4504            result.scopes_matched.push(matches);
   4505        }
   4506    }
   4507 
   4508    /// Clears the cascade data, but not the invalidation data.
   4509    fn clear_cascade_data(&mut self) {
   4510        self.normal_rules.clear();
   4511        if let Some(ref mut slotted_rules) = self.slotted_rules {
   4512            slotted_rules.clear();
   4513        }
   4514        if let Some(ref mut part_rules) = self.part_rules {
   4515            part_rules.clear();
   4516        }
   4517        if let Some(ref mut host_rules) = self.featureless_host_rules {
   4518            host_rules.clear();
   4519        }
   4520        self.animations.clear();
   4521        self.custom_property_registrations.clear();
   4522        self.layer_id.clear();
   4523        self.layers.clear();
   4524        self.layers.push(CascadeLayer::root());
   4525        self.custom_media.clear();
   4526        self.container_conditions.clear();
   4527        self.container_conditions
   4528            .push(ContainerConditionReference::none());
   4529        self.scope_conditions.clear();
   4530        self.scope_conditions.push(ScopeConditionReference::none());
   4531        #[cfg(feature = "gecko")]
   4532        self.extra_data.clear();
   4533        self.rules_source_order = 0;
   4534        self.num_selectors = 0;
   4535        self.num_declarations = 0;
   4536    }
   4537 
   4538    fn clear_invalidation_data(&mut self) {
   4539        self.invalidation_map.clear();
   4540        self.relative_selector_invalidation_map.clear();
   4541        self.additional_relative_selector_invalidation_map.clear();
   4542        self.attribute_dependencies.clear();
   4543        self.nth_of_attribute_dependencies.clear();
   4544        self.nth_of_custom_state_dependencies.clear();
   4545        self.nth_of_class_dependencies.clear();
   4546        self.state_dependencies = ElementState::empty();
   4547        self.nth_of_state_dependencies = ElementState::empty();
   4548        self.document_state_dependencies = DocumentState::empty();
   4549        self.mapped_ids.clear();
   4550        self.nth_of_mapped_ids.clear();
   4551        self.selectors_for_cache_revalidation.clear();
   4552        self.effective_media_query_results.clear();
   4553        self.scope_subject_map.clear();
   4554    }
   4555 }
   4556 
   4557 fn note_scope_selector_for_invalidation(
   4558    quirks_mode: QuirksMode,
   4559    scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
   4560    dependency_vector: &mut Vec<Dependency>,
   4561    invalidation_map: &mut InvalidationMap,
   4562    relative_selector_invalidation_map: &mut InvalidationMap,
   4563    additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
   4564    visitor: &mut StylistSelectorVisitor<'_>,
   4565    scope_kind: ScopeDependencyInvalidationKind,
   4566    s: &Selector<SelectorImpl>,
   4567 ) -> Result<(), AllocErr> {
   4568    let mut new_inner_dependencies = note_selector_for_invalidation(
   4569        &s.clone(),
   4570        quirks_mode,
   4571        invalidation_map,
   4572        relative_selector_invalidation_map,
   4573        additional_relative_selector_invalidation_map,
   4574        Some(&scope_dependencies),
   4575        Some(scope_kind),
   4576    )?;
   4577    s.visit(visitor);
   4578    new_inner_dependencies.as_mut().map(|dep| {
   4579        dependency_vector.append(dep);
   4580    });
   4581    Ok(())
   4582 }
   4583 
   4584 fn build_scope_dependencies(
   4585    quirks_mode: QuirksMode,
   4586    mut cur_scope_inner_dependencies: Vec<Dependency>,
   4587    mut visitor: StylistSelectorVisitor<'_>,
   4588    cond: &ScopeBoundsWithHashes,
   4589    mut invalidation_map: &mut InvalidationMap,
   4590    mut relative_selector_invalidation_map: &mut InvalidationMap,
   4591    mut additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
   4592 ) -> Result<Vec<Dependency>, AllocErr> {
   4593    if cond.end.is_some() {
   4594        let deps =
   4595            ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
   4596        let mut end_dependency_vector = Vec::new();
   4597        for s in cond.end_selectors() {
   4598            note_scope_selector_for_invalidation(
   4599                quirks_mode,
   4600                &deps,
   4601                &mut end_dependency_vector,
   4602                &mut invalidation_map,
   4603                &mut relative_selector_invalidation_map,
   4604                &mut additional_relative_selector_invalidation_map,
   4605                &mut visitor,
   4606                ScopeDependencyInvalidationKind::ScopeEnd,
   4607                s,
   4608            )?;
   4609        }
   4610        cur_scope_inner_dependencies.append(&mut end_dependency_vector);
   4611    }
   4612    let inner_scope_dependencies =
   4613        ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
   4614 
   4615    Ok(if cond.start.is_some() {
   4616        let mut dependency_vector = Vec::new();
   4617        for s in cond.start_selectors() {
   4618            note_scope_selector_for_invalidation(
   4619                quirks_mode,
   4620                &inner_scope_dependencies,
   4621                &mut dependency_vector,
   4622                &mut invalidation_map,
   4623                &mut relative_selector_invalidation_map,
   4624                &mut additional_relative_selector_invalidation_map,
   4625                &mut visitor,
   4626                ScopeDependencyInvalidationKind::ExplicitScope,
   4627                s,
   4628            )?;
   4629        }
   4630        dependency_vector
   4631    } else {
   4632        vec![Dependency::new(
   4633            IMPLICIT_SCOPE.slice()[0].clone(),
   4634            0,
   4635            Some(inner_scope_dependencies),
   4636            DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
   4637        )]
   4638    })
   4639 }
   4640 
   4641 impl CascadeDataCacheEntry for CascadeData {
   4642    fn rebuild<S>(
   4643        device: &Device,
   4644        quirks_mode: QuirksMode,
   4645        collection: SheetCollectionFlusher<S>,
   4646        guard: &SharedRwLockReadGuard,
   4647        old: &Self,
   4648        difference: &mut CascadeDataDifference,
   4649    ) -> Result<Arc<Self>, AllocErr>
   4650    where
   4651        S: StylesheetInDocument + PartialEq + 'static,
   4652    {
   4653        debug_assert!(collection.dirty(), "We surely need to do something?");
   4654        // If we're doing a full rebuild anyways, don't bother cloning the data.
   4655        let mut updatable_entry = match collection.data_validity() {
   4656            DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
   4657            DataValidity::FullyInvalid => Self::new(),
   4658        };
   4659        updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
   4660        Ok(Arc::new(updatable_entry))
   4661    }
   4662 
   4663    #[cfg(feature = "gecko")]
   4664    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
   4665        self.normal_rules.add_size_of(ops, sizes);
   4666        if let Some(ref slotted_rules) = self.slotted_rules {
   4667            slotted_rules.add_size_of(ops, sizes);
   4668        }
   4669        if let Some(ref part_rules) = self.part_rules {
   4670            part_rules.add_size_of(ops, sizes);
   4671        }
   4672        if let Some(ref host_rules) = self.featureless_host_rules {
   4673            host_rules.add_size_of(ops, sizes);
   4674        }
   4675        sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
   4676        sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
   4677        sizes.mOther += self.animations.size_of(ops);
   4678        sizes.mOther += self.effective_media_query_results.size_of(ops);
   4679        sizes.mOther += self.extra_data.size_of(ops);
   4680    }
   4681 }
   4682 
   4683 impl Default for CascadeData {
   4684    fn default() -> Self {
   4685        CascadeData::new()
   4686    }
   4687 }
   4688 
   4689 /// A rule, that wraps a style rule, but represents a single selector of the
   4690 /// rule.
   4691 #[derive(Clone, Debug, MallocSizeOf)]
   4692 pub struct Rule {
   4693    /// The selector this struct represents. We store this and the
   4694    /// any_{important,normal} booleans inline in the Rule to avoid
   4695    /// pointer-chasing when gathering applicable declarations, which
   4696    /// can ruin performance when there are a lot of rules.
   4697    #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
   4698    pub selector: Selector<SelectorImpl>,
   4699 
   4700    /// The ancestor hashes associated with the selector.
   4701    pub hashes: AncestorHashes,
   4702 
   4703    /// The source order this style rule appears in. Note that we only use
   4704    /// three bytes to store this value in ApplicableDeclarationsBlock, so
   4705    /// we could repurpose that storage here if we needed to.
   4706    pub source_order: u32,
   4707 
   4708    /// The current layer id of this style rule.
   4709    pub layer_id: LayerId,
   4710 
   4711    /// The current @container rule id.
   4712    pub container_condition_id: ContainerConditionId,
   4713 
   4714    /// True if this rule is inside @starting-style.
   4715    pub is_starting_style: bool,
   4716 
   4717    /// The current @scope rule id.
   4718    pub scope_condition_id: ScopeConditionId,
   4719 
   4720    /// The actual style rule.
   4721    #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
   4722    pub style_source: StyleSource,
   4723 }
   4724 
   4725 impl SelectorMapEntry for Rule {
   4726    fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
   4727        self.selector.iter()
   4728    }
   4729 }
   4730 
   4731 impl Rule {
   4732    /// Returns the specificity of the rule.
   4733    pub fn specificity(&self) -> u32 {
   4734        self.selector.specificity()
   4735    }
   4736 
   4737    /// Turns this rule into an `ApplicableDeclarationBlock` for the given
   4738    /// cascade level.
   4739    pub fn to_applicable_declaration_block(
   4740        &self,
   4741        level: CascadeLevel,
   4742        cascade_data: &CascadeData,
   4743        scope_proximity: ScopeProximity,
   4744    ) -> ApplicableDeclarationBlock {
   4745        ApplicableDeclarationBlock::new(
   4746            self.style_source.clone(),
   4747            self.source_order,
   4748            level,
   4749            self.specificity(),
   4750            cascade_data.layer_order_for(self.layer_id),
   4751            scope_proximity,
   4752        )
   4753    }
   4754 
   4755    /// Creates a new Rule.
   4756    pub fn new(
   4757        selector: Selector<SelectorImpl>,
   4758        hashes: AncestorHashes,
   4759        style_source: StyleSource,
   4760        source_order: u32,
   4761        layer_id: LayerId,
   4762        container_condition_id: ContainerConditionId,
   4763        is_starting_style: bool,
   4764        scope_condition_id: ScopeConditionId,
   4765    ) -> Self {
   4766        Self {
   4767            selector,
   4768            hashes,
   4769            style_source,
   4770            source_order,
   4771            layer_id,
   4772            container_condition_id,
   4773            is_starting_style,
   4774            scope_condition_id,
   4775        }
   4776    }
   4777 }
   4778 
   4779 // The size of this is critical to performance on the bloom-basic
   4780 // microbenchmark.
   4781 // When iterating over a large Rule array, we want to be able to fast-reject
   4782 // selectors (with the inline hashes) with as few cache misses as possible.
   4783 size_of_test!(Rule, 40);
   4784 
   4785 /// A function to be able to test the revalidation stuff.
   4786 pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
   4787    let mut needs_revalidation = false;
   4788    let mut mapped_ids = Default::default();
   4789    let mut nth_of_mapped_ids = Default::default();
   4790    let mut attribute_dependencies = Default::default();
   4791    let mut nth_of_class_dependencies = Default::default();
   4792    let mut nth_of_attribute_dependencies = Default::default();
   4793    let mut nth_of_custom_state_dependencies = Default::default();
   4794    let mut state_dependencies = ElementState::empty();
   4795    let mut nth_of_state_dependencies = ElementState::empty();
   4796    let mut document_state_dependencies = DocumentState::empty();
   4797    let mut visitor = StylistSelectorVisitor {
   4798        passed_rightmost_selector: false,
   4799        needs_revalidation: &mut needs_revalidation,
   4800        in_selector_list_of: SelectorListKind::default(),
   4801        mapped_ids: &mut mapped_ids,
   4802        nth_of_mapped_ids: &mut nth_of_mapped_ids,
   4803        attribute_dependencies: &mut attribute_dependencies,
   4804        nth_of_class_dependencies: &mut nth_of_class_dependencies,
   4805        nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
   4806        nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
   4807        state_dependencies: &mut state_dependencies,
   4808        nth_of_state_dependencies: &mut nth_of_state_dependencies,
   4809        document_state_dependencies: &mut document_state_dependencies,
   4810    };
   4811    s.visit(&mut visitor);
   4812    needs_revalidation
   4813 }