Skip to content

Commit b46e196

Browse files
heycamemilio
authored andcommitted
style: Generate RestyleHints to selector match at specific descendant depths.
1 parent 178939d commit b46e196

File tree

1 file changed

+49
-18
lines changed

1 file changed

+49
-18
lines changed

components/style/restyle_hints.rs

+49-18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use smallvec::SmallVec;
2626
use std::borrow::Borrow;
2727
use std::cell::Cell;
2828
use std::clone::Clone;
29+
use std::cmp;
2930
use stylist::SelectorMap;
3031

3132
/// When the ElementState of an element (like IN_HOVER_STATE) changes,
@@ -113,6 +114,12 @@ impl RestyleDepths {
113114
RestyleDepths(0xff)
114115
}
115116

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+
116123
/// Returns whether this `RestyleDepths` represents the current element
117124
/// depth and the depths of all the current element's descendants.
118125
fn is_self_and_descendants(&self) -> bool {
@@ -210,6 +217,19 @@ impl RestyleHint {
210217
}
211218
}
212219

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+
213233
/// Creates a new `RestyleHint` that indicates selector matching must be
214234
/// re-run on all of the element's later siblings and their descendants.
215235
#[inline]
@@ -682,22 +702,6 @@ fn is_attr_selector(sel: &Component<SelectorImpl>) -> bool {
682702
}
683703
}
684704

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-
701705
#[derive(Clone, Debug)]
702706
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
703707
/// The aspects of an selector which are sensitive.
@@ -827,6 +831,8 @@ impl DependencySet {
827831
let mut combinator = None;
828832
let mut iter = selector.inner.complex.iter();
829833
let mut index = 0;
834+
let mut child_combinators_seen = 0;
835+
let mut saw_descendant_combinator = false;
830836

831837
loop {
832838
let sequence_start = index;
@@ -844,9 +850,34 @@ impl DependencySet {
844850
index += 1; // Account for the simple selector.
845851
}
846852

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+
847861
// If we found a sensitivity, add an entry in the dependency set.
848862
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+
};
850881

851882
let dep_selector = if sequence_start == 0 {
852883
// Reuse the bloom hashes if this is the base selector.
@@ -953,7 +984,7 @@ impl DependencySet {
953984
return true;
954985
}
955986

956-
// We can ignore the selector replacements, since they would have already
987+
// We can ignore the selector flags, since they would have already
957988
// been set during original matching for any element that might
958989
// change its matching behavior here.
959990
let matched_then =

0 commit comments

Comments
 (0)