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