Use a more compact representation to store eager pseudo-elements.

This means that ElementStyles only need a single word to store eager pseudos.

MozReview-Commit-ID: 5bDXlDweN46
This commit is contained in:
Bobby Holley 2017-03-31 18:04:29 -07:00
parent 1ff008caa3
commit 3f0d022ba2
6 changed files with 207 additions and 97 deletions

View file

@ -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,15 +71,30 @@ 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.
@ -99,11 +118,13 @@ impl PseudoElement {
/// 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 |
@ -387,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)