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