Skip to main content

style/invalidation/
media_queries.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//! Code related to the invalidation of media-query-affected rules.
6
7use crate::context::QuirksMode;
8use crate::derives::*;
9use crate::device::Device;
10use crate::shared_lock::SharedRwLockReadGuard;
11use crate::stylesheets::{CustomMediaMap, DocumentRule, ImportRule, MediaRule};
12use crate::stylesheets::{NestedRuleIterationCondition, StylesheetContents, SupportsRule};
13use rustc_hash::FxHashSet;
14
15/// A key for a given media query result.
16///
17/// NOTE: It happens to be the case that all the media lists we care about
18/// happen to have a stable address, so we can just use an opaque pointer to
19/// represent them.
20///
21/// Also, note that right now when a rule or stylesheet is removed, we do a full
22/// style flush, so there's no need to worry about other item created with the
23/// same pointer address.
24///
25/// If this changes, though, we may need to remove the item from the cache if
26/// present before it goes away.
27#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
28pub struct MediaListKey(usize);
29
30impl MediaListKey {
31    /// Create a MediaListKey from a raw usize.
32    pub fn from_raw(k: usize) -> Self {
33        MediaListKey(k)
34    }
35}
36
37/// A trait to get a given `MediaListKey` for a given item that can hold a
38/// `MediaList`.
39pub trait ToMediaListKey: Sized {
40    /// Get a `MediaListKey` for this item. This key needs to uniquely identify
41    /// the item.
42    fn to_media_list_key(&self) -> MediaListKey {
43        MediaListKey(self as *const Self as usize)
44    }
45}
46
47impl ToMediaListKey for StylesheetContents {}
48impl ToMediaListKey for ImportRule {}
49impl ToMediaListKey for MediaRule {}
50
51/// A struct that holds the result of a media query evaluation pass for the
52/// media queries that evaluated successfully.
53#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
54pub struct EffectiveMediaQueryResults {
55    /// The set of media lists that matched last time.
56    set: FxHashSet<MediaListKey>,
57}
58
59impl Default for EffectiveMediaQueryResults {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65impl EffectiveMediaQueryResults {
66    /// Trivially constructs an empty `EffectiveMediaQueryResults`.
67    pub fn new() -> Self {
68        Self {
69            set: FxHashSet::default(),
70        }
71    }
72
73    /// Resets the results, using an empty key.
74    pub fn clear(&mut self) {
75        self.set.clear()
76    }
77
78    /// Returns whether a given item was known to be effective when the results
79    /// were cached.
80    pub fn was_effective<T>(&self, item: &T) -> bool
81    where
82        T: ToMediaListKey,
83    {
84        self.set.contains(&item.to_media_list_key())
85    }
86
87    /// Notices that an effective item has been seen, and caches it as matching.
88    pub fn saw_effective<T>(&mut self, item: &T)
89    where
90        T: ToMediaListKey,
91    {
92        // NOTE(emilio): We can't assert that we don't cache the same item twice
93        // because of stylesheet reusing... shrug.
94        self.set.insert(item.to_media_list_key());
95    }
96}
97
98/// A filter that filters over effective rules, but allowing all potentially
99/// effective `@media` rules.
100pub struct PotentiallyEffectiveMediaRules;
101
102impl NestedRuleIterationCondition for PotentiallyEffectiveMediaRules {
103    fn process_import(
104        _: &SharedRwLockReadGuard,
105        _: &Device,
106        _: QuirksMode,
107        _: &CustomMediaMap,
108        _: &ImportRule,
109    ) -> bool {
110        true
111    }
112
113    fn process_media(
114        _: &SharedRwLockReadGuard,
115        _: &Device,
116        _: QuirksMode,
117        _: &CustomMediaMap,
118        _: &MediaRule,
119    ) -> bool {
120        true
121    }
122
123    /// Whether we should process the nested rules in a given `@-moz-document` rule.
124    fn process_document(
125        guard: &SharedRwLockReadGuard,
126        device: &Device,
127        quirks_mode: QuirksMode,
128        rule: &DocumentRule,
129    ) -> bool {
130        use crate::stylesheets::EffectiveRules;
131        EffectiveRules::process_document(guard, device, quirks_mode, rule)
132    }
133
134    /// Whether we should process the nested rules in a given `@supports` rule.
135    fn process_supports(
136        guard: &SharedRwLockReadGuard,
137        device: &Device,
138        quirks_mode: QuirksMode,
139        rule: &SupportsRule,
140    ) -> bool {
141        use crate::stylesheets::EffectiveRules;
142        EffectiveRules::process_supports(guard, device, quirks_mode, rule)
143    }
144}