From 7e69cf82be31a38db8f5a1b3c6454fdf89c28b35 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 26 Apr 2017 13:48:13 -0700 Subject: [PATCH] Store SelectorInner and only revalidate up to the rightmost ancestor combinator. MozReview-Commit-ID: HiTGVhwuvCE --- components/selectors/parser.rs | 37 ++++++++++++++++++++++++++++++++++ components/style/stylist.rs | 6 +++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 3d05f7ec7340..2f83d43c8935 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -169,6 +169,27 @@ impl SelectorInner { } } + /// Creates a clone of this selector with everything to the left of + /// (and including) the rightmost ancestor combinator removed. So + /// the selector |span foo > bar + baz| will become |bar + baz|. + /// This is used for revalidation selectors in servo. + /// + /// The bloom filter hashes are copied, even though they correspond to + /// parts of the selector that have been stripped out, because they are + /// still useful for fast-rejecting the reduced selectors. + pub fn slice_to_first_ancestor_combinator(&self) -> Self { + let maybe_pos = self.complex.iter_raw() + .position(|s| s.as_combinator() + .map_or(false, |c| c.is_ancestor())); + match maybe_pos { + None => self.clone(), + Some(index) => SelectorInner { + complex: self.complex.slice_to(index), + ancestor_hashes: self.ancestor_hashes.clone(), + }, + } + } + /// Creates a SelectorInner from a Vec of Components. Used in tests. pub fn from_vec(vec: Vec>) -> Self { let complex = ComplexSelector::from_vec(vec); @@ -319,6 +340,14 @@ impl ComplexSelector { ComplexSelector(self.0.clone().slice_to(self.0.len() - index)) } + /// Returns a ComplexSelector identical to |self| but with the leftmost + /// |len() - index| entries removed. + pub fn slice_to(&self, index: usize) -> Self { + // Note that we convert the slice_to to slice_from because selectors are + // stored left-to-right but logical order is right-to-left. + ComplexSelector(self.0.clone().slice_from(self.0.len() - index)) + } + /// Creates a ComplexSelector from a vec of Components. Used in tests. pub fn from_vec(vec: Vec>) -> Self { ComplexSelector(ArcSlice::new(vec.into_boxed_slice())) @@ -499,6 +528,14 @@ impl Component { pub fn is_combinator(&self) -> bool { matches!(*self, Component::Combinator(_)) } + + /// Returns the value as a combinator if applicable, None otherwise. + pub fn as_combinator(&self) -> Option { + match *self { + Component::Combinator(c) => Some(c), + _ => None, + } + } } #[derive(Eq, PartialEq, Clone, Hash, Copy, Debug)] diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 08e87601fbea..78a77266800f 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -115,7 +115,7 @@ pub struct Stylist { /// on state that is not otherwise visible to the cache, like attributes or /// tree-structural state like child index and pseudos). #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] - selectors_for_cache_revalidation: Vec>, + selectors_for_cache_revalidation: Vec>, /// The total number of selectors. num_selectors: usize, @@ -336,7 +336,7 @@ impl Stylist { self.dependencies.note_selector(selector); if needs_revalidation(selector) { - self.selectors_for_cache_revalidation.push(selector.clone()); + self.selectors_for_cache_revalidation.push(selector.inner.slice_to_first_ancestor_combinator()); } } } @@ -837,7 +837,7 @@ impl Stylist { for (i, ref selector) in self.selectors_for_cache_revalidation .iter().enumerate() { - results.set(i, matches_selector(&selector.inner, + results.set(i, matches_selector(selector, element, Some(bloom), &mut StyleRelations::empty(),