mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Use left-to-right indices in the invalidator.
This will make easier to create external invalidations, and also makes reasoning about the invalidator a bit easier.
This commit is contained in:
parent
086c48210c
commit
f1cc225e97
5 changed files with 46 additions and 39 deletions
|
@ -299,11 +299,10 @@ where
|
||||||
/// Whether a compound selector matched, and whether it was the rightmost
|
/// Whether a compound selector matched, and whether it was the rightmost
|
||||||
/// selector inside the complex selector.
|
/// selector inside the complex selector.
|
||||||
pub enum CompoundSelectorMatchingResult {
|
pub enum CompoundSelectorMatchingResult {
|
||||||
|
/// The selector was fully matched.
|
||||||
|
FullyMatched,
|
||||||
/// The compound selector matched, and the next combinator offset is
|
/// The compound selector matched, and the next combinator offset is
|
||||||
/// `next_combinator_offset`.
|
/// `next_combinator_offset`.
|
||||||
///
|
|
||||||
/// If the next combinator offset is zero, it means that it's the rightmost
|
|
||||||
/// selector.
|
|
||||||
Matched { next_combinator_offset: usize, },
|
Matched { next_combinator_offset: usize, },
|
||||||
/// The selector didn't match.
|
/// The selector didn't match.
|
||||||
NotMatched,
|
NotMatched,
|
||||||
|
@ -325,8 +324,9 @@ pub fn matches_compound_selector<E>(
|
||||||
where
|
where
|
||||||
E: Element
|
E: Element
|
||||||
{
|
{
|
||||||
|
debug_assert_ne!(from_offset, 0);
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
selector.combinator_at(from_offset); // This asserts.
|
selector.combinator_at_parse_order(from_offset - 1); // This asserts.
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut local_context = LocalMatchingContext {
|
let mut local_context = LocalMatchingContext {
|
||||||
|
@ -334,10 +334,11 @@ where
|
||||||
matches_hover_and_active_quirk: false,
|
matches_hover_and_active_quirk: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
for component in selector.iter_raw_parse_order_from(from_offset - 1) {
|
for component in selector.iter_raw_parse_order_from(from_offset) {
|
||||||
if matches!(*component, Component::Combinator(..)) {
|
if matches!(*component, Component::Combinator(..)) {
|
||||||
|
debug_assert_ne!(from_offset, 0, "Selector started with a combinator?");
|
||||||
return CompoundSelectorMatchingResult::Matched {
|
return CompoundSelectorMatchingResult::Matched {
|
||||||
next_combinator_offset: from_offset - 1,
|
next_combinator_offset: from_offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,12 +351,10 @@ where
|
||||||
return CompoundSelectorMatchingResult::NotMatched;
|
return CompoundSelectorMatchingResult::NotMatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
from_offset -= 1;
|
from_offset += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CompoundSelectorMatchingResult::Matched {
|
CompoundSelectorMatchingResult::FullyMatched
|
||||||
next_combinator_offset: 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches a complex selector.
|
/// Matches a complex selector.
|
||||||
|
|
|
@ -440,12 +440,11 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the combinator at index `index` (one-indexed from the right),
|
/// Returns the combinator at index `index` (zero-indexed from the right),
|
||||||
/// or panics if the component is not a combinator.
|
/// or panics if the component is not a combinator.
|
||||||
///
|
#[inline]
|
||||||
/// FIXME(bholley): Use more intuitive indexing.
|
pub fn combinator_at_match_order(&self, index: usize) -> Combinator {
|
||||||
pub fn combinator_at(&self, index: usize) -> Combinator {
|
match self.0.slice[index] {
|
||||||
match self.0.slice[index - 1] {
|
|
||||||
Component::Combinator(c) => c,
|
Component::Combinator(c) => c,
|
||||||
ref other => {
|
ref other => {
|
||||||
panic!("Not a combinator: {:?}, {:?}, index: {}",
|
panic!("Not a combinator: {:?}, {:?}, index: {}",
|
||||||
|
@ -460,16 +459,24 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
self.0.slice.iter()
|
self.0.slice.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the combinator at index `index` (zero-indexed from the left),
|
||||||
|
/// or panics if the component is not a combinator.
|
||||||
|
#[inline]
|
||||||
|
pub fn combinator_at_parse_order(&self, index: usize) -> Combinator {
|
||||||
|
match self.0.slice[self.len() - index - 1] {
|
||||||
|
Component::Combinator(c) => c,
|
||||||
|
ref other => {
|
||||||
|
panic!("Not a combinator: {:?}, {:?}, index: {}",
|
||||||
|
other, self, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the sequence of simple selectors and
|
/// Returns an iterator over the sequence of simple selectors and
|
||||||
/// combinators, in parse order (from left to right), _starting_
|
/// combinators, in parse order (from left to right), starting from
|
||||||
/// 'offset_from_right' entries from the past-the-end sentinel on
|
/// `offset`.
|
||||||
/// the right. So "0" panics,. "1" iterates nothing, and "len"
|
pub fn iter_raw_parse_order_from(&self, offset: usize) -> Rev<slice::Iter<Component<Impl>>> {
|
||||||
/// iterates the entire sequence.
|
self.0.slice[..self.len() - offset].iter().rev()
|
||||||
///
|
|
||||||
/// FIXME(bholley): This API is rather unintuive, and should really
|
|
||||||
/// be changed to accept an offset from the left. Same for combinator_at.
|
|
||||||
pub fn iter_raw_parse_order_from(&self, offset_from_right: usize) -> Rev<slice::Iter<Component<Impl>>> {
|
|
||||||
self.0.slice[..offset_from_right].iter().rev()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Selector from a vec of Components, specified in parse order. Used in tests.
|
/// Creates a Selector from a vec of Components, specified in parse order. Used in tests.
|
||||||
|
|
|
@ -463,16 +463,18 @@ where
|
||||||
|
|
||||||
if dependency.affects_descendants() {
|
if dependency.affects_descendants() {
|
||||||
debug_assert_ne!(dependency.selector_offset, 0);
|
debug_assert_ne!(dependency.selector_offset, 0);
|
||||||
|
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
||||||
debug_assert!(!dependency.affects_later_siblings());
|
debug_assert!(!dependency.affects_later_siblings());
|
||||||
self.descendant_invalidations.push(Invalidation::new(
|
self.descendant_invalidations.push(Invalidation::new(
|
||||||
dependency.selector.clone(),
|
dependency.selector.clone(),
|
||||||
dependency.selector_offset,
|
dependency.selector.len() - dependency.selector_offset + 1,
|
||||||
));
|
));
|
||||||
} else if dependency.affects_later_siblings() {
|
} else if dependency.affects_later_siblings() {
|
||||||
debug_assert_ne!(dependency.selector_offset, 0);
|
debug_assert_ne!(dependency.selector_offset, 0);
|
||||||
|
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
||||||
self.sibling_invalidations.push(Invalidation::new(
|
self.sibling_invalidations.push(Invalidation::new(
|
||||||
dependency.selector.clone(),
|
dependency.selector.clone(),
|
||||||
dependency.selector_offset,
|
dependency.selector.len() - dependency.selector_offset + 1,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ impl Dependency {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(self.selector.combinator_at(self.selector_offset))
|
Some(self.selector.combinator_at_match_order(self.selector_offset - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this dependency affects the style of the element.
|
/// Whether this dependency affects the style of the element.
|
||||||
|
|
|
@ -114,14 +114,13 @@ enum InvalidationKind {
|
||||||
|
|
||||||
/// An `Invalidation` is a complex selector that describes which elements,
|
/// An `Invalidation` is a complex selector that describes which elements,
|
||||||
/// relative to a current element we are processing, must be restyled.
|
/// relative to a current element we are processing, must be restyled.
|
||||||
///
|
|
||||||
/// When `offset` points to the right-most compound selector in `selector`,
|
|
||||||
/// then the Invalidation `represents` the fact that the current element
|
|
||||||
/// must be restyled if the compound selector matches. Otherwise, if
|
|
||||||
/// describes which descendants (or later siblings) must be restyled.
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Invalidation {
|
pub struct Invalidation {
|
||||||
selector: Selector<SelectorImpl>,
|
selector: Selector<SelectorImpl>,
|
||||||
|
/// The offset of the selector pointing to a compound selector.
|
||||||
|
///
|
||||||
|
/// This order is a "parse order" offset, that is, zero is the leftmost part
|
||||||
|
/// of the selector written as parsed / serialized.
|
||||||
offset: usize,
|
offset: usize,
|
||||||
/// Whether the invalidation was already matched by any previous sibling or
|
/// Whether the invalidation was already matched by any previous sibling or
|
||||||
/// ancestor.
|
/// ancestor.
|
||||||
|
@ -149,7 +148,7 @@ impl Invalidation {
|
||||||
// for the weird pseudos in <input type="number">.
|
// for the weird pseudos in <input type="number">.
|
||||||
//
|
//
|
||||||
// We should be able to do better here!
|
// We should be able to do better here!
|
||||||
match self.selector.combinator_at(self.offset) {
|
match self.selector.combinator_at_parse_order(self.offset - 1) {
|
||||||
Combinator::NextSibling |
|
Combinator::NextSibling |
|
||||||
Combinator::Child => false,
|
Combinator::Child => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
|
@ -157,7 +156,7 @@ impl Invalidation {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kind(&self) -> InvalidationKind {
|
fn kind(&self) -> InvalidationKind {
|
||||||
if self.selector.combinator_at(self.offset).is_ancestor() {
|
if self.selector.combinator_at_parse_order(self.offset - 1).is_ancestor() {
|
||||||
InvalidationKind::Descendant
|
InvalidationKind::Descendant
|
||||||
} else {
|
} else {
|
||||||
InvalidationKind::Sibling
|
InvalidationKind::Sibling
|
||||||
|
@ -170,7 +169,7 @@ impl fmt::Debug for Invalidation {
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
|
|
||||||
f.write_str("Invalidation(")?;
|
f.write_str("Invalidation(")?;
|
||||||
for component in self.selector.iter_raw_parse_order_from(self.offset - 1) {
|
for component in self.selector.iter_raw_parse_order_from(self.offset) {
|
||||||
if matches!(*component, Component::Combinator(..)) {
|
if matches!(*component, Component::Combinator(..)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -624,14 +623,14 @@ where
|
||||||
let mut invalidated_self = false;
|
let mut invalidated_self = false;
|
||||||
let mut matched = false;
|
let mut matched = false;
|
||||||
match matching_result {
|
match matching_result {
|
||||||
CompoundSelectorMatchingResult::Matched { next_combinator_offset: 0 } => {
|
CompoundSelectorMatchingResult::FullyMatched => {
|
||||||
debug!(" > Invalidation matched completely");
|
debug!(" > Invalidation matched completely");
|
||||||
matched = true;
|
matched = true;
|
||||||
invalidated_self = true;
|
invalidated_self = true;
|
||||||
}
|
}
|
||||||
CompoundSelectorMatchingResult::Matched { next_combinator_offset } => {
|
CompoundSelectorMatchingResult::Matched { next_combinator_offset } => {
|
||||||
let next_combinator =
|
let next_combinator =
|
||||||
invalidation.selector.combinator_at(next_combinator_offset);
|
invalidation.selector.combinator_at_parse_order(next_combinator_offset);
|
||||||
matched = true;
|
matched = true;
|
||||||
|
|
||||||
if matches!(next_combinator, Combinator::PseudoElement) {
|
if matches!(next_combinator, Combinator::PseudoElement) {
|
||||||
|
@ -640,7 +639,7 @@ where
|
||||||
// around, so there could also be state pseudo-classes.
|
// around, so there could also be state pseudo-classes.
|
||||||
let pseudo_selector =
|
let pseudo_selector =
|
||||||
invalidation.selector
|
invalidation.selector
|
||||||
.iter_raw_parse_order_from(next_combinator_offset - 1)
|
.iter_raw_parse_order_from(next_combinator_offset + 1)
|
||||||
.skip_while(|c| matches!(**c, Component::NonTSPseudoClass(..)))
|
.skip_while(|c| matches!(**c, Component::NonTSPseudoClass(..)))
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -681,7 +680,7 @@ where
|
||||||
|
|
||||||
let next_invalidation = Invalidation {
|
let next_invalidation = Invalidation {
|
||||||
selector: invalidation.selector.clone(),
|
selector: invalidation.selector.clone(),
|
||||||
offset: next_combinator_offset,
|
offset: next_combinator_offset + 1,
|
||||||
matched_by_any_previous: false,
|
matched_by_any_previous: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue