Skip to main content

style/
stylist.rs

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