Skip to main content

style/
stylist.rs

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