From fe74e70a2da3d0261cf1f30286e11313bf6aed28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 31 May 2017 14:04:25 +0200 Subject: [PATCH 1/4] Bug 1369187: style: Add an API to fast-reject eager pseudos. r=bholley Also, do nothing for now (we'll hook the Gecko pieces here when the time comes). Let me know if you want to hold-off landing this. MozReview-Commit-ID: 6PIhfp6sxk4 --- components/style/dom.rs | 17 ++++++++++++++++- components/style/matching.rs | 4 ++++ 2 files changed, 20 insertions(+), 1 deletion(-) 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/matching.rs b/components/style/matching.rs index 539f591cac5..6dc335de1dc 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -1106,6 +1106,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. From 509a450cff69a1bbfc5f8078983301c15de80023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 31 May 2017 16:59:43 +0200 Subject: [PATCH 2/4] Bug 1369187: style: Add first-line and first-letter to the set of eager pseudo styles. r=bholley MozReview-Commit-ID: DmpX0nA2DOw --- .../style/gecko/generated/pseudo_element_definition.rs | 6 ++++-- components/style/gecko/pseudo_element_definition.mako.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) 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)}; From a529c139049d27100dc4c30d9816c546fcad2d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 31 May 2017 17:15:54 +0200 Subject: [PATCH 3/4] Bug 1369187: style: Use ArrayVec for the pseudo-elements we need to restyle. r=bholley Just a drive-by, easy optimization. MozReview-Commit-ID: AVaeWvBHLzc --- components/style/data.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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() { From 93c39b073072bed1c2de3f31ef3d79832a3d49bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 31 May 2017 17:20:31 +0200 Subject: [PATCH 4/4] Bug 1369187: style: Assert that if we find an eager, element-backed pseudo, it's ::before or ::after. r=bholley This holds because ::first-line and ::first-letter are not element-backed. MozReview-Commit-ID: 67FU15pCLqW --- components/style/matching.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/style/matching.rs b/components/style/matching.rs index 6dc335de1dc..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() {