diff options
-rw-r--r-- | components/style/restyle_hints.rs | 79 |
1 files changed, 43 insertions, 36 deletions
diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index 8710e590421..193b7e82a9d 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -525,56 +525,63 @@ impl DependencySet { /// Adds a selector to this `DependencySet`. pub fn note_selector(&mut self, selector: &Selector<SelectorImpl>) { - let mut is_pseudo_element = selector.pseudo_element.is_some(); - - let mut next = Some(selector.inner.complex.clone()); let mut combinator = None; + let mut iter = selector.inner.complex.iter(); + let mut index = 0; - while let Some(current) = next.take() { - // Set up our visitor. + loop { + let sequence_start = index; let mut visitor = SensitivitiesVisitor { sensitivities: Sensitivities::new() }; - let mut hint = combinator_to_restyle_hint(combinator); - - if is_pseudo_element { - // TODO(emilio): use more fancy restyle hints to avoid restyling - // the whole subtree when pseudos change. - // - // We currently need is_pseudo_element to handle eager pseudos - // (so the style the parent stores doesn't become stale), and - // restyle_descendants to handle all of them (::before and - // ::after, because we find them in the subtree, and other lazy - // pseudos for the same reason). - hint |= RESTYLE_SELF | RESTYLE_DESCENDANTS; - is_pseudo_element = false; - } - { - // Visit all the simple selectors. - let mut iter = current.iter(); - let mut index = 0usize; - for ss in &mut iter { - ss.visit(&mut visitor); - index += 1; - } - - // Prepare the next sequence of simple selectors. - if let Some(next_combinator) = iter.next_sequence() { - next = Some(current.slice_from(index + 1)); - combinator = Some(next_combinator); - } + // Visit all the simple selectors in this sequence. + // + // Note that this works because we can't have combinators nested + // inside simple selectors (i.e. in :not() or :-moz-any()). If we + // ever support that we'll need to visit complex selectors as well. + for ss in &mut iter { + ss.visit(&mut visitor); + index += 1; // Account for the simple selector. } - // Note what we found. + // If we found a sensitivity, add an entry in the dependency set. if !visitor.sensitivities.is_empty() { + let mut hint = combinator_to_restyle_hint(combinator); + let dep_selector; + if sequence_start == 0 { + if selector.pseudo_element.is_some() { + // TODO(emilio): use more fancy restyle hints to avoid + // restyling the whole subtree when pseudos change. + // + // We currently need is_pseudo_element to handle eager + // pseudos (so the style the parent stores doesn't + // become stale), and restyle_descendants to handle all + // of them (::before and ::after, because we find them + // in the subtree, and other lazy pseudos for the same + // reason). + hint |= RESTYLE_SELF | RESTYLE_DESCENDANTS; + } + + // Reuse the bloom hashes if this is the base selector. + dep_selector = selector.inner.clone(); + } else { + dep_selector = SelectorInner::new(selector.inner.complex.slice_from(sequence_start)); + } + self.add_dependency(Dependency { sensitivities: visitor.sensitivities, hint: hint, - selector: SelectorInner::new(current), - }) + selector: dep_selector, + }); + } + + combinator = iter.next_sequence(); + if combinator.is_none() { + break; } + index += 1; // Account for the combinator. } } |