mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
style: Generate RestyleHints to selector match at specific descendant depths.
This commit is contained in:
parent
178939d8ce
commit
b46e196fa9
1 changed files with 49 additions and 18 deletions
|
@ -26,6 +26,7 @@ use smallvec::SmallVec;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::clone::Clone;
|
use std::clone::Clone;
|
||||||
|
use std::cmp;
|
||||||
use stylist::SelectorMap;
|
use stylist::SelectorMap;
|
||||||
|
|
||||||
/// When the ElementState of an element (like IN_HOVER_STATE) changes,
|
/// When the ElementState of an element (like IN_HOVER_STATE) changes,
|
||||||
|
@ -113,6 +114,12 @@ impl RestyleDepths {
|
||||||
RestyleDepths(0xff)
|
RestyleDepths(0xff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a `RestyleDepths` representing the specified depth, where zero
|
||||||
|
/// is the current element depth, one is its children's depths, etc.
|
||||||
|
fn for_depth(depth: u32) -> Self {
|
||||||
|
RestyleDepths(1u8 << cmp::min(depth, 7))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns whether this `RestyleDepths` represents the current element
|
/// Returns whether this `RestyleDepths` represents the current element
|
||||||
/// depth and the depths of all the current element's descendants.
|
/// depth and the depths of all the current element's descendants.
|
||||||
fn is_self_and_descendants(&self) -> bool {
|
fn is_self_and_descendants(&self) -> bool {
|
||||||
|
@ -210,6 +217,19 @@ impl RestyleHint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new `RestyleHint` that indicates selector matching must be
|
||||||
|
/// re-run on the descendants of element at the specified depth, where 0
|
||||||
|
/// indicates the element itself, 1 is its children, 2 its grandchildren,
|
||||||
|
/// etc.
|
||||||
|
#[inline]
|
||||||
|
pub fn descendants_at_depth(depth: u32) -> Self {
|
||||||
|
RestyleHint {
|
||||||
|
match_under_self: RestyleDepths::for_depth(depth),
|
||||||
|
match_later_siblings: false,
|
||||||
|
replacements: RestyleReplacements::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new `RestyleHint` that indicates selector matching must be
|
/// Creates a new `RestyleHint` that indicates selector matching must be
|
||||||
/// re-run on all of the element's later siblings and their descendants.
|
/// re-run on all of the element's later siblings and their descendants.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -682,22 +702,6 @@ fn is_attr_selector(sel: &Component<SelectorImpl>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combinator_to_restyle_hint(combinator: Option<Combinator>) -> RestyleHint {
|
|
||||||
match combinator {
|
|
||||||
None => RestyleHint::for_self(),
|
|
||||||
Some(c) => match c {
|
|
||||||
// NB: RestyleHint::subtree() and not RestyleHint::descendants() is
|
|
||||||
// needed to handle properly eager pseudos, otherwise we may leave
|
|
||||||
// a stale style on the parent.
|
|
||||||
Combinator::PseudoElement => RestyleHint::subtree(),
|
|
||||||
Combinator::Child => RestyleHint::descendants(),
|
|
||||||
Combinator::Descendant => RestyleHint::descendants(),
|
|
||||||
Combinator::NextSibling => RestyleHint::later_siblings(),
|
|
||||||
Combinator::LaterSibling => RestyleHint::later_siblings(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
/// The aspects of an selector which are sensitive.
|
/// The aspects of an selector which are sensitive.
|
||||||
|
@ -827,6 +831,8 @@ impl DependencySet {
|
||||||
let mut combinator = None;
|
let mut combinator = None;
|
||||||
let mut iter = selector.inner.complex.iter();
|
let mut iter = selector.inner.complex.iter();
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
let mut child_combinators_seen = 0;
|
||||||
|
let mut saw_descendant_combinator = false;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let sequence_start = index;
|
let sequence_start = index;
|
||||||
|
@ -844,9 +850,34 @@ impl DependencySet {
|
||||||
index += 1; // Account for the simple selector.
|
index += 1; // Account for the simple selector.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep track of how many child combinators we've encountered,
|
||||||
|
// and whether we've encountered a descendant combinator at all.
|
||||||
|
match combinator {
|
||||||
|
Some(Combinator::Child) => child_combinators_seen += 1,
|
||||||
|
Some(Combinator::Descendant) => saw_descendant_combinator = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
// If we found a sensitivity, add an entry in the dependency set.
|
// If we found a sensitivity, add an entry in the dependency set.
|
||||||
if !visitor.sensitivities.is_empty() {
|
if !visitor.sensitivities.is_empty() {
|
||||||
let hint = combinator_to_restyle_hint(combinator);
|
// Compute a RestyleHint given the current combinator and the
|
||||||
|
// tracked number of child combinators and presence of a
|
||||||
|
// descendant combinator.
|
||||||
|
let hint = match combinator {
|
||||||
|
// NB: RestyleHint::subtree() and not
|
||||||
|
// RestyleHint::descendants() is needed to handle properly
|
||||||
|
// eager pseudos, otherwise we may leave a stale style on
|
||||||
|
// the parent.
|
||||||
|
Some(Combinator::PseudoElement) => RestyleHint::subtree(),
|
||||||
|
Some(Combinator::Child) if !saw_descendant_combinator => {
|
||||||
|
RestyleHint::descendants_at_depth(child_combinators_seen)
|
||||||
|
}
|
||||||
|
Some(Combinator::Child) |
|
||||||
|
Some(Combinator::Descendant) => RestyleHint::descendants(),
|
||||||
|
Some(Combinator::NextSibling) |
|
||||||
|
Some(Combinator::LaterSibling) => RestyleHint::later_siblings(),
|
||||||
|
None => RestyleHint::for_self(),
|
||||||
|
};
|
||||||
|
|
||||||
let dep_selector = if sequence_start == 0 {
|
let dep_selector = if sequence_start == 0 {
|
||||||
// Reuse the bloom hashes if this is the base selector.
|
// Reuse the bloom hashes if this is the base selector.
|
||||||
|
@ -953,7 +984,7 @@ impl DependencySet {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can ignore the selector replacements, since they would have already
|
// We can ignore the selector flags, since they would have already
|
||||||
// been set during original matching for any element that might
|
// been set during original matching for any element that might
|
||||||
// change its matching behavior here.
|
// change its matching behavior here.
|
||||||
let matched_then =
|
let matched_then =
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue