diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs index 7dabb37397e..6db52526441 100644 --- a/components/malloc_size_of/lib.rs +++ b/components/malloc_size_of/lib.rs @@ -717,10 +717,7 @@ where Component::Root | Component::Empty | Component::Scope | - Component::NthChild(..) | - Component::NthLastChild(..) | - Component::NthOfType(..) | - Component::NthLastOfType(..) | + Component::Nth(..) | Component::FirstOfType | Component::LastOfType | Component::OnlyOfType | diff --git a/components/selectors/builder.rs b/components/selectors/builder.rs index 113107109fb..3bda08c8ff8 100644 --- a/components/selectors/builder.rs +++ b/components/selectors/builder.rs @@ -322,10 +322,7 @@ where Component::Root | Component::Empty | Component::Scope | - Component::NthChild(..) | - Component::NthLastChild(..) | - Component::NthOfType(..) | - Component::NthLastOfType(..) | + Component::Nth(..) | Component::FirstOfType | Component::LastOfType | Component::OnlyOfType | diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 30fd037ce7c..3afe67cbb33 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -8,7 +8,7 @@ use crate::attr::{ }; use crate::bloom::{BloomFilter, BLOOM_HASH_MASK}; use crate::nth_index_cache::NthIndexCacheInner; -use crate::parser::{AncestorHashes, Combinator, Component, LocalName}; +use crate::parser::{AncestorHashes, Combinator, Component, LocalName, NthType}; use crate::parser::{NonTSPseudoClass, Selector, SelectorImpl, SelectorIter, SelectorList}; use crate::tree::Element; use bitflags::bitflags; @@ -391,10 +391,7 @@ fn hover_and_active_quirk_applies( Component::LastChild | Component::OnlyChild | Component::Empty | - Component::NthChild(_, _) | - Component::NthLastChild(_, _) | - Component::NthOfType(_, _) | - Component::NthLastOfType(_, _) | + Component::Nth(_) | Component::FirstOfType | Component::LastOfType | Component::OnlyOfType => false, @@ -815,18 +812,14 @@ where Some(ref scope_element) => element.opaque() == *scope_element, None => element.is_root(), }, - Component::NthChild(a, b) => { - matches_generic_nth_child(element, context.shared, a, b, false, false) - }, - Component::NthLastChild(a, b) => { - matches_generic_nth_child(element, context.shared, a, b, false, true) - }, - Component::NthOfType(a, b) => { - matches_generic_nth_child(element, context.shared, a, b, true, false) - }, - Component::NthLastOfType(a, b) => { - matches_generic_nth_child(element, context.shared, a, b, true, true) - }, + Component::Nth(nth_data) => matches_generic_nth_child( + element, + context.shared, + nth_data.a, + nth_data.b, + nth_data.ty == NthType::OfType || nth_data.ty == NthType::LastOfType, + nth_data.ty == NthType::LastChild || nth_data.ty == NthType::LastOfType, + ), Component::FirstOfType => { matches_generic_nth_child(element, context.shared, 0, 1, true, false) }, diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index b4e35c31c20..de89b14d3c2 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -1036,6 +1036,27 @@ impl Combinator { } } +/// An enum for the different types of :nth- pseudoclasses +#[derive(Copy, Clone, Eq, PartialEq, ToShmem)] +#[shmem(no_bounds)] +pub enum NthType { + Child, + LastChild, + OfType, + LastOfType, +} + +/// The properties that comprise an :nth- pseudoclass as of Selectors 3 (e.g., +/// nth-child(An+B)). +/// https://www.w3.org/TR/selectors-3/#nth-child-pseudo +#[derive(Copy, Clone, Eq, PartialEq, ToShmem)] +#[shmem(no_bounds)] +pub struct NthSelectorData { + pub ty: NthType, + pub a: i32, + pub b: i32, +} + /// A CSS simple selector or combinator. We store both in the same enum for /// optimal packing and cache performance, see [1]. /// @@ -1084,10 +1105,7 @@ pub enum Component { Root, Empty, Scope, - NthChild(i32, i32), - NthLastChild(i32, i32), - NthOfType(i32, i32), - NthLastOfType(i32, i32), + Nth(NthSelectorData), FirstOfType, LastOfType, OnlyOfType, @@ -1598,15 +1616,14 @@ impl ToCss for Component { FirstOfType => dest.write_str(":first-of-type"), LastOfType => dest.write_str(":last-of-type"), OnlyOfType => dest.write_str(":only-of-type"), - NthChild(a, b) | NthLastChild(a, b) | NthOfType(a, b) | NthLastOfType(a, b) => { - match *self { - NthChild(_, _) => dest.write_str(":nth-child(")?, - NthLastChild(_, _) => dest.write_str(":nth-last-child(")?, - NthOfType(_, _) => dest.write_str(":nth-of-type(")?, - NthLastOfType(_, _) => dest.write_str(":nth-last-of-type(")?, - _ => unreachable!(), + Nth(nth_data) => { + match nth_data.ty { + NthType::Child => dest.write_str(":nth-child(")?, + NthType::LastChild => dest.write_str(":nth-last-child(")?, + NthType::OfType => dest.write_str(":nth-of-type(")?, + NthType::LastOfType => dest.write_str(":nth-last-of-type(")?, } - write_affine(dest, a, b)?; + write_affine(dest, nth_data.a, nth_data.b)?; dest.write_char(')') }, Is(ref list) | Where(ref list) | Negation(ref list) | Has(ref list) => { @@ -2312,10 +2329,10 @@ where Impl: SelectorImpl, { match_ignore_ascii_case! { &name, - "nth-child" => return parse_nth_pseudo_class(parser, input, state, Component::NthChild), - "nth-of-type" => return parse_nth_pseudo_class(parser, input, state, Component::NthOfType), - "nth-last-child" => return parse_nth_pseudo_class(parser, input, state, Component::NthLastChild), - "nth-last-of-type" => return parse_nth_pseudo_class(parser, input, state, Component::NthLastOfType), + "nth-child" => return parse_nth_pseudo_class(parser, input, state, NthType::Child), + "nth-of-type" => return parse_nth_pseudo_class(parser, input, state, NthType::OfType), + "nth-last-child" => return parse_nth_pseudo_class(parser, input, state, NthType::LastChild), + "nth-last-of-type" => return parse_nth_pseudo_class(parser, input, state, NthType::LastOfType), "is" if parser.parse_is_and_where() => return parse_is_where_has(parser, input, state, Component::Is), "where" if parser.parse_is_and_where() => return parse_is_where_has(parser, input, state, Component::Where), "has" if parser.parse_has() => return parse_is_where_has(parser, input, state, Component::Has), @@ -2342,22 +2359,21 @@ where P::parse_non_ts_functional_pseudo_class(parser, name, input).map(Component::NonTSPseudoClass) } -fn parse_nth_pseudo_class<'i, 't, P, Impl, F>( +fn parse_nth_pseudo_class<'i, 't, P, Impl>( _: &P, input: &mut CssParser<'i, 't>, state: SelectorParsingState, - selector: F, + ty: NthType, ) -> Result, ParseError<'i, P::Error>> where P: Parser<'i, Impl = Impl>, Impl: SelectorImpl, - F: FnOnce(i32, i32) -> Component, { if !state.allows_tree_structural_pseudo_classes() { return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState)); } let (a, b) = parse_nth(input)?; - Ok(selector(a, b)) + Ok(Component::Nth(NthSelectorData { ty, a, b })) } /// Returns whether the name corresponds to a CSS2 pseudo-element that diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 31adb253687..0d91d8d741c 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -1921,10 +1921,7 @@ fn component_needs_revalidation( Component::FirstChild | Component::LastChild | Component::OnlyChild | - Component::NthChild(..) | - Component::NthLastChild(..) | - Component::NthOfType(..) | - Component::NthLastOfType(..) | + Component::Nth(..) | Component::FirstOfType | Component::LastOfType | Component::OnlyOfType => true,