style/
stylist.rs

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