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