aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/applicable_declarations.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/applicable_declarations.rs')
-rw-r--r--components/style/applicable_declarations.rs105
1 files changed, 67 insertions, 38 deletions
diff --git a/components/style/applicable_declarations.rs b/components/style/applicable_declarations.rs
index ab7c47307d7..d4674fa1bc7 100644
--- a/components/style/applicable_declarations.rs
+++ b/components/style/applicable_declarations.rs
@@ -5,12 +5,11 @@
//! Applicable declarations management.
use properties::PropertyDeclarationBlock;
-use rule_tree::{CascadeLevel, StyleSource};
+use rule_tree::{CascadeLevel, ShadowCascadeOrder, StyleSource};
use servo_arc::Arc;
use shared_lock::Locked;
use smallvec::SmallVec;
use std::fmt::{self, Debug};
-use std::mem;
/// List of applicable declarations. This is a transient structure that shuttles
/// declarations between selector matching and inserting into the rule tree, and
@@ -25,45 +24,67 @@ pub type ApplicableDeclarationList = SmallVec<[ApplicableDeclarationBlock; 16]>;
/// That's a limit that could be reached in realistic webpages, so we use
/// 24 bits and enforce defined behavior in the overflow case.
///
-/// Note that the value of 24 is also hard-coded into the level() accessor,
-/// which does a byte-aligned load of the 4th byte. If you change this value
-/// you'll need to change that as well.
-///
/// [1] https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/css/
/// RuleSet.h?l=128&rcl=90140ab80b84d0f889abc253410f44ed54ae04f3
+const SOURCE_ORDER_SHIFT: usize = 0;
const SOURCE_ORDER_BITS: usize = 24;
-const SOURCE_ORDER_MASK: u32 = (1 << SOURCE_ORDER_BITS) - 1;
-const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK;
+const SOURCE_ORDER_MAX: u32 = (1 << SOURCE_ORDER_BITS) - 1;
+const SOURCE_ORDER_MASK: u32 = SOURCE_ORDER_MAX << SOURCE_ORDER_SHIFT;
+
+/// We store up-to-15 shadow order levels.
+///
+/// You'd need an element slotted across 16 components with ::slotted rules to
+/// trigger this as of this writing, which looks... Unlikely.
+const SHADOW_CASCADE_ORDER_SHIFT: usize = SOURCE_ORDER_BITS;
+const SHADOW_CASCADE_ORDER_BITS: usize = 4;
+const SHADOW_CASCADE_ORDER_MAX: u8 = (1 << SHADOW_CASCADE_ORDER_BITS) - 1;
+const SHADOW_CASCADE_ORDER_MASK: u32 = (SHADOW_CASCADE_ORDER_MAX as u32) << SHADOW_CASCADE_ORDER_SHIFT;
-/// Stores the source order of a block and the cascade level it belongs to.
+const CASCADE_LEVEL_SHIFT: usize = SOURCE_ORDER_BITS + SHADOW_CASCADE_ORDER_BITS;
+const CASCADE_LEVEL_BITS: usize = 4;
+const CASCADE_LEVEL_MAX: u8 = (1 << CASCADE_LEVEL_BITS) - 1;
+const CASCADE_LEVEL_MASK: u32 = (CASCADE_LEVEL_MAX as u32) << CASCADE_LEVEL_SHIFT;
+
+/// Stores the source order of a block, the cascade level it belongs to, and the
+/// counter needed to handle Shadow DOM cascade order properly.
#[derive(Clone, Copy, Eq, MallocSizeOf, PartialEq)]
-struct SourceOrderAndCascadeLevel(u32);
+struct ApplicableDeclarationBits(u32);
-impl SourceOrderAndCascadeLevel {
- fn new(source_order: u32, cascade_level: CascadeLevel) -> SourceOrderAndCascadeLevel {
+impl ApplicableDeclarationBits {
+ fn new(
+ source_order: u32,
+ cascade_level: CascadeLevel,
+ shadow_cascade_order: ShadowCascadeOrder,
+ ) -> Self {
+ debug_assert!(
+ cascade_level as u8 <= CASCADE_LEVEL_MAX,
+ "Gotta find more bits!"
+ );
let mut bits = ::std::cmp::min(source_order, SOURCE_ORDER_MAX);
- bits |= (cascade_level as u8 as u32) << SOURCE_ORDER_BITS;
- SourceOrderAndCascadeLevel(bits)
+ bits |= ((shadow_cascade_order & SHADOW_CASCADE_ORDER_MAX) as u32) << SHADOW_CASCADE_ORDER_SHIFT;
+ bits |= (cascade_level as u8 as u32) << CASCADE_LEVEL_SHIFT;
+ ApplicableDeclarationBits(bits)
}
- fn order(&self) -> u32 {
- self.0 & SOURCE_ORDER_MASK
+ fn source_order(&self) -> u32 {
+ (self.0 & SOURCE_ORDER_MASK) >> SOURCE_ORDER_SHIFT
+ }
+
+ fn shadow_cascade_order(&self) -> ShadowCascadeOrder {
+ ((self.0 & SHADOW_CASCADE_ORDER_MASK) >> SHADOW_CASCADE_ORDER_SHIFT) as ShadowCascadeOrder
}
fn level(&self) -> CascadeLevel {
- unsafe {
- // Transmute rather than shifting so that we're sure the compiler
- // emits a simple byte-aligned load.
- let as_bytes: [u8; 4] = mem::transmute(self.0);
- CascadeLevel::from_byte(as_bytes[3])
- }
+ let byte = ((self.0 & CASCADE_LEVEL_MASK) >> CASCADE_LEVEL_SHIFT) as u8;
+ unsafe { CascadeLevel::from_byte(byte) }
}
}
-impl Debug for SourceOrderAndCascadeLevel {
+impl Debug for ApplicableDeclarationBits {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("SourceOrderAndCascadeLevel")
- .field("order", &self.order())
+ f.debug_struct("ApplicableDeclarationBits")
+ .field("source_order", &self.source_order())
+ .field("shadow_cascade_order", &self.shadow_cascade_order())
.field("level", &self.level())
.finish()
}
@@ -79,8 +100,9 @@ pub struct ApplicableDeclarationBlock {
/// The style source, either a style rule, or a property declaration block.
#[ignore_malloc_size_of = "Arc"]
pub source: StyleSource,
- /// The source order of the block, and the cascade level it belongs to.
- order_and_level: SourceOrderAndCascadeLevel,
+ /// The bits containing the source order, cascade level, and shadow cascade
+ /// order.
+ bits: ApplicableDeclarationBits,
/// The specificity of the selector this block is represented by.
pub specificity: u32,
}
@@ -95,38 +117,45 @@ impl ApplicableDeclarationBlock {
) -> Self {
ApplicableDeclarationBlock {
source: StyleSource::Declarations(declarations),
- order_and_level: SourceOrderAndCascadeLevel::new(0, level),
+ bits: ApplicableDeclarationBits::new(0, level, 0),
specificity: 0,
}
}
/// Constructs an applicable declaration block from the given components
#[inline]
- pub fn new(source: StyleSource, order: u32, level: CascadeLevel, specificity: u32) -> Self {
+ pub fn new(
+ source: StyleSource,
+ order: u32,
+ level: CascadeLevel,
+ specificity: u32,
+ shadow_cascade_order: ShadowCascadeOrder,
+ ) -> Self {
ApplicableDeclarationBlock {
- source: source,
- order_and_level: SourceOrderAndCascadeLevel::new(order, level),
- specificity: specificity,
+ source,
+ bits: ApplicableDeclarationBits::new(order, level, shadow_cascade_order),
+ specificity,
}
}
/// Returns the source order of the block.
#[inline]
pub fn source_order(&self) -> u32 {
- self.order_and_level.order()
+ self.bits.source_order()
}
/// Returns the cascade level of the block.
#[inline]
pub fn level(&self) -> CascadeLevel {
- self.order_and_level.level()
+ self.bits.level()
}
- /// Convenience method to consume self and return the source alongside the
- /// level.
+ /// Convenience method to consume self and return the right thing for the
+ /// rule tree to iterate over.
#[inline]
- pub fn order_and_level(self) -> (StyleSource, CascadeLevel) {
+ pub fn for_rule_tree(self) -> (StyleSource, CascadeLevel, ShadowCascadeOrder) {
let level = self.level();
- (self.source, level)
+ let cascade_order = self.bits.shadow_cascade_order();
+ (self.source, level, cascade_order)
}
}