aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/rule_tree/mod.rs
diff options
context:
space:
mode:
authorAnthony Ramine <nox@nox.paris>2020-04-15 17:23:44 +0200
committerAnthony Ramine <nox@nox.paris>2020-04-17 11:43:39 +0200
commit1ea6a0cdd4c4a986823158713e1da47347844b0c (patch)
treebba7d962fd2d3167d2aa4ae78dea384067f4155f /components/style/rule_tree/mod.rs
parent13db0c158452dc4a1f865dbfa54c96a08dbd1530 (diff)
downloadservo-1ea6a0cdd4c4a986823158713e1da47347844b0c.tar.gz
servo-1ea6a0cdd4c4a986823158713e1da47347844b0c.zip
Move CascadeLevel to its own rule_tree submodule
Diffstat (limited to 'components/style/rule_tree/mod.rs')
-rw-r--r--components/style/rule_tree/mod.rs278
1 files changed, 4 insertions, 274 deletions
diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs
index 9844148bffe..f9f9500144f 100644
--- a/components/style/rule_tree/mod.rs
+++ b/components/style/rule_tree/mod.rs
@@ -10,7 +10,7 @@ use crate::applicable_declarations::ApplicableDeclarationList;
use crate::hash::FxHashMap;
use crate::properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
-use crate::stylesheets::{Origin, StyleRule};
+use crate::stylesheets::StyleRule;
use crate::thread_state;
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
use parking_lot::RwLock;
@@ -21,7 +21,10 @@ use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
+mod level;
mod map;
+
+pub use self::level::{CascadeLevel, ShadowCascadeOrder};
use self::map::Map;
/// The rule tree, the structure servo uses to preserve the results of selector
@@ -172,61 +175,6 @@ const FREE_LIST_SENTINEL: *mut RuleNode = 0x01 as *mut RuleNode;
/// another thread is currently adding an entry). We spin if we find this value.
const FREE_LIST_LOCKED: *mut RuleNode = 0x02 as *mut RuleNode;
-/// A counter to track how many shadow root rules deep we are. This is used to
-/// handle:
-///
-/// https://drafts.csswg.org/css-scoping/#shadow-cascading
-///
-/// See the static functions for the meaning of different values.
-#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
-pub struct ShadowCascadeOrder(i8);
-
-impl ShadowCascadeOrder {
- /// A level for the outermost shadow tree (the shadow tree we own, and the
- /// ones from the slots we're slotted in).
- #[inline]
- pub fn for_outermost_shadow_tree() -> Self {
- Self(-1)
- }
-
- /// A level for the element's tree.
- #[inline]
- fn for_same_tree() -> Self {
- Self(0)
- }
-
- /// A level for the innermost containing tree (the one closest to the
- /// element).
- #[inline]
- pub fn for_innermost_containing_tree() -> Self {
- Self(1)
- }
-
- /// Decrement the level, moving inwards. We should only move inwards if
- /// we're traversing slots.
- #[inline]
- pub fn dec(&mut self) {
- debug_assert!(self.0 < 0);
- self.0 = self.0.saturating_sub(1);
- }
-
- /// The level, moving inwards. We should only move inwards if we're
- /// traversing slots.
- #[inline]
- pub fn inc(&mut self) {
- debug_assert_ne!(self.0, -1);
- self.0 = self.0.saturating_add(1);
- }
-}
-
-impl std::ops::Neg for ShadowCascadeOrder {
- type Output = Self;
- #[inline]
- fn neg(self) -> Self {
- Self(self.0.neg())
- }
-}
-
impl RuleTree {
/// Construct a new rule tree.
pub fn new() -> Self {
@@ -630,224 +578,6 @@ impl RuleTree {
/// where it likely did not result from a rigorous performance analysis.)
const RULE_TREE_GC_INTERVAL: usize = 300;
-/// The cascade level these rules are relevant at, as per[1][2][3].
-///
-/// Presentational hints for SVG and HTML are in the "author-level
-/// zero-specificity" level, that is, right after user rules, and before author
-/// rules.
-///
-/// The order of variants declared here is significant, and must be in
-/// _ascending_ order of precedence.
-///
-/// See also [4] for the Shadow DOM bits. We rely on the invariant that rules
-/// from outside the tree the element is in can't affect the element.
-///
-/// The opposite is not true (i.e., :host and ::slotted) from an "inner" shadow
-/// tree may affect an element connected to the document or an "outer" shadow
-/// tree.
-///
-/// [1]: https://drafts.csswg.org/css-cascade/#cascade-origin
-/// [2]: https://drafts.csswg.org/css-cascade/#preshint
-/// [3]: https://html.spec.whatwg.org/multipage/#presentational-hints
-/// [4]: https://drafts.csswg.org/css-scoping/#shadow-cascading
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd)]
-pub enum CascadeLevel {
- /// Normal User-Agent rules.
- UANormal,
- /// User normal rules.
- UserNormal,
- /// Presentational hints.
- PresHints,
- /// Shadow DOM styles from author styles.
- AuthorNormal {
- /// The order in the shadow tree hierarchy. This number is relative to
- /// the tree of the element, and thus the only invariants that need to
- /// be preserved is:
- ///
- /// * Zero is the same tree as the element that matched the rule. This
- /// is important so that we can optimize style attribute insertions.
- ///
- /// * The levels are ordered in accordance with
- /// https://drafts.csswg.org/css-scoping/#shadow-cascading
- shadow_cascade_order: ShadowCascadeOrder,
- },
- /// SVG SMIL animations.
- SMILOverride,
- /// CSS animations and script-generated animations.
- Animations,
- /// Author-supplied important rules.
- AuthorImportant {
- /// The order in the shadow tree hierarchy, inverted, so that PartialOrd
- /// does the right thing.
- shadow_cascade_order: ShadowCascadeOrder,
- },
- /// User important rules.
- UserImportant,
- /// User-agent important rules.
- UAImportant,
- /// Transitions
- Transitions,
-}
-
-impl CascadeLevel {
- /// Pack this cascade level in a single byte.
- ///
- /// We have 10 levels, which we can represent with 4 bits, and then a
- /// cascade order optionally, which we can clamp to three bits max, and
- /// represent with a fourth bit for the sign.
- ///
- /// So this creates: SOOODDDD
- ///
- /// Where `S` is the sign of the order (one if negative, 0 otherwise), `O`
- /// is the absolute value of the order, and `D`s are the discriminant.
- #[inline]
- pub fn to_byte_lossy(&self) -> u8 {
- let (discriminant, order) = match *self {
- Self::UANormal => (0, 0),
- Self::UserNormal => (1, 0),
- Self::PresHints => (2, 0),
- Self::AuthorNormal {
- shadow_cascade_order,
- } => (3, shadow_cascade_order.0),
- Self::SMILOverride => (4, 0),
- Self::Animations => (5, 0),
- Self::AuthorImportant {
- shadow_cascade_order,
- } => (6, shadow_cascade_order.0),
- Self::UserImportant => (7, 0),
- Self::UAImportant => (8, 0),
- Self::Transitions => (9, 0),
- };
-
- debug_assert_eq!(discriminant & 0xf, discriminant);
- if order == 0 {
- return discriminant;
- }
-
- let negative = order < 0;
- let value = std::cmp::min(order.abs() as u8, 0b111);
- (negative as u8) << 7 | value << 4 | discriminant
- }
-
- /// Convert back from the single-byte representation of the cascade level
- /// explained above.
- #[inline]
- pub fn from_byte(b: u8) -> Self {
- let order = {
- let abs = ((b & 0b01110000) >> 4) as i8;
- let negative = b & 0b10000000 != 0;
- if negative {
- -abs
- } else {
- abs
- }
- };
- let discriminant = b & 0xf;
- let level = match discriminant {
- 0 => Self::UANormal,
- 1 => Self::UserNormal,
- 2 => Self::PresHints,
- 3 => {
- return Self::AuthorNormal {
- shadow_cascade_order: ShadowCascadeOrder(order),
- }
- },
- 4 => Self::SMILOverride,
- 5 => Self::Animations,
- 6 => {
- return Self::AuthorImportant {
- shadow_cascade_order: ShadowCascadeOrder(order),
- }
- },
- 7 => Self::UserImportant,
- 8 => Self::UAImportant,
- 9 => Self::Transitions,
- _ => unreachable!("Didn't expect {} as a discriminant", discriminant),
- };
- debug_assert_eq!(order, 0, "Didn't expect an order value for {:?}", level);
- level
- }
-
- /// Select a lock guard for this level
- pub fn guard<'a>(&self, guards: &'a StylesheetGuards<'a>) -> &'a SharedRwLockReadGuard<'a> {
- match *self {
- CascadeLevel::UANormal |
- CascadeLevel::UserNormal |
- CascadeLevel::UserImportant |
- CascadeLevel::UAImportant => guards.ua_or_user,
- _ => guards.author,
- }
- }
-
- /// Returns the cascade level for author important declarations from the
- /// same tree as the element.
- #[inline]
- pub fn same_tree_author_important() -> Self {
- CascadeLevel::AuthorImportant {
- shadow_cascade_order: ShadowCascadeOrder::for_same_tree(),
- }
- }
-
- /// Returns the cascade level for author normal declarations from the same
- /// tree as the element.
- #[inline]
- pub fn same_tree_author_normal() -> Self {
- CascadeLevel::AuthorNormal {
- shadow_cascade_order: ShadowCascadeOrder::for_same_tree(),
- }
- }
-
- /// Returns whether this cascade level represents important rules of some
- /// sort.
- #[inline]
- pub fn is_important(&self) -> bool {
- match *self {
- CascadeLevel::AuthorImportant { .. } |
- CascadeLevel::UserImportant |
- CascadeLevel::UAImportant => true,
- _ => false,
- }
- }
-
- /// Returns the importance relevant for this rule. Pretty similar to
- /// `is_important`.
- #[inline]
- pub fn importance(&self) -> Importance {
- if self.is_important() {
- Importance::Important
- } else {
- Importance::Normal
- }
- }
-
- /// Returns the cascade origin of the rule.
- #[inline]
- pub fn origin(&self) -> Origin {
- match *self {
- CascadeLevel::UAImportant | CascadeLevel::UANormal => Origin::UserAgent,
- CascadeLevel::UserImportant | CascadeLevel::UserNormal => Origin::User,
- CascadeLevel::PresHints |
- CascadeLevel::AuthorNormal { .. } |
- CascadeLevel::AuthorImportant { .. } |
- CascadeLevel::SMILOverride |
- CascadeLevel::Animations |
- CascadeLevel::Transitions => Origin::Author,
- }
- }
-
- /// Returns whether this cascade level represents an animation rules.
- #[inline]
- pub fn is_animation(&self) -> bool {
- match *self {
- CascadeLevel::SMILOverride | CascadeLevel::Animations | CascadeLevel::Transitions => {
- true
- },
- _ => false,
- }
- }
-}
-
/// A node in the rule tree.
pub struct RuleNode {
/// The root node. Only the root has no root pointer, for obvious reasons.