tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

level.rs (8336B)


      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 #![forbid(unsafe_code)]
      6 
      7 use crate::derives::*;
      8 use crate::properties::Importance;
      9 use crate::shared_lock::{SharedRwLockReadGuard, StylesheetGuards};
     10 use crate::stylesheets::Origin;
     11 
     12 /// The cascade level these rules are relevant at, as per[1][2][3].
     13 ///
     14 /// Presentational hints for SVG and HTML are in the "author-level
     15 /// zero-specificity" level, that is, right after user rules, and before author
     16 /// rules.
     17 ///
     18 /// The order of variants declared here is significant, and must be in
     19 /// _ascending_ order of precedence.
     20 ///
     21 /// See also [4] for the Shadow DOM bits. We rely on the invariant that rules
     22 /// from outside the tree the element is in can't affect the element.
     23 ///
     24 /// The opposite is not true (i.e., :host and ::slotted) from an "inner" shadow
     25 /// tree may affect an element connected to the document or an "outer" shadow
     26 /// tree.
     27 ///
     28 /// [1]: https://drafts.csswg.org/css-cascade/#cascade-origin
     29 /// [2]: https://drafts.csswg.org/css-cascade/#preshint
     30 /// [3]: https://html.spec.whatwg.org/multipage/#presentational-hints
     31 /// [4]: https://drafts.csswg.org/css-scoping/#shadow-cascading
     32 #[repr(u8)]
     33 #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
     34 pub enum CascadeLevel {
     35    /// Normal User-Agent rules.
     36    UANormal,
     37    /// User normal rules.
     38    UserNormal,
     39    /// Presentational hints.
     40    PresHints,
     41    /// Shadow DOM styles from author styles.
     42    AuthorNormal {
     43        /// The order in the shadow tree hierarchy. This number is relative to
     44        /// the tree of the element, and thus the only invariants that need to
     45        /// be preserved is:
     46        ///
     47        ///  * Zero is the same tree as the element that matched the rule. This
     48        ///    is important so that we can optimize style attribute insertions.
     49        ///
     50        ///  * The levels are ordered in accordance with
     51        ///    https://drafts.csswg.org/css-scoping/#shadow-cascading
     52        shadow_cascade_order: ShadowCascadeOrder,
     53    },
     54    /// https://drafts.csswg.org/css-anchor-position-1/#position-fallback-origin
     55    PositionFallback,
     56    /// SVG SMIL animations.
     57    SMILOverride,
     58    /// CSS animations and script-generated animations.
     59    Animations,
     60    /// Author-supplied important rules.
     61    AuthorImportant {
     62        /// The order in the shadow tree hierarchy, inverted, so that PartialOrd
     63        /// does the right thing.
     64        shadow_cascade_order: ShadowCascadeOrder,
     65    },
     66    /// User important rules.
     67    UserImportant,
     68    /// User-agent important rules.
     69    UAImportant,
     70    /// Transitions
     71    Transitions,
     72 }
     73 
     74 impl CascadeLevel {
     75    /// Convert this level from "unimportant" to "important".
     76    pub fn important(&self) -> Self {
     77        match *self {
     78            Self::UANormal => Self::UAImportant,
     79            Self::UserNormal => Self::UserImportant,
     80            Self::AuthorNormal {
     81                shadow_cascade_order,
     82            } => Self::AuthorImportant {
     83                shadow_cascade_order: -shadow_cascade_order,
     84            },
     85            Self::PresHints
     86            | Self::PositionFallback
     87            | Self::SMILOverride
     88            | Self::Animations
     89            | Self::AuthorImportant { .. }
     90            | Self::UserImportant
     91            | Self::UAImportant
     92            | Self::Transitions => *self,
     93        }
     94    }
     95 
     96    /// Convert this level from "important" to "non-important".
     97    pub fn unimportant(&self) -> Self {
     98        match *self {
     99            Self::UAImportant => Self::UANormal,
    100            Self::UserImportant => Self::UserNormal,
    101            Self::AuthorImportant {
    102                shadow_cascade_order,
    103            } => Self::AuthorNormal {
    104                shadow_cascade_order: -shadow_cascade_order,
    105            },
    106            Self::PresHints
    107            | Self::PositionFallback
    108            | Self::SMILOverride
    109            | Self::Animations
    110            | Self::AuthorNormal { .. }
    111            | Self::UserNormal
    112            | Self::UANormal
    113            | Self::Transitions => *self,
    114        }
    115    }
    116 
    117    /// Select a lock guard for this level
    118    pub fn guard<'a>(&self, guards: &'a StylesheetGuards<'a>) -> &'a SharedRwLockReadGuard<'a> {
    119        match *self {
    120            Self::UANormal | Self::UserNormal | Self::UserImportant | Self::UAImportant => {
    121                guards.ua_or_user
    122            },
    123            _ => guards.author,
    124        }
    125    }
    126 
    127    /// Returns the cascade level for author important declarations from the
    128    /// same tree as the element.
    129    #[inline]
    130    pub fn same_tree_author_important() -> Self {
    131        Self::AuthorImportant {
    132            shadow_cascade_order: ShadowCascadeOrder::for_same_tree(),
    133        }
    134    }
    135 
    136    /// Returns the cascade level for author normal declarations from the same
    137    /// tree as the element.
    138    #[inline]
    139    pub fn same_tree_author_normal() -> Self {
    140        Self::AuthorNormal {
    141            shadow_cascade_order: ShadowCascadeOrder::for_same_tree(),
    142        }
    143    }
    144 
    145    /// Returns whether this cascade level represents important rules of some
    146    /// sort.
    147    #[inline]
    148    pub fn is_important(&self) -> bool {
    149        match *self {
    150            Self::AuthorImportant { .. } | Self::UserImportant | Self::UAImportant => true,
    151            _ => false,
    152        }
    153    }
    154 
    155    /// Returns the importance relevant for this rule. Pretty similar to
    156    /// `is_important`.
    157    #[inline]
    158    pub fn importance(&self) -> Importance {
    159        if self.is_important() {
    160            Importance::Important
    161        } else {
    162            Importance::Normal
    163        }
    164    }
    165 
    166    /// Returns the cascade origin of the rule.
    167    #[inline]
    168    pub fn origin(&self) -> Origin {
    169        match *self {
    170            Self::UAImportant | Self::UANormal => Origin::UserAgent,
    171            Self::UserImportant | Self::UserNormal => Origin::User,
    172            Self::PresHints
    173            | Self::PositionFallback { .. }
    174            | Self::AuthorNormal { .. }
    175            | Self::AuthorImportant { .. }
    176            | Self::SMILOverride
    177            | Self::Animations
    178            | Self::Transitions => Origin::Author,
    179        }
    180    }
    181 
    182    /// Returns whether this cascade level represents an animation rules.
    183    #[inline]
    184    pub fn is_animation(&self) -> bool {
    185        match *self {
    186            Self::SMILOverride | Self::Animations | Self::Transitions => true,
    187            _ => false,
    188        }
    189    }
    190 }
    191 
    192 /// A counter to track how many shadow root rules deep we are. This is used to
    193 /// handle:
    194 ///
    195 /// https://drafts.csswg.org/css-scoping/#shadow-cascading
    196 ///
    197 /// See the static functions for the meaning of different values.
    198 #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
    199 pub struct ShadowCascadeOrder(i8);
    200 
    201 impl ShadowCascadeOrder {
    202    /// We keep a maximum of 3 bits of order as a limit so that we can pack
    203    /// CascadeLevel in one byte by using half of it for the order, if that ends
    204    /// up being necessary.
    205    const MAX: i8 = 0b111;
    206    const MIN: i8 = -Self::MAX;
    207 
    208    /// A level for the outermost shadow tree (the shadow tree we own, and the
    209    /// ones from the slots we're slotted in).
    210    #[inline]
    211    pub fn for_outermost_shadow_tree() -> Self {
    212        Self(-1)
    213    }
    214 
    215    /// A level for the element's tree.
    216    #[inline]
    217    fn for_same_tree() -> Self {
    218        Self(0)
    219    }
    220 
    221    /// A level for the innermost containing tree (the one closest to the
    222    /// element).
    223    #[inline]
    224    pub fn for_innermost_containing_tree() -> Self {
    225        Self(1)
    226    }
    227 
    228    /// Decrement the level, moving inwards. We should only move inwards if
    229    /// we're traversing slots.
    230    #[inline]
    231    pub fn dec(&mut self) {
    232        debug_assert!(self.0 < 0);
    233        if self.0 != Self::MIN {
    234            self.0 -= 1;
    235        }
    236    }
    237 
    238    /// The level, moving inwards. We should only move inwards if we're
    239    /// traversing slots.
    240    #[inline]
    241    pub fn inc(&mut self) {
    242        debug_assert_ne!(self.0, -1);
    243        if self.0 != Self::MAX {
    244            self.0 += 1;
    245        }
    246    }
    247 }
    248 
    249 impl std::ops::Neg for ShadowCascadeOrder {
    250    type Output = Self;
    251    #[inline]
    252    fn neg(self) -> Self {
    253        Self(self.0.neg())
    254    }
    255 }