diff --git a/components/style/data.rs b/components/style/data.rs index 2cf5bd56eb1..5d56ace2441 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -4,6 +4,7 @@ //! Per-node data used in style calculation. +use arrayvec::ArrayVec; use context::SharedStyleContext; use dom::TElement; use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; @@ -193,8 +194,8 @@ impl EagerPseudoStyles { } /// Returns a list of the pseudo-elements. - pub fn keys(&self) -> Vec { - let mut v = Vec::new(); + pub fn keys(&self) -> ArrayVec<[PseudoElement; EAGER_PSEUDO_COUNT]> { + let mut v = ArrayVec::new(); if let Some(ref arr) = self.0 { for i in 0..EAGER_PSEUDO_COUNT { if arr[i].is_some() { diff --git a/components/style/dom.rs b/components/style/dom.rs index bb41785da69..e2673593997 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -382,6 +382,20 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + pseudo: Option<&PseudoElement>) -> Option<&'a PreExistingComputedValues>; + /// Whether a given element may generate a pseudo-element. + /// + /// This is useful to avoid computing, for example, pseudo styles for + /// `::-first-line` or `::-first-letter`, when we know it won't affect us. + /// + /// TODO(emilio, bz): actually implement the logic for it. + fn may_generate_pseudo( + &self, + _pseudo: &PseudoElement, + _primary_style: &ComputedValues, + ) -> bool { + true + } + /// Returns true if this element may have a descendant needing style processing. /// /// Note that we cannot guarantee the existence of such an element, because @@ -444,7 +458,8 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + false } - /// Flag that this element has a descendant for animation-only restyle processing. + /// Flag that this element has a descendant for animation-only restyle + /// processing. /// /// Only safe to call with exclusive access to the element. unsafe fn set_animation_only_dirty_descendants(&self) { diff --git a/components/style/gecko/generated/pseudo_element_definition.rs b/components/style/gecko/generated/pseudo_element_definition.rs index 4f627fe9459..224ef0ce480 100644 --- a/components/style/gecko/generated/pseudo_element_definition.rs +++ b/components/style/gecko/generated/pseudo_element_definition.rs @@ -176,12 +176,14 @@ pub enum PseudoElement { /// The number of eager pseudo-elements. -pub const EAGER_PSEUDO_COUNT: usize = 2; +pub const EAGER_PSEUDO_COUNT: usize = 4; /// The list of eager pseudos. pub const EAGER_PSEUDOS: [PseudoElement; EAGER_PSEUDO_COUNT] = [ PseudoElement::Before, PseudoElement::After, + PseudoElement::FirstLine, + PseudoElement::FirstLetter, ]; impl PseudoElement { @@ -458,7 +460,7 @@ impl PseudoElement { #[inline] pub fn is_eager(&self) -> bool { matches!(*self, - PseudoElement::Before | PseudoElement::After) + PseudoElement::Before | PseudoElement::After | PseudoElement::FirstLine | PseudoElement::FirstLetter) } /// Gets the flags associated to this pseudo-element, or 0 if it's an diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs index 81bf539f2e1..77ac1e0f1fb 100644 --- a/components/style/gecko/pseudo_element_definition.mako.rs +++ b/components/style/gecko/pseudo_element_definition.mako.rs @@ -11,7 +11,7 @@ pub enum PseudoElement { % endfor } -<% EAGER_PSEUDOS = ["Before", "After"] %> +<% EAGER_PSEUDOS = ["Before", "After", "FirstLine", "FirstLetter"] %> /// The number of eager pseudo-elements. pub const EAGER_PSEUDO_COUNT: usize = ${len(EAGER_PSEUDOS)}; diff --git a/components/style/matching.rs b/components/style/matching.rs index 539f591cac5..eb88914f8ed 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -357,6 +357,7 @@ trait PrivateMatchMethods: TElement { // below like a lazy pseudo. let only_default_rules = context.shared.traversal_flags.for_default_styles(); if pseudo.is_eager() && !only_default_rules { + debug_assert!(pseudo.is_before_or_after()); let parent = self.parent_element().unwrap(); if !parent.may_have_animations() || primary_style.rules.get_animation_rules().is_empty() { @@ -1106,6 +1107,10 @@ pub trait MatchMethods : TElement { return } + if !self.may_generate_pseudo(&pseudo, data.styles().primary.values()) { + return; + } + debug_assert!(applicable_declarations.is_empty()); // NB: We handle animation rules for ::before and ::after when // traversing them.