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        let mut matching_context = MatchingContext::new_for_revalidation(
1829            bloom,
1830            selector_caches,
1831            self.quirks_mode,
1832            needs_selector_flags,
1833        );
1834
1835        // Note that, by the time we're revalidating, we're guaranteed that the
1836        // candidate and the entry have the same id, classes, and local name.
1837        // This means we're guaranteed to get the same rulehash buckets for all
1838        // the lookups, which means that the bitvecs are comparable. We verify
1839        // this in the caller by asserting that the bitvecs are same-length.
1840        let mut result = RevalidationResult::default();
1841        let mut relevant_attributes = &mut result.relevant_attributes;
1842        let selectors_matched = &mut result.selectors_matched;
1843
1844        let matches_document_rules =
1845            element.each_applicable_non_document_style_rule_data(|data, host| {
1846                matching_context.with_shadow_host(Some(host), |matching_context| {
1847                    data.selectors_for_cache_revalidation.lookup(
1848                        element,
1849                        self.quirks_mode,
1850                        Some(&mut relevant_attributes),
1851                        |selector_and_hashes| {
1852                            selectors_matched.push(matches_selector(
1853                                &selector_and_hashes.selector,
1854                                selector_and_hashes.selector_offset,
1855                                Some(&selector_and_hashes.hashes),
1856                                &element,
1857                                matching_context,
1858                            ));
1859                            true
1860                        },
1861                    );
1862                })
1863            });
1864
1865        for (data, origin) in self.cascade_data.iter_origins() {
1866            if origin == Origin::Author && !matches_document_rules {
1867                continue;
1868            }
1869
1870            data.selectors_for_cache_revalidation.lookup(
1871                element,
1872                self.quirks_mode,
1873                Some(&mut relevant_attributes),
1874                |selector_and_hashes| {
1875                    selectors_matched.push(matches_selector(
1876                        &selector_and_hashes.selector,
1877                        selector_and_hashes.selector_offset,
1878                        Some(&selector_and_hashes.hashes),
1879                        &element,
1880                        &mut matching_context,
1881                    ));
1882                    true
1883                },
1884            );
1885        }
1886
1887        result
1888    }
1889
1890    /// Computes currently active scopes for the given element for revalidation purposes.
1891    pub fn revalidate_scopes<E: TElement>(
1892        &self,
1893        element: &E,
1894        selector_caches: &mut SelectorCaches,
1895        needs_selector_flags: NeedsSelectorFlags,
1896    ) -> ScopeRevalidationResult {
1897        let mut matching_context = MatchingContext::new(
1898            MatchingMode::Normal,
1899            None,
1900            selector_caches,
1901            self.quirks_mode,
1902            needs_selector_flags,
1903            MatchingForInvalidation::No,
1904        );
1905
1906        let mut result = ScopeRevalidationResult::default();
1907        let matches_document_rules =
1908            element.each_applicable_non_document_style_rule_data(|data, host| {
1909                matching_context.with_shadow_host(Some(host), |matching_context| {
1910                    data.revalidate_scopes(element, matching_context, &mut result);
1911                })
1912            });
1913
1914        for (data, origin) in self.cascade_data.iter_origins() {
1915            if origin == Origin::Author && !matches_document_rules {
1916                continue;
1917            }
1918
1919            data.revalidate_scopes(element, &mut matching_context, &mut result);
1920        }
1921
1922        result
1923    }
1924
1925    /// Computes styles for a given declaration with parent_style.
1926    ///
1927    /// FIXME(emilio): the lack of pseudo / cascade flags look quite dubious,
1928    /// hopefully this is only used for some canvas font stuff.
1929    ///
1930    /// TODO(emilio): The type parameter can go away when
1931    /// https://github.com/rust-lang/rust/issues/35121 is fixed.
1932    pub fn compute_for_declarations<E>(
1933        &self,
1934        guards: &StylesheetGuards,
1935        parent_style: &ComputedValues,
1936        declarations: Arc<Locked<PropertyDeclarationBlock>>,
1937    ) -> Arc<ComputedValues>
1938    where
1939        E: TElement,
1940    {
1941        let block = declarations.read_with(guards.author);
1942
1943        // We don't bother inserting these declarations in the rule tree, since
1944        // it'd be quite useless and slow.
1945        //
1946        // TODO(emilio): Now that we fixed bug 1493420, we should consider
1947        // reversing this as it shouldn't be slow anymore, and should avoid
1948        // generating two instantiations of apply_declarations.
1949        properties::apply_declarations::<E, _>(
1950            &self,
1951            /* pseudo = */ None,
1952            self.rule_tree.root(),
1953            guards,
1954            block.declaration_importance_iter().map(|(declaration, _)| {
1955                (
1956                    declaration,
1957                    CascadePriority::new(
1958                        CascadeLevel::same_tree_author_normal(),
1959                        LayerOrder::root(),
1960                    ),
1961                )
1962            }),
1963            Some(parent_style),
1964            Some(parent_style),
1965            FirstLineReparenting::No,
1966            &PositionTryFallbacksTryTactic::default(),
1967            CascadeMode::Unvisited {
1968                visited_rules: None,
1969            },
1970            Default::default(),
1971            /* rule_cache = */ None,
1972            &mut Default::default(),
1973            /* element = */ None,
1974        )
1975    }
1976
1977    /// Accessor for a shared reference to the device.
1978    #[inline]
1979    pub fn device(&self) -> &Device {
1980        &self.device
1981    }
1982
1983    /// Accessor for a mutable reference to the device.
1984    #[inline]
1985    pub fn device_mut(&mut self) -> &mut Device {
1986        &mut self.device
1987    }
1988
1989    /// Accessor for a shared reference to the rule tree.
1990    #[inline]
1991    pub fn rule_tree(&self) -> &RuleTree {
1992        &self.rule_tree
1993    }
1994
1995    /// Returns the script-registered custom property registry.
1996    #[inline]
1997    pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
1998        &self.script_custom_properties
1999    }
2000
2001    /// Returns the script-registered custom property registry, as a mutable ref.
2002    #[inline]
2003    pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
2004        &mut self.script_custom_properties
2005    }
2006
2007    /// Measures heap usage.
2008    #[cfg(feature = "gecko")]
2009    pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2010        self.cascade_data.add_size_of(ops, sizes);
2011        self.author_data_cache.add_size_of(ops, sizes);
2012        sizes.mRuleTree += self.rule_tree.size_of(ops);
2013
2014        // We may measure other fields in the future if DMD says it's worth it.
2015    }
2016
2017    /// Shutdown the static data that this module stores.
2018    pub fn shutdown() {
2019        let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
2020    }
2021}
2022
2023/// A vector that is sorted in layer order.
2024#[derive(Clone, Debug, Deref, MallocSizeOf)]
2025pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
2026impl<T> Default for LayerOrderedVec<T> {
2027    fn default() -> Self {
2028        Self(Default::default())
2029    }
2030}
2031
2032/// A map that is sorted in layer order.
2033#[derive(Clone, Debug, Deref, MallocSizeOf)]
2034pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
2035impl<T> Default for LayerOrderedMap<T> {
2036    fn default() -> Self {
2037        Self(Default::default())
2038    }
2039}
2040
2041impl<T: 'static> LayerOrderedVec<T> {
2042    fn clear(&mut self) {
2043        self.0.clear();
2044    }
2045    fn push(&mut self, v: T, id: LayerId) {
2046        self.0.push((v, id));
2047    }
2048    fn sort(&mut self, layers: &[CascadeLayer]) {
2049        self.0
2050            .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
2051    }
2052}
2053
2054impl<T: 'static> LayerOrderedMap<T> {
2055    fn shrink_if_needed(&mut self) {
2056        self.0.shrink_if_needed();
2057    }
2058    fn clear(&mut self) {
2059        self.0.clear();
2060    }
2061    fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
2062        self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
2063    }
2064    fn try_insert_with(
2065        &mut self,
2066        name: Atom,
2067        v: T,
2068        id: LayerId,
2069        cmp: impl Fn(&T, &T) -> Ordering,
2070    ) -> Result<(), AllocErr> {
2071        self.0.try_reserve(1)?;
2072        let vec = self.0.entry(name).or_default();
2073        if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
2074            if *last_id == id {
2075                if cmp(&val, &v) != Ordering::Greater {
2076                    *val = v;
2077                }
2078                return Ok(());
2079            }
2080        }
2081        vec.push((v, id));
2082        Ok(())
2083    }
2084    fn sort(&mut self, layers: &[CascadeLayer]) {
2085        self.sort_with(layers, |_, _| Ordering::Equal)
2086    }
2087    fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
2088        for (_, v) in self.0.iter_mut() {
2089            v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
2090                let order1 = layers[id1.0 as usize].order;
2091                let order2 = layers[id2.0 as usize].order;
2092                order1.cmp(&order2).then_with(|| cmp(v1, v2))
2093            })
2094        }
2095    }
2096    /// Get an entry on the LayerOrderedMap by name.
2097    pub fn get(&self, name: &Atom) -> Option<&T> {
2098        let vec = self.0.get(name)?;
2099        Some(&vec.last()?.0)
2100    }
2101}
2102
2103/// Wrapper to allow better tracking of memory usage by page rule lists.
2104///
2105/// This includes the layer ID for use with the named page table.
2106#[derive(Clone, Debug, MallocSizeOf)]
2107pub struct PageRuleData {
2108    /// Layer ID for sorting page rules after matching.
2109    pub layer: LayerId,
2110    /// Page rule
2111    #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
2112    pub rule: Arc<Locked<PageRule>>,
2113}
2114
2115/// Stores page rules indexed by page names.
2116#[derive(Clone, Debug, Default, MallocSizeOf)]
2117pub struct PageRuleMap {
2118    /// Page rules, indexed by page name. An empty atom indicates no page name.
2119    pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
2120}
2121
2122impl PageRuleMap {
2123    #[inline]
2124    fn clear(&mut self) {
2125        self.rules.clear();
2126    }
2127
2128    /// Uses page-name and pseudo-classes to match all applicable
2129    /// page-rules and append them to the matched_rules vec.
2130    /// This will ensure correct rule order for cascading.
2131    pub fn match_and_append_rules(
2132        &self,
2133        matched_rules: &mut Vec<ApplicableDeclarationBlock>,
2134        origin: Origin,
2135        guards: &StylesheetGuards,
2136        cascade_data: &DocumentCascadeData,
2137        name: &Option<Atom>,
2138        pseudos: PagePseudoClassFlags,
2139    ) {
2140        let level = match origin {
2141            Origin::UserAgent => CascadeLevel::UANormal,
2142            Origin::User => CascadeLevel::UserNormal,
2143            Origin::Author => CascadeLevel::same_tree_author_normal(),
2144        };
2145        let cascade_data = cascade_data.borrow_for_origin(origin);
2146        let start = matched_rules.len();
2147
2148        self.match_and_add_rules(
2149            matched_rules,
2150            level,
2151            guards,
2152            cascade_data,
2153            &atom!(""),
2154            pseudos,
2155        );
2156        if let Some(name) = name {
2157            self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
2158        }
2159
2160        // Because page-rules do not have source location information stored,
2161        // use stable sort to ensure source locations are preserved.
2162        matched_rules[start..].sort_by_key(|block| block.sort_key());
2163    }
2164
2165    fn match_and_add_rules(
2166        &self,
2167        extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
2168        level: CascadeLevel,
2169        guards: &StylesheetGuards,
2170        cascade_data: &CascadeData,
2171        name: &Atom,
2172        pseudos: PagePseudoClassFlags,
2173    ) {
2174        let rules = match self.rules.get(name) {
2175            Some(rules) => rules,
2176            None => return,
2177        };
2178        for data in rules.iter() {
2179            let rule = data.rule.read_with(level.guard(&guards));
2180            let specificity = match rule.match_specificity(pseudos) {
2181                Some(specificity) => specificity,
2182                None => continue,
2183            };
2184            let block = rule.block.clone();
2185            extra_declarations.push(ApplicableDeclarationBlock::new(
2186                StyleSource::from_declarations(block),
2187                0,
2188                level,
2189                specificity,
2190                cascade_data.layer_order_for(data.layer),
2191                ScopeProximity::infinity(), // Page rule can't have nested rules anyway.
2192            ));
2193        }
2194    }
2195}
2196
2197impl MallocShallowSizeOf for PageRuleMap {
2198    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2199        self.rules.shallow_size_of(ops)
2200    }
2201}
2202
2203type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
2204
2205/// This struct holds data which users of Stylist may want to extract from stylesheets which can be
2206/// done at the same time as updating.
2207#[derive(Clone, Debug, Default)]
2208pub struct ExtraStyleData {
2209    /// A list of effective font-face rules and their origin.
2210    pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
2211
2212    /// A list of effective font-feature-values rules.
2213    pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
2214
2215    /// A list of effective font-palette-values rules.
2216    pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
2217
2218    /// A map of effective counter-style rules.
2219    pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
2220
2221    /// A map of effective @position-try rules.
2222    pub position_try_rules: PositionTryMap,
2223
2224    /// A map of effective page rules.
2225    pub pages: PageRuleMap,
2226}
2227
2228impl ExtraStyleData {
2229    /// Add the given @font-face rule.
2230    fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2231        self.font_faces.push(rule.clone(), layer);
2232    }
2233
2234    /// Add the given @font-feature-values rule.
2235    fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2236        self.font_feature_values.push(rule.clone(), layer);
2237    }
2238
2239    /// Add the given @font-palette-values rule.
2240    fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2241        self.font_palette_values.push(rule.clone(), layer);
2242    }
2243
2244    /// Add the given @counter-style rule.
2245    fn add_counter_style(
2246        &mut self,
2247        guard: &SharedRwLockReadGuard,
2248        rule: &Arc<Locked<CounterStyleRule>>,
2249        layer: LayerId,
2250    ) -> Result<(), AllocErr> {
2251        let name = rule.read_with(guard).name().0.clone();
2252        self.counter_styles.try_insert(name, rule.clone(), layer)
2253    }
2254
2255    /// Add the given @position-try rule.
2256    fn add_position_try(
2257        &mut self,
2258        name: Atom,
2259        rule: Arc<Locked<PositionTryRule>>,
2260        layer: LayerId,
2261    ) -> Result<(), AllocErr> {
2262        self.position_try_rules.try_insert(name, rule, layer)
2263    }
2264
2265    /// Add the given @page rule.
2266    fn add_page(
2267        &mut self,
2268        guard: &SharedRwLockReadGuard,
2269        rule: &Arc<Locked<PageRule>>,
2270        layer: LayerId,
2271    ) -> Result<(), AllocErr> {
2272        let page_rule = rule.read_with(guard);
2273        let mut add_rule = |name| {
2274            let vec = self.pages.rules.entry(name).or_default();
2275            vec.push(PageRuleData {
2276                layer,
2277                rule: rule.clone(),
2278            });
2279        };
2280        if page_rule.selectors.0.is_empty() {
2281            add_rule(atom!(""));
2282        } else {
2283            for selector in page_rule.selectors.as_slice() {
2284                add_rule(selector.name.0.clone());
2285            }
2286        }
2287        Ok(())
2288    }
2289
2290    fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2291        self.font_faces.sort(layers);
2292        self.font_feature_values.sort(layers);
2293        self.font_palette_values.sort(layers);
2294        self.counter_styles.sort(layers);
2295        self.position_try_rules.sort(layers);
2296    }
2297
2298    fn clear(&mut self) {
2299        self.font_faces.clear();
2300        self.font_feature_values.clear();
2301        self.font_palette_values.clear();
2302        self.counter_styles.clear();
2303        self.position_try_rules.clear();
2304        self.pages.clear();
2305    }
2306}
2307
2308// Don't let a prefixed keyframes animation override
2309// a non-prefixed one.
2310fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2311    if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2312        Ordering::Equal
2313    } else if v2.vendor_prefix.is_some() {
2314        Ordering::Greater
2315    } else {
2316        Ordering::Less
2317    }
2318}
2319
2320/// An iterator over the different ExtraStyleData.
2321pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2322
2323impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2324    type Item = (&'a ExtraStyleData, Origin);
2325
2326    fn next(&mut self) -> Option<Self::Item> {
2327        self.0.next().map(|d| (&d.0.extra_data, d.1))
2328    }
2329}
2330
2331impl MallocSizeOf for ExtraStyleData {
2332    /// Measure heap usage.
2333    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2334        let mut n = 0;
2335        n += self.font_faces.shallow_size_of(ops);
2336        n += self.font_feature_values.shallow_size_of(ops);
2337        n += self.font_palette_values.shallow_size_of(ops);
2338        n += self.counter_styles.shallow_size_of(ops);
2339        n += self.position_try_rules.shallow_size_of(ops);
2340        n += self.pages.shallow_size_of(ops);
2341        n
2342    }
2343}
2344
2345/// SelectorMapEntry implementation for use in our revalidation selector map.
2346#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
2347#[derive(Clone, Debug)]
2348struct RevalidationSelectorAndHashes {
2349    #[cfg_attr(
2350        feature = "gecko",
2351        ignore_malloc_size_of = "CssRules have primary refs, we measure there"
2352    )]
2353    selector: Selector<SelectorImpl>,
2354    selector_offset: usize,
2355    hashes: AncestorHashes,
2356}
2357
2358impl RevalidationSelectorAndHashes {
2359    fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2360        let selector_offset = {
2361            // We basically want to check whether the first combinator is a
2362            // pseudo-element combinator.  If it is, we want to use the offset
2363            // one past it.  Otherwise, our offset is 0.
2364            let mut index = 0;
2365            let mut iter = selector.iter();
2366
2367            // First skip over the first ComplexSelector.
2368            //
2369            // We can't check what sort of what combinator we have until we do
2370            // that.
2371            for _ in &mut iter {
2372                index += 1; // Simple selector
2373            }
2374
2375            match iter.next_sequence() {
2376                Some(Combinator::PseudoElement) => index + 1, // +1 for the combinator
2377                _ => 0,
2378            }
2379        };
2380
2381        RevalidationSelectorAndHashes {
2382            selector,
2383            selector_offset,
2384            hashes,
2385        }
2386    }
2387}
2388
2389impl SelectorMapEntry for RevalidationSelectorAndHashes {
2390    fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2391        self.selector.iter_from(self.selector_offset)
2392    }
2393}
2394
2395/// A selector visitor implementation that collects all the state the Stylist
2396/// cares about a selector.
2397struct StylistSelectorVisitor<'a> {
2398    /// Whether we've past the rightmost compound selector, not counting
2399    /// pseudo-elements.
2400    passed_rightmost_selector: bool,
2401
2402    /// Whether the selector needs revalidation for the style sharing cache.
2403    needs_revalidation: &'a mut bool,
2404
2405    /// Flags for which selector list-containing components the visitor is
2406    /// inside of, if any
2407    in_selector_list_of: SelectorListKind,
2408
2409    /// The filter with all the id's getting referenced from rightmost
2410    /// selectors.
2411    mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2412
2413    /// The filter with the IDs getting referenced from the selector list of
2414    /// :nth-child(... of <selector list>) selectors.
2415    nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2416
2417    /// The filter with the local names of attributes there are selectors for.
2418    attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2419
2420    /// The filter with the classes getting referenced from the selector list of
2421    /// :nth-child(... of <selector list>) selectors.
2422    nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2423
2424    /// The filter with the local names of attributes there are selectors for
2425    /// within the selector list of :nth-child(... of <selector list>)
2426    /// selectors.
2427    nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2428
2429    /// The filter with the local names of custom states in selectors for
2430    /// within the selector list of :nth-child(... of <selector list>)
2431    /// selectors.
2432    nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2433
2434    /// All the states selectors in the page reference.
2435    state_dependencies: &'a mut ElementState,
2436
2437    /// All the state selectors in the page reference within the selector list
2438    /// of :nth-child(... of <selector list>) selectors.
2439    nth_of_state_dependencies: &'a mut ElementState,
2440
2441    /// All the document states selectors in the page reference.
2442    document_state_dependencies: &'a mut DocumentState,
2443}
2444
2445fn component_needs_revalidation(
2446    c: &Component<SelectorImpl>,
2447    passed_rightmost_selector: bool,
2448) -> bool {
2449    match *c {
2450        Component::ID(_) => {
2451            // TODO(emilio): This could also check that the ID is not already in
2452            // the rule hash. In that case, we could avoid making this a
2453            // revalidation selector too.
2454            //
2455            // See https://bugzilla.mozilla.org/show_bug.cgi?id=1369611
2456            passed_rightmost_selector
2457        },
2458        Component::AttributeInNoNamespaceExists { .. }
2459        | Component::AttributeInNoNamespace { .. }
2460        | Component::AttributeOther(_)
2461        | Component::Empty
2462        | Component::Nth(_)
2463        | Component::NthOf(_)
2464        | Component::Has(_) => true,
2465        Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2466        _ => false,
2467    }
2468}
2469
2470impl<'a> StylistSelectorVisitor<'a> {
2471    fn visit_nested_selector(
2472        &mut self,
2473        in_selector_list_of: SelectorListKind,
2474        selector: &Selector<SelectorImpl>,
2475    ) {
2476        let old_passed_rightmost_selector = self.passed_rightmost_selector;
2477        let old_in_selector_list_of = self.in_selector_list_of;
2478
2479        self.passed_rightmost_selector = false;
2480        self.in_selector_list_of = in_selector_list_of;
2481        let _ret = selector.visit(self);
2482        debug_assert!(_ret, "We never return false");
2483
2484        self.passed_rightmost_selector = old_passed_rightmost_selector;
2485        self.in_selector_list_of = old_in_selector_list_of;
2486    }
2487}
2488
2489impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2490    type Impl = SelectorImpl;
2491
2492    fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2493        *self.needs_revalidation =
2494            *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2495
2496        // NOTE(emilio): this call happens before we visit any of the simple
2497        // selectors in the next ComplexSelector, so we can use this to skip
2498        // looking at them.
2499        self.passed_rightmost_selector = self.passed_rightmost_selector
2500            || !matches!(combinator, None | Some(Combinator::PseudoElement));
2501
2502        true
2503    }
2504
2505    fn visit_selector_list(
2506        &mut self,
2507        list_kind: SelectorListKind,
2508        list: &[Selector<Self::Impl>],
2509    ) -> bool {
2510        let in_selector_list_of = self.in_selector_list_of | list_kind;
2511        for selector in list {
2512            self.visit_nested_selector(in_selector_list_of, selector);
2513        }
2514        true
2515    }
2516
2517    fn visit_relative_selector_list(
2518        &mut self,
2519        list: &[selectors::parser::RelativeSelector<Self::Impl>],
2520    ) -> bool {
2521        let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2522        for selector in list {
2523            self.visit_nested_selector(in_selector_list_of, &selector.selector);
2524        }
2525        true
2526    }
2527
2528    fn visit_attribute_selector(
2529        &mut self,
2530        _ns: &NamespaceConstraint<&Namespace>,
2531        name: &LocalName,
2532        lower_name: &LocalName,
2533    ) -> bool {
2534        if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2535            self.nth_of_attribute_dependencies.insert(name.clone());
2536            if name != lower_name {
2537                self.nth_of_attribute_dependencies
2538                    .insert(lower_name.clone());
2539            }
2540        }
2541
2542        self.attribute_dependencies.insert(name.clone());
2543        if name != lower_name {
2544            self.attribute_dependencies.insert(lower_name.clone());
2545        }
2546
2547        true
2548    }
2549
2550    fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2551        *self.needs_revalidation = *self.needs_revalidation
2552            || component_needs_revalidation(s, self.passed_rightmost_selector);
2553
2554        match *s {
2555            Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2556                // CustomStateSet is special cased as it is a functional pseudo
2557                // class with unbounded inner values. This is different to
2558                // other psuedo class like :emtpy or :dir() which can be packed
2559                // into the ElementState bitflags. For CustomState, however,
2560                // the state name should be checked for presence in the selector.
2561                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2562                    self.nth_of_custom_state_dependencies.insert(name.0.clone());
2563                }
2564            },
2565            Component::NonTSPseudoClass(ref p) => {
2566                self.state_dependencies.insert(p.state_flag());
2567                self.document_state_dependencies
2568                    .insert(p.document_state_flag());
2569
2570                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2571                    self.nth_of_state_dependencies.insert(p.state_flag());
2572                }
2573            },
2574            Component::ID(ref id) => {
2575                // We want to stop storing mapped ids as soon as we've moved off
2576                // the rightmost ComplexSelector that is not a pseudo-element.
2577                //
2578                // That can be detected by a visit_complex_selector call with a
2579                // combinator other than None and PseudoElement.
2580                //
2581                // Importantly, this call happens before we visit any of the
2582                // simple selectors in that ComplexSelector.
2583                //
2584                // NOTE(emilio): See the comment regarding on when this may
2585                // break in visit_complex_selector.
2586                if !self.passed_rightmost_selector {
2587                    self.mapped_ids.insert(id.0.clone());
2588                }
2589
2590                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2591                    self.nth_of_mapped_ids.insert(id.0.clone());
2592                }
2593            },
2594            Component::Class(ref class)
2595                if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2596            {
2597                self.nth_of_class_dependencies.insert(class.0.clone());
2598            },
2599            _ => {},
2600        }
2601
2602        true
2603    }
2604}
2605
2606/// A set of rules for element and pseudo-elements.
2607#[derive(Clone, Debug, Default, MallocSizeOf)]
2608struct GenericElementAndPseudoRules<Map> {
2609    /// Rules from stylesheets at this `CascadeData`'s origin.
2610    element_map: Map,
2611
2612    /// Rules from stylesheets at this `CascadeData`'s origin that correspond
2613    /// to a given pseudo-element.
2614    ///
2615    /// FIXME(emilio): There are a bunch of wasted entries here in practice.
2616    /// Figure out a good way to do a `PerNonAnonBox` and `PerAnonBox` (for
2617    /// `precomputed_values_for_pseudo`) without duplicating a lot of code.
2618    pseudos_map: PerPseudoElementMap<Self>,
2619}
2620
2621impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2622    #[inline(always)]
2623    fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
2624        let mut current = self;
2625        for &pseudo_element in pseudo_elements {
2626            debug_assert!(
2627                !pseudo_element.is_precomputed()
2628                    && !pseudo_element.is_unknown_webkit_pseudo_element(),
2629                "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2630                 and unknown webkit pseudos should be discarded before getting here"
2631            );
2632
2633            current = current
2634                .pseudos_map
2635                .get_or_insert_with(pseudo_element, Default::default);
2636        }
2637
2638        &mut current.element_map
2639    }
2640
2641    #[inline]
2642    fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2643        let mut current = self;
2644        for pseudo in pseudo_elements {
2645            current = current.pseudos_map.get(&pseudo)?;
2646        }
2647        Some(&current.element_map)
2648    }
2649
2650    /// Measures heap usage.
2651    #[cfg(feature = "gecko")]
2652    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2653        sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2654
2655        for elem in self.pseudos_map.iter() {
2656            sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2657        }
2658    }
2659}
2660
2661type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2662type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2663type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2664
2665impl ElementAndPseudoRules {
2666    // TODO(emilio): Should we retain storage of these?
2667    fn clear(&mut self) {
2668        self.element_map.clear();
2669        self.pseudos_map.clear();
2670    }
2671
2672    fn shrink_if_needed(&mut self) {
2673        self.element_map.shrink_if_needed();
2674        for pseudo in self.pseudos_map.iter_mut() {
2675            pseudo.shrink_if_needed();
2676        }
2677    }
2678}
2679
2680impl PartElementAndPseudoRules {
2681    // TODO(emilio): Should we retain storage of these?
2682    fn clear(&mut self) {
2683        self.element_map.clear();
2684        self.pseudos_map.clear();
2685    }
2686}
2687
2688/// The id of a given layer, a sequentially-increasing identifier.
2689#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2690pub struct LayerId(u16);
2691
2692impl LayerId {
2693    /// The id of the root layer.
2694    pub const fn root() -> Self {
2695        Self(0)
2696    }
2697}
2698
2699#[derive(Clone, Debug, MallocSizeOf)]
2700struct CascadeLayer {
2701    id: LayerId,
2702    order: LayerOrder,
2703    children: Vec<LayerId>,
2704}
2705
2706impl CascadeLayer {
2707    const fn root() -> Self {
2708        Self {
2709            id: LayerId::root(),
2710            order: LayerOrder::root(),
2711            children: vec![],
2712        }
2713    }
2714}
2715
2716/// The id of a given container condition, a sequentially-increasing identifier
2717/// for a given style set.
2718#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2719pub struct ContainerConditionId(u16);
2720
2721impl ContainerConditionId {
2722    /// A special id that represents no container rule.
2723    pub const fn none() -> Self {
2724        Self(0)
2725    }
2726}
2727
2728#[derive(Clone, Debug, MallocSizeOf)]
2729struct ContainerConditionReference {
2730    parent: ContainerConditionId,
2731    #[ignore_malloc_size_of = "Arc"]
2732    condition: Option<Arc<ContainerCondition>>,
2733}
2734
2735impl ContainerConditionReference {
2736    const fn none() -> Self {
2737        Self {
2738            parent: ContainerConditionId::none(),
2739            condition: None,
2740        }
2741    }
2742}
2743
2744/// The id of a given scope condition, a sequentially-increasing identifier
2745/// for a given style set.
2746#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2747pub struct ScopeConditionId(u16);
2748
2749impl ScopeConditionId {
2750    /// Construct a new scope condition id.
2751    pub fn new(id: u16) -> Self {
2752        Self(id)
2753    }
2754
2755    /// A special id that represents no scope rule.
2756    pub const fn none() -> Self {
2757        Self(0)
2758    }
2759}
2760
2761/// Data required to process this scope condition.
2762#[derive(Clone, Debug, MallocSizeOf)]
2763pub struct ScopeConditionReference {
2764    /// The ID of outer scope condition, `none()` otherwise.
2765    parent: ScopeConditionId,
2766    /// Start and end bounds of the scope. None implies sentinel data (i.e. Not a scope condition).
2767    condition: Option<ScopeBoundsWithHashes>,
2768    /// Implicit scope root of this scope condition, computed unconditionally,
2769    /// even if the start bound may be Some.
2770    #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2771    implicit_scope_root: StylistImplicitScopeRoot,
2772    /// Is the condition trivial? See `ScopeBoundsWithHashes::is_trivial`.
2773    is_trivial: bool,
2774}
2775
2776impl ScopeConditionReference {
2777    /// Create a new scope condition.
2778    pub fn new(
2779        parent: ScopeConditionId,
2780        condition: Option<ScopeBoundsWithHashes>,
2781        implicit_scope_root: ImplicitScopeRoot,
2782        is_trivial: bool,
2783    ) -> Self {
2784        Self {
2785            parent,
2786            condition,
2787            implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2788            is_trivial,
2789        }
2790    }
2791
2792    /// Create a sentinel scope condition.
2793    pub const fn none() -> Self {
2794        Self {
2795            parent: ScopeConditionId::none(),
2796            condition: None,
2797            implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2798            is_trivial: true,
2799        }
2800    }
2801}
2802
2803/// All potential sscope root candidates.
2804pub struct ScopeRootCandidates {
2805    /// List of scope root candidates.
2806    pub candidates: Vec<ScopeRootCandidate>,
2807    /// Is the scope condition matching these candidates trivial? See `ScopeBoundsWithHashes::is_trivial`.
2808    pub is_trivial: bool,
2809}
2810
2811impl Default for ScopeRootCandidates {
2812    fn default() -> Self {
2813        Self {
2814            candidates: vec![],
2815            is_trivial: true,
2816        }
2817    }
2818}
2819
2820impl ScopeRootCandidates {
2821    fn empty(is_trivial: bool) -> Self {
2822        Self {
2823            candidates: vec![],
2824            is_trivial,
2825        }
2826    }
2827}
2828
2829/// Start and end bound of a scope, along with their selector hashes.
2830#[derive(Clone, Debug, MallocSizeOf)]
2831pub struct ScopeBoundWithHashes {
2832    // TODO(dshin): With replaced parent selectors, these may be unique...
2833    #[ignore_malloc_size_of = "Arc"]
2834    selectors: SelectorList<SelectorImpl>,
2835    hashes: SmallVec<[AncestorHashes; 1]>,
2836}
2837
2838impl ScopeBoundWithHashes {
2839    fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
2840        let mut hashes = SmallVec::with_capacity(selectors.len());
2841        for selector in selectors.slice() {
2842            hashes.push(AncestorHashes::new(selector, quirks_mode));
2843        }
2844        Self { selectors, hashes }
2845    }
2846
2847    fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
2848        let hashes = selectors
2849            .slice()
2850            .iter()
2851            .map(|_| AncestorHashes {
2852                packed_hashes: [0, 0, 0],
2853            })
2854            .collect();
2855        Self { selectors, hashes }
2856    }
2857}
2858
2859/// Bounds for this scope, along with corresponding selector hashes.
2860#[derive(Clone, Debug, MallocSizeOf)]
2861pub struct ScopeBoundsWithHashes {
2862    /// Start of the scope bound. If None, implies implicit scope root.
2863    start: Option<ScopeBoundWithHashes>,
2864    /// Optional end of the scope bound.
2865    end: Option<ScopeBoundWithHashes>,
2866}
2867
2868impl ScopeBoundsWithHashes {
2869    /// Create a new scope bound, hashing selectors for fast rejection.
2870    fn new(
2871        quirks_mode: QuirksMode,
2872        start: Option<SelectorList<SelectorImpl>>,
2873        end: Option<SelectorList<SelectorImpl>>,
2874    ) -> Self {
2875        Self {
2876            start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
2877            end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
2878        }
2879    }
2880
2881    /// Create a new scope bound, but not hashing any selector.
2882    pub fn new_no_hash(
2883        start: Option<SelectorList<SelectorImpl>>,
2884        end: Option<SelectorList<SelectorImpl>>,
2885    ) -> Self {
2886        Self {
2887            start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
2888            end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
2889        }
2890    }
2891
2892    fn selectors_for<'a>(
2893        bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
2894    ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2895        bound_with_hashes
2896            .map(|b| b.selectors.slice().iter())
2897            .into_iter()
2898            .flatten()
2899    }
2900
2901    fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2902        Self::selectors_for(self.start.as_ref())
2903    }
2904
2905    fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2906        Self::selectors_for(self.end.as_ref())
2907    }
2908
2909    fn is_trivial(&self) -> bool {
2910        fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
2911            bound.as_ref().map_or(default, |bound| {
2912                scope_selector_list_is_trivial(&bound.selectors)
2913            })
2914        }
2915
2916        // Given an implicit scope, we are unable to tell if the cousins share the same implicit root.
2917        scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
2918    }
2919}
2920
2921/// Find all scope conditions for a given condition ID, indexing into the given list of scope conditions.
2922pub fn scope_root_candidates<E>(
2923    scope_conditions: &[ScopeConditionReference],
2924    id: ScopeConditionId,
2925    element: &E,
2926    override_matches_shadow_host_for_part: bool,
2927    scope_subject_map: &ScopeSubjectMap,
2928    context: &mut MatchingContext<SelectorImpl>,
2929) -> ScopeRootCandidates
2930where
2931    E: TElement,
2932{
2933    let condition_ref = &scope_conditions[id.0 as usize];
2934    let bounds = match condition_ref.condition {
2935        None => return ScopeRootCandidates::default(),
2936        Some(ref c) => c,
2937    };
2938    // Make sure the parent scopes ara evaluated first. This runs a bit counter to normal
2939    // selector matching where rightmost selectors match first. However, this avoids having
2940    // to traverse through descendants (i.e. Avoids tree traversal vs linear traversal).
2941    let outer_result = scope_root_candidates(
2942        scope_conditions,
2943        condition_ref.parent,
2944        element,
2945        override_matches_shadow_host_for_part,
2946        scope_subject_map,
2947        context,
2948    );
2949
2950    let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
2951    let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
2952    if !is_outermost_scope && outer_result.candidates.is_empty() {
2953        return ScopeRootCandidates::empty(is_trivial);
2954    }
2955
2956    let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
2957        if let Some(filter) = context.bloom_filter {
2958            // Use the bloom filter here. If our ancestors do not have the right hashes,
2959            // there's no point in traversing up. Besides, the filter is built for this depth,
2960            // so the filter contains more data than it should, the further we go up the ancestor
2961            // chain. It wouldn't generate wrong results, but makes the traversal even more pointless.
2962            if !start
2963                .hashes
2964                .iter()
2965                .any(|entry| selector_may_match(entry, filter))
2966            {
2967                return ScopeRootCandidates::empty(is_trivial);
2968            }
2969        }
2970        (
2971            ScopeTarget::Selector(&start.selectors),
2972            scope_start_matches_shadow_host(&start.selectors),
2973        )
2974    } else {
2975        let implicit_root = condition_ref.implicit_scope_root;
2976        match implicit_root {
2977            StylistImplicitScopeRoot::Normal(r) => (
2978                ScopeTarget::Implicit(r.element(context.current_host.clone())),
2979                r.matches_shadow_host(),
2980            ),
2981            StylistImplicitScopeRoot::Cached(index) => {
2982                let host = context
2983                    .current_host
2984                    .expect("Cached implicit scope for light DOM implicit scope");
2985                match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
2986                    None => return ScopeRootCandidates::empty(is_trivial),
2987                    Some(root) => (
2988                        ScopeTarget::Implicit(root.element(context.current_host.clone())),
2989                        root.matches_shadow_host(),
2990                    ),
2991                }
2992            },
2993        }
2994    };
2995    // For `::part`, we need to be able to reach the outer tree. Parts without the corresponding
2996    // `exportparts` attribute will be rejected at the selector matching time.
2997    let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
2998
2999    let potential_scope_roots = if is_outermost_scope {
3000        collect_scope_roots(
3001            *element,
3002            None,
3003            context,
3004            &root_target,
3005            matches_shadow_host,
3006            scope_subject_map,
3007        )
3008    } else {
3009        let mut result = vec![];
3010        for activation in outer_result.candidates {
3011            let mut this_result = collect_scope_roots(
3012                *element,
3013                Some(activation.root),
3014                context,
3015                &root_target,
3016                matches_shadow_host,
3017                scope_subject_map,
3018            );
3019            result.append(&mut this_result);
3020        }
3021        result
3022    };
3023
3024    if potential_scope_roots.is_empty() {
3025        return ScopeRootCandidates::empty(is_trivial);
3026    }
3027
3028    let candidates = if let Some(end) = bounds.end.as_ref() {
3029        let mut result = vec![];
3030        // If any scope-end selector matches, we're not in scope.
3031        for scope_root in potential_scope_roots {
3032            if end
3033                .selectors
3034                .slice()
3035                .iter()
3036                .zip(end.hashes.iter())
3037                .all(|(selector, hashes)| {
3038                    // Like checking for scope-start, use the bloom filter here.
3039                    if let Some(filter) = context.bloom_filter {
3040                        if !selector_may_match(hashes, filter) {
3041                            // Selector this hash belongs to won't cause us to be out of this scope.
3042                            return true;
3043                        }
3044                    }
3045
3046                    !element_is_outside_of_scope(
3047                        selector,
3048                        *element,
3049                        scope_root.root,
3050                        context,
3051                        matches_shadow_host,
3052                    )
3053                })
3054            {
3055                result.push(scope_root);
3056            }
3057        }
3058        result
3059    } else {
3060        potential_scope_roots
3061    };
3062
3063    ScopeRootCandidates {
3064        candidates,
3065        is_trivial,
3066    }
3067}
3068
3069/// Implicit scope root, which may or may not be cached (i.e. For shadow DOM author
3070/// styles that are cached and shared).
3071#[derive(Copy, Clone, Debug, MallocSizeOf)]
3072enum StylistImplicitScopeRoot {
3073    Normal(ImplicitScopeRoot),
3074    Cached(usize),
3075}
3076// Should be safe, only mutated through mutable methods in `Stylist`.
3077unsafe impl Sync for StylistImplicitScopeRoot {}
3078
3079impl StylistImplicitScopeRoot {
3080    const fn default_const() -> Self {
3081        // Use the "safest" fallback.
3082        Self::Normal(ImplicitScopeRoot::DocumentElement)
3083    }
3084}
3085
3086impl Default for StylistImplicitScopeRoot {
3087    fn default() -> Self {
3088        Self::default_const()
3089    }
3090}
3091
3092/// Data resulting from performing the CSS cascade that is specific to a given
3093/// origin.
3094///
3095/// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
3096/// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
3097#[derive(Debug, Clone, MallocSizeOf)]
3098pub struct CascadeData {
3099    /// The data coming from normal style rules that apply to elements at this
3100    /// cascade level.
3101    normal_rules: ElementAndPseudoRules,
3102
3103    /// The `:host` pseudo rules that are the rightmost selector (without
3104    /// accounting for pseudo-elements), or `:scope` rules that may match
3105    /// the featureless host.
3106    featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
3107
3108    /// The data coming from ::slotted() pseudo-element rules.
3109    ///
3110    /// We need to store them separately because an element needs to match
3111    /// ::slotted() pseudo-element rules in different shadow roots.
3112    ///
3113    /// In particular, we need to go through all the style data in all the
3114    /// containing style scopes starting from the closest assigned slot.
3115    slotted_rules: Option<Box<ElementAndPseudoRules>>,
3116
3117    /// The data coming from ::part() pseudo-element rules.
3118    ///
3119    /// We need to store them separately because an element needs to match
3120    /// ::part() pseudo-element rules in different shadow roots.
3121    part_rules: Option<Box<PartElementAndPseudoRules>>,
3122
3123    /// The invalidation map for these rules.
3124    invalidation_map: InvalidationMap,
3125
3126    /// The relative selector equivalent of the invalidation map.
3127    relative_selector_invalidation_map: InvalidationMap,
3128
3129    additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
3130
3131    /// The attribute local names that appear in attribute selectors.  Used
3132    /// to avoid taking element snapshots when an irrelevant attribute changes.
3133    /// (We don't bother storing the namespace, since namespaced attributes are
3134    /// rare.)
3135    attribute_dependencies: PrecomputedHashSet<LocalName>,
3136
3137    /// The classes that appear in the selector list of
3138    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
3139    /// an element when an irrelevant class changes.
3140    nth_of_class_dependencies: PrecomputedHashSet<Atom>,
3141
3142    /// The attributes that appear in the selector list of
3143    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
3144    /// an element when an irrelevant attribute changes.
3145    nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
3146
3147    /// The custom states that appear in the selector list of
3148    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
3149    /// an element when an irrelevant custom state changes.
3150    nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
3151
3152    /// The element state bits that are relied on by selectors.  Like
3153    /// `attribute_dependencies`, this is used to avoid taking element snapshots
3154    /// when an irrelevant element state bit changes.
3155    state_dependencies: ElementState,
3156
3157    /// The element state bits that are relied on by selectors that appear in
3158    /// the selector list of :nth-child(... of <selector list>).
3159    nth_of_state_dependencies: ElementState,
3160
3161    /// The document state bits that are relied on by selectors.  This is used
3162    /// to tell whether we need to restyle the entire document when a document
3163    /// state bit changes.
3164    document_state_dependencies: DocumentState,
3165
3166    /// The ids that appear in the rightmost complex selector of selectors (and
3167    /// hence in our selector maps).  Used to determine when sharing styles is
3168    /// safe: we disallow style sharing for elements whose id matches this
3169    /// filter, and hence might be in one of our selector maps.
3170    mapped_ids: PrecomputedHashSet<Atom>,
3171
3172    /// The IDs that appear in the selector list of
3173    /// :nth-child(... of <selector list>). Used to avoid restyling siblings
3174    /// of an element when an irrelevant ID changes.
3175    nth_of_mapped_ids: PrecomputedHashSet<Atom>,
3176
3177    /// Selectors that require explicit cache revalidation (i.e. which depend
3178    /// on state that is not otherwise visible to the cache, like attributes or
3179    /// tree-structural state like child index and pseudos).
3180    #[ignore_malloc_size_of = "Arc"]
3181    selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
3182
3183    /// A map with all the animations at this `CascadeData`'s origin, indexed
3184    /// by name.
3185    animations: LayerOrderedMap<KeyframesAnimation>,
3186
3187    /// A map with all the layer-ordered registrations from style at this `CascadeData`'s origin,
3188    /// indexed by name.
3189    #[ignore_malloc_size_of = "Arc"]
3190    custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
3191
3192    /// Custom media query registrations.
3193    custom_media: CustomMediaMap,
3194
3195    /// A map from cascade layer name to layer order.
3196    layer_id: FxHashMap<LayerName, LayerId>,
3197
3198    /// The list of cascade layers, indexed by their layer id.
3199    layers: SmallVec<[CascadeLayer; 1]>,
3200
3201    /// The list of container conditions, indexed by their id.
3202    container_conditions: SmallVec<[ContainerConditionReference; 1]>,
3203
3204    /// The list of scope conditions, indexed by their id.
3205    scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
3206
3207    /// Map of unique selectors on scope start selectors' subjects.
3208    scope_subject_map: ScopeSubjectMap,
3209
3210    /// Effective media query results cached from the last rebuild.
3211    effective_media_query_results: EffectiveMediaQueryResults,
3212
3213    /// Extra data, like different kinds of rules, etc.
3214    extra_data: ExtraStyleData,
3215
3216    /// A monotonically increasing counter to represent the order on which a
3217    /// style rule appears in a stylesheet, needed to sort them by source order.
3218    rules_source_order: u32,
3219
3220    /// The total number of selectors.
3221    num_selectors: usize,
3222
3223    /// The total number of declarations.
3224    num_declarations: usize,
3225}
3226
3227static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
3228    // Implicit scope, as per https://github.com/w3c/csswg-drafts/issues/10196
3229    // Also, `&` is `:where(:scope)`, as per https://github.com/w3c/csswg-drafts/issues/9740
3230    // ``:where(:scope)` effectively behaves the same as the implicit scope.
3231    let list = SelectorList::implicit_scope();
3232    list.mark_as_intentionally_leaked();
3233    list
3234});
3235
3236fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3237    // TODO(emilio): Should we carry a MatchesFeaturelessHost rather than a bool around?
3238    // Pre-existing behavior with multiple selectors matches this tho.
3239    start
3240        .slice()
3241        .iter()
3242        .any(|s| s.matches_featureless_host(true).may_match())
3243}
3244
3245/// Replace any occurrence of parent selector in the given selector with a implicit scope selector.
3246pub fn replace_parent_selector_with_implicit_scope(
3247    selectors: &SelectorList<SelectorImpl>,
3248) -> SelectorList<SelectorImpl> {
3249    selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3250}
3251
3252impl CascadeData {
3253    /// Creates an empty `CascadeData`.
3254    pub fn new() -> Self {
3255        Self {
3256            normal_rules: ElementAndPseudoRules::default(),
3257            featureless_host_rules: None,
3258            slotted_rules: None,
3259            part_rules: None,
3260            invalidation_map: InvalidationMap::new(),
3261            relative_selector_invalidation_map: InvalidationMap::new(),
3262            additional_relative_selector_invalidation_map:
3263                AdditionalRelativeSelectorInvalidationMap::new(),
3264            nth_of_mapped_ids: PrecomputedHashSet::default(),
3265            nth_of_class_dependencies: PrecomputedHashSet::default(),
3266            nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3267            nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3268            nth_of_state_dependencies: ElementState::empty(),
3269            attribute_dependencies: PrecomputedHashSet::default(),
3270            state_dependencies: ElementState::empty(),
3271            document_state_dependencies: DocumentState::empty(),
3272            mapped_ids: PrecomputedHashSet::default(),
3273            selectors_for_cache_revalidation: SelectorMap::new(),
3274            animations: Default::default(),
3275            custom_property_registrations: Default::default(),
3276            custom_media: Default::default(),
3277            layer_id: Default::default(),
3278            layers: smallvec::smallvec![CascadeLayer::root()],
3279            container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3280            scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3281            scope_subject_map: Default::default(),
3282            extra_data: ExtraStyleData::default(),
3283            effective_media_query_results: EffectiveMediaQueryResults::new(),
3284            rules_source_order: 0,
3285            num_selectors: 0,
3286            num_declarations: 0,
3287        }
3288    }
3289
3290    /// Rebuild the cascade data from a given SheetCollection, incrementally if possible.
3291    pub fn rebuild<'a, S>(
3292        &mut self,
3293        device: &Device,
3294        quirks_mode: QuirksMode,
3295        collection: SheetCollectionFlusher<S>,
3296        guard: &SharedRwLockReadGuard,
3297        difference: &mut CascadeDataDifference,
3298    ) -> Result<(), AllocErr>
3299    where
3300        S: StylesheetInDocument + PartialEq + 'static,
3301    {
3302        if !collection.dirty() {
3303            return Ok(());
3304        }
3305
3306        let validity = collection.data_validity();
3307
3308        let mut old_position_try_data = LayerOrderedMap::default();
3309        if validity != DataValidity::Valid {
3310            old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
3311            self.clear_cascade_data();
3312            if validity == DataValidity::FullyInvalid {
3313                self.clear_invalidation_data();
3314            }
3315        }
3316
3317        let mut result = Ok(());
3318
3319        collection.each(|index, stylesheet, rebuild_kind| {
3320            result = self.add_stylesheet(
3321                device,
3322                quirks_mode,
3323                stylesheet,
3324                index,
3325                guard,
3326                rebuild_kind,
3327                /* precomputed_pseudo_element_decls = */ None,
3328                if validity == DataValidity::Valid {
3329                    Some(difference)
3330                } else {
3331                    None
3332                },
3333            );
3334            result.is_ok()
3335        });
3336
3337        self.did_finish_rebuild();
3338
3339        // For DataValidity::Valid, we pass the difference down to `add_stylesheet` so that we
3340        // populate it with new data. Otherwise we need to diff with the old data.
3341        if validity != DataValidity::Valid {
3342            difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
3343        }
3344
3345        result
3346    }
3347
3348    /// Returns the custom media query map.
3349    pub fn custom_media_map(&self) -> &CustomMediaMap {
3350        &self.custom_media
3351    }
3352
3353    /// Returns the invalidation map.
3354    pub fn invalidation_map(&self) -> &InvalidationMap {
3355        &self.invalidation_map
3356    }
3357
3358    /// Returns the relative selector invalidation map.
3359    pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3360        &self.relative_selector_invalidation_map
3361    }
3362
3363    /// Returns the relative selector invalidation map data.
3364    pub fn relative_invalidation_map_attributes(
3365        &self,
3366    ) -> &AdditionalRelativeSelectorInvalidationMap {
3367        &self.additional_relative_selector_invalidation_map
3368    }
3369
3370    /// Returns whether the given ElementState bit is relied upon by a selector
3371    /// of some rule.
3372    #[inline]
3373    pub fn has_state_dependency(&self, state: ElementState) -> bool {
3374        self.state_dependencies.intersects(state)
3375    }
3376
3377    /// Returns whether the given Custom State is relied upon by a selector
3378    /// of some rule in the selector list of :nth-child(... of <selector list>).
3379    #[inline]
3380    pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3381        self.nth_of_custom_state_dependencies.contains(state)
3382    }
3383
3384    /// Returns whether the given ElementState bit is relied upon by a selector
3385    /// of some rule in the selector list of :nth-child(... of <selector list>).
3386    #[inline]
3387    pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3388        self.nth_of_state_dependencies.intersects(state)
3389    }
3390
3391    /// Returns whether the given attribute might appear in an attribute
3392    /// selector of some rule.
3393    #[inline]
3394    pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3395        self.attribute_dependencies.contains(local_name)
3396    }
3397
3398    /// Returns whether the given ID might appear in an ID selector in the
3399    /// selector list of :nth-child(... of <selector list>).
3400    #[inline]
3401    pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3402        self.nth_of_mapped_ids.contains(id)
3403    }
3404
3405    /// Returns whether the given class might appear in a class selector in the
3406    /// selector list of :nth-child(... of <selector list>).
3407    #[inline]
3408    pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3409        self.nth_of_class_dependencies.contains(class)
3410    }
3411
3412    /// Returns whether the given attribute might appear in an attribute
3413    /// selector in the selector list of :nth-child(... of <selector list>).
3414    #[inline]
3415    pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3416        self.nth_of_attribute_dependencies.contains(local_name)
3417    }
3418
3419    /// Returns the normal rule map for a given pseudo-element.
3420    #[inline]
3421    pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3422        self.normal_rules.rules(pseudo_elements)
3423    }
3424
3425    /// Returns the featureless pseudo rule map for a given pseudo-element.
3426    #[inline]
3427    pub fn featureless_host_rules(
3428        &self,
3429        pseudo_elements: &[PseudoElement],
3430    ) -> Option<&SelectorMap<Rule>> {
3431        self.featureless_host_rules
3432            .as_ref()
3433            .and_then(|d| d.rules(pseudo_elements))
3434    }
3435
3436    /// Whether there's any featureless rule that could match in this scope.
3437    pub fn any_featureless_host_rules(&self) -> bool {
3438        self.featureless_host_rules.is_some()
3439    }
3440
3441    /// Returns the slotted rule map for a given pseudo-element.
3442    #[inline]
3443    pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3444        self.slotted_rules
3445            .as_ref()
3446            .and_then(|d| d.rules(pseudo_elements))
3447    }
3448
3449    /// Whether there's any ::slotted rule that could match in this scope.
3450    pub fn any_slotted_rule(&self) -> bool {
3451        self.slotted_rules.is_some()
3452    }
3453
3454    /// Returns the parts rule map for a given pseudo-element.
3455    #[inline]
3456    pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3457        self.part_rules
3458            .as_ref()
3459            .and_then(|d| d.rules(pseudo_elements))
3460    }
3461
3462    /// Whether there's any ::part rule that could match in this scope.
3463    pub fn any_part_rule(&self) -> bool {
3464        self.part_rules.is_some()
3465    }
3466
3467    #[inline]
3468    fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3469        self.layers[id.0 as usize].order
3470    }
3471
3472    pub(crate) fn container_condition_matches<E>(
3473        &self,
3474        mut id: ContainerConditionId,
3475        stylist: &Stylist,
3476        element: E,
3477        context: &mut MatchingContext<E::Impl>,
3478    ) -> bool
3479    where
3480        E: TElement,
3481    {
3482        loop {
3483            let condition_ref = &self.container_conditions[id.0 as usize];
3484            let condition = match condition_ref.condition {
3485                None => return true,
3486                Some(ref c) => c,
3487            };
3488            let matches = condition
3489                .matches(
3490                    stylist,
3491                    element,
3492                    context.extra_data.originating_element_style,
3493                    &mut context.extra_data.cascade_input_flags,
3494                )
3495                .to_bool(/* unknown = */ false);
3496            if !matches {
3497                return false;
3498            }
3499            id = condition_ref.parent;
3500        }
3501    }
3502
3503    pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3504        &self,
3505        rule: &Rule,
3506        element: E,
3507        context: &mut MatchingContext<E::Impl>,
3508    ) -> ScopeProximity {
3509        context
3510            .extra_data
3511            .cascade_input_flags
3512            .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3513
3514        // Whether the scope root matches a shadow host mostly olny depends on scope-intrinsic
3515        // parameters (i.e. bounds/implicit scope) - except for the use of `::parts`, where
3516        // matching crosses the shadow boundary.
3517        let result = scope_root_candidates(
3518            &self.scope_conditions,
3519            rule.scope_condition_id,
3520            &element,
3521            rule.selector.is_part(),
3522            &self.scope_subject_map,
3523            context,
3524        );
3525        for candidate in result.candidates {
3526            if context.nest_for_scope(Some(candidate.root), |context| {
3527                matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
3528            }) {
3529                return candidate.proximity;
3530            }
3531        }
3532        ScopeProximity::infinity()
3533    }
3534
3535    fn did_finish_rebuild(&mut self) {
3536        self.shrink_maps_if_needed();
3537        self.compute_layer_order();
3538    }
3539
3540    fn shrink_maps_if_needed(&mut self) {
3541        self.normal_rules.shrink_if_needed();
3542        if let Some(ref mut host_rules) = self.featureless_host_rules {
3543            host_rules.shrink_if_needed();
3544        }
3545        if let Some(ref mut slotted_rules) = self.slotted_rules {
3546            slotted_rules.shrink_if_needed();
3547        }
3548        self.animations.shrink_if_needed();
3549        self.custom_property_registrations.shrink_if_needed();
3550        self.invalidation_map.shrink_if_needed();
3551        self.relative_selector_invalidation_map.shrink_if_needed();
3552        self.additional_relative_selector_invalidation_map
3553            .shrink_if_needed();
3554        self.attribute_dependencies.shrink_if_needed();
3555        self.nth_of_attribute_dependencies.shrink_if_needed();
3556        self.nth_of_custom_state_dependencies.shrink_if_needed();
3557        self.nth_of_class_dependencies.shrink_if_needed();
3558        self.nth_of_mapped_ids.shrink_if_needed();
3559        self.mapped_ids.shrink_if_needed();
3560        self.layer_id.shrink_if_needed();
3561        self.selectors_for_cache_revalidation.shrink_if_needed();
3562        self.scope_subject_map.shrink_if_needed();
3563    }
3564
3565    fn compute_layer_order(&mut self) {
3566        debug_assert_ne!(
3567            self.layers.len(),
3568            0,
3569            "There should be at least the root layer!"
3570        );
3571        if self.layers.len() == 1 {
3572            return; // Nothing to do
3573        }
3574        let (first, remaining) = self.layers.split_at_mut(1);
3575        let root = &mut first[0];
3576        let mut order = LayerOrder::first();
3577        compute_layer_order_for_subtree(root, remaining, &mut order);
3578
3579        // NOTE(emilio): This is a bit trickier than it should to avoid having
3580        // to clone() around layer indices.
3581        fn compute_layer_order_for_subtree(
3582            parent: &mut CascadeLayer,
3583            remaining_layers: &mut [CascadeLayer],
3584            order: &mut LayerOrder,
3585        ) {
3586            for child in parent.children.iter() {
3587                debug_assert!(
3588                    parent.id < *child,
3589                    "Children are always registered after parents"
3590                );
3591                let child_index = (child.0 - parent.id.0 - 1) as usize;
3592                let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3593                let child = &mut first[child_index];
3594                compute_layer_order_for_subtree(child, remaining, order);
3595            }
3596
3597            if parent.id != LayerId::root() {
3598                parent.order = *order;
3599                order.inc();
3600            }
3601        }
3602        self.extra_data.sort_by_layer(&self.layers);
3603        self.animations
3604            .sort_with(&self.layers, compare_keyframes_in_same_layer);
3605        self.custom_property_registrations.sort(&self.layers)
3606    }
3607
3608    /// Collects all the applicable media query results into `results`.
3609    ///
3610    /// This duplicates part of the logic in `add_stylesheet`, which is
3611    /// a bit unfortunate.
3612    ///
3613    /// FIXME(emilio): With a bit of smartness in
3614    /// `media_feature_affected_matches`, we could convert
3615    /// `EffectiveMediaQueryResults` into a vector without too much effort.
3616    fn collect_applicable_media_query_results_into<S>(
3617        device: &Device,
3618        stylesheet: &S,
3619        guard: &SharedRwLockReadGuard,
3620        results: &mut Vec<MediaListKey>,
3621        contents_list: &mut StyleSheetContentList,
3622        custom_media_map: &mut CustomMediaMap,
3623    ) where
3624        S: StylesheetInDocument + 'static,
3625    {
3626        if !stylesheet.enabled() {
3627            return;
3628        }
3629        if !stylesheet.is_effective_for_device(device, &custom_media_map, guard) {
3630            return;
3631        }
3632
3633        debug!(" + {:?}", stylesheet);
3634        let contents = stylesheet.contents(guard);
3635        results.push(contents.to_media_list_key());
3636
3637        // Safety: StyleSheetContents are reference-counted with Arc.
3638        contents_list.push(StylesheetContentsPtr(unsafe {
3639            Arc::from_raw_addrefed(&*contents)
3640        }));
3641
3642        let mut iter = stylesheet
3643            .contents(guard)
3644            .effective_rules(device, custom_media_map, guard);
3645        while let Some(rule) = iter.next() {
3646            match *rule {
3647                CssRule::CustomMedia(ref custom_media) => {
3648                    iter.custom_media()
3649                        .insert(custom_media.name.0.clone(), custom_media.condition.clone());
3650                },
3651                CssRule::Import(ref lock) => {
3652                    let import_rule = lock.read_with(guard);
3653                    debug!(" + {:?}", import_rule.stylesheet.media(guard));
3654                    results.push(import_rule.to_media_list_key());
3655                },
3656                CssRule::Media(ref media_rule) => {
3657                    debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3658                    results.push(media_rule.to_media_list_key());
3659                },
3660                _ => {},
3661            }
3662        }
3663    }
3664
3665    fn add_styles(
3666        &mut self,
3667        selectors: &SelectorList<SelectorImpl>,
3668        declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3669        ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3670        containing_rule_state: &ContainingRuleState,
3671        mut replaced_selectors: Option<&mut ReplacedSelectors>,
3672        guard: &SharedRwLockReadGuard,
3673        rebuild_kind: SheetRebuildKind,
3674        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3675        quirks_mode: QuirksMode,
3676        mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
3677    ) -> Result<(), AllocErr> {
3678        self.num_declarations += declarations.read_with(guard).len();
3679        for selector in selectors.slice() {
3680            self.num_selectors += 1;
3681
3682            let pseudo_elements = selector.pseudo_elements();
3683            let inner_pseudo_element = pseudo_elements.get(0);
3684            if let Some(pseudo) = inner_pseudo_element {
3685                if pseudo.is_precomputed() {
3686                    debug_assert!(selector.is_universal());
3687                    debug_assert!(ancestor_selectors.is_none());
3688                    debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3689                    // Because we precompute pseudos, we cannot possibly calculate scope proximity.
3690                    debug_assert!(!containing_rule_state.scope_is_effective());
3691                    precomputed_pseudo_element_decls
3692                        .as_mut()
3693                        .expect("Expected precomputed declarations for the UA level")
3694                        .get_or_insert_with(pseudo, Vec::new)
3695                        .push(ApplicableDeclarationBlock::new(
3696                            StyleSource::from_declarations(declarations.clone()),
3697                            self.rules_source_order,
3698                            CascadeLevel::UANormal,
3699                            selector.specificity(),
3700                            LayerOrder::root(),
3701                            ScopeProximity::infinity(),
3702                        ));
3703                    continue;
3704                }
3705                if pseudo_elements
3706                    .iter()
3707                    .any(|p| p.is_unknown_webkit_pseudo_element())
3708                {
3709                    continue;
3710                }
3711            }
3712
3713            debug_assert!(!pseudo_elements
3714                .iter()
3715                .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
3716
3717            let selector = match ancestor_selectors {
3718                Some(ref s) => selector.replace_parent_selector(&s),
3719                None => selector.clone(),
3720            };
3721
3722            let hashes = AncestorHashes::new(&selector, quirks_mode);
3723
3724            let rule = Rule::new(
3725                selector,
3726                hashes,
3727                StyleSource::from_declarations(declarations.clone()),
3728                self.rules_source_order,
3729                containing_rule_state.layer_id,
3730                containing_rule_state.container_condition_id,
3731                containing_rule_state.in_starting_style,
3732                containing_rule_state.containing_scope_rule_state.id,
3733            );
3734
3735            if let Some(ref mut replaced_selectors) = replaced_selectors {
3736                replaced_selectors.push(rule.selector.clone())
3737            }
3738
3739            if rebuild_kind.should_rebuild_invalidation() {
3740                let mut scope_dependencies = note_selector_for_invalidation(
3741                    &rule.selector,
3742                    quirks_mode,
3743                    &mut self.invalidation_map,
3744                    &mut self.relative_selector_invalidation_map,
3745                    &mut self.additional_relative_selector_invalidation_map,
3746                    None,
3747                    None,
3748                )?;
3749                let mut needs_revalidation = false;
3750                let mut visitor = StylistSelectorVisitor {
3751                    needs_revalidation: &mut needs_revalidation,
3752                    passed_rightmost_selector: false,
3753                    in_selector_list_of: SelectorListKind::default(),
3754                    mapped_ids: &mut self.mapped_ids,
3755                    nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3756                    attribute_dependencies: &mut self.attribute_dependencies,
3757                    nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3758                    nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3759                    nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3760                    state_dependencies: &mut self.state_dependencies,
3761                    nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3762                    document_state_dependencies: &mut self.document_state_dependencies,
3763                };
3764                rule.selector.visit(&mut visitor);
3765
3766                if needs_revalidation {
3767                    self.selectors_for_cache_revalidation.insert(
3768                        RevalidationSelectorAndHashes::new(
3769                            rule.selector.clone(),
3770                            rule.hashes.clone(),
3771                        ),
3772                        quirks_mode,
3773                    )?;
3774                }
3775
3776                match (
3777                    scope_dependencies.as_mut(),
3778                    collected_scope_dependencies.as_mut(),
3779                ) {
3780                    (Some(inner_scope_deps), Some(scope_deps)) => {
3781                        scope_deps.append(inner_scope_deps)
3782                    },
3783                    _ => {},
3784                }
3785            }
3786
3787            // Part is special, since given it doesn't have any
3788            // selectors inside, it's not worth using a whole
3789            // SelectorMap for it.
3790            if let Some(parts) = rule.selector.parts() {
3791                // ::part() has all semantics, so we just need to
3792                // put any of them in the selector map.
3793                //
3794                // We choose the last one quite arbitrarily,
3795                // expecting it's slightly more likely to be more
3796                // specific.
3797                let map = self
3798                    .part_rules
3799                    .get_or_insert_with(|| Box::new(Default::default()))
3800                    .for_insertion(&pseudo_elements);
3801                map.try_reserve(1)?;
3802                let vec = map.entry(parts.last().unwrap().clone().0).or_default();
3803                vec.try_reserve(1)?;
3804                vec.push(rule);
3805            } else {
3806                let scope_matches_shadow_host = containing_rule_state
3807                    .containing_scope_rule_state
3808                    .matches_shadow_host
3809                    == ScopeMatchesShadowHost::Yes;
3810                let matches_featureless_host_only = match rule
3811                    .selector
3812                    .matches_featureless_host(scope_matches_shadow_host)
3813                {
3814                    MatchesFeaturelessHost::Only => true,
3815                    MatchesFeaturelessHost::Yes => {
3816                        // We need to insert this in featureless_host_rules but also normal_rules.
3817                        self.featureless_host_rules
3818                            .get_or_insert_with(|| Box::new(Default::default()))
3819                            .for_insertion(&pseudo_elements)
3820                            .insert(rule.clone(), quirks_mode)?;
3821                        false
3822                    },
3823                    MatchesFeaturelessHost::Never => false,
3824                };
3825
3826                // NOTE(emilio): It's fine to look at :host and then at
3827                // ::slotted(..), since :host::slotted(..) could never
3828                // possibly match, as <slot> is not a valid shadow host.
3829                // :scope may match featureless shadow host if the scope
3830                // root is the shadow root.
3831                // See https://github.com/w3c/csswg-drafts/issues/9025
3832                let rules = if matches_featureless_host_only {
3833                    self.featureless_host_rules
3834                        .get_or_insert_with(|| Box::new(Default::default()))
3835                } else if rule.selector.is_slotted() {
3836                    self.slotted_rules
3837                        .get_or_insert_with(|| Box::new(Default::default()))
3838                } else {
3839                    &mut self.normal_rules
3840                }
3841                .for_insertion(&pseudo_elements);
3842                rules.insert(rule, quirks_mode)?;
3843            }
3844        }
3845        self.rules_source_order += 1;
3846        Ok(())
3847    }
3848
3849    fn add_rule_list<S>(
3850        &mut self,
3851        rules: std::slice::Iter<CssRule>,
3852        device: &Device,
3853        quirks_mode: QuirksMode,
3854        stylesheet: &S,
3855        sheet_index: usize,
3856        guard: &SharedRwLockReadGuard,
3857        rebuild_kind: SheetRebuildKind,
3858        containing_rule_state: &mut ContainingRuleState,
3859        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3860        mut difference: Option<&mut CascadeDataDifference>,
3861    ) -> Result<(), AllocErr>
3862    where
3863        S: StylesheetInDocument + 'static,
3864    {
3865        for rule in rules {
3866            // Handle leaf rules first, as those are by far the most common
3867            // ones, and are always effective, so we can skip some checks.
3868            let mut handled = true;
3869            let mut list_for_nested_rules = None;
3870            match *rule {
3871                CssRule::Style(ref locked) => {
3872                    let style_rule = locked.read_with(guard);
3873                    let has_nested_rules = style_rule.rules.is_some();
3874                    let mut replaced_selectors = ReplacedSelectors::new();
3875                    let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
3876                    let collect_replaced_selectors =
3877                        has_nested_rules && ancestor_selectors.is_some();
3878                    let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
3879                        .scope_is_effective()
3880                        .then(|| Vec::new());
3881                    self.add_styles(
3882                        &style_rule.selectors,
3883                        &style_rule.block,
3884                        ancestor_selectors,
3885                        containing_rule_state,
3886                        if collect_replaced_selectors {
3887                            Some(&mut replaced_selectors)
3888                        } else {
3889                            None
3890                        },
3891                        guard,
3892                        rebuild_kind,
3893                        precomputed_pseudo_element_decls.as_deref_mut(),
3894                        quirks_mode,
3895                        inner_dependencies.as_mut(),
3896                    )?;
3897                    if let Some(mut scope_dependencies) = inner_dependencies {
3898                        containing_rule_state
3899                            .containing_scope_rule_state
3900                            .inner_dependencies
3901                            .append(&mut scope_dependencies);
3902                    }
3903                    if has_nested_rules {
3904                        handled = false;
3905                        list_for_nested_rules = Some(if collect_replaced_selectors {
3906                            SelectorList::from_iter(replaced_selectors.drain(..))
3907                        } else {
3908                            style_rule.selectors.clone()
3909                        });
3910                    }
3911                },
3912                CssRule::NestedDeclarations(ref rule) => {
3913                    if let Some(ref ancestor_selectors) =
3914                        containing_rule_state.ancestor_selector_lists.last()
3915                    {
3916                        let decls = &rule.read_with(guard).block;
3917                        let selectors = match containing_rule_state.nested_declarations_context {
3918                            NestedDeclarationsContext::Style => ancestor_selectors,
3919                            NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
3920                        };
3921                        let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
3922                            .scope_is_effective()
3923                            .then(|| Vec::new());
3924                        self.add_styles(
3925                            selectors,
3926                            decls,
3927                            /* ancestor_selectors = */ None,
3928                            containing_rule_state,
3929                            /* replaced_selectors = */ None,
3930                            guard,
3931                            // We don't need to rebuild invalidation data, since our ancestor style
3932                            // rule would've done this.
3933                            SheetRebuildKind::CascadeOnly,
3934                            precomputed_pseudo_element_decls.as_deref_mut(),
3935                            quirks_mode,
3936                            inner_dependencies.as_mut(),
3937                        )?;
3938                        if let Some(mut scope_dependencies) = inner_dependencies {
3939                            containing_rule_state
3940                                .containing_scope_rule_state
3941                                .inner_dependencies
3942                                .append(&mut scope_dependencies);
3943                        }
3944                    }
3945                },
3946                CssRule::Keyframes(ref keyframes_rule) => {
3947                    debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
3948                    let keyframes_rule = keyframes_rule.read_with(guard);
3949                    let name = keyframes_rule.name.as_atom().clone();
3950                    let animation = KeyframesAnimation::from_keyframes(
3951                        &keyframes_rule.keyframes,
3952                        keyframes_rule.vendor_prefix.clone(),
3953                        guard,
3954                    );
3955                    self.animations.try_insert_with(
3956                        name,
3957                        animation,
3958                        containing_rule_state.layer_id,
3959                        compare_keyframes_in_same_layer,
3960                    )?;
3961                },
3962                CssRule::Property(ref registration) => {
3963                    self.custom_property_registrations.try_insert(
3964                        registration.name.0.clone(),
3965                        Arc::clone(registration),
3966                        containing_rule_state.layer_id,
3967                    )?;
3968                },
3969                CssRule::FontFace(ref rule) => {
3970                    // NOTE(emilio): We don't care about container_condition_id
3971                    // because:
3972                    //
3973                    //     Global, name-defining at-rules such as @keyframes or
3974                    //     @font-face or @layer that are defined inside container
3975                    //     queries are not constrained by the container query
3976                    //     conditions.
3977                    //
3978                    // https://drafts.csswg.org/css-contain-3/#container-rule
3979                    // (Same elsewhere)
3980                    self.extra_data
3981                        .add_font_face(rule, containing_rule_state.layer_id);
3982                },
3983                CssRule::FontFeatureValues(ref rule) => {
3984                    self.extra_data
3985                        .add_font_feature_values(rule, containing_rule_state.layer_id);
3986                },
3987                CssRule::FontPaletteValues(ref rule) => {
3988                    self.extra_data
3989                        .add_font_palette_values(rule, containing_rule_state.layer_id);
3990                },
3991                CssRule::CounterStyle(ref rule) => {
3992                    self.extra_data.add_counter_style(
3993                        guard,
3994                        rule,
3995                        containing_rule_state.layer_id,
3996                    )?;
3997                },
3998                CssRule::PositionTry(ref rule) => {
3999                    let name = rule.read_with(guard).name.0.clone();
4000                    if let Some(ref mut difference) = difference {
4001                        difference.changed_position_try_names.insert(name.clone());
4002                    }
4003                    self.extra_data.add_position_try(
4004                        name,
4005                        rule.clone(),
4006                        containing_rule_state.layer_id,
4007                    )?;
4008                },
4009                CssRule::Page(ref rule) => {
4010                    self.extra_data
4011                        .add_page(guard, rule, containing_rule_state.layer_id)?;
4012                    handled = false;
4013                },
4014                _ => {
4015                    handled = false;
4016                },
4017            }
4018
4019            if handled {
4020                // Assert that there are no children, and that the rule is
4021                // effective.
4022                if cfg!(debug_assertions) {
4023                    let mut effective = false;
4024                    let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4025                        rule,
4026                        device,
4027                        quirks_mode,
4028                        &self.custom_media,
4029                        guard,
4030                        &mut effective,
4031                    );
4032                    debug_assert!(children.is_none());
4033                    debug_assert!(effective);
4034                }
4035                continue;
4036            }
4037
4038            let mut effective = false;
4039            let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4040                rule,
4041                device,
4042                quirks_mode,
4043                &self.custom_media,
4044                guard,
4045                &mut effective,
4046            );
4047            if !effective {
4048                continue;
4049            }
4050
4051            fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
4052                // TODO: Measure what's more common / expensive, if
4053                // layer.clone() or the double hash lookup in the insert
4054                // case.
4055                if let Some(id) = data.layer_id.get(layer) {
4056                    return *id;
4057                }
4058                let id = LayerId(data.layers.len() as u16);
4059
4060                let parent_layer_id = if layer.layer_names().len() > 1 {
4061                    let mut parent = layer.clone();
4062                    parent.0.pop();
4063
4064                    *data
4065                        .layer_id
4066                        .get_mut(&parent)
4067                        .expect("Parent layers should be registered before child layers")
4068                } else {
4069                    LayerId::root()
4070                };
4071
4072                data.layers[parent_layer_id.0 as usize].children.push(id);
4073                data.layers.push(CascadeLayer {
4074                    id,
4075                    // NOTE(emilio): Order is evaluated after rebuild in
4076                    // compute_layer_order.
4077                    order: LayerOrder::first(),
4078                    children: vec![],
4079                });
4080
4081                data.layer_id.insert(layer.clone(), id);
4082
4083                id
4084            }
4085
4086            fn maybe_register_layers(
4087                data: &mut CascadeData,
4088                name: Option<&LayerName>,
4089                containing_rule_state: &mut ContainingRuleState,
4090            ) {
4091                let anon_name;
4092                let name = match name {
4093                    Some(name) => name,
4094                    None => {
4095                        anon_name = LayerName::new_anonymous();
4096                        &anon_name
4097                    },
4098                };
4099                for name in name.layer_names() {
4100                    containing_rule_state.layer_name.0.push(name.clone());
4101                    containing_rule_state.layer_id =
4102                        maybe_register_layer(data, &containing_rule_state.layer_name);
4103                }
4104                debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
4105            }
4106
4107            let saved_containing_rule_state = containing_rule_state.save();
4108            match *rule {
4109                CssRule::Import(ref lock) => {
4110                    let import_rule = lock.read_with(guard);
4111                    if rebuild_kind.should_rebuild_invalidation() {
4112                        self.effective_media_query_results
4113                            .saw_effective(import_rule);
4114                    }
4115                    match import_rule.layer {
4116                        ImportLayer::Named(ref name) => {
4117                            maybe_register_layers(self, Some(name), containing_rule_state)
4118                        },
4119                        ImportLayer::Anonymous => {
4120                            maybe_register_layers(self, None, containing_rule_state)
4121                        },
4122                        ImportLayer::None => {},
4123                    }
4124                },
4125                CssRule::Media(ref media_rule) => {
4126                    if rebuild_kind.should_rebuild_invalidation() {
4127                        self.effective_media_query_results
4128                            .saw_effective(&**media_rule);
4129                    }
4130                },
4131                CssRule::LayerBlock(ref rule) => {
4132                    maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
4133                },
4134                CssRule::CustomMedia(ref custom_media) => {
4135                    self.custom_media
4136                        .insert(custom_media.name.0.clone(), custom_media.condition.clone());
4137                },
4138                CssRule::LayerStatement(ref rule) => {
4139                    for name in &*rule.names {
4140                        maybe_register_layers(self, Some(name), containing_rule_state);
4141                        // Register each layer individually.
4142                        containing_rule_state.restore(&saved_containing_rule_state);
4143                    }
4144                },
4145                CssRule::Style(..) => {
4146                    containing_rule_state.nested_declarations_context =
4147                        NestedDeclarationsContext::Style;
4148                    if let Some(s) = list_for_nested_rules {
4149                        containing_rule_state.ancestor_selector_lists.push(s);
4150                    }
4151                },
4152                CssRule::Container(ref rule) => {
4153                    let id = ContainerConditionId(self.container_conditions.len() as u16);
4154                    self.container_conditions.push(ContainerConditionReference {
4155                        parent: containing_rule_state.container_condition_id,
4156                        condition: Some(rule.condition.clone()),
4157                    });
4158                    containing_rule_state.container_condition_id = id;
4159                },
4160                CssRule::StartingStyle(..) => {
4161                    containing_rule_state.in_starting_style = true;
4162                },
4163                CssRule::Scope(ref rule) => {
4164                    containing_rule_state.nested_declarations_context =
4165                        NestedDeclarationsContext::Scope;
4166                    let id = ScopeConditionId(self.scope_conditions.len() as u16);
4167                    let mut matches_shadow_host = false;
4168                    let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
4169                        matches_shadow_host = scope_start_matches_shadow_host(start);
4170                        // Would be unused, but use the default as fallback.
4171                        StylistImplicitScopeRoot::default()
4172                    } else {
4173                        // (Re)Moving stylesheets trigger a complete flush, so saving the implicit
4174                        // root here should be safe.
4175                        if let Some(root) = stylesheet.implicit_scope_root() {
4176                            matches_shadow_host = root.matches_shadow_host();
4177                            match root {
4178                                ImplicitScopeRoot::InLightTree(_)
4179                                | ImplicitScopeRoot::Constructed
4180                                | ImplicitScopeRoot::DocumentElement => {
4181                                    StylistImplicitScopeRoot::Normal(root)
4182                                },
4183                                ImplicitScopeRoot::ShadowHost(_)
4184                                | ImplicitScopeRoot::InShadowTree(_) => {
4185                                    // Style data can be shared between shadow trees, so we must
4186                                    // query the implicit root for that specific tree.
4187                                    // Shared stylesheet means shared sheet indices, so we can
4188                                    // use that to locate the implicit root.
4189                                    // Technically, this can also be applied to the light tree,
4190                                    // but that requires also knowing about what cascade level we're at.
4191                                    StylistImplicitScopeRoot::Cached(sheet_index)
4192                                },
4193                            }
4194                        } else {
4195                            // Could not find implicit scope root, but use the default as fallback.
4196                            StylistImplicitScopeRoot::default()
4197                        }
4198                    };
4199
4200                    let replaced =
4201                        {
4202                            let start = rule.bounds.start.as_ref().map(|selector| {
4203                                match containing_rule_state.ancestor_selector_lists.last() {
4204                                    Some(s) => selector.replace_parent_selector(s),
4205                                    None => selector.clone(),
4206                                }
4207                            });
4208                            let implicit_scope_selector = &*IMPLICIT_SCOPE;
4209                            let end = rule.bounds.end.as_ref().map(|selector| {
4210                                selector.replace_parent_selector(implicit_scope_selector)
4211                            });
4212                            containing_rule_state
4213                                .ancestor_selector_lists
4214                                .push(implicit_scope_selector.clone());
4215                            ScopeBoundsWithHashes::new(quirks_mode, start, end)
4216                        };
4217
4218                    if let Some(selectors) = replaced.start.as_ref() {
4219                        self.scope_subject_map
4220                            .add_bound_start(&selectors.selectors, quirks_mode);
4221                    }
4222
4223                    let is_trivial = replaced.is_trivial();
4224                    self.scope_conditions.push(ScopeConditionReference {
4225                        parent: containing_rule_state.containing_scope_rule_state.id,
4226                        condition: Some(replaced),
4227                        implicit_scope_root,
4228                        is_trivial,
4229                    });
4230
4231                    containing_rule_state
4232                        .containing_scope_rule_state
4233                        .matches_shadow_host
4234                        .nest_for_scope(matches_shadow_host);
4235                    containing_rule_state.containing_scope_rule_state.id = id;
4236                    containing_rule_state
4237                        .containing_scope_rule_state
4238                        .inner_dependencies
4239                        .reserve(children.iter().len());
4240                },
4241                // We don't care about any other rule.
4242                _ => {},
4243            }
4244
4245            if let Some(children) = children {
4246                self.add_rule_list(
4247                    children,
4248                    device,
4249                    quirks_mode,
4250                    stylesheet,
4251                    sheet_index,
4252                    guard,
4253                    rebuild_kind,
4254                    containing_rule_state,
4255                    precomputed_pseudo_element_decls.as_deref_mut(),
4256                    difference.as_deref_mut(),
4257                )?;
4258            }
4259
4260            if let Some(scope_restore_data) =
4261                containing_rule_state.restore(&saved_containing_rule_state)
4262            {
4263                let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
4264                let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
4265                if let Some(cond) = cur_scope.condition.as_ref() {
4266                    let mut _unused = false;
4267                    let visitor = StylistSelectorVisitor {
4268                        needs_revalidation: &mut _unused,
4269                        passed_rightmost_selector: true,
4270                        in_selector_list_of: SelectorListKind::default(),
4271                        mapped_ids: &mut self.mapped_ids,
4272                        nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
4273                        attribute_dependencies: &mut self.attribute_dependencies,
4274                        nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
4275                        nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
4276                        nth_of_custom_state_dependencies: &mut self
4277                            .nth_of_custom_state_dependencies,
4278                        state_dependencies: &mut self.state_dependencies,
4279                        nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
4280                        document_state_dependencies: &mut self.document_state_dependencies,
4281                    };
4282
4283                    let dependency_vector = build_scope_dependencies(
4284                        quirks_mode,
4285                        cur_scope_inner_dependencies,
4286                        visitor,
4287                        cond,
4288                        &mut self.invalidation_map,
4289                        &mut self.relative_selector_invalidation_map,
4290                        &mut self.additional_relative_selector_invalidation_map,
4291                    )?;
4292
4293                    containing_rule_state
4294                        .containing_scope_rule_state
4295                        .inner_dependencies
4296                        .extend(dependency_vector);
4297                }
4298            }
4299        }
4300
4301        Ok(())
4302    }
4303
4304    // Returns Err(..) to signify OOM
4305    fn add_stylesheet<S>(
4306        &mut self,
4307        device: &Device,
4308        quirks_mode: QuirksMode,
4309        stylesheet: &S,
4310        sheet_index: usize,
4311        guard: &SharedRwLockReadGuard,
4312        rebuild_kind: SheetRebuildKind,
4313        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4314        mut difference: Option<&mut CascadeDataDifference>,
4315    ) -> Result<(), AllocErr>
4316    where
4317        S: StylesheetInDocument + 'static,
4318    {
4319        if !stylesheet.enabled() {
4320            return Ok(());
4321        }
4322
4323        if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
4324            return Ok(());
4325        }
4326
4327        let contents = stylesheet.contents(guard);
4328        if rebuild_kind.should_rebuild_invalidation() {
4329            self.effective_media_query_results.saw_effective(&*contents);
4330        }
4331
4332        let mut state = ContainingRuleState::default();
4333        self.add_rule_list(
4334            contents.rules(guard).iter(),
4335            device,
4336            quirks_mode,
4337            stylesheet,
4338            sheet_index,
4339            guard,
4340            rebuild_kind,
4341            &mut state,
4342            precomputed_pseudo_element_decls.as_deref_mut(),
4343            difference.as_deref_mut(),
4344        )?;
4345
4346        Ok(())
4347    }
4348
4349    /// Returns whether all the media-feature affected values matched before and
4350    /// match now in the given stylesheet.
4351    pub fn media_feature_affected_matches<S>(
4352        &self,
4353        stylesheet: &S,
4354        guard: &SharedRwLockReadGuard,
4355        device: &Device,
4356        quirks_mode: QuirksMode,
4357    ) -> bool
4358    where
4359        S: StylesheetInDocument + 'static,
4360    {
4361        use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4362
4363        let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
4364
4365        let contents = stylesheet.contents(guard);
4366        let effective_then = self.effective_media_query_results.was_effective(contents);
4367
4368        if effective_now != effective_then {
4369            debug!(
4370                " > Stylesheet {:?} changed -> {}, {}",
4371                stylesheet.media(guard),
4372                effective_then,
4373                effective_now
4374            );
4375            return false;
4376        }
4377
4378        if !effective_now {
4379            return true;
4380        }
4381
4382        // We don't need a custom media map for PotentiallyEffectiveMediaRules.
4383        let custom_media = CustomMediaMap::default();
4384        let mut iter =
4385            contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
4386        while let Some(rule) = iter.next() {
4387            match *rule {
4388                CssRule::Style(..)
4389                | CssRule::NestedDeclarations(..)
4390                | CssRule::Namespace(..)
4391                | CssRule::FontFace(..)
4392                | CssRule::Container(..)
4393                | CssRule::CounterStyle(..)
4394                | CssRule::Supports(..)
4395                | CssRule::Keyframes(..)
4396                | CssRule::Margin(..)
4397                | CssRule::Page(..)
4398                | CssRule::Property(..)
4399                | CssRule::Document(..)
4400                | CssRule::LayerBlock(..)
4401                | CssRule::LayerStatement(..)
4402                | CssRule::FontPaletteValues(..)
4403                | CssRule::FontFeatureValues(..)
4404                | CssRule::Scope(..)
4405                | CssRule::StartingStyle(..)
4406                | CssRule::CustomMedia(..)
4407                | CssRule::PositionTry(..) => {
4408                    // Not affected by device changes. @custom-media is handled by the potential
4409                    // @media rules referencing it being handled.
4410                    continue;
4411                },
4412                CssRule::Import(ref lock) => {
4413                    let import_rule = lock.read_with(guard);
4414                    let effective_now = match import_rule.stylesheet.media(guard) {
4415                        Some(m) => m.evaluate(
4416                            device,
4417                            quirks_mode,
4418                            &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4419                        ),
4420                        None => true,
4421                    };
4422                    let effective_then = self
4423                        .effective_media_query_results
4424                        .was_effective(import_rule);
4425                    if effective_now != effective_then {
4426                        debug!(
4427                            " > @import rule {:?} changed {} -> {}",
4428                            import_rule.stylesheet.media(guard),
4429                            effective_then,
4430                            effective_now
4431                        );
4432                        return false;
4433                    }
4434
4435                    if !effective_now {
4436                        iter.skip_children();
4437                    }
4438                },
4439                CssRule::Media(ref media_rule) => {
4440                    let mq = media_rule.media_queries.read_with(guard);
4441                    let effective_now = mq.evaluate(
4442                        device,
4443                        quirks_mode,
4444                        &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4445                    );
4446                    let effective_then = self
4447                        .effective_media_query_results
4448                        .was_effective(&**media_rule);
4449
4450                    if effective_now != effective_then {
4451                        debug!(
4452                            " > @media rule {:?} changed {} -> {}",
4453                            mq, effective_then, effective_now
4454                        );
4455                        return false;
4456                    }
4457
4458                    if !effective_now {
4459                        iter.skip_children();
4460                    }
4461                },
4462            }
4463        }
4464
4465        true
4466    }
4467
4468    /// Returns the custom properties map.
4469    pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4470        &self.custom_property_registrations
4471    }
4472
4473    fn revalidate_scopes<E: TElement>(
4474        &self,
4475        element: &E,
4476        matching_context: &mut MatchingContext<E::Impl>,
4477        result: &mut ScopeRevalidationResult,
4478    ) {
4479        // TODO(dshin): A scope block may not contain style rule for this element, but we don't keep
4480        // track of that, so we check _all_ scope conditions. It's possible for two comparable elements
4481        // to share scope & relevant styles rules, but also differ in scopes that do not contain style
4482        // rules relevant to them. So while we can be certain that an identical result share scoped styles
4483        // (Given that other sharing conditions are met), it is uncertain if elements with non-matching
4484        // results do not.
4485        for condition_id in 1..self.scope_conditions.len() {
4486            let condition = &self.scope_conditions[condition_id];
4487            let matches = if condition.is_trivial {
4488                // Just ignore this condition - for style sharing candidates, guaranteed
4489                // the same match result.
4490                continue;
4491            } else {
4492                let result = scope_root_candidates(
4493                    &self.scope_conditions,
4494                    ScopeConditionId(condition_id as u16),
4495                    element,
4496                    // This should be ok since we aren't sharing styles across shadow boundaries.
4497                    false,
4498                    &self.scope_subject_map,
4499                    matching_context,
4500                );
4501                !result.candidates.is_empty()
4502            };
4503            result.scopes_matched.push(matches);
4504        }
4505    }
4506
4507    /// Clears the cascade data, but not the invalidation data.
4508    fn clear_cascade_data(&mut self) {
4509        self.normal_rules.clear();
4510        if let Some(ref mut slotted_rules) = self.slotted_rules {
4511            slotted_rules.clear();
4512        }
4513        if let Some(ref mut part_rules) = self.part_rules {
4514            part_rules.clear();
4515        }
4516        if let Some(ref mut host_rules) = self.featureless_host_rules {
4517            host_rules.clear();
4518        }
4519        self.animations.clear();
4520        self.custom_property_registrations.clear();
4521        self.layer_id.clear();
4522        self.layers.clear();
4523        self.layers.push(CascadeLayer::root());
4524        self.custom_media.clear();
4525        self.container_conditions.clear();
4526        self.container_conditions
4527            .push(ContainerConditionReference::none());
4528        self.scope_conditions.clear();
4529        self.scope_conditions.push(ScopeConditionReference::none());
4530        self.extra_data.clear();
4531        self.rules_source_order = 0;
4532        self.num_selectors = 0;
4533        self.num_declarations = 0;
4534    }
4535
4536    fn clear_invalidation_data(&mut self) {
4537        self.invalidation_map.clear();
4538        self.relative_selector_invalidation_map.clear();
4539        self.additional_relative_selector_invalidation_map.clear();
4540        self.attribute_dependencies.clear();
4541        self.nth_of_attribute_dependencies.clear();
4542        self.nth_of_custom_state_dependencies.clear();
4543        self.nth_of_class_dependencies.clear();
4544        self.state_dependencies = ElementState::empty();
4545        self.nth_of_state_dependencies = ElementState::empty();
4546        self.document_state_dependencies = DocumentState::empty();
4547        self.mapped_ids.clear();
4548        self.nth_of_mapped_ids.clear();
4549        self.selectors_for_cache_revalidation.clear();
4550        self.effective_media_query_results.clear();
4551        self.scope_subject_map.clear();
4552    }
4553}
4554
4555fn note_scope_selector_for_invalidation(
4556    quirks_mode: QuirksMode,
4557    scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
4558    dependency_vector: &mut Vec<Dependency>,
4559    invalidation_map: &mut InvalidationMap,
4560    relative_selector_invalidation_map: &mut InvalidationMap,
4561    additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4562    visitor: &mut StylistSelectorVisitor<'_>,
4563    scope_kind: ScopeDependencyInvalidationKind,
4564    s: &Selector<SelectorImpl>,
4565) -> Result<(), AllocErr> {
4566    let mut new_inner_dependencies = note_selector_for_invalidation(
4567        &s.clone(),
4568        quirks_mode,
4569        invalidation_map,
4570        relative_selector_invalidation_map,
4571        additional_relative_selector_invalidation_map,
4572        Some(&scope_dependencies),
4573        Some(scope_kind),
4574    )?;
4575    s.visit(visitor);
4576    new_inner_dependencies.as_mut().map(|dep| {
4577        dependency_vector.append(dep);
4578    });
4579    Ok(())
4580}
4581
4582fn build_scope_dependencies(
4583    quirks_mode: QuirksMode,
4584    mut cur_scope_inner_dependencies: Vec<Dependency>,
4585    mut visitor: StylistSelectorVisitor<'_>,
4586    cond: &ScopeBoundsWithHashes,
4587    mut invalidation_map: &mut InvalidationMap,
4588    mut relative_selector_invalidation_map: &mut InvalidationMap,
4589    mut additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4590) -> Result<Vec<Dependency>, AllocErr> {
4591    if cond.end.is_some() {
4592        let deps =
4593            ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
4594        let mut end_dependency_vector = Vec::new();
4595        for s in cond.end_selectors() {
4596            note_scope_selector_for_invalidation(
4597                quirks_mode,
4598                &deps,
4599                &mut end_dependency_vector,
4600                &mut invalidation_map,
4601                &mut relative_selector_invalidation_map,
4602                &mut additional_relative_selector_invalidation_map,
4603                &mut visitor,
4604                ScopeDependencyInvalidationKind::ScopeEnd,
4605                s,
4606            )?;
4607        }
4608        cur_scope_inner_dependencies.append(&mut end_dependency_vector);
4609    }
4610    let inner_scope_dependencies =
4611        ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
4612
4613    Ok(if cond.start.is_some() {
4614        let mut dependency_vector = Vec::new();
4615        for s in cond.start_selectors() {
4616            note_scope_selector_for_invalidation(
4617                quirks_mode,
4618                &inner_scope_dependencies,
4619                &mut dependency_vector,
4620                &mut invalidation_map,
4621                &mut relative_selector_invalidation_map,
4622                &mut additional_relative_selector_invalidation_map,
4623                &mut visitor,
4624                ScopeDependencyInvalidationKind::ExplicitScope,
4625                s,
4626            )?;
4627        }
4628        dependency_vector
4629    } else {
4630        vec![Dependency::new(
4631            IMPLICIT_SCOPE.slice()[0].clone(),
4632            0,
4633            Some(inner_scope_dependencies),
4634            DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
4635        )]
4636    })
4637}
4638
4639impl CascadeDataCacheEntry for CascadeData {
4640    fn rebuild<S>(
4641        device: &Device,
4642        quirks_mode: QuirksMode,
4643        collection: SheetCollectionFlusher<S>,
4644        guard: &SharedRwLockReadGuard,
4645        old: &Self,
4646        difference: &mut CascadeDataDifference,
4647    ) -> Result<Arc<Self>, AllocErr>
4648    where
4649        S: StylesheetInDocument + PartialEq + 'static,
4650    {
4651        debug_assert!(collection.dirty(), "We surely need to do something?");
4652        // If we're doing a full rebuild anyways, don't bother cloning the data.
4653        let mut updatable_entry = match collection.data_validity() {
4654            DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4655            DataValidity::FullyInvalid => Self::new(),
4656        };
4657        updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
4658        Ok(Arc::new(updatable_entry))
4659    }
4660
4661    #[cfg(feature = "gecko")]
4662    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4663        self.normal_rules.add_size_of(ops, sizes);
4664        if let Some(ref slotted_rules) = self.slotted_rules {
4665            slotted_rules.add_size_of(ops, sizes);
4666        }
4667        if let Some(ref part_rules) = self.part_rules {
4668            part_rules.add_size_of(ops, sizes);
4669        }
4670        if let Some(ref host_rules) = self.featureless_host_rules {
4671            host_rules.add_size_of(ops, sizes);
4672        }
4673        sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4674        sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4675        sizes.mOther += self.animations.size_of(ops);
4676        sizes.mOther += self.effective_media_query_results.size_of(ops);
4677        sizes.mOther += self.extra_data.size_of(ops);
4678    }
4679}
4680
4681impl Default for CascadeData {
4682    fn default() -> Self {
4683        CascadeData::new()
4684    }
4685}
4686
4687/// A rule, that wraps a style rule, but represents a single selector of the
4688/// rule.
4689#[derive(Clone, Debug, MallocSizeOf)]
4690pub struct Rule {
4691    /// The selector this struct represents. We store this and the
4692    /// any_{important,normal} booleans inline in the Rule to avoid
4693    /// pointer-chasing when gathering applicable declarations, which
4694    /// can ruin performance when there are a lot of rules.
4695    #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4696    pub selector: Selector<SelectorImpl>,
4697
4698    /// The ancestor hashes associated with the selector.
4699    pub hashes: AncestorHashes,
4700
4701    /// The source order this style rule appears in. Note that we only use
4702    /// three bytes to store this value in ApplicableDeclarationsBlock, so
4703    /// we could repurpose that storage here if we needed to.
4704    pub source_order: u32,
4705
4706    /// The current layer id of this style rule.
4707    pub layer_id: LayerId,
4708
4709    /// The current @container rule id.
4710    pub container_condition_id: ContainerConditionId,
4711
4712    /// True if this rule is inside @starting-style.
4713    pub is_starting_style: bool,
4714
4715    /// The current @scope rule id.
4716    pub scope_condition_id: ScopeConditionId,
4717
4718    /// The actual style rule.
4719    #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4720    pub style_source: StyleSource,
4721}
4722
4723impl SelectorMapEntry for Rule {
4724    fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4725        self.selector.iter()
4726    }
4727}
4728
4729impl Rule {
4730    /// Returns the specificity of the rule.
4731    pub fn specificity(&self) -> u32 {
4732        self.selector.specificity()
4733    }
4734
4735    /// Turns this rule into an `ApplicableDeclarationBlock` for the given
4736    /// cascade level.
4737    pub fn to_applicable_declaration_block(
4738        &self,
4739        level: CascadeLevel,
4740        cascade_data: &CascadeData,
4741        scope_proximity: ScopeProximity,
4742    ) -> ApplicableDeclarationBlock {
4743        ApplicableDeclarationBlock::new(
4744            self.style_source.clone(),
4745            self.source_order,
4746            level,
4747            self.specificity(),
4748            cascade_data.layer_order_for(self.layer_id),
4749            scope_proximity,
4750        )
4751    }
4752
4753    /// Creates a new Rule.
4754    pub fn new(
4755        selector: Selector<SelectorImpl>,
4756        hashes: AncestorHashes,
4757        style_source: StyleSource,
4758        source_order: u32,
4759        layer_id: LayerId,
4760        container_condition_id: ContainerConditionId,
4761        is_starting_style: bool,
4762        scope_condition_id: ScopeConditionId,
4763    ) -> Self {
4764        Self {
4765            selector,
4766            hashes,
4767            style_source,
4768            source_order,
4769            layer_id,
4770            container_condition_id,
4771            is_starting_style,
4772            scope_condition_id,
4773        }
4774    }
4775}
4776
4777// The size of this is critical to performance on the bloom-basic
4778// microbenchmark.
4779// When iterating over a large Rule array, we want to be able to fast-reject
4780// selectors (with the inline hashes) with as few cache misses as possible.
4781size_of_test!(Rule, 40);
4782
4783/// A function to be able to test the revalidation stuff.
4784pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
4785    let mut needs_revalidation = false;
4786    let mut mapped_ids = Default::default();
4787    let mut nth_of_mapped_ids = Default::default();
4788    let mut attribute_dependencies = Default::default();
4789    let mut nth_of_class_dependencies = Default::default();
4790    let mut nth_of_attribute_dependencies = Default::default();
4791    let mut nth_of_custom_state_dependencies = Default::default();
4792    let mut state_dependencies = ElementState::empty();
4793    let mut nth_of_state_dependencies = ElementState::empty();
4794    let mut document_state_dependencies = DocumentState::empty();
4795    let mut visitor = StylistSelectorVisitor {
4796        passed_rightmost_selector: false,
4797        needs_revalidation: &mut needs_revalidation,
4798        in_selector_list_of: SelectorListKind::default(),
4799        mapped_ids: &mut mapped_ids,
4800        nth_of_mapped_ids: &mut nth_of_mapped_ids,
4801        attribute_dependencies: &mut attribute_dependencies,
4802        nth_of_class_dependencies: &mut nth_of_class_dependencies,
4803        nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
4804        nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
4805        state_dependencies: &mut state_dependencies,
4806        nth_of_state_dependencies: &mut nth_of_state_dependencies,
4807        document_state_dependencies: &mut document_state_dependencies,
4808    };
4809    s.visit(&mut visitor);
4810    needs_revalidation
4811}