diff options
Diffstat (limited to 'components/style/servo/selector_parser.rs')
-rw-r--r-- | components/style/servo/selector_parser.rs | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index e45e82358dd..a2be7c46415 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -19,6 +19,7 @@ use selectors::parser::{AttrSelector, SelectorMethods}; use std::borrow::Cow; use std::fmt; use std::fmt::Debug; +use std::mem; /// A pseudo-element, both public and private. /// @@ -26,10 +27,13 @@ use std::fmt::Debug; #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] +#[repr(usize)] pub enum PseudoElement { + // Eager pseudos. Keep these first so that eager_index() works. + After = 0, Before, - After, Selection, + // Non-eager pseudos. DetailsSummary, DetailsContent, ServoText, @@ -48,8 +52,8 @@ impl ToCss for PseudoElement { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { use self::PseudoElement::*; dest.write_str(match *self { - Before => "::before", After => "::after", + Before => "::before", Selection => "::selection", DetailsSummary => "::-servo-details-summary", DetailsContent => "::-servo-details-content", @@ -67,25 +71,60 @@ impl ToCss for PseudoElement { } } +/// The number of eager pseudo-elements. Keep this in sync with cascade_type. +pub const EAGER_PSEUDO_COUNT: usize = 3; + impl PseudoElement { + /// Gets the canonical index of this eagerly-cascaded pseudo-element. + #[inline] + pub fn eager_index(&self) -> usize { + debug_assert!(self.is_eager()); + self.clone() as usize + } + + /// Creates a pseudo-element from an eager index. + #[inline] + pub fn from_eager_index(i: usize) -> Self { + assert!(i < EAGER_PSEUDO_COUNT); + let result: PseudoElement = unsafe { mem::transmute(i) }; + debug_assert!(result.is_eager()); + result + } + /// Whether the current pseudo element is :before or :after. #[inline] pub fn is_before_or_after(&self) -> bool { - match *self { - PseudoElement::Before | - PseudoElement::After => true, - _ => false, - } + matches!(*self, PseudoElement::After | PseudoElement::Before) + } + + /// Whether this pseudo-element is eagerly-cascaded. + #[inline] + pub fn is_eager(&self) -> bool { + self.cascade_type() == PseudoElementCascadeType::Eager + } + + /// Whether this pseudo-element is lazily-cascaded. + #[inline] + pub fn is_lazy(&self) -> bool { + self.cascade_type() == PseudoElementCascadeType::Lazy + } + + /// Whether this pseudo-element is precomputed. + #[inline] + pub fn is_precomputed(&self) -> bool { + self.cascade_type() == PseudoElementCascadeType::Precomputed } /// Returns which kind of cascade type has this pseudo. /// /// For more info on cascade types, see docs/components/style.md + /// + /// Note: Keep this in sync with EAGER_PSEUDO_COUNT. #[inline] pub fn cascade_type(&self) -> PseudoElementCascadeType { match *self { - PseudoElement::Before | PseudoElement::After | + PseudoElement::Before | PseudoElement::Selection => PseudoElementCascadeType::Eager, PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy, PseudoElement::DetailsContent | @@ -369,6 +408,17 @@ impl SelectorImpl { pseudo.cascade_type() } + /// A helper to traverse each eagerly cascaded pseudo-element, executing + /// `fun` on it. + #[inline] + pub fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F) + where F: FnMut(PseudoElement), + { + for i in 0..EAGER_PSEUDO_COUNT { + fun(PseudoElement::from_eager_index(i)); + } + } + /// Executes `fun` for each pseudo-element. #[inline] pub fn each_pseudo_element<F>(mut fun: F) @@ -396,12 +446,6 @@ impl SelectorImpl { pub fn pseudo_class_state_flag(pc: &NonTSPseudoClass) -> ElementState { pc.state_flag() } - - /// Returns whether this pseudo is either :before or :after. - #[inline] - pub fn pseudo_is_before_or_after(pseudo: &PseudoElement) -> bool { - pseudo.is_before_or_after() - } } /// Servo's version of an element snapshot. |