@@ -26,6 +26,7 @@ use smallvec::SmallVec;
26
26
use std:: borrow:: Borrow ;
27
27
use std:: cell:: Cell ;
28
28
use std:: clone:: Clone ;
29
+ use std:: cmp;
29
30
use stylist:: SelectorMap ;
30
31
31
32
/// When the ElementState of an element (like IN_HOVER_STATE) changes,
@@ -113,6 +114,12 @@ impl RestyleDepths {
113
114
RestyleDepths ( 0xff )
114
115
}
115
116
117
+ /// Returns a `RestyleDepths` representing the specified depth, where zero
118
+ /// is the current element depth, one is its children's depths, etc.
119
+ fn for_depth ( depth : u32 ) -> Self {
120
+ RestyleDepths ( 1u8 << cmp:: min ( depth, 7 ) )
121
+ }
122
+
116
123
/// Returns whether this `RestyleDepths` represents the current element
117
124
/// depth and the depths of all the current element's descendants.
118
125
fn is_self_and_descendants ( & self ) -> bool {
@@ -210,6 +217,19 @@ impl RestyleHint {
210
217
}
211
218
}
212
219
220
+ /// Creates a new `RestyleHint` that indicates selector matching must be
221
+ /// re-run on the descendants of element at the specified depth, where 0
222
+ /// indicates the element itself, 1 is its children, 2 its grandchildren,
223
+ /// etc.
224
+ #[ inline]
225
+ pub fn descendants_at_depth ( depth : u32 ) -> Self {
226
+ RestyleHint {
227
+ match_under_self : RestyleDepths :: for_depth ( depth) ,
228
+ match_later_siblings : false ,
229
+ replacements : RestyleReplacements :: empty ( ) ,
230
+ }
231
+ }
232
+
213
233
/// Creates a new `RestyleHint` that indicates selector matching must be
214
234
/// re-run on all of the element's later siblings and their descendants.
215
235
#[ inline]
@@ -682,22 +702,6 @@ fn is_attr_selector(sel: &Component<SelectorImpl>) -> bool {
682
702
}
683
703
}
684
704
685
- fn combinator_to_restyle_hint ( combinator : Option < Combinator > ) -> RestyleHint {
686
- match combinator {
687
- None => RestyleHint :: for_self ( ) ,
688
- Some ( c) => match c {
689
- // NB: RestyleHint::subtree() and not RestyleHint::descendants() is
690
- // needed to handle properly eager pseudos, otherwise we may leave
691
- // a stale style on the parent.
692
- Combinator :: PseudoElement => RestyleHint :: subtree ( ) ,
693
- Combinator :: Child => RestyleHint :: descendants ( ) ,
694
- Combinator :: Descendant => RestyleHint :: descendants ( ) ,
695
- Combinator :: NextSibling => RestyleHint :: later_siblings ( ) ,
696
- Combinator :: LaterSibling => RestyleHint :: later_siblings ( ) ,
697
- }
698
- }
699
- }
700
-
701
705
#[ derive( Clone , Debug ) ]
702
706
#[ cfg_attr( feature = "servo" , derive( HeapSizeOf ) ) ]
703
707
/// The aspects of an selector which are sensitive.
@@ -827,6 +831,8 @@ impl DependencySet {
827
831
let mut combinator = None ;
828
832
let mut iter = selector. inner . complex . iter ( ) ;
829
833
let mut index = 0 ;
834
+ let mut child_combinators_seen = 0 ;
835
+ let mut saw_descendant_combinator = false ;
830
836
831
837
loop {
832
838
let sequence_start = index;
@@ -844,9 +850,34 @@ impl DependencySet {
844
850
index += 1 ; // Account for the simple selector.
845
851
}
846
852
853
+ // Keep track of how many child combinators we've encountered,
854
+ // and whether we've encountered a descendant combinator at all.
855
+ match combinator {
856
+ Some ( Combinator :: Child ) => child_combinators_seen += 1 ,
857
+ Some ( Combinator :: Descendant ) => saw_descendant_combinator = true ,
858
+ _ => { }
859
+ }
860
+
847
861
// If we found a sensitivity, add an entry in the dependency set.
848
862
if !visitor. sensitivities . is_empty ( ) {
849
- let hint = combinator_to_restyle_hint ( combinator) ;
863
+ // Compute a RestyleHint given the current combinator and the
864
+ // tracked number of child combinators and presence of a
865
+ // descendant combinator.
866
+ let hint = match combinator {
867
+ // NB: RestyleHint::subtree() and not
868
+ // RestyleHint::descendants() is needed to handle properly
869
+ // eager pseudos, otherwise we may leave a stale style on
870
+ // the parent.
871
+ Some ( Combinator :: PseudoElement ) => RestyleHint :: subtree ( ) ,
872
+ Some ( Combinator :: Child ) if !saw_descendant_combinator => {
873
+ RestyleHint :: descendants_at_depth ( child_combinators_seen)
874
+ }
875
+ Some ( Combinator :: Child ) |
876
+ Some ( Combinator :: Descendant ) => RestyleHint :: descendants ( ) ,
877
+ Some ( Combinator :: NextSibling ) |
878
+ Some ( Combinator :: LaterSibling ) => RestyleHint :: later_siblings ( ) ,
879
+ None => RestyleHint :: for_self ( ) ,
880
+ } ;
850
881
851
882
let dep_selector = if sequence_start == 0 {
852
883
// Reuse the bloom hashes if this is the base selector.
@@ -953,7 +984,7 @@ impl DependencySet {
953
984
return true ;
954
985
}
955
986
956
- // We can ignore the selector replacements , since they would have already
987
+ // We can ignore the selector flags , since they would have already
957
988
// been set during original matching for any element that might
958
989
// change its matching behavior here.
959
990
let matched_then =
0 commit comments