Skip to main content

selectors/
parser.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use crate::attr::{AttrSelectorOperator, AttrSelectorWithOptionalNamespace};
6use crate::attr::{NamespaceConstraint, ParsedAttrSelectorOperation, ParsedCaseSensitivity};
7use crate::bloom::BLOOM_HASH_MASK;
8use crate::builder::{
9    relative_selector_list_specificity_and_flags, selector_list_specificity_and_flags,
10    SelectorBuilder, SelectorFlags, Specificity, SpecificityAndFlags,
11};
12use crate::context::QuirksMode;
13use crate::sink::Push;
14use crate::visitor::SelectorListKind;
15pub use crate::visitor::SelectorVisitor;
16use bitflags::bitflags;
17use cssparser::match_ignore_ascii_case;
18use cssparser::parse_nth;
19use cssparser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind};
20use cssparser::{CowRcStr, Delimiter, SourceLocation};
21use cssparser::{Parser as CssParser, ToCss, Token};
22use debug_unreachable::debug_unreachable;
23use precomputed_hash::PrecomputedHash;
24use servo_arc::{Arc, ArcUnionBorrow, ThinArc, ThinArcUnion, UniqueArc};
25use smallvec::SmallVec;
26use std::borrow::{Borrow, Cow};
27use std::fmt::{self, Debug};
28use std::iter::Rev;
29use std::slice;
30
31#[cfg(feature = "to_shmem")]
32use to_shmem_derive::ToShmem;
33
34/// A trait that represents a pseudo-element.
35pub trait PseudoElement: Sized + ToCss {
36    /// The `SelectorImpl` this pseudo-element is used for.
37    type Impl: SelectorImpl;
38
39    /// Whether the pseudo-element supports a given state selector to the right
40    /// of it.
41    fn accepts_state_pseudo_classes(&self) -> bool {
42        false
43    }
44
45    /// Whether this pseudo-element is valid after a ::slotted(..) pseudo.
46    fn valid_after_slotted(&self) -> bool {
47        false
48    }
49
50    /// Whether this pseudo-element is valid when directly after a ::before/::after pseudo.
51    fn valid_after_before_or_after(&self) -> bool {
52        false
53    }
54
55    /// Whether this pseudo-element is element-backed.
56    /// https://drafts.csswg.org/css-pseudo-4/#element-like
57    fn parses_as_element_backed(&self) -> bool {
58        false
59    }
60
61    /// Whether this pseudo-element is ::before or ::after pseudo element,
62    /// which are treated specially when deciding what can come after them.
63    /// https://drafts.csswg.org/css-pseudo-4/#generated-content
64    fn is_before_or_after(&self) -> bool {
65        false
66    }
67
68    /// The count we contribute to the specificity from this pseudo-element.
69    fn specificity_count(&self) -> u32 {
70        1
71    }
72
73    /// Whether this pseudo-element is in a pseudo-element tree (excluding the pseudo-element
74    /// root).
75    /// https://drafts.csswg.org/css-view-transitions-1/#pseudo-root
76    fn is_in_pseudo_element_tree(&self) -> bool {
77        false
78    }
79}
80
81/// A trait that represents a pseudo-class.
82pub trait NonTSPseudoClass: Sized + ToCss {
83    /// The `SelectorImpl` this pseudo-element is used for.
84    type Impl: SelectorImpl;
85
86    /// Whether this pseudo-class is :active or :hover.
87    fn is_active_or_hover(&self) -> bool;
88
89    /// Whether this pseudo-class belongs to:
90    ///
91    /// https://drafts.csswg.org/selectors-4/#useraction-pseudos
92    fn is_user_action_state(&self) -> bool;
93
94    fn visit<V>(&self, _visitor: &mut V) -> bool
95    where
96        V: SelectorVisitor<Impl = Self::Impl>,
97    {
98        true
99    }
100}
101
102/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a
103/// Cow::Owned if `s` had to be converted into ASCII lowercase.
104fn to_ascii_lowercase(s: &str) -> Cow<'_, str> {
105    if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
106        let mut string = s.to_owned();
107        string[first_uppercase..].make_ascii_lowercase();
108        string.into()
109    } else {
110        s.into()
111    }
112}
113
114bitflags! {
115    /// Flags that indicate at which point of parsing a selector are we.
116    #[derive(Copy, Clone)]
117    struct SelectorParsingState: u16 {
118        /// Whether we should avoid adding default namespaces to selectors that
119        /// aren't type or universal selectors.
120        const SKIP_DEFAULT_NAMESPACE = 1 << 0;
121
122        /// Whether we've parsed a ::slotted() pseudo-element already.
123        ///
124        /// If so, then we can only parse a subset of pseudo-elements, and
125        /// whatever comes after them if so.
126        const AFTER_SLOTTED = 1 << 1;
127        /// Whether we've parsed a ::part() or element-backed pseudo-element already.
128        ///
129        /// If so, then we can only parse a subset of pseudo-elements, and
130        /// whatever comes after them if so.
131        const AFTER_PART_LIKE = 1 << 2;
132        /// Whether we've parsed a non-element-backed pseudo-element (as in, an
133        /// `Impl::PseudoElement` thus not accounting for `::slotted` or
134        /// `::part`) already.
135        ///
136        /// If so, then other pseudo-elements and most other selectors are
137        /// disallowed.
138        const AFTER_NON_ELEMENT_BACKED_PSEUDO = 1 << 3;
139        /// Whether we've parsed a non-stateful pseudo-element (again, as-in
140        /// `Impl::PseudoElement`) already. If so, then other pseudo-classes are
141        /// disallowed. If this flag is set, `AFTER_NON_ELEMENT_BACKED_PSEUDO` must be set
142        /// as well.
143        const AFTER_NON_STATEFUL_PSEUDO_ELEMENT = 1 << 4;
144        // Whether we've parsed a generated pseudo-element (as in ::before, ::after).
145        // If so then some other pseudo elements are disallowed (e.g. another generated pseudo)
146        // while others allowed (e.g. ::marker).
147        const AFTER_BEFORE_OR_AFTER_PSEUDO = 1 << 5;
148
149        /// Whether we are after any of the pseudo-like things.
150        const AFTER_PSEUDO = Self::AFTER_PART_LIKE.bits() | Self::AFTER_SLOTTED.bits() | Self::AFTER_NON_ELEMENT_BACKED_PSEUDO.bits() | Self::AFTER_BEFORE_OR_AFTER_PSEUDO.bits();
151
152        /// Whether we explicitly disallow combinators.
153        const DISALLOW_COMBINATORS = 1 << 6;
154
155        /// Whether we explicitly disallow pseudo-element-like things.
156        const DISALLOW_PSEUDOS = 1 << 7;
157
158        /// Whether we explicitly disallow relative selectors (i.e. `:has()`).
159        const DISALLOW_RELATIVE_SELECTOR = 1 << 8;
160
161        /// Whether we've parsed a pseudo-element which is in a pseudo-element tree (i.e. it is a
162        /// descendant pseudo of a pseudo-element root).
163        const IN_PSEUDO_ELEMENT_TREE = 1 << 9;
164    }
165}
166
167impl SelectorParsingState {
168    #[inline]
169    fn allows_slotted(self) -> bool {
170        !self.intersects(Self::AFTER_PSEUDO | Self::DISALLOW_PSEUDOS)
171    }
172
173    #[inline]
174    fn allows_part(self) -> bool {
175        !self.intersects(Self::AFTER_PSEUDO | Self::DISALLOW_PSEUDOS)
176    }
177
178    #[inline]
179    fn allows_non_functional_pseudo_classes(self) -> bool {
180        !self.intersects(Self::AFTER_SLOTTED | Self::AFTER_NON_STATEFUL_PSEUDO_ELEMENT)
181    }
182
183    #[inline]
184    fn allows_tree_structural_pseudo_classes(self) -> bool {
185        !self.intersects(Self::AFTER_PSEUDO) || self.intersects(Self::IN_PSEUDO_ELEMENT_TREE)
186    }
187
188    #[inline]
189    fn allows_combinators(self) -> bool {
190        !self.intersects(Self::DISALLOW_COMBINATORS)
191    }
192
193    #[inline]
194    fn allows_only_child_pseudo_class_only(self) -> bool {
195        self.intersects(Self::IN_PSEUDO_ELEMENT_TREE)
196    }
197}
198
199pub type SelectorParseError<'i> = ParseError<'i, SelectorParseErrorKind<'i>>;
200
201#[derive(Clone, Debug, PartialEq)]
202pub enum SelectorParseErrorKind<'i> {
203    NoQualifiedNameInAttributeSelector(Token<'i>),
204    EmptySelector,
205    DanglingCombinator,
206    NonCompoundSelector,
207    NonPseudoElementAfterSlotted,
208    InvalidPseudoElementAfterSlotted,
209    InvalidPseudoElementInsideWhere,
210    InvalidState,
211    UnexpectedTokenInAttributeSelector(Token<'i>),
212    PseudoElementExpectedColon(Token<'i>),
213    PseudoElementExpectedIdent(Token<'i>),
214    NoIdentForPseudo(Token<'i>),
215    UnsupportedPseudoClassOrElement(CowRcStr<'i>),
216    UnexpectedIdent(CowRcStr<'i>),
217    ExpectedNamespace(CowRcStr<'i>),
218    ExpectedBarInAttr(Token<'i>),
219    BadValueInAttr(Token<'i>),
220    InvalidQualNameInAttr(Token<'i>),
221    ExplicitNamespaceUnexpectedToken(Token<'i>),
222    ClassNeedsIdent(Token<'i>),
223}
224
225macro_rules! with_all_bounds {
226    (
227        [ $( $InSelector: tt )* ]
228        [ $( $CommonBounds: tt )* ]
229        [ $( $FromStr: tt )* ]
230    ) => {
231        /// This trait allows to define the parser implementation in regards
232        /// of pseudo-classes/elements
233        ///
234        /// NB: We need Clone so that we can derive(Clone) on struct with that
235        /// are parameterized on SelectorImpl. See
236        /// <https://github.com/rust-lang/rust/issues/26925>
237        pub trait SelectorImpl: Clone + Debug + Sized + 'static {
238            type ExtraMatchingData<'a>: Sized + Default;
239            type AttrValue: $($InSelector)*;
240            type Identifier: $($InSelector)* + PrecomputedHash;
241            type LocalName: $($InSelector)* + Borrow<Self::BorrowedLocalName> + PrecomputedHash;
242            type NamespaceUrl: $($CommonBounds)* + Default + Borrow<Self::BorrowedNamespaceUrl> + PrecomputedHash;
243            type NamespacePrefix: $($InSelector)* + Default;
244            type BorrowedNamespaceUrl: ?Sized + Eq;
245            type BorrowedLocalName: ?Sized + Eq;
246
247            /// non tree-structural pseudo-classes
248            /// (see: https://drafts.csswg.org/selectors/#structural-pseudos)
249            type NonTSPseudoClass: $($CommonBounds)* + NonTSPseudoClass<Impl = Self>;
250
251            /// pseudo-elements
252            type PseudoElement: $($CommonBounds)* + PseudoElement<Impl = Self>;
253
254            /// Whether attribute hashes should be collected for filtering
255            /// purposes.
256            fn should_collect_attr_hash(_name: &Self::LocalName) -> bool {
257                false
258            }
259        }
260    }
261}
262
263macro_rules! with_bounds {
264    ( [ $( $CommonBounds: tt )* ] [ $( $FromStr: tt )* ]) => {
265        with_all_bounds! {
266            [$($CommonBounds)* + $($FromStr)* + ToCss]
267            [$($CommonBounds)*]
268            [$($FromStr)*]
269        }
270    }
271}
272
273with_bounds! {
274    [Clone + Eq]
275    [for<'a> From<&'a str>]
276}
277
278pub trait Parser<'i> {
279    type Impl: SelectorImpl;
280    type Error: 'i + From<SelectorParseErrorKind<'i>>;
281
282    /// Whether to parse the `::slotted()` pseudo-element.
283    fn parse_slotted(&self) -> bool {
284        false
285    }
286
287    /// Whether to parse the `::part()` pseudo-element.
288    fn parse_part(&self) -> bool {
289        false
290    }
291
292    /// Whether to parse the selector list of nth-child() or nth-last-child().
293    fn parse_nth_child_of(&self) -> bool {
294        false
295    }
296
297    /// Whether to parse `:is` and `:where` pseudo-classes.
298    fn parse_is_and_where(&self) -> bool {
299        false
300    }
301
302    /// Whether to parse the :has pseudo-class.
303    fn parse_has(&self) -> bool {
304        false
305    }
306
307    /// Whether to parse the '&' delimiter as a parent selector.
308    fn parse_parent_selector(&self) -> bool {
309        false
310    }
311
312    /// Whether the given function name is an alias for the `:is()` function.
313    fn is_is_alias(&self, _name: &str) -> bool {
314        false
315    }
316
317    /// Whether to parse the `:host` pseudo-class.
318    fn parse_host(&self) -> bool {
319        false
320    }
321
322    /// Whether to allow forgiving selector-list parsing.
323    fn allow_forgiving_selectors(&self) -> bool {
324        true
325    }
326
327    /// This function can return an "Err" pseudo-element in order to support CSS2.1
328    /// pseudo-elements.
329    fn parse_non_ts_pseudo_class(
330        &self,
331        location: SourceLocation,
332        name: CowRcStr<'i>,
333    ) -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ParseError<'i, Self::Error>> {
334        Err(
335            location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
336                name,
337            )),
338        )
339    }
340
341    fn parse_non_ts_functional_pseudo_class<'t>(
342        &self,
343        name: CowRcStr<'i>,
344        parser: &mut CssParser<'i, 't>,
345        _after_part: bool,
346    ) -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ParseError<'i, Self::Error>> {
347        Err(
348            parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
349                name,
350            )),
351        )
352    }
353
354    fn parse_pseudo_element(
355        &self,
356        location: SourceLocation,
357        name: CowRcStr<'i>,
358    ) -> Result<<Self::Impl as SelectorImpl>::PseudoElement, ParseError<'i, Self::Error>> {
359        Err(
360            location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
361                name,
362            )),
363        )
364    }
365
366    fn parse_functional_pseudo_element<'t>(
367        &self,
368        name: CowRcStr<'i>,
369        arguments: &mut CssParser<'i, 't>,
370    ) -> Result<<Self::Impl as SelectorImpl>::PseudoElement, ParseError<'i, Self::Error>> {
371        Err(
372            arguments.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
373                name,
374            )),
375        )
376    }
377
378    fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
379        None
380    }
381
382    fn namespace_for_prefix(
383        &self,
384        _prefix: &<Self::Impl as SelectorImpl>::NamespacePrefix,
385    ) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
386        None
387    }
388}
389
390/// A selector list is a tagged pointer with either a single selector, or a ThinArc<()> of multiple
391/// selectors.
392#[derive(Clone, Eq, Debug, PartialEq)]
393#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
394#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
395pub struct SelectorList<Impl: SelectorImpl>(
396    #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
397    ThinArcUnion<SpecificityAndFlags, Component<Impl>, (), Selector<Impl>>,
398);
399
400impl<Impl: SelectorImpl> SelectorList<Impl> {
401    /// See Arc::mark_as_intentionally_leaked
402    pub fn mark_as_intentionally_leaked(&self) {
403        if let ArcUnionBorrow::Second(ref list) = self.0.borrow() {
404            list.with_arc(|list| list.mark_as_intentionally_leaked())
405        }
406        self.slice()
407            .iter()
408            .for_each(|s| s.mark_as_intentionally_leaked())
409    }
410
411    pub fn from_one(selector: Selector<Impl>) -> Self {
412        #[cfg(debug_assertions)]
413        let selector_repr = unsafe { *(&selector as *const _ as *const usize) };
414        let list = Self(ThinArcUnion::from_first(selector.into_data()));
415        #[cfg(debug_assertions)]
416        debug_assert_eq!(
417            selector_repr,
418            unsafe { *(&list as *const _ as *const usize) },
419            "We rely on the same bit representation for the single selector variant"
420        );
421        list
422    }
423
424    pub fn from_iter(mut iter: impl ExactSizeIterator<Item = Selector<Impl>>) -> Self {
425        if iter.len() == 1 {
426            Self::from_one(iter.next().unwrap())
427        } else {
428            Self(ThinArcUnion::from_second(ThinArc::from_header_and_iter(
429                (),
430                iter,
431            )))
432        }
433    }
434
435    #[inline]
436    pub fn slice(&self) -> &[Selector<Impl>] {
437        match self.0.borrow() {
438            ArcUnionBorrow::First(..) => {
439                // SAFETY: see from_one.
440                let selector: &Selector<Impl> = unsafe { std::mem::transmute(self) };
441                std::slice::from_ref(selector)
442            },
443            ArcUnionBorrow::Second(list) => list.get().slice(),
444        }
445    }
446
447    #[inline]
448    pub fn len(&self) -> usize {
449        match self.0.borrow() {
450            ArcUnionBorrow::First(..) => 1,
451            ArcUnionBorrow::Second(list) => list.len(),
452        }
453    }
454
455    /// Returns the address on the heap of the ThinArc for memory reporting.
456    pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
457        match self.0.borrow() {
458            ArcUnionBorrow::First(s) => s.with_arc(|a| a.heap_ptr()),
459            ArcUnionBorrow::Second(s) => s.with_arc(|a| a.heap_ptr()),
460        }
461    }
462}
463
464/// Uniquely identify a selector based on its components, which is behind ThinArc and
465/// is therefore stable.
466#[derive(Clone, Copy, Hash, Eq, PartialEq)]
467pub struct SelectorKey(usize);
468
469impl SelectorKey {
470    /// Create a new key based on the given selector.
471    pub fn new<Impl: SelectorImpl>(selector: &Selector<Impl>) -> Self {
472        Self(selector.0.slice().as_ptr() as usize)
473    }
474}
475
476/// Whether or not we're using forgiving parsing mode
477#[derive(PartialEq)]
478enum ForgivingParsing {
479    /// Discard the entire selector list upon encountering any invalid selector.
480    /// This is the default behavior for almost all of CSS.
481    No,
482    /// Ignore invalid selectors, potentially creating an empty selector list.
483    ///
484    /// This is the error recovery mode of :is() and :where()
485    Yes,
486}
487
488/// Flag indicating if we're parsing relative selectors.
489#[derive(Copy, Clone, PartialEq)]
490pub enum ParseRelative {
491    /// Expect selectors to start with a combinator, assuming descendant combinator if not present.
492    ForHas,
493    /// Allow selectors to start with a combinator, prepending a parent selector if so. Do nothing
494    /// otherwise
495    ForNesting,
496    /// Allow selectors to start with a combinator, prepending a scope selector if so. Do nothing
497    /// otherwise
498    ForScope,
499    /// Treat as parse error if any selector begins with a combinator.
500    No,
501}
502
503impl<Impl: SelectorImpl> SelectorList<Impl> {
504    /// Returns a selector list with a single `:scope` selector (with specificity)
505    pub fn scope() -> Self {
506        Self::from_one(Selector::scope())
507    }
508    /// Returns a selector list with a single implicit `:scope` selector (no specificity)
509    pub fn implicit_scope() -> Self {
510        Self::from_one(Selector::implicit_scope())
511    }
512
513    /// Parse a comma-separated list of Selectors.
514    /// <https://drafts.csswg.org/selectors/#grouping>
515    ///
516    /// Return the Selectors or Err if there is an invalid selector.
517    pub fn parse<'i, 't, P>(
518        parser: &P,
519        input: &mut CssParser<'i, 't>,
520        parse_relative: ParseRelative,
521    ) -> Result<Self, ParseError<'i, P::Error>>
522    where
523        P: Parser<'i, Impl = Impl>,
524    {
525        Self::parse_with_state(
526            parser,
527            input,
528            SelectorParsingState::empty(),
529            ForgivingParsing::No,
530            parse_relative,
531        )
532    }
533
534    /// Same as `parse`, but disallow parsing of pseudo-elements.
535    pub fn parse_disallow_pseudo<'i, 't, P>(
536        parser: &P,
537        input: &mut CssParser<'i, 't>,
538        parse_relative: ParseRelative,
539    ) -> Result<Self, ParseError<'i, P::Error>>
540    where
541        P: Parser<'i, Impl = Impl>,
542    {
543        Self::parse_with_state(
544            parser,
545            input,
546            SelectorParsingState::DISALLOW_PSEUDOS,
547            ForgivingParsing::No,
548            parse_relative,
549        )
550    }
551
552    pub fn parse_forgiving<'i, 't, P>(
553        parser: &P,
554        input: &mut CssParser<'i, 't>,
555        parse_relative: ParseRelative,
556    ) -> Result<Self, ParseError<'i, P::Error>>
557    where
558        P: Parser<'i, Impl = Impl>,
559    {
560        Self::parse_with_state(
561            parser,
562            input,
563            SelectorParsingState::empty(),
564            ForgivingParsing::Yes,
565            parse_relative,
566        )
567    }
568
569    #[inline]
570    fn parse_with_state<'i, 't, P>(
571        parser: &P,
572        input: &mut CssParser<'i, 't>,
573        state: SelectorParsingState,
574        recovery: ForgivingParsing,
575        parse_relative: ParseRelative,
576    ) -> Result<Self, ParseError<'i, P::Error>>
577    where
578        P: Parser<'i, Impl = Impl>,
579    {
580        let mut values = SmallVec::<[_; 4]>::new();
581        let forgiving = recovery == ForgivingParsing::Yes && parser.allow_forgiving_selectors();
582        loop {
583            let selector = input.parse_until_before(Delimiter::Comma, |input| {
584                let start = input.position();
585                let mut selector = parse_selector(parser, input, state, parse_relative);
586                if forgiving && (selector.is_err() || input.expect_exhausted().is_err()) {
587                    input.expect_no_error_token()?;
588                    selector = Ok(Selector::new_invalid(input.slice_from(start)));
589                }
590                selector
591            })?;
592
593            values.push(selector);
594
595            match input.next() {
596                Ok(&Token::Comma) => {},
597                Ok(_) => unreachable!(),
598                Err(_) => break,
599            }
600        }
601        Ok(Self::from_iter(values.into_iter()))
602    }
603
604    /// Replaces the parent selector in all the items of the selector list.
605    pub fn replace_parent_selector(&self, parent: &SelectorList<Impl>) -> Self {
606        Self::from_iter(
607            self.slice()
608                .iter()
609                .map(|selector| selector.replace_parent_selector(parent)),
610        )
611    }
612
613    /// Creates a SelectorList from a Vec of selectors. Used in tests.
614    #[allow(dead_code)]
615    pub(crate) fn from_vec(v: Vec<Selector<Impl>>) -> Self {
616        SelectorList::from_iter(v.into_iter())
617    }
618}
619
620/// Parses one compound selector suitable for nested stuff like :-moz-any, etc.
621fn parse_inner_compound_selector<'i, 't, P, Impl>(
622    parser: &P,
623    input: &mut CssParser<'i, 't>,
624    state: SelectorParsingState,
625) -> Result<Selector<Impl>, ParseError<'i, P::Error>>
626where
627    P: Parser<'i, Impl = Impl>,
628    Impl: SelectorImpl,
629{
630    parse_selector(
631        parser,
632        input,
633        state | SelectorParsingState::DISALLOW_PSEUDOS | SelectorParsingState::DISALLOW_COMBINATORS,
634        ParseRelative::No,
635    )
636}
637
638/// Ancestor hashes for the bloom filter. We precompute these and store them
639/// inline with selectors to optimize cache performance during matching.
640/// This matters a lot.
641///
642/// We use 4 hashes, which is copied from Gecko, who copied it from WebKit.
643/// Note that increasing the number of hashes here will adversely affect the
644/// cache hit when fast-rejecting long lists of Rules with inline hashes.
645///
646/// Because the bloom filter only uses the bottom 24 bits of the hash, we pack
647/// the fourth hash into the upper bits of the first three hashes in order to
648/// shrink Rule (whose size matters a lot). This scheme minimizes the runtime
649/// overhead of the packing for the first three hashes (we just need to mask
650/// off the upper bits) at the expense of making the fourth somewhat more
651/// complicated to assemble, because we often bail out before checking all the
652/// hashes.
653#[derive(Clone, Debug, Eq, PartialEq)]
654pub struct AncestorHashes {
655    pub packed_hashes: [u32; 3],
656}
657
658pub(crate) fn collect_selector_hashes<'a, Impl: SelectorImpl, Iter>(
659    iter: Iter,
660    quirks_mode: QuirksMode,
661    hashes: &mut [u32; 4],
662    len: &mut usize,
663    create_inner_iterator: fn(&'a Selector<Impl>) -> Iter,
664) -> bool
665where
666    Iter: Iterator<Item = &'a Component<Impl>>,
667{
668    for component in iter {
669        let hash = match *component {
670            Component::LocalName(LocalName {
671                ref name,
672                ref lower_name,
673            }) => {
674                // Only insert the local-name into the filter if it's all
675                // lowercase.  Otherwise we would need to test both hashes, and
676                // our data structures aren't really set up for that.
677                if name != lower_name {
678                    continue;
679                }
680                name.precomputed_hash()
681            },
682            Component::DefaultNamespace(ref url) | Component::Namespace(_, ref url) => {
683                url.precomputed_hash()
684            },
685            // In quirks mode, class and id selectors should match
686            // case-insensitively, so just avoid inserting them into the filter.
687            Component::ID(ref id) if quirks_mode != QuirksMode::Quirks => id.precomputed_hash(),
688            Component::Class(ref class) if quirks_mode != QuirksMode::Quirks => {
689                class.precomputed_hash()
690            },
691            Component::AttributeInNoNamespace { ref local_name, .. }
692                if Impl::should_collect_attr_hash(local_name) =>
693            {
694                // AttributeInNoNamespace is only used when local_name ==
695                // local_name_lower.
696                local_name.precomputed_hash()
697            },
698            Component::AttributeInNoNamespaceExists {
699                ref local_name,
700                ref local_name_lower,
701                ..
702            } => {
703                // Only insert the local-name into the filter if it's all
704                // lowercase.  Otherwise we would need to test both hashes, and
705                // our data structures aren't really set up for that.
706                if local_name != local_name_lower || !Impl::should_collect_attr_hash(local_name) {
707                    continue;
708                }
709                local_name.precomputed_hash()
710            },
711            Component::AttributeOther(ref selector) => {
712                if selector.local_name != selector.local_name_lower
713                    || !Impl::should_collect_attr_hash(&selector.local_name)
714                {
715                    continue;
716                }
717                selector.local_name.precomputed_hash()
718            },
719            Component::Is(ref list) | Component::Where(ref list) => {
720                // :where and :is OR their selectors, so we can't put any hash
721                // in the filter if there's more than one selector, as that'd
722                // exclude elements that may match one of the other selectors.
723                let slice = list.slice();
724                if slice.len() == 1
725                    && !collect_selector_hashes(
726                        create_inner_iterator(&slice[0]),
727                        quirks_mode,
728                        hashes,
729                        len,
730                        create_inner_iterator,
731                    )
732                {
733                    return false;
734                }
735                continue;
736            },
737            _ => continue,
738        };
739
740        hashes[*len] = hash & BLOOM_HASH_MASK;
741        *len += 1;
742        if *len == hashes.len() {
743            return false;
744        }
745    }
746    true
747}
748
749fn collect_ancestor_hashes<Impl: SelectorImpl>(
750    mut iter: SelectorIter<Impl>,
751    quirks_mode: QuirksMode,
752    hashes: &mut [u32; 4],
753    len: &mut usize,
754) -> bool {
755    loop {
756        while let Some(item) = iter.next() {
757            if let Component::Is(ref list) | Component::Where(ref list) = item {
758                let slice = list.slice();
759                if slice.len() == 1
760                    && !collect_ancestor_hashes(slice[0].iter(), quirks_mode, hashes, len)
761                {
762                    return false;
763                }
764            }
765        }
766        let Some(c) = iter.next_sequence() else {
767            return true;
768        };
769        match c {
770            // We got to an ancestor combinator, let collect_selector_hashes take it from there.
771            Combinator::Child | Combinator::Descendant => break,
772            Combinator::LaterSibling | Combinator::NextSibling => {
773                iter.skip_until_ancestor();
774                break;
775            },
776            // Keep scanning the subject for other potential ancestor combinators inside :where()
777            // and :is(). Note that if this is ever changed to stop at the "pseudo-element"
778            // combinator and treat it as a regular ancestor combinator, we will need to fix the way
779            // we compute hashes for revalidation selectors.
780            Combinator::Part | Combinator::SlotAssignment | Combinator::PseudoElement => {},
781        }
782    }
783
784    collect_selector_hashes(AncestorIter(iter), quirks_mode, hashes, len, |s| {
785        AncestorIter(s.iter())
786    })
787}
788
789impl AncestorHashes {
790    pub fn new<Impl: SelectorImpl>(selector: &Selector<Impl>, quirks_mode: QuirksMode) -> Self {
791        // Compute ancestor hashes for the bloom filter.
792        let mut hashes = [0u32; 4];
793        let mut len = 0;
794        collect_ancestor_hashes(selector.iter(), quirks_mode, &mut hashes, &mut len);
795        debug_assert!(len <= 4);
796
797        // Now, pack the fourth hash (if it exists) into the upper byte of each of
798        // the other three hashes.
799        if len == 4 {
800            let fourth = hashes[3];
801            hashes[0] |= (fourth & 0x000000ff) << 24;
802            hashes[1] |= (fourth & 0x0000ff00) << 16;
803            hashes[2] |= (fourth & 0x00ff0000) << 8;
804        }
805
806        AncestorHashes {
807            packed_hashes: [hashes[0], hashes[1], hashes[2]],
808        }
809    }
810
811    /// Returns the fourth hash, reassembled from parts.
812    pub fn fourth_hash(&self) -> u32 {
813        ((self.packed_hashes[0] & 0xff000000) >> 24)
814            | ((self.packed_hashes[1] & 0xff000000) >> 16)
815            | ((self.packed_hashes[2] & 0xff000000) >> 8)
816    }
817}
818
819#[inline]
820pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
821    // Rust type’s default, not default namespace
822    Impl::NamespaceUrl::default()
823}
824
825pub(super) type SelectorData<Impl> = ThinArc<SpecificityAndFlags, Component<Impl>>;
826
827/// Whether a selector may match a featureless host element, and whether it may match other
828/// elements.
829#[derive(Clone, Copy, Debug, Eq, PartialEq)]
830pub enum MatchesFeaturelessHost {
831    /// The selector may match a featureless host, but also a non-featureless element.
832    Yes,
833    /// The selector is guaranteed to never match a non-featureless host element.
834    Only,
835    /// The selector never matches a featureless host.
836    Never,
837}
838
839impl MatchesFeaturelessHost {
840    /// Whether we may match.
841    #[inline]
842    pub fn may_match(self) -> bool {
843        return !matches!(self, Self::Never);
844    }
845}
846
847/// A Selector stores a sequence of simple selectors and combinators. The
848/// iterator classes allow callers to iterate at either the raw sequence level or
849/// at the level of sequences of simple selectors separated by combinators. Most
850/// callers want the higher-level iterator.
851///
852/// We store compound selectors internally right-to-left (in matching order).
853/// Additionally, we invert the order of top-level compound selectors so that
854/// each one matches left-to-right. This is because matching namespace, local name,
855/// id, and class are all relatively cheap, whereas matching pseudo-classes might
856/// be expensive (depending on the pseudo-class). Since authors tend to put the
857/// pseudo-classes on the right, it's faster to start matching on the left.
858///
859/// This reordering doesn't change the semantics of selector matching, and we
860/// handle it in to_css to make it invisible to serialization.
861#[derive(Clone, Eq, PartialEq)]
862#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
863#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
864#[repr(transparent)]
865pub struct Selector<Impl: SelectorImpl>(
866    #[cfg_attr(feature = "to_shmem", shmem(field_bound))] SelectorData<Impl>,
867);
868
869impl<Impl: SelectorImpl> Selector<Impl> {
870    /// See Arc::mark_as_intentionally_leaked
871    pub fn mark_as_intentionally_leaked(&self) {
872        self.0.mark_as_intentionally_leaked()
873    }
874
875    fn scope() -> Self {
876        Self(ThinArc::from_header_and_iter(
877            SpecificityAndFlags {
878                specificity: Specificity::single_class_like().into(),
879                flags: SelectorFlags::HAS_SCOPE,
880            },
881            std::iter::once(Component::Scope),
882        ))
883    }
884
885    /// An implicit scope selector, much like :where(:scope).
886    fn implicit_scope() -> Self {
887        Self(ThinArc::from_header_and_iter(
888            SpecificityAndFlags {
889                specificity: 0,
890                flags: SelectorFlags::HAS_SCOPE,
891            },
892            std::iter::once(Component::ImplicitScope),
893        ))
894    }
895
896    #[inline]
897    pub fn specificity(&self) -> u32 {
898        self.0.header.specificity
899    }
900
901    #[inline]
902    pub(crate) fn flags(&self) -> SelectorFlags {
903        self.0.header.flags
904    }
905
906    #[inline]
907    pub fn has_pseudo_element(&self) -> bool {
908        self.flags().intersects(SelectorFlags::HAS_PSEUDO)
909    }
910
911    #[inline]
912    pub fn has_parent_selector(&self) -> bool {
913        self.flags().intersects(SelectorFlags::HAS_PARENT)
914    }
915
916    #[inline]
917    pub fn has_scope_selector(&self) -> bool {
918        self.flags().intersects(SelectorFlags::HAS_SCOPE)
919    }
920
921    #[inline]
922    pub fn is_slotted(&self) -> bool {
923        self.flags().intersects(SelectorFlags::HAS_SLOTTED)
924    }
925
926    #[inline]
927    pub fn is_part(&self) -> bool {
928        self.flags().intersects(SelectorFlags::HAS_PART)
929    }
930
931    #[inline]
932    pub fn parts(&self) -> Option<&[Impl::Identifier]> {
933        if !self.is_part() {
934            return None;
935        }
936
937        let mut iter = self.iter();
938        if self.has_pseudo_element() {
939            // Skip the pseudo-element.
940            for _ in &mut iter {}
941
942            let combinator = iter.next_sequence()?;
943            debug_assert_eq!(combinator, Combinator::PseudoElement);
944        }
945
946        for component in iter {
947            if let Component::Part(ref part) = *component {
948                return Some(part);
949            }
950        }
951
952        debug_assert!(false, "is_part() lied somehow?");
953        None
954    }
955
956    #[inline]
957    pub fn pseudo_element(&self) -> Option<&Impl::PseudoElement> {
958        if !self.has_pseudo_element() {
959            return None;
960        }
961
962        for component in self.iter() {
963            if let Component::PseudoElement(ref pseudo) = *component {
964                return Some(pseudo);
965            }
966        }
967
968        debug_assert!(false, "has_pseudo_element lied!");
969        None
970    }
971
972    #[inline]
973    pub fn pseudo_elements(&self) -> SmallVec<[&Impl::PseudoElement; 3]> {
974        let mut pseudos = SmallVec::new();
975
976        if !self.has_pseudo_element() {
977            return pseudos;
978        }
979
980        let mut iter = self.iter();
981        loop {
982            for component in &mut iter {
983                if let Component::PseudoElement(ref pseudo) = *component {
984                    pseudos.push(pseudo);
985                }
986            }
987            match iter.next_sequence() {
988                Some(Combinator::PseudoElement) => {},
989                _ => break,
990            }
991        }
992
993        debug_assert!(!pseudos.is_empty(), "has_pseudo_element lied!");
994
995        pseudos
996    }
997
998    /// Whether this selector (pseudo-element part excluded) matches every element.
999    ///
1000    /// Used for "pre-computed" pseudo-elements in components/style/stylist.rs
1001    #[inline]
1002    pub fn is_universal(&self) -> bool {
1003        self.iter_raw_match_order().all(|c| {
1004            matches!(
1005                *c,
1006                Component::ExplicitUniversalType
1007                    | Component::ExplicitAnyNamespace
1008                    | Component::Combinator(Combinator::PseudoElement)
1009                    | Component::PseudoElement(..)
1010            )
1011        })
1012    }
1013
1014    /// Whether this selector may match a featureless shadow host, with no combinators to the
1015    /// left, and optionally has a pseudo-element to the right.
1016    #[inline]
1017    pub fn matches_featureless_host(
1018        &self,
1019        scope_matches_featureless_host: bool,
1020    ) -> MatchesFeaturelessHost {
1021        let flags = self.flags();
1022        if !flags.intersects(SelectorFlags::HAS_HOST | SelectorFlags::HAS_SCOPE) {
1023            return MatchesFeaturelessHost::Never;
1024        }
1025
1026        let mut iter = self.iter();
1027        if flags.intersects(SelectorFlags::HAS_PSEUDO) {
1028            for _ in &mut iter {
1029                // Skip over pseudo-elements
1030            }
1031            match iter.next_sequence() {
1032                Some(c) if c.is_pseudo_element() => {},
1033                _ => {
1034                    debug_assert!(false, "Pseudo selector without pseudo combinator?");
1035                    return MatchesFeaturelessHost::Never;
1036                },
1037            }
1038        }
1039
1040        let compound_matches = crate::matching::compound_matches_featureless_host(
1041            &mut iter,
1042            scope_matches_featureless_host,
1043        );
1044        if iter.next_sequence().is_some() {
1045            return MatchesFeaturelessHost::Never;
1046        }
1047        return compound_matches;
1048    }
1049
1050    /// Returns an iterator over this selector in matching order (right-to-left).
1051    /// When a combinator is reached, the iterator will return None, and
1052    /// next_sequence() may be called to continue to the next sequence.
1053    #[inline]
1054    pub fn iter(&self) -> SelectorIter<'_, Impl> {
1055        SelectorIter {
1056            iter: self.iter_raw_match_order(),
1057            next_combinator: None,
1058        }
1059    }
1060
1061    /// Same as `iter()`, but skips `RelativeSelectorAnchor` and its associated combinator.
1062    #[inline]
1063    pub fn iter_skip_relative_selector_anchor(&self) -> SelectorIter<'_, Impl> {
1064        if cfg!(debug_assertions) {
1065            let mut selector_iter = self.iter_raw_parse_order_from(0);
1066            assert!(
1067                matches!(
1068                    selector_iter.next().unwrap(),
1069                    Component::RelativeSelectorAnchor
1070                ),
1071                "Relative selector does not start with RelativeSelectorAnchor"
1072            );
1073            assert!(
1074                selector_iter.next().unwrap().is_combinator(),
1075                "Relative combinator does not exist"
1076            );
1077        }
1078
1079        SelectorIter {
1080            iter: self.0.slice()[..self.len() - 2].iter(),
1081            next_combinator: None,
1082        }
1083    }
1084
1085    /// Returns an iterator over this selector in matching order (right-to-left),
1086    /// skipping the rightmost |offset| Components.
1087    #[inline]
1088    pub fn iter_from(&self, offset: usize) -> SelectorIter<'_, Impl> {
1089        let iter = self.0.slice()[offset..].iter();
1090        SelectorIter {
1091            iter,
1092            next_combinator: None,
1093        }
1094    }
1095
1096    /// Returns the combinator at index `index` (zero-indexed from the right),
1097    /// or panics if the component is not a combinator.
1098    #[inline]
1099    pub fn combinator_at_match_order(&self, index: usize) -> Combinator {
1100        match self.0.slice()[index] {
1101            Component::Combinator(c) => c,
1102            ref other => panic!(
1103                "Not a combinator: {:?}, {:?}, index: {}",
1104                other, self, index
1105            ),
1106        }
1107    }
1108
1109    /// Returns an iterator over the entire sequence of simple selectors and
1110    /// combinators, in matching order (from right to left).
1111    #[inline]
1112    pub fn iter_raw_match_order(&self) -> slice::Iter<'_, Component<Impl>> {
1113        self.0.slice().iter()
1114    }
1115
1116    /// Returns the combinator at index `index` (zero-indexed from the left),
1117    /// or panics if the component is not a combinator.
1118    #[inline]
1119    pub fn combinator_at_parse_order(&self, index: usize) -> Combinator {
1120        match self.0.slice()[self.len() - index - 1] {
1121            Component::Combinator(c) => c,
1122            ref other => panic!(
1123                "Not a combinator: {:?}, {:?}, index: {}",
1124                other, self, index
1125            ),
1126        }
1127    }
1128
1129    /// Returns an iterator over the sequence of simple selectors and
1130    /// combinators, in parse order (from left to right), starting from
1131    /// `offset`.
1132    #[inline]
1133    pub fn iter_raw_parse_order_from(
1134        &self,
1135        offset: usize,
1136    ) -> Rev<slice::Iter<'_, Component<Impl>>> {
1137        self.0.slice()[..self.len() - offset].iter().rev()
1138    }
1139
1140    /// Creates a Selector from a vec of Components, specified in parse order. Used in tests.
1141    #[allow(dead_code)]
1142    pub(crate) fn from_vec(
1143        vec: Vec<Component<Impl>>,
1144        specificity: u32,
1145        flags: SelectorFlags,
1146    ) -> Self {
1147        let mut builder = SelectorBuilder::default();
1148        for component in vec.into_iter() {
1149            if let Some(combinator) = component.as_combinator() {
1150                builder.push_combinator(combinator);
1151            } else {
1152                builder.push_simple_selector(component);
1153            }
1154        }
1155        let spec = SpecificityAndFlags { specificity, flags };
1156        Selector(builder.build_with_specificity_and_flags(spec, ParseRelative::No))
1157    }
1158
1159    #[inline]
1160    fn into_data(self) -> SelectorData<Impl> {
1161        self.0
1162    }
1163
1164    pub fn replace_parent_selector(&self, parent: &SelectorList<Impl>) -> Self {
1165        let parent_specificity_and_flags = selector_list_specificity_and_flags(
1166            parent.slice().iter(),
1167            /* for_nesting_parent = */ true,
1168        );
1169
1170        let mut specificity = Specificity::from(self.specificity());
1171        let mut flags = self.flags() - SelectorFlags::HAS_PARENT;
1172        let forbidden_flags = SelectorFlags::forbidden_for_nesting();
1173
1174        fn replace_parent_on_selector_list<Impl: SelectorImpl>(
1175            orig: &[Selector<Impl>],
1176            parent: &SelectorList<Impl>,
1177            specificity: &mut Specificity,
1178            flags: &mut SelectorFlags,
1179            propagate_specificity: bool,
1180            forbidden_flags: SelectorFlags,
1181        ) -> Option<SelectorList<Impl>> {
1182            if !orig.iter().any(|s| s.has_parent_selector()) {
1183                return None;
1184            }
1185
1186            let result =
1187                SelectorList::from_iter(orig.iter().map(|s| s.replace_parent_selector(parent)));
1188
1189            let result_specificity_and_flags = selector_list_specificity_and_flags(
1190                result.slice().iter(),
1191                /* for_nesting_parent = */ false,
1192            );
1193            if propagate_specificity {
1194                *specificity += Specificity::from(
1195                    result_specificity_and_flags.specificity
1196                        - selector_list_specificity_and_flags(
1197                            orig.iter(),
1198                            /* for_nesting_parent = */ false,
1199                        )
1200                        .specificity,
1201                );
1202            }
1203            flags.insert(result_specificity_and_flags.flags - forbidden_flags);
1204            Some(result)
1205        }
1206
1207        fn replace_parent_on_relative_selector_list<Impl: SelectorImpl>(
1208            orig: &[RelativeSelector<Impl>],
1209            parent: &SelectorList<Impl>,
1210            specificity: &mut Specificity,
1211            flags: &mut SelectorFlags,
1212            forbidden_flags: SelectorFlags,
1213        ) -> Box<[RelativeSelector<Impl>]> {
1214            let mut any = false;
1215
1216            let result = orig
1217                .iter()
1218                .map(|s| {
1219                    if !s.selector.has_parent_selector() {
1220                        return s.clone();
1221                    }
1222                    any = true;
1223                    RelativeSelector {
1224                        match_hint: s.match_hint,
1225                        selector: s.selector.replace_parent_selector(parent),
1226                    }
1227                })
1228                .collect();
1229
1230            if !any {
1231                return result;
1232            }
1233
1234            let result_specificity_and_flags = relative_selector_list_specificity_and_flags(
1235                &result, /* for_nesting_parent = */ false,
1236            );
1237            flags.insert(result_specificity_and_flags.flags - forbidden_flags);
1238            *specificity += Specificity::from(
1239                result_specificity_and_flags.specificity
1240                    - relative_selector_list_specificity_and_flags(
1241                        orig, /* for_nesting_parent = */ false,
1242                    )
1243                    .specificity,
1244            );
1245            result
1246        }
1247
1248        fn replace_parent_on_selector<Impl: SelectorImpl>(
1249            orig: &Selector<Impl>,
1250            parent: &SelectorList<Impl>,
1251            specificity: &mut Specificity,
1252            flags: &mut SelectorFlags,
1253            forbidden_flags: SelectorFlags,
1254        ) -> Selector<Impl> {
1255            let new_selector = orig.replace_parent_selector(parent);
1256            *specificity += Specificity::from(new_selector.specificity() - orig.specificity());
1257            flags.insert(new_selector.flags() - forbidden_flags);
1258            new_selector
1259        }
1260
1261        if !self.has_parent_selector() {
1262            return self.clone();
1263        }
1264
1265        let iter = self.iter_raw_match_order().map(|component| {
1266            use self::Component::*;
1267            match *component {
1268                LocalName(..)
1269                | ID(..)
1270                | Class(..)
1271                | AttributeInNoNamespaceExists { .. }
1272                | AttributeInNoNamespace { .. }
1273                | AttributeOther(..)
1274                | ExplicitUniversalType
1275                | ExplicitAnyNamespace
1276                | ExplicitNoNamespace
1277                | DefaultNamespace(..)
1278                | Namespace(..)
1279                | Root
1280                | Empty
1281                | Scope
1282                | ImplicitScope
1283                | Nth(..)
1284                | NonTSPseudoClass(..)
1285                | PseudoElement(..)
1286                | Combinator(..)
1287                | Host(None)
1288                | Part(..)
1289                | Invalid(..)
1290                | RelativeSelectorAnchor => component.clone(),
1291                ParentSelector => {
1292                    specificity += Specificity::from(parent_specificity_and_flags.specificity);
1293                    flags.insert(parent_specificity_and_flags.flags - forbidden_flags);
1294                    Is(parent.clone())
1295                },
1296                Negation(ref selectors) => {
1297                    Negation(
1298                        replace_parent_on_selector_list(
1299                            selectors.slice(),
1300                            parent,
1301                            &mut specificity,
1302                            &mut flags,
1303                            /* propagate_specificity = */ true,
1304                            forbidden_flags,
1305                        )
1306                        .unwrap_or_else(|| selectors.clone()),
1307                    )
1308                },
1309                Is(ref selectors) => {
1310                    Is(replace_parent_on_selector_list(
1311                        selectors.slice(),
1312                        parent,
1313                        &mut specificity,
1314                        &mut flags,
1315                        /* propagate_specificity = */ true,
1316                        forbidden_flags,
1317                    )
1318                    .unwrap_or_else(|| selectors.clone()))
1319                },
1320                Where(ref selectors) => {
1321                    Where(
1322                        replace_parent_on_selector_list(
1323                            selectors.slice(),
1324                            parent,
1325                            &mut specificity,
1326                            &mut flags,
1327                            /* propagate_specificity = */ false,
1328                            forbidden_flags,
1329                        )
1330                        .unwrap_or_else(|| selectors.clone()),
1331                    )
1332                },
1333                Has(ref selectors) => Has(replace_parent_on_relative_selector_list(
1334                    selectors,
1335                    parent,
1336                    &mut specificity,
1337                    &mut flags,
1338                    forbidden_flags,
1339                )),
1340                Host(Some(ref selector)) => Host(Some(replace_parent_on_selector(
1341                    selector,
1342                    parent,
1343                    &mut specificity,
1344                    &mut flags,
1345                    forbidden_flags,
1346                ))),
1347                NthOf(ref data) => {
1348                    let selectors = replace_parent_on_selector_list(
1349                        data.selectors(),
1350                        parent,
1351                        &mut specificity,
1352                        &mut flags,
1353                        /* propagate_specificity = */ true,
1354                        forbidden_flags,
1355                    );
1356                    NthOf(match selectors {
1357                        Some(s) => {
1358                            NthOfSelectorData::new(data.nth_data(), s.slice().iter().cloned())
1359                        },
1360                        None => data.clone(),
1361                    })
1362                },
1363                Slotted(ref selector) => Slotted(replace_parent_on_selector(
1364                    selector,
1365                    parent,
1366                    &mut specificity,
1367                    &mut flags,
1368                    forbidden_flags,
1369                )),
1370            }
1371        });
1372        let mut items = UniqueArc::from_header_and_iter(Default::default(), iter);
1373        *items.header_mut() = SpecificityAndFlags {
1374            specificity: specificity.into(),
1375            flags,
1376        };
1377        Selector(items.shareable())
1378    }
1379
1380    /// Returns count of simple selectors and combinators in the Selector.
1381    #[inline]
1382    pub fn len(&self) -> usize {
1383        self.0.len()
1384    }
1385
1386    /// Returns the address on the heap of the ThinArc for memory reporting.
1387    pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
1388        self.0.heap_ptr()
1389    }
1390
1391    /// Traverse selector components inside `self`.
1392    ///
1393    /// Implementations of this method should call `SelectorVisitor` methods
1394    /// or other impls of `Visit` as appropriate based on the fields of `Self`.
1395    ///
1396    /// A return value of `false` indicates terminating the traversal.
1397    /// It should be propagated with an early return.
1398    /// On the contrary, `true` indicates that all fields of `self` have been traversed:
1399    ///
1400    /// ```rust,ignore
1401    /// if !visitor.visit_simple_selector(&self.some_simple_selector) {
1402    ///     return false;
1403    /// }
1404    /// if !self.some_component.visit(visitor) {
1405    ///     return false;
1406    /// }
1407    /// true
1408    /// ```
1409    pub fn visit<V>(&self, visitor: &mut V) -> bool
1410    where
1411        V: SelectorVisitor<Impl = Impl>,
1412    {
1413        let mut current = self.iter();
1414        let mut combinator = None;
1415        loop {
1416            if !visitor.visit_complex_selector(combinator) {
1417                return false;
1418            }
1419
1420            for selector in &mut current {
1421                if !selector.visit(visitor) {
1422                    return false;
1423                }
1424            }
1425
1426            combinator = current.next_sequence();
1427            if combinator.is_none() {
1428                break;
1429            }
1430        }
1431
1432        true
1433    }
1434
1435    /// Parse a selector, without any pseudo-element.
1436    #[inline]
1437    pub fn parse<'i, 't, P>(
1438        parser: &P,
1439        input: &mut CssParser<'i, 't>,
1440    ) -> Result<Self, ParseError<'i, P::Error>>
1441    where
1442        P: Parser<'i, Impl = Impl>,
1443    {
1444        parse_selector(
1445            parser,
1446            input,
1447            SelectorParsingState::empty(),
1448            ParseRelative::No,
1449        )
1450    }
1451
1452    pub fn new_invalid(s: &str) -> Self {
1453        fn check_for_parent(input: &mut CssParser, has_parent: &mut bool) {
1454            while let Ok(t) = input.next() {
1455                match *t {
1456                    Token::Function(_)
1457                    | Token::ParenthesisBlock
1458                    | Token::CurlyBracketBlock
1459                    | Token::SquareBracketBlock => {
1460                        let _ = input.parse_nested_block(
1461                            |i| -> Result<(), ParseError<'_, BasicParseError>> {
1462                                check_for_parent(i, has_parent);
1463                                Ok(())
1464                            },
1465                        );
1466                    },
1467                    Token::Delim('&') => {
1468                        *has_parent = true;
1469                    },
1470                    _ => {},
1471                }
1472                if *has_parent {
1473                    break;
1474                }
1475            }
1476        }
1477        let mut has_parent = false;
1478        {
1479            let mut parser = cssparser::ParserInput::new(s);
1480            let mut parser = CssParser::new(&mut parser);
1481            check_for_parent(&mut parser, &mut has_parent);
1482        }
1483        Self(ThinArc::from_header_and_iter(
1484            SpecificityAndFlags {
1485                specificity: 0,
1486                flags: if has_parent {
1487                    SelectorFlags::HAS_PARENT
1488                } else {
1489                    SelectorFlags::empty()
1490                },
1491            },
1492            std::iter::once(Component::Invalid(Arc::new(String::from(s.trim())))),
1493        ))
1494    }
1495
1496    /// Is the compound starting at the offset the subject compound, or referring to its pseudo-element?
1497    pub fn is_rightmost(&self, offset: usize) -> bool {
1498        // There can really be only one pseudo-element, and it's not really valid for anything else to
1499        // follow it.
1500        offset == 0
1501            || matches!(
1502                self.combinator_at_match_order(offset - 1),
1503                Combinator::PseudoElement
1504            )
1505    }
1506}
1507
1508#[derive(Clone)]
1509pub struct SelectorIter<'a, Impl: 'a + SelectorImpl> {
1510    iter: slice::Iter<'a, Component<Impl>>,
1511    next_combinator: Option<Combinator>,
1512}
1513
1514impl<'a, Impl: 'a + SelectorImpl> SelectorIter<'a, Impl> {
1515    /// Prepares this iterator to point to the next sequence to the left,
1516    /// returning the combinator if the sequence was found.
1517    #[inline]
1518    pub fn next_sequence(&mut self) -> Option<Combinator> {
1519        self.next_combinator.take()
1520    }
1521
1522    /// Skips a sequence of simple selectors and all subsequent sequences until
1523    /// a non-pseudo-element ancestor combinator is reached.
1524    fn skip_until_ancestor(&mut self) {
1525        loop {
1526            while self.next().is_some() {}
1527            if self.next_sequence().is_none_or(|c| c.is_ancestor()) {
1528                break;
1529            }
1530        }
1531    }
1532
1533    #[inline]
1534    pub(crate) fn matches_for_stateless_pseudo_element(&mut self) -> bool {
1535        let first = match self.next() {
1536            Some(c) => c,
1537            // Note that this is the common path that we keep inline: the
1538            // pseudo-element not having anything to its right.
1539            None => return true,
1540        };
1541        self.matches_for_stateless_pseudo_element_internal(first)
1542    }
1543
1544    #[inline(never)]
1545    fn matches_for_stateless_pseudo_element_internal(&mut self, first: &Component<Impl>) -> bool {
1546        if !first.matches_for_stateless_pseudo_element() {
1547            return false;
1548        }
1549        for component in self {
1550            // The only other parser-allowed Components in this sequence are
1551            // state pseudo-classes, or one of the other things that can contain
1552            // them.
1553            if !component.matches_for_stateless_pseudo_element() {
1554                return false;
1555            }
1556        }
1557        true
1558    }
1559
1560    /// Returns remaining count of the simple selectors and combinators in the Selector.
1561    #[inline]
1562    pub fn selector_length(&self) -> usize {
1563        self.iter.len()
1564    }
1565}
1566
1567impl<'a, Impl: SelectorImpl> Iterator for SelectorIter<'a, Impl> {
1568    type Item = &'a Component<Impl>;
1569
1570    #[inline]
1571    fn next(&mut self) -> Option<Self::Item> {
1572        debug_assert!(
1573            self.next_combinator.is_none(),
1574            "You should call next_sequence!"
1575        );
1576        match *self.iter.next()? {
1577            Component::Combinator(c) => {
1578                self.next_combinator = Some(c);
1579                None
1580            },
1581            ref x => Some(x),
1582        }
1583    }
1584}
1585
1586impl<'a, Impl: SelectorImpl> fmt::Debug for SelectorIter<'a, Impl> {
1587    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1588        let iter = self.iter.clone().rev();
1589        for component in iter {
1590            component.to_css(f)?
1591        }
1592        Ok(())
1593    }
1594}
1595
1596/// An iterator over all combinators in a selector. Does not traverse selectors within psuedoclasses.
1597struct CombinatorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
1598impl<'a, Impl: 'a + SelectorImpl> CombinatorIter<'a, Impl> {
1599    fn new(inner: SelectorIter<'a, Impl>) -> Self {
1600        let mut result = CombinatorIter(inner);
1601        result.consume_non_combinators();
1602        result
1603    }
1604
1605    fn consume_non_combinators(&mut self) {
1606        while self.0.next().is_some() {}
1607    }
1608}
1609
1610impl<'a, Impl: SelectorImpl> Iterator for CombinatorIter<'a, Impl> {
1611    type Item = Combinator;
1612    fn next(&mut self) -> Option<Self::Item> {
1613        let result = self.0.next_sequence();
1614        self.consume_non_combinators();
1615        result
1616    }
1617}
1618
1619/// An iterator over all simple selectors belonging to ancestors.
1620struct AncestorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
1621impl<'a, Impl: SelectorImpl> Iterator for AncestorIter<'a, Impl> {
1622    type Item = &'a Component<Impl>;
1623    fn next(&mut self) -> Option<Self::Item> {
1624        // Grab the next simple selector in the sequence if available.
1625        let next = self.0.next();
1626        if next.is_some() {
1627            return next;
1628        }
1629        // See if there are more sequences. If so, skip any non-ancestor sequences.
1630        if !self.0.next_sequence()?.is_ancestor() {
1631            self.0.skip_until_ancestor();
1632        }
1633        self.0.next()
1634    }
1635}
1636
1637#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1638#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1639pub enum Combinator {
1640    Child,        //  >
1641    Descendant,   // space
1642    NextSibling,  // +
1643    LaterSibling, // ~
1644    /// A dummy combinator we use to the left of pseudo-elements.
1645    ///
1646    /// It serializes as the empty string, and acts effectively as a child
1647    /// combinator in most cases.  If we ever actually start using a child
1648    /// combinator for this, we will need to fix up the way hashes are computed
1649    /// for revalidation selectors.
1650    PseudoElement,
1651    /// Another combinator used for ::slotted(), which represent the jump from
1652    /// a node to its assigned slot.
1653    SlotAssignment,
1654    /// Another combinator used for `::part()`, which represents the jump from
1655    /// the part to the containing shadow host.
1656    Part,
1657}
1658
1659impl Combinator {
1660    /// Returns true if this combinator is a pseudo-element combinator.
1661    #[inline]
1662    pub fn is_pseudo_element(&self) -> bool {
1663        matches!(*self, Combinator::PseudoElement)
1664    }
1665
1666    /// Returns true if this combinator is a next- or later-sibling combinator.
1667    #[inline]
1668    pub fn is_sibling(&self) -> bool {
1669        matches!(*self, Combinator::NextSibling | Combinator::LaterSibling)
1670    }
1671
1672    /// Returns true if this combinator represents a jump to an ancestor. Note that this includes
1673    /// combinators like ::part() / ::slotted() and pseudo-elements!
1674    #[inline]
1675    pub fn is_ancestor(&self) -> bool {
1676        !self.is_sibling()
1677    }
1678}
1679
1680/// An enum for the different types of :nth- pseudoclasses
1681#[derive(Copy, Clone, Eq, PartialEq)]
1682#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1683#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1684pub enum NthType {
1685    Child,
1686    LastChild,
1687    OnlyChild,
1688    OfType,
1689    LastOfType,
1690    OnlyOfType,
1691}
1692
1693impl NthType {
1694    pub fn is_only(self) -> bool {
1695        self == Self::OnlyChild || self == Self::OnlyOfType
1696    }
1697
1698    pub fn is_of_type(self) -> bool {
1699        self == Self::OfType || self == Self::LastOfType || self == Self::OnlyOfType
1700    }
1701
1702    pub fn is_from_end(self) -> bool {
1703        self == Self::LastChild || self == Self::LastOfType
1704    }
1705}
1706
1707/// The properties that comprise an An+B syntax
1708#[derive(Copy, Clone, Eq, PartialEq, Debug)]
1709#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1710#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1711pub struct AnPlusB(pub i32, pub i32);
1712
1713impl AnPlusB {
1714    #[inline]
1715    pub fn matches_index(&self, i: i32) -> bool {
1716        // Is there a non-negative integer n such that An+B=i?
1717        match i.checked_sub(self.1) {
1718            None => false,
1719            Some(an) => match an.checked_div(self.0) {
1720                Some(n) => n >= 0 && self.0 * n == an,
1721                None /* a == 0 */ => an == 0,
1722            },
1723        }
1724    }
1725}
1726
1727impl ToCss for AnPlusB {
1728    /// Serialize <an+b> (part of the CSS Syntax spec).
1729    /// <https://drafts.csswg.org/css-syntax-3/#serialize-an-anb-value>
1730    #[inline]
1731    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1732    where
1733        W: fmt::Write,
1734    {
1735        match (self.0, self.1) {
1736            (0, 0) => dest.write_char('0'),
1737
1738            (1, 0) => dest.write_char('n'),
1739            (-1, 0) => dest.write_str("-n"),
1740            (_, 0) => write!(dest, "{}n", self.0),
1741
1742            (0, _) => write!(dest, "{}", self.1),
1743            (1, _) => write!(dest, "n{:+}", self.1),
1744            (-1, _) => write!(dest, "-n{:+}", self.1),
1745            (_, _) => write!(dest, "{}n{:+}", self.0, self.1),
1746        }
1747    }
1748}
1749
1750/// The properties that comprise an :nth- pseudoclass as of Selectors 3 (e.g.,
1751/// nth-child(An+B)).
1752/// https://www.w3.org/TR/selectors-3/#nth-child-pseudo
1753#[derive(Copy, Clone, Eq, PartialEq)]
1754#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1755#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1756pub struct NthSelectorData {
1757    pub ty: NthType,
1758    pub is_function: bool,
1759    pub an_plus_b: AnPlusB,
1760}
1761
1762impl NthSelectorData {
1763    /// Returns selector data for :only-{child,of-type}
1764    #[inline]
1765    pub const fn only(of_type: bool) -> Self {
1766        Self {
1767            ty: if of_type {
1768                NthType::OnlyOfType
1769            } else {
1770                NthType::OnlyChild
1771            },
1772            is_function: false,
1773            an_plus_b: AnPlusB(0, 1),
1774        }
1775    }
1776
1777    /// Returns selector data for :first-{child,of-type}
1778    #[inline]
1779    pub const fn first(of_type: bool) -> Self {
1780        Self {
1781            ty: if of_type {
1782                NthType::OfType
1783            } else {
1784                NthType::Child
1785            },
1786            is_function: false,
1787            an_plus_b: AnPlusB(0, 1),
1788        }
1789    }
1790
1791    /// Returns selector data for :last-{child,of-type}
1792    #[inline]
1793    pub const fn last(of_type: bool) -> Self {
1794        Self {
1795            ty: if of_type {
1796                NthType::LastOfType
1797            } else {
1798                NthType::LastChild
1799            },
1800            is_function: false,
1801            an_plus_b: AnPlusB(0, 1),
1802        }
1803    }
1804
1805    /// Returns true if this is an edge selector that is not `:*-of-type``
1806    #[inline]
1807    pub fn is_simple_edge(&self) -> bool {
1808        self.an_plus_b.0 == 0
1809            && self.an_plus_b.1 == 1
1810            && !self.ty.is_of_type()
1811            && !self.ty.is_only()
1812    }
1813
1814    /// Writes the beginning of the selector.
1815    #[inline]
1816    fn write_start<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
1817        dest.write_str(match self.ty {
1818            NthType::Child if self.is_function => ":nth-child(",
1819            NthType::Child => ":first-child",
1820            NthType::LastChild if self.is_function => ":nth-last-child(",
1821            NthType::LastChild => ":last-child",
1822            NthType::OfType if self.is_function => ":nth-of-type(",
1823            NthType::OfType => ":first-of-type",
1824            NthType::LastOfType if self.is_function => ":nth-last-of-type(",
1825            NthType::LastOfType => ":last-of-type",
1826            NthType::OnlyChild => ":only-child",
1827            NthType::OnlyOfType => ":only-of-type",
1828        })
1829    }
1830
1831    #[inline]
1832    fn write_affine<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
1833        self.an_plus_b.to_css(dest)
1834    }
1835}
1836
1837/// The properties that comprise an :nth- pseudoclass as of Selectors 4 (e.g.,
1838/// nth-child(An+B [of S]?)).
1839/// https://www.w3.org/TR/selectors-4/#nth-child-pseudo
1840#[derive(Clone, Eq, PartialEq)]
1841#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1842#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1843pub struct NthOfSelectorData<Impl: SelectorImpl>(
1844    #[cfg_attr(feature = "to_shmem", shmem(field_bound))] ThinArc<NthSelectorData, Selector<Impl>>,
1845);
1846
1847impl<Impl: SelectorImpl> NthOfSelectorData<Impl> {
1848    /// Returns selector data for :nth-{,last-}{child,of-type}(An+B [of S])
1849    #[inline]
1850    pub fn new<I>(nth_data: &NthSelectorData, selectors: I) -> Self
1851    where
1852        I: Iterator<Item = Selector<Impl>> + ExactSizeIterator,
1853    {
1854        Self(ThinArc::from_header_and_iter(*nth_data, selectors))
1855    }
1856
1857    /// Returns the An+B part of the selector
1858    #[inline]
1859    pub fn nth_data(&self) -> &NthSelectorData {
1860        &self.0.header
1861    }
1862
1863    /// Returns the selector list part of the selector
1864    #[inline]
1865    pub fn selectors(&self) -> &[Selector<Impl>] {
1866        self.0.slice()
1867    }
1868}
1869
1870/// Flag indicating where a given relative selector's match would be contained.
1871#[derive(Clone, Copy, Eq, PartialEq)]
1872#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1873pub enum RelativeSelectorMatchHint {
1874    /// Within this element's subtree.
1875    InSubtree,
1876    /// Within this element's direct children.
1877    InChild,
1878    /// This element's next sibling.
1879    InNextSibling,
1880    /// Within this element's next sibling's subtree.
1881    InNextSiblingSubtree,
1882    /// Within this element's subsequent siblings.
1883    InSibling,
1884    /// Across this element's subsequent siblings and their subtrees.
1885    InSiblingSubtree,
1886}
1887
1888impl RelativeSelectorMatchHint {
1889    /// Create a new relative selector match hint based on its composition.
1890    pub fn new(
1891        relative_combinator: Combinator,
1892        has_child_or_descendants: bool,
1893        has_adjacent_or_next_siblings: bool,
1894    ) -> Self {
1895        match relative_combinator {
1896            Combinator::Descendant => RelativeSelectorMatchHint::InSubtree,
1897            Combinator::Child => {
1898                if !has_child_or_descendants {
1899                    RelativeSelectorMatchHint::InChild
1900                } else {
1901                    // Technically, for any composition that consists of child combinators only,
1902                    // the search space is depth-constrained, but it's probably not worth optimizing for.
1903                    RelativeSelectorMatchHint::InSubtree
1904                }
1905            },
1906            Combinator::NextSibling => {
1907                if !has_child_or_descendants && !has_adjacent_or_next_siblings {
1908                    RelativeSelectorMatchHint::InNextSibling
1909                } else if !has_child_or_descendants && has_adjacent_or_next_siblings {
1910                    RelativeSelectorMatchHint::InSibling
1911                } else if has_child_or_descendants && !has_adjacent_or_next_siblings {
1912                    // Match won't cross multiple siblings.
1913                    RelativeSelectorMatchHint::InNextSiblingSubtree
1914                } else {
1915                    RelativeSelectorMatchHint::InSiblingSubtree
1916                }
1917            },
1918            Combinator::LaterSibling => {
1919                if !has_child_or_descendants {
1920                    RelativeSelectorMatchHint::InSibling
1921                } else {
1922                    // Even if the match may not cross multiple siblings, we have to look until
1923                    // we find a match anyway.
1924                    RelativeSelectorMatchHint::InSiblingSubtree
1925                }
1926            },
1927            Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
1928                debug_assert!(false, "Unexpected relative combinator");
1929                RelativeSelectorMatchHint::InSubtree
1930            },
1931        }
1932    }
1933
1934    /// Is the match traversal direction towards the descendant of this element (As opposed to siblings)?
1935    pub fn is_descendant_direction(&self) -> bool {
1936        matches!(*self, Self::InChild | Self::InSubtree)
1937    }
1938
1939    /// Is the match traversal terminated at the next sibling?
1940    pub fn is_next_sibling(&self) -> bool {
1941        matches!(*self, Self::InNextSibling | Self::InNextSiblingSubtree)
1942    }
1943
1944    /// Does the match involve matching the subtree?
1945    pub fn is_subtree(&self) -> bool {
1946        matches!(
1947            *self,
1948            Self::InSubtree | Self::InSiblingSubtree | Self::InNextSiblingSubtree
1949        )
1950    }
1951}
1952
1953/// Count of combinators in a given relative selector, not traversing selectors of pseudoclasses.
1954#[derive(Clone, Copy)]
1955pub struct RelativeSelectorCombinatorCount {
1956    relative_combinator: Combinator,
1957    pub child_or_descendants: usize,
1958    pub adjacent_or_next_siblings: usize,
1959}
1960
1961impl RelativeSelectorCombinatorCount {
1962    /// Create a new relative selector combinator count from a given relative selector.
1963    pub fn new<Impl: SelectorImpl>(relative_selector: &RelativeSelector<Impl>) -> Self {
1964        let mut result = RelativeSelectorCombinatorCount {
1965            relative_combinator: relative_selector.selector.combinator_at_parse_order(1),
1966            child_or_descendants: 0,
1967            adjacent_or_next_siblings: 0,
1968        };
1969
1970        for combinator in CombinatorIter::new(
1971            relative_selector
1972                .selector
1973                .iter_skip_relative_selector_anchor(),
1974        ) {
1975            match combinator {
1976                Combinator::Descendant | Combinator::Child => {
1977                    result.child_or_descendants += 1;
1978                },
1979                Combinator::NextSibling | Combinator::LaterSibling => {
1980                    result.adjacent_or_next_siblings += 1;
1981                },
1982                Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
1983                    continue;
1984                },
1985            };
1986        }
1987        result
1988    }
1989
1990    /// Get the match hint based on the current combinator count.
1991    pub fn get_match_hint(&self) -> RelativeSelectorMatchHint {
1992        RelativeSelectorMatchHint::new(
1993            self.relative_combinator,
1994            self.child_or_descendants != 0,
1995            self.adjacent_or_next_siblings != 0,
1996        )
1997    }
1998}
1999
2000/// Storage for a relative selector.
2001#[derive(Clone, Eq, PartialEq)]
2002#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
2003#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
2004pub struct RelativeSelector<Impl: SelectorImpl> {
2005    /// Match space constraining hint.
2006    pub match_hint: RelativeSelectorMatchHint,
2007    /// The selector. Guaranteed to contain `RelativeSelectorAnchor` and the relative combinator in parse order.
2008    #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2009    pub selector: Selector<Impl>,
2010}
2011
2012bitflags! {
2013    /// Composition of combinators in a given selector, not traversing selectors of pseudoclasses.
2014    #[derive(Clone, Debug, Eq, PartialEq)]
2015    struct CombinatorComposition: u8 {
2016        const DESCENDANTS = 1 << 0;
2017        const SIBLINGS = 1 << 1;
2018    }
2019}
2020
2021impl CombinatorComposition {
2022    fn for_relative_selector<Impl: SelectorImpl>(inner_selector: &Selector<Impl>) -> Self {
2023        let mut result = CombinatorComposition::empty();
2024        for combinator in CombinatorIter::new(inner_selector.iter_skip_relative_selector_anchor()) {
2025            match combinator {
2026                Combinator::Descendant | Combinator::Child => {
2027                    result.insert(Self::DESCENDANTS);
2028                },
2029                Combinator::NextSibling | Combinator::LaterSibling => {
2030                    result.insert(Self::SIBLINGS);
2031                },
2032                Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
2033                    continue;
2034                },
2035            };
2036            if result.is_all() {
2037                break;
2038            }
2039        }
2040        return result;
2041    }
2042}
2043
2044impl<Impl: SelectorImpl> RelativeSelector<Impl> {
2045    fn from_selector_list(selector_list: SelectorList<Impl>) -> Box<[Self]> {
2046        selector_list
2047            .slice()
2048            .iter()
2049            .map(|selector| {
2050                // It's more efficient to keep track of all this during the parse time, but that seems like a lot of special
2051                // case handling for what it's worth.
2052                if cfg!(debug_assertions) {
2053                    let relative_selector_anchor = selector.iter_raw_parse_order_from(0).next();
2054                    debug_assert!(
2055                        relative_selector_anchor.is_some(),
2056                        "Relative selector is empty"
2057                    );
2058                    debug_assert!(
2059                        matches!(
2060                            relative_selector_anchor.unwrap(),
2061                            Component::RelativeSelectorAnchor
2062                        ),
2063                        "Relative selector anchor is missing"
2064                    );
2065                }
2066                // Leave a hint for narrowing down the search space when we're matching.
2067                let composition = CombinatorComposition::for_relative_selector(&selector);
2068                let match_hint = RelativeSelectorMatchHint::new(
2069                    selector.combinator_at_parse_order(1),
2070                    composition.intersects(CombinatorComposition::DESCENDANTS),
2071                    composition.intersects(CombinatorComposition::SIBLINGS),
2072                );
2073                RelativeSelector {
2074                    match_hint,
2075                    selector: selector.clone(),
2076                }
2077            })
2078            .collect()
2079    }
2080}
2081
2082/// A CSS simple selector or combinator. We store both in the same enum for
2083/// optimal packing and cache performance, see [1].
2084///
2085/// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973
2086#[derive(Clone, Eq, PartialEq)]
2087#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
2088#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
2089pub enum Component<Impl: SelectorImpl> {
2090    LocalName(LocalName<Impl>),
2091
2092    ID(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::Identifier),
2093    Class(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::Identifier),
2094
2095    AttributeInNoNamespaceExists {
2096        #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2097        local_name: Impl::LocalName,
2098        local_name_lower: Impl::LocalName,
2099    },
2100    // Used only when local_name is already lowercase.
2101    AttributeInNoNamespace {
2102        local_name: Impl::LocalName,
2103        operator: AttrSelectorOperator,
2104        #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2105        value: Impl::AttrValue,
2106        case_sensitivity: ParsedCaseSensitivity,
2107    },
2108    // Use a Box in the less common cases with more data to keep size_of::<Component>() small.
2109    AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>),
2110
2111    ExplicitUniversalType,
2112    ExplicitAnyNamespace,
2113
2114    ExplicitNoNamespace,
2115    DefaultNamespace(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NamespaceUrl),
2116    Namespace(
2117        #[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NamespacePrefix,
2118        #[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NamespaceUrl,
2119    ),
2120
2121    /// Pseudo-classes
2122    Negation(SelectorList<Impl>),
2123    Root,
2124    Empty,
2125    Scope,
2126    /// :scope added implicitly into scoped rules (i.e. In `@scope`) not
2127    /// explicitly using `:scope` or `&` selectors.
2128    ///
2129    /// https://drafts.csswg.org/css-cascade-6/#scoped-rules
2130    ///
2131    /// Unlike the normal `:scope` selector, this does not add any specificity.
2132    /// See https://github.com/w3c/csswg-drafts/issues/10196
2133    ImplicitScope,
2134    ParentSelector,
2135    Nth(NthSelectorData),
2136    NthOf(NthOfSelectorData<Impl>),
2137    NonTSPseudoClass(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NonTSPseudoClass),
2138    /// The ::slotted() pseudo-element:
2139    ///
2140    /// https://drafts.csswg.org/css-scoping/#slotted-pseudo
2141    ///
2142    /// The selector here is a compound selector, that is, no combinators.
2143    ///
2144    /// NOTE(emilio): This should support a list of selectors, but as of this
2145    /// writing no other browser does, and that allows them to put ::slotted()
2146    /// in the rule hash, so we do that too.
2147    ///
2148    /// See https://github.com/w3c/csswg-drafts/issues/2158
2149    Slotted(Selector<Impl>),
2150    /// The `::part` pseudo-element.
2151    ///   https://drafts.csswg.org/css-shadow-parts/#part
2152    Part(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Box<[Impl::Identifier]>),
2153    /// The `:host` pseudo-class:
2154    ///
2155    /// https://drafts.csswg.org/css-scoping/#host-selector
2156    ///
2157    /// NOTE(emilio): This should support a list of selectors, but as of this
2158    /// writing no other browser does, and that allows them to put :host()
2159    /// in the rule hash, so we do that too.
2160    ///
2161    /// See https://github.com/w3c/csswg-drafts/issues/2158
2162    Host(Option<Selector<Impl>>),
2163    /// The `:where` pseudo-class.
2164    ///
2165    /// https://drafts.csswg.org/selectors/#zero-matches
2166    ///
2167    /// The inner argument is conceptually a SelectorList, but we move the
2168    /// selectors to the heap to keep Component small.
2169    Where(SelectorList<Impl>),
2170    /// The `:is` pseudo-class.
2171    ///
2172    /// https://drafts.csswg.org/selectors/#matches-pseudo
2173    ///
2174    /// Same comment as above re. the argument.
2175    Is(SelectorList<Impl>),
2176    /// The `:has` pseudo-class.
2177    ///
2178    /// https://drafts.csswg.org/selectors/#has-pseudo
2179    ///
2180    /// Same comment as above re. the argument.
2181    Has(Box<[RelativeSelector<Impl>]>),
2182    /// An invalid selector inside :is() / :where().
2183    Invalid(Arc<String>),
2184    /// An implementation-dependent pseudo-element selector.
2185    PseudoElement(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::PseudoElement),
2186
2187    Combinator(Combinator),
2188
2189    /// Used only for relative selectors, which starts with a combinator
2190    /// (With an implied descendant combinator if not specified).
2191    ///
2192    /// https://drafts.csswg.org/selectors-4/#typedef-relative-selector
2193    RelativeSelectorAnchor,
2194}
2195
2196impl<Impl: SelectorImpl> Component<Impl> {
2197    /// Returns true if this is a combinator.
2198    #[inline]
2199    pub fn is_combinator(&self) -> bool {
2200        matches!(*self, Component::Combinator(_))
2201    }
2202
2203    /// Returns true if this is a :host() selector.
2204    #[inline]
2205    pub fn is_host(&self) -> bool {
2206        matches!(*self, Component::Host(..))
2207    }
2208
2209    /// Returns the value as a combinator if applicable, None otherwise.
2210    pub fn as_combinator(&self) -> Option<Combinator> {
2211        match *self {
2212            Component::Combinator(c) => Some(c),
2213            _ => None,
2214        }
2215    }
2216
2217    /// Whether a given selector (to the right of a pseudo-element) should match for stateless
2218    /// pseudo-elements. Note that generally nothing matches for those, but since we have :not(),
2219    /// we still need to traverse nested selector lists.
2220    fn matches_for_stateless_pseudo_element(&self) -> bool {
2221        match *self {
2222            Component::Negation(ref selectors) => !selectors.slice().iter().all(|selector| {
2223                selector
2224                    .iter_raw_match_order()
2225                    .all(|c| c.matches_for_stateless_pseudo_element())
2226            }),
2227            Component::Is(ref selectors) | Component::Where(ref selectors) => {
2228                selectors.slice().iter().any(|selector| {
2229                    selector
2230                        .iter_raw_match_order()
2231                        .all(|c| c.matches_for_stateless_pseudo_element())
2232                })
2233            },
2234            _ => false,
2235        }
2236    }
2237
2238    pub fn visit<V>(&self, visitor: &mut V) -> bool
2239    where
2240        V: SelectorVisitor<Impl = Impl>,
2241    {
2242        use self::Component::*;
2243        if !visitor.visit_simple_selector(self) {
2244            return false;
2245        }
2246
2247        match *self {
2248            Slotted(ref selector) => {
2249                if !selector.visit(visitor) {
2250                    return false;
2251                }
2252            },
2253            Host(Some(ref selector)) => {
2254                if !selector.visit(visitor) {
2255                    return false;
2256                }
2257            },
2258            AttributeInNoNamespaceExists {
2259                ref local_name,
2260                ref local_name_lower,
2261            } => {
2262                if !visitor.visit_attribute_selector(
2263                    &NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
2264                    local_name,
2265                    local_name_lower,
2266                ) {
2267                    return false;
2268                }
2269            },
2270            AttributeInNoNamespace { ref local_name, .. } => {
2271                if !visitor.visit_attribute_selector(
2272                    &NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
2273                    local_name,
2274                    local_name,
2275                ) {
2276                    return false;
2277                }
2278            },
2279            AttributeOther(ref attr_selector) => {
2280                let empty_string;
2281                let namespace = match attr_selector.namespace() {
2282                    Some(ns) => ns,
2283                    None => {
2284                        empty_string = crate::parser::namespace_empty_string::<Impl>();
2285                        NamespaceConstraint::Specific(&empty_string)
2286                    },
2287                };
2288                if !visitor.visit_attribute_selector(
2289                    &namespace,
2290                    &attr_selector.local_name,
2291                    &attr_selector.local_name_lower,
2292                ) {
2293                    return false;
2294                }
2295            },
2296
2297            NonTSPseudoClass(ref pseudo_class) => {
2298                if !pseudo_class.visit(visitor) {
2299                    return false;
2300                }
2301            },
2302            Negation(ref list) | Is(ref list) | Where(ref list) => {
2303                let list_kind = SelectorListKind::from_component(self);
2304                debug_assert!(!list_kind.is_empty());
2305                if !visitor.visit_selector_list(list_kind, list.slice()) {
2306                    return false;
2307                }
2308            },
2309            NthOf(ref nth_of_data) => {
2310                if !visitor.visit_selector_list(SelectorListKind::NTH_OF, nth_of_data.selectors()) {
2311                    return false;
2312                }
2313            },
2314            Has(ref list) => {
2315                if !visitor.visit_relative_selector_list(list) {
2316                    return false;
2317                }
2318            },
2319            _ => {},
2320        }
2321
2322        true
2323    }
2324
2325    // Returns true if this has any selector that requires an index calculation. e.g.
2326    // :nth-child, :first-child, etc. For nested selectors, return true only if the
2327    // indexed selector is in its subject compound.
2328    pub fn has_indexed_selector_in_subject(&self) -> bool {
2329        match *self {
2330            Component::NthOf(..) | Component::Nth(..) => return true,
2331            Component::Is(ref selectors)
2332            | Component::Where(ref selectors)
2333            | Component::Negation(ref selectors) => {
2334                // Check the subject compound.
2335                for selector in selectors.slice() {
2336                    let mut iter = selector.iter();
2337                    while let Some(c) = iter.next() {
2338                        if c.has_indexed_selector_in_subject() {
2339                            return true;
2340                        }
2341                    }
2342                }
2343            },
2344            _ => (),
2345        };
2346        false
2347    }
2348}
2349
2350#[derive(Clone, Eq, PartialEq)]
2351#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
2352#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
2353pub struct LocalName<Impl: SelectorImpl> {
2354    #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2355    pub name: Impl::LocalName,
2356    pub lower_name: Impl::LocalName,
2357}
2358
2359impl<Impl: SelectorImpl> Debug for Selector<Impl> {
2360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2361        f.write_str("Selector(")?;
2362        self.to_css(f)?;
2363        write!(
2364            f,
2365            ", specificity = {:#x}, flags = {:?})",
2366            self.specificity(),
2367            self.flags()
2368        )
2369    }
2370}
2371
2372impl<Impl: SelectorImpl> Debug for Component<Impl> {
2373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2374        self.to_css(f)
2375    }
2376}
2377impl<Impl: SelectorImpl> Debug for AttrSelectorWithOptionalNamespace<Impl> {
2378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2379        self.to_css(f)
2380    }
2381}
2382impl<Impl: SelectorImpl> Debug for LocalName<Impl> {
2383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2384        self.to_css(f)
2385    }
2386}
2387
2388fn serialize_selector_list<'a, Impl, I, W>(iter: I, dest: &mut W) -> fmt::Result
2389where
2390    Impl: SelectorImpl,
2391    I: Iterator<Item = &'a Selector<Impl>>,
2392    W: fmt::Write,
2393{
2394    let mut first = true;
2395    for selector in iter {
2396        if !first {
2397            dest.write_str(", ")?;
2398        }
2399        first = false;
2400        selector.to_css(dest)?;
2401    }
2402    Ok(())
2403}
2404
2405impl<Impl: SelectorImpl> ToCss for SelectorList<Impl> {
2406    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2407    where
2408        W: fmt::Write,
2409    {
2410        serialize_selector_list(self.slice().iter(), dest)
2411    }
2412}
2413
2414impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
2415    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2416    where
2417        W: fmt::Write,
2418    {
2419        // Compound selectors invert the order of their contents, so we need to
2420        // undo that during serialization.
2421        //
2422        // This two-iterator strategy involves walking over the selector twice.
2423        // We could do something more clever, but selector serialization probably
2424        // isn't hot enough to justify it, and the stringification likely
2425        // dominates anyway.
2426        //
2427        // NB: A parse-order iterator is a Rev<>, which doesn't expose as_slice(),
2428        // which we need for |split|. So we split by combinators on a match-order
2429        // sequence and then reverse.
2430
2431        let mut combinators = self
2432            .iter_raw_match_order()
2433            .rev()
2434            .filter_map(|x| x.as_combinator());
2435        let compound_selectors = self
2436            .iter_raw_match_order()
2437            .as_slice()
2438            .split(|x| x.is_combinator())
2439            .rev();
2440
2441        let mut combinators_exhausted = false;
2442        for compound in compound_selectors {
2443            debug_assert!(!combinators_exhausted);
2444
2445            // https://drafts.csswg.org/cssom/#serializing-selectors
2446            let first_compound = match compound.first() {
2447                None => continue,
2448                Some(c) => c,
2449            };
2450            if matches!(
2451                first_compound,
2452                Component::RelativeSelectorAnchor | Component::ImplicitScope
2453            ) {
2454                debug_assert!(
2455                    compound.len() == 1,
2456                    "RelativeSelectorAnchor/ImplicitScope should only be a simple selector"
2457                );
2458                if let Some(c) = combinators.next() {
2459                    c.to_css_relative(dest)?;
2460                } else {
2461                    // Direct property declarations in `@scope` does not have
2462                    // combinators, since its selector is `:implicit-scope`.
2463                    debug_assert!(
2464                        matches!(first_compound, Component::ImplicitScope),
2465                        "Only implicit :scope may not have any combinator"
2466                    );
2467                }
2468                continue;
2469            }
2470
2471            // 1. If there is only one simple selector in the compound selectors
2472            //    which is a universal selector, append the result of
2473            //    serializing the universal selector to s.
2474            //
2475            // Check if `!compound.empty()` first--this can happen if we have
2476            // something like `... > ::before`, because we store `>` and `::`
2477            // both as combinators internally.
2478            //
2479            // If we are in this case, after we have serialized the universal
2480            // selector, we skip Step 2 and continue with the algorithm.
2481            let (can_elide_namespace, first_non_namespace) = match compound[0] {
2482                Component::ExplicitAnyNamespace
2483                | Component::ExplicitNoNamespace
2484                | Component::Namespace(..) => (false, 1),
2485                Component::DefaultNamespace(..) => (true, 1),
2486                _ => (true, 0),
2487            };
2488            let mut perform_step_2 = true;
2489            let next_combinator = combinators.next();
2490            if first_non_namespace == compound.len() - 1 {
2491                match (next_combinator, &compound[first_non_namespace]) {
2492                    // We have to be careful here, because if there is a
2493                    // pseudo element "combinator" there isn't really just
2494                    // the one simple selector. Technically this compound
2495                    // selector contains the pseudo element selector as well
2496                    // -- Combinator::PseudoElement, just like
2497                    // Combinator::SlotAssignment, don't exist in the
2498                    // spec.
2499                    (Some(Combinator::PseudoElement), _)
2500                    | (Some(Combinator::SlotAssignment), _) => (),
2501                    (_, &Component::ExplicitUniversalType) => {
2502                        // Iterate over everything so we serialize the namespace
2503                        // too.
2504                        for simple in compound.iter() {
2505                            simple.to_css(dest)?;
2506                        }
2507                        // Skip step 2, which is an "otherwise".
2508                        perform_step_2 = false;
2509                    },
2510                    _ => (),
2511                }
2512            }
2513
2514            // 2. Otherwise, for each simple selector in the compound selectors
2515            //    that is not a universal selector of which the namespace prefix
2516            //    maps to a namespace that is not the default namespace
2517            //    serialize the simple selector and append the result to s.
2518            //
2519            // See https://github.com/w3c/csswg-drafts/issues/1606, which is
2520            // proposing to change this to match up with the behavior asserted
2521            // in cssom/serialize-namespaced-type-selectors.html, which the
2522            // following code tries to match.
2523            if perform_step_2 {
2524                for simple in compound.iter() {
2525                    if let Component::ExplicitUniversalType = *simple {
2526                        // Can't have a namespace followed by a pseudo-element
2527                        // selector followed by a universal selector in the same
2528                        // compound selector, so we don't have to worry about the
2529                        // real namespace being in a different `compound`.
2530                        if can_elide_namespace {
2531                            continue;
2532                        }
2533                    }
2534                    simple.to_css(dest)?;
2535                }
2536            }
2537
2538            // 3. If this is not the last part of the chain of the selector
2539            //    append a single SPACE (U+0020), followed by the combinator
2540            //    ">", "+", "~", ">>", "||", as appropriate, followed by another
2541            //    single SPACE (U+0020) if the combinator was not whitespace, to
2542            //    s.
2543            match next_combinator {
2544                Some(c) => c.to_css(dest)?,
2545                None => combinators_exhausted = true,
2546            };
2547
2548            // 4. If this is the last part of the chain of the selector and
2549            //    there is a pseudo-element, append "::" followed by the name of
2550            //    the pseudo-element, to s.
2551            //
2552            // (we handle this above)
2553        }
2554
2555        Ok(())
2556    }
2557}
2558
2559impl Combinator {
2560    fn to_css_internal<W>(&self, dest: &mut W, prefix_space: bool) -> fmt::Result
2561    where
2562        W: fmt::Write,
2563    {
2564        if matches!(
2565            *self,
2566            Combinator::PseudoElement | Combinator::Part | Combinator::SlotAssignment
2567        ) {
2568            return Ok(());
2569        }
2570        if prefix_space {
2571            dest.write_char(' ')?;
2572        }
2573        match *self {
2574            Combinator::Child => dest.write_str("> "),
2575            Combinator::Descendant => Ok(()),
2576            Combinator::NextSibling => dest.write_str("+ "),
2577            Combinator::LaterSibling => dest.write_str("~ "),
2578            Combinator::PseudoElement | Combinator::Part | Combinator::SlotAssignment => unsafe {
2579                debug_unreachable!("Already handled")
2580            },
2581        }
2582    }
2583
2584    fn to_css_relative<W>(&self, dest: &mut W) -> fmt::Result
2585    where
2586        W: fmt::Write,
2587    {
2588        self.to_css_internal(dest, false)
2589    }
2590}
2591
2592impl ToCss for Combinator {
2593    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2594    where
2595        W: fmt::Write,
2596    {
2597        self.to_css_internal(dest, true)
2598    }
2599}
2600
2601impl<Impl: SelectorImpl> ToCss for Component<Impl> {
2602    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2603    where
2604        W: fmt::Write,
2605    {
2606        use self::Component::*;
2607
2608        match *self {
2609            Combinator(ref c) => c.to_css(dest),
2610            Slotted(ref selector) => {
2611                dest.write_str("::slotted(")?;
2612                selector.to_css(dest)?;
2613                dest.write_char(')')
2614            },
2615            Part(ref part_names) => {
2616                dest.write_str("::part(")?;
2617                for (i, name) in part_names.iter().enumerate() {
2618                    if i != 0 {
2619                        dest.write_char(' ')?;
2620                    }
2621                    name.to_css(dest)?;
2622                }
2623                dest.write_char(')')
2624            },
2625            PseudoElement(ref p) => p.to_css(dest),
2626            ID(ref s) => {
2627                dest.write_char('#')?;
2628                s.to_css(dest)
2629            },
2630            Class(ref s) => {
2631                dest.write_char('.')?;
2632                s.to_css(dest)
2633            },
2634            LocalName(ref s) => s.to_css(dest),
2635            ExplicitUniversalType => dest.write_char('*'),
2636
2637            DefaultNamespace(_) => Ok(()),
2638            ExplicitNoNamespace => dest.write_char('|'),
2639            ExplicitAnyNamespace => dest.write_str("*|"),
2640            Namespace(ref prefix, _) => {
2641                prefix.to_css(dest)?;
2642                dest.write_char('|')
2643            },
2644
2645            AttributeInNoNamespaceExists { ref local_name, .. } => {
2646                dest.write_char('[')?;
2647                local_name.to_css(dest)?;
2648                dest.write_char(']')
2649            },
2650            AttributeInNoNamespace {
2651                ref local_name,
2652                operator,
2653                ref value,
2654                case_sensitivity,
2655                ..
2656            } => {
2657                dest.write_char('[')?;
2658                local_name.to_css(dest)?;
2659                operator.to_css(dest)?;
2660                value.to_css(dest)?;
2661                match case_sensitivity {
2662                    ParsedCaseSensitivity::CaseSensitive
2663                    | ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
2664                    },
2665                    ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
2666                    ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
2667                }
2668                dest.write_char(']')
2669            },
2670            AttributeOther(ref attr_selector) => attr_selector.to_css(dest),
2671
2672            // Pseudo-classes
2673            Root => dest.write_str(":root"),
2674            Empty => dest.write_str(":empty"),
2675            Scope => dest.write_str(":scope"),
2676            ParentSelector => dest.write_char('&'),
2677            Host(ref selector) => {
2678                dest.write_str(":host")?;
2679                if let Some(ref selector) = *selector {
2680                    dest.write_char('(')?;
2681                    selector.to_css(dest)?;
2682                    dest.write_char(')')?;
2683                }
2684                Ok(())
2685            },
2686            Nth(ref nth_data) => {
2687                nth_data.write_start(dest)?;
2688                if nth_data.is_function {
2689                    nth_data.write_affine(dest)?;
2690                    dest.write_char(')')?;
2691                }
2692                Ok(())
2693            },
2694            NthOf(ref nth_of_data) => {
2695                let nth_data = nth_of_data.nth_data();
2696                nth_data.write_start(dest)?;
2697                debug_assert!(
2698                    nth_data.is_function,
2699                    "A selector must be a function to hold An+B notation"
2700                );
2701                nth_data.write_affine(dest)?;
2702                debug_assert!(
2703                    matches!(nth_data.ty, NthType::Child | NthType::LastChild),
2704                    "Only :nth-child or :nth-last-child can be of a selector list"
2705                );
2706                debug_assert!(
2707                    !nth_of_data.selectors().is_empty(),
2708                    "The selector list should not be empty"
2709                );
2710                dest.write_str(" of ")?;
2711                serialize_selector_list(nth_of_data.selectors().iter(), dest)?;
2712                dest.write_char(')')
2713            },
2714            Is(ref list) | Where(ref list) | Negation(ref list) => {
2715                match *self {
2716                    Where(..) => dest.write_str(":where(")?,
2717                    Is(..) => dest.write_str(":is(")?,
2718                    Negation(..) => dest.write_str(":not(")?,
2719                    _ => unreachable!(),
2720                }
2721                serialize_selector_list(list.slice().iter(), dest)?;
2722                dest.write_str(")")
2723            },
2724            Has(ref list) => {
2725                dest.write_str(":has(")?;
2726                serialize_selector_list(list.iter().map(|rel| &rel.selector), dest)?;
2727                dest.write_str(")")
2728            },
2729            NonTSPseudoClass(ref pseudo) => pseudo.to_css(dest),
2730            Invalid(ref css) => dest.write_str(css),
2731            RelativeSelectorAnchor | ImplicitScope => Ok(()),
2732        }
2733    }
2734}
2735
2736impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> {
2737    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2738    where
2739        W: fmt::Write,
2740    {
2741        dest.write_char('[')?;
2742        match self.namespace {
2743            Some(NamespaceConstraint::Specific((ref prefix, _))) => {
2744                prefix.to_css(dest)?;
2745                dest.write_char('|')?
2746            },
2747            Some(NamespaceConstraint::Any) => dest.write_str("*|")?,
2748            None => {},
2749        }
2750        self.local_name.to_css(dest)?;
2751        match self.operation {
2752            ParsedAttrSelectorOperation::Exists => {},
2753            ParsedAttrSelectorOperation::WithValue {
2754                operator,
2755                case_sensitivity,
2756                ref value,
2757            } => {
2758                operator.to_css(dest)?;
2759                value.to_css(dest)?;
2760                match case_sensitivity {
2761                    ParsedCaseSensitivity::CaseSensitive
2762                    | ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
2763                    },
2764                    ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
2765                    ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
2766                }
2767            },
2768        }
2769        dest.write_char(']')
2770    }
2771}
2772
2773impl<Impl: SelectorImpl> ToCss for LocalName<Impl> {
2774    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2775    where
2776        W: fmt::Write,
2777    {
2778        self.name.to_css(dest)
2779    }
2780}
2781
2782/// Build up a Selector.
2783/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
2784///
2785/// `Err` means invalid selector.
2786fn parse_selector<'i, 't, P, Impl>(
2787    parser: &P,
2788    input: &mut CssParser<'i, 't>,
2789    mut state: SelectorParsingState,
2790    parse_relative: ParseRelative,
2791) -> Result<Selector<Impl>, ParseError<'i, P::Error>>
2792where
2793    P: Parser<'i, Impl = Impl>,
2794    Impl: SelectorImpl,
2795{
2796    let mut builder = SelectorBuilder::default();
2797
2798    // Helps rewind less, but also simplifies dealing with relative combinators below.
2799    input.skip_whitespace();
2800
2801    if parse_relative != ParseRelative::No {
2802        let combinator = try_parse_combinator(input);
2803        match parse_relative {
2804            ParseRelative::ForHas => {
2805                builder.push_simple_selector(Component::RelativeSelectorAnchor);
2806                // Do we see a combinator? If so, push that. Otherwise, push a descendant
2807                // combinator.
2808                builder.push_combinator(combinator.unwrap_or(Combinator::Descendant));
2809            },
2810            ParseRelative::ForNesting | ParseRelative::ForScope => {
2811                if let Ok(combinator) = combinator {
2812                    let selector = match parse_relative {
2813                        ParseRelative::ForHas | ParseRelative::No => unreachable!(),
2814                        ParseRelative::ForNesting => Component::ParentSelector,
2815                        // See https://github.com/w3c/csswg-drafts/issues/10196
2816                        // Implicitly added `:scope` does not add specificity
2817                        // for non-relative selectors, so do the same.
2818                        ParseRelative::ForScope => Component::ImplicitScope,
2819                    };
2820                    builder.push_simple_selector(selector);
2821                    builder.push_combinator(combinator);
2822                }
2823            },
2824            ParseRelative::No => unreachable!(),
2825        }
2826    }
2827    loop {
2828        // Parse a sequence of simple selectors.
2829        let empty = parse_compound_selector(parser, &mut state, input, &mut builder)?;
2830        if empty {
2831            return Err(input.new_custom_error(if builder.has_combinators() {
2832                SelectorParseErrorKind::DanglingCombinator
2833            } else {
2834                SelectorParseErrorKind::EmptySelector
2835            }));
2836        }
2837
2838        if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2839            debug_assert!(state.intersects(
2840                SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO
2841                    | SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO
2842                    | SelectorParsingState::AFTER_SLOTTED
2843                    | SelectorParsingState::AFTER_PART_LIKE
2844            ));
2845            break;
2846        }
2847
2848        let combinator = if let Ok(c) = try_parse_combinator(input) {
2849            c
2850        } else {
2851            break;
2852        };
2853
2854        if !state.allows_combinators() {
2855            return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
2856        }
2857
2858        builder.push_combinator(combinator);
2859    }
2860    return Ok(Selector(builder.build(parse_relative)));
2861}
2862
2863fn try_parse_combinator<'i, 't>(input: &mut CssParser<'i, 't>) -> Result<Combinator, ()> {
2864    let mut any_whitespace = false;
2865    loop {
2866        let before_this_token = input.state();
2867        match input.next_including_whitespace() {
2868            Err(_e) => return Err(()),
2869            Ok(&Token::WhiteSpace(_)) => any_whitespace = true,
2870            Ok(&Token::Delim('>')) => {
2871                return Ok(Combinator::Child);
2872            },
2873            Ok(&Token::Delim('+')) => {
2874                return Ok(Combinator::NextSibling);
2875            },
2876            Ok(&Token::Delim('~')) => {
2877                return Ok(Combinator::LaterSibling);
2878            },
2879            Ok(_) => {
2880                input.reset(&before_this_token);
2881                if any_whitespace {
2882                    return Ok(Combinator::Descendant);
2883                } else {
2884                    return Err(());
2885                }
2886            },
2887        }
2888    }
2889}
2890
2891/// * `Err(())`: Invalid selector, abort
2892/// * `Ok(false)`: Not a type selector, could be something else. `input` was not consumed.
2893/// * `Ok(true)`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
2894fn parse_type_selector<'i, 't, P, Impl, S>(
2895    parser: &P,
2896    input: &mut CssParser<'i, 't>,
2897    state: SelectorParsingState,
2898    sink: &mut S,
2899) -> Result<bool, ParseError<'i, P::Error>>
2900where
2901    P: Parser<'i, Impl = Impl>,
2902    Impl: SelectorImpl,
2903    S: Push<Component<Impl>>,
2904{
2905    match parse_qualified_name(parser, input, /* in_attr_selector = */ false) {
2906        Err(ParseError {
2907            kind: ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput),
2908            ..
2909        })
2910        | Ok(OptionalQName::None(_)) => Ok(false),
2911        Ok(OptionalQName::Some(namespace, local_name)) => {
2912            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2913                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
2914            }
2915            match namespace {
2916                QNamePrefix::ImplicitAnyNamespace => {},
2917                QNamePrefix::ImplicitDefaultNamespace(url) => {
2918                    sink.push(Component::DefaultNamespace(url))
2919                },
2920                QNamePrefix::ExplicitNamespace(prefix, url) => {
2921                    sink.push(match parser.default_namespace() {
2922                        Some(ref default_url) if url == *default_url => {
2923                            Component::DefaultNamespace(url)
2924                        },
2925                        _ => Component::Namespace(prefix, url),
2926                    })
2927                },
2928                QNamePrefix::ExplicitNoNamespace => sink.push(Component::ExplicitNoNamespace),
2929                QNamePrefix::ExplicitAnyNamespace => {
2930                    match parser.default_namespace() {
2931                        // Element type selectors that have no namespace
2932                        // component (no namespace separator) represent elements
2933                        // without regard to the element's namespace (equivalent
2934                        // to "*|") unless a default namespace has been declared
2935                        // for namespaced selectors (e.g. in CSS, in the style
2936                        // sheet). If a default namespace has been declared,
2937                        // such selectors will represent only elements in the
2938                        // default namespace.
2939                        // -- Selectors § 6.1.1
2940                        // So we'll have this act the same as the
2941                        // QNamePrefix::ImplicitAnyNamespace case.
2942                        None => {},
2943                        Some(_) => sink.push(Component::ExplicitAnyNamespace),
2944                    }
2945                },
2946                QNamePrefix::ImplicitNoNamespace => {
2947                    unreachable!() // Not returned with in_attr_selector = false
2948                },
2949            }
2950            match local_name {
2951                Some(name) => sink.push(Component::LocalName(LocalName {
2952                    lower_name: to_ascii_lowercase(&name).as_ref().into(),
2953                    name: name.as_ref().into(),
2954                })),
2955                None => sink.push(Component::ExplicitUniversalType),
2956            }
2957            Ok(true)
2958        },
2959        Err(e) => Err(e),
2960    }
2961}
2962
2963#[derive(Debug)]
2964enum SimpleSelectorParseResult<Impl: SelectorImpl> {
2965    SimpleSelector(Component<Impl>),
2966    PseudoElement(Impl::PseudoElement),
2967    SlottedPseudo(Selector<Impl>),
2968    PartPseudo(Box<[Impl::Identifier]>),
2969}
2970
2971#[derive(Debug)]
2972enum QNamePrefix<Impl: SelectorImpl> {
2973    ImplicitNoNamespace,                          // `foo` in attr selectors
2974    ImplicitAnyNamespace,                         // `foo` in type selectors, without a default ns
2975    ImplicitDefaultNamespace(Impl::NamespaceUrl), // `foo` in type selectors, with a default ns
2976    ExplicitNoNamespace,                          // `|foo`
2977    ExplicitAnyNamespace,                         // `*|foo`
2978    ExplicitNamespace(Impl::NamespacePrefix, Impl::NamespaceUrl), // `prefix|foo`
2979}
2980
2981enum OptionalQName<'i, Impl: SelectorImpl> {
2982    Some(QNamePrefix<Impl>, Option<CowRcStr<'i>>),
2983    None(Token<'i>),
2984}
2985
2986/// * `Err(())`: Invalid selector, abort
2987/// * `Ok(None(token))`: Not a simple selector, could be something else. `input` was not consumed,
2988///                      but the token is still returned.
2989/// * `Ok(Some(namespace, local_name))`: `None` for the local name means a `*` universal selector
2990fn parse_qualified_name<'i, 't, P, Impl>(
2991    parser: &P,
2992    input: &mut CssParser<'i, 't>,
2993    in_attr_selector: bool,
2994) -> Result<OptionalQName<'i, Impl>, ParseError<'i, P::Error>>
2995where
2996    P: Parser<'i, Impl = Impl>,
2997    Impl: SelectorImpl,
2998{
2999    let default_namespace = |local_name| {
3000        let namespace = match parser.default_namespace() {
3001            Some(url) => QNamePrefix::ImplicitDefaultNamespace(url),
3002            None => QNamePrefix::ImplicitAnyNamespace,
3003        };
3004        Ok(OptionalQName::Some(namespace, local_name))
3005    };
3006
3007    let explicit_namespace = |input: &mut CssParser<'i, 't>, namespace| {
3008        let location = input.current_source_location();
3009        match input.next_including_whitespace() {
3010            Ok(&Token::Delim('*')) if !in_attr_selector => Ok(OptionalQName::Some(namespace, None)),
3011            Ok(&Token::Ident(ref local_name)) => {
3012                Ok(OptionalQName::Some(namespace, Some(local_name.clone())))
3013            },
3014            Ok(t) if in_attr_selector => {
3015                let e = SelectorParseErrorKind::InvalidQualNameInAttr(t.clone());
3016                Err(location.new_custom_error(e))
3017            },
3018            Ok(t) => Err(location.new_custom_error(
3019                SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(t.clone()),
3020            )),
3021            Err(e) => Err(e.into()),
3022        }
3023    };
3024
3025    let start = input.state();
3026    match input.next_including_whitespace() {
3027        Ok(Token::Ident(value)) => {
3028            let value = value.clone();
3029            let after_ident = input.state();
3030            match input.next_including_whitespace() {
3031                Ok(&Token::Delim('|')) => {
3032                    let prefix = value.as_ref().into();
3033                    let result = parser.namespace_for_prefix(&prefix);
3034                    let url = result.ok_or(
3035                        after_ident
3036                            .source_location()
3037                            .new_custom_error(SelectorParseErrorKind::ExpectedNamespace(value)),
3038                    )?;
3039                    explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
3040                },
3041                _ => {
3042                    input.reset(&after_ident);
3043                    if in_attr_selector {
3044                        Ok(OptionalQName::Some(
3045                            QNamePrefix::ImplicitNoNamespace,
3046                            Some(value),
3047                        ))
3048                    } else {
3049                        default_namespace(Some(value))
3050                    }
3051                },
3052            }
3053        },
3054        Ok(Token::Delim('*')) => {
3055            let after_star = input.state();
3056            match input.next_including_whitespace() {
3057                Ok(&Token::Delim('|')) => {
3058                    explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
3059                },
3060                _ if !in_attr_selector => {
3061                    input.reset(&after_star);
3062                    default_namespace(None)
3063                },
3064                result => {
3065                    let t = result?;
3066                    Err(after_star
3067                        .source_location()
3068                        .new_custom_error(SelectorParseErrorKind::ExpectedBarInAttr(t.clone())))
3069                },
3070            }
3071        },
3072        Ok(Token::Delim('|')) => explicit_namespace(input, QNamePrefix::ExplicitNoNamespace),
3073        Ok(t) => {
3074            let t = t.clone();
3075            input.reset(&start);
3076            Ok(OptionalQName::None(t))
3077        },
3078        Err(e) => {
3079            input.reset(&start);
3080            Err(e.into())
3081        },
3082    }
3083}
3084
3085fn parse_attribute_selector<'i, 't, P, Impl>(
3086    parser: &P,
3087    input: &mut CssParser<'i, 't>,
3088) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3089where
3090    P: Parser<'i, Impl = Impl>,
3091    Impl: SelectorImpl,
3092{
3093    let namespace;
3094    let local_name;
3095
3096    input.skip_whitespace();
3097
3098    match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
3099        OptionalQName::None(t) => {
3100            return Err(input.new_custom_error(
3101                SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(t),
3102            ));
3103        },
3104        OptionalQName::Some(_, None) => unreachable!(),
3105        OptionalQName::Some(ns, Some(ln)) => {
3106            local_name = ln;
3107            namespace = match ns {
3108                QNamePrefix::ImplicitNoNamespace | QNamePrefix::ExplicitNoNamespace => None,
3109                QNamePrefix::ExplicitNamespace(prefix, url) => {
3110                    Some(NamespaceConstraint::Specific((prefix, url)))
3111                },
3112                QNamePrefix::ExplicitAnyNamespace => Some(NamespaceConstraint::Any),
3113                QNamePrefix::ImplicitAnyNamespace | QNamePrefix::ImplicitDefaultNamespace(_) => {
3114                    unreachable!() // Not returned with in_attr_selector = true
3115                },
3116            }
3117        },
3118    }
3119
3120    let location = input.current_source_location();
3121    let operator = match input.next() {
3122        // [foo]
3123        Err(_) => {
3124            let local_name_lower = to_ascii_lowercase(&local_name).as_ref().into();
3125            let local_name = local_name.as_ref().into();
3126            if let Some(namespace) = namespace {
3127                return Ok(Component::AttributeOther(Box::new(
3128                    AttrSelectorWithOptionalNamespace {
3129                        namespace: Some(namespace),
3130                        local_name,
3131                        local_name_lower,
3132                        operation: ParsedAttrSelectorOperation::Exists,
3133                    },
3134                )));
3135            } else {
3136                return Ok(Component::AttributeInNoNamespaceExists {
3137                    local_name,
3138                    local_name_lower,
3139                });
3140            }
3141        },
3142
3143        // [foo=bar]
3144        Ok(&Token::Delim('=')) => AttrSelectorOperator::Equal,
3145        // [foo~=bar]
3146        Ok(&Token::IncludeMatch) => AttrSelectorOperator::Includes,
3147        // [foo|=bar]
3148        Ok(&Token::DashMatch) => AttrSelectorOperator::DashMatch,
3149        // [foo^=bar]
3150        Ok(&Token::PrefixMatch) => AttrSelectorOperator::Prefix,
3151        // [foo*=bar]
3152        Ok(&Token::SubstringMatch) => AttrSelectorOperator::Substring,
3153        // [foo$=bar]
3154        Ok(&Token::SuffixMatch) => AttrSelectorOperator::Suffix,
3155        Ok(t) => {
3156            return Err(location.new_custom_error(
3157                SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(t.clone()),
3158            ));
3159        },
3160    };
3161
3162    let value = match input.expect_ident_or_string() {
3163        Ok(t) => t.clone(),
3164        Err(BasicParseError {
3165            kind: BasicParseErrorKind::UnexpectedToken(t),
3166            location,
3167        }) => return Err(location.new_custom_error(SelectorParseErrorKind::BadValueInAttr(t))),
3168        Err(e) => return Err(e.into()),
3169    };
3170
3171    let attribute_flags = parse_attribute_flags(input)?;
3172    let value = value.as_ref().into();
3173    let local_name_lower;
3174    let local_name_is_ascii_lowercase;
3175    let case_sensitivity;
3176    {
3177        let local_name_lower_cow = to_ascii_lowercase(&local_name);
3178        case_sensitivity =
3179            attribute_flags.to_case_sensitivity(local_name_lower_cow.as_ref(), namespace.is_some());
3180        local_name_lower = local_name_lower_cow.as_ref().into();
3181        local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..));
3182    }
3183    let local_name = local_name.as_ref().into();
3184    if namespace.is_some() || !local_name_is_ascii_lowercase {
3185        Ok(Component::AttributeOther(Box::new(
3186            AttrSelectorWithOptionalNamespace {
3187                namespace,
3188                local_name,
3189                local_name_lower,
3190                operation: ParsedAttrSelectorOperation::WithValue {
3191                    operator,
3192                    case_sensitivity,
3193                    value,
3194                },
3195            },
3196        )))
3197    } else {
3198        Ok(Component::AttributeInNoNamespace {
3199            local_name,
3200            operator,
3201            value,
3202            case_sensitivity,
3203        })
3204    }
3205}
3206
3207/// An attribute selector can have 's' or 'i' as flags, or no flags at all.
3208enum AttributeFlags {
3209    // Matching should be case-sensitive ('s' flag).
3210    CaseSensitive,
3211    // Matching should be case-insensitive ('i' flag).
3212    AsciiCaseInsensitive,
3213    // No flags.  Matching behavior depends on the name of the attribute.
3214    CaseSensitivityDependsOnName,
3215}
3216
3217impl AttributeFlags {
3218    fn to_case_sensitivity(
3219        self,
3220        local_name_lower: &str,
3221        have_namespace: bool,
3222    ) -> ParsedCaseSensitivity {
3223        match self {
3224            AttributeFlags::CaseSensitive => ParsedCaseSensitivity::ExplicitCaseSensitive,
3225            AttributeFlags::AsciiCaseInsensitive => ParsedCaseSensitivity::AsciiCaseInsensitive,
3226            AttributeFlags::CaseSensitivityDependsOnName => {
3227                if !have_namespace
3228                    && include!(concat!(
3229                        env!("OUT_DIR"),
3230                        "/ascii_case_insensitive_html_attributes.rs"
3231                    ))
3232                    .contains(local_name_lower)
3233                {
3234                    ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
3235                } else {
3236                    ParsedCaseSensitivity::CaseSensitive
3237                }
3238            },
3239        }
3240    }
3241}
3242
3243fn parse_attribute_flags<'i, 't>(
3244    input: &mut CssParser<'i, 't>,
3245) -> Result<AttributeFlags, BasicParseError<'i>> {
3246    let location = input.current_source_location();
3247    let token = match input.next() {
3248        Ok(t) => t,
3249        Err(..) => {
3250            // Selectors spec says language-defined; HTML says it depends on the
3251            // exact attribute name.
3252            return Ok(AttributeFlags::CaseSensitivityDependsOnName);
3253        },
3254    };
3255
3256    let ident = match *token {
3257        Token::Ident(ref i) => i,
3258        ref other => return Err(location.new_basic_unexpected_token_error(other.clone())),
3259    };
3260
3261    Ok(match_ignore_ascii_case! {
3262        ident,
3263        "i" => AttributeFlags::AsciiCaseInsensitive,
3264        "s" => AttributeFlags::CaseSensitive,
3265        _ => return Err(location.new_basic_unexpected_token_error(token.clone())),
3266    })
3267}
3268
3269/// Level 3: Parse **one** simple_selector.  (Though we might insert a second
3270/// implied "<defaultns>|*" type selector.)
3271fn parse_negation<'i, 't, P, Impl>(
3272    parser: &P,
3273    input: &mut CssParser<'i, 't>,
3274    state: SelectorParsingState,
3275) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3276where
3277    P: Parser<'i, Impl = Impl>,
3278    Impl: SelectorImpl,
3279{
3280    let list = SelectorList::parse_with_state(
3281        parser,
3282        input,
3283        state
3284            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3285            | SelectorParsingState::DISALLOW_PSEUDOS,
3286        ForgivingParsing::No,
3287        ParseRelative::No,
3288    )?;
3289
3290    Ok(Component::Negation(list))
3291}
3292
3293/// simple_selector_sequence
3294/// : [ type_selector | universal ] [ HASH | class | attrib | pseudo | negation ]*
3295/// | [ HASH | class | attrib | pseudo | negation ]+
3296///
3297/// `Err(())` means invalid selector.
3298/// `Ok(true)` is an empty selector
3299fn parse_compound_selector<'i, 't, P, Impl>(
3300    parser: &P,
3301    state: &mut SelectorParsingState,
3302    input: &mut CssParser<'i, 't>,
3303    builder: &mut SelectorBuilder<Impl>,
3304) -> Result<bool, ParseError<'i, P::Error>>
3305where
3306    P: Parser<'i, Impl = Impl>,
3307    Impl: SelectorImpl,
3308{
3309    input.skip_whitespace();
3310
3311    let mut empty = true;
3312    if parse_type_selector(parser, input, *state, builder)? {
3313        empty = false;
3314    }
3315
3316    loop {
3317        let result = match parse_one_simple_selector(parser, input, *state)? {
3318            None => break,
3319            Some(result) => result,
3320        };
3321
3322        if empty {
3323            if let Some(url) = parser.default_namespace() {
3324                // If there was no explicit type selector, but there is a
3325                // default namespace, there is an implicit "<defaultns>|*" type
3326                // selector. Except for :host() or :not() / :is() / :where(),
3327                // where we ignore it.
3328                //
3329                // https://drafts.csswg.org/css-scoping/#host-element-in-tree:
3330                //
3331                //     When considered within its own shadow trees, the shadow
3332                //     host is featureless. Only the :host, :host(), and
3333                //     :host-context() pseudo-classes are allowed to match it.
3334                //
3335                // https://drafts.csswg.org/selectors-4/#featureless:
3336                //
3337                //     A featureless element does not match any selector at all,
3338                //     except those it is explicitly defined to match. If a
3339                //     given selector is allowed to match a featureless element,
3340                //     it must do so while ignoring the default namespace.
3341                //
3342                // https://drafts.csswg.org/selectors-4/#matches
3343                //
3344                //     Default namespace declarations do not affect the compound
3345                //     selector representing the subject of any selector within
3346                //     a :is() pseudo-class, unless that compound selector
3347                //     contains an explicit universal selector or type selector.
3348                //
3349                //     (Similar quotes for :where() / :not())
3350                //
3351                let ignore_default_ns = state
3352                    .intersects(SelectorParsingState::SKIP_DEFAULT_NAMESPACE)
3353                    || matches!(
3354                        result,
3355                        SimpleSelectorParseResult::SimpleSelector(Component::Host(..))
3356                    );
3357                if !ignore_default_ns {
3358                    builder.push_simple_selector(Component::DefaultNamespace(url));
3359                }
3360            }
3361        }
3362
3363        empty = false;
3364
3365        match result {
3366            SimpleSelectorParseResult::SimpleSelector(s) => {
3367                builder.push_simple_selector(s);
3368            },
3369            SimpleSelectorParseResult::PartPseudo(part_names) => {
3370                state.insert(SelectorParsingState::AFTER_PART_LIKE);
3371                builder.push_combinator(Combinator::Part);
3372                builder.push_simple_selector(Component::Part(part_names));
3373            },
3374            SimpleSelectorParseResult::SlottedPseudo(selector) => {
3375                state.insert(SelectorParsingState::AFTER_SLOTTED);
3376                builder.push_combinator(Combinator::SlotAssignment);
3377                builder.push_simple_selector(Component::Slotted(selector));
3378            },
3379            SimpleSelectorParseResult::PseudoElement(p) => {
3380                if p.parses_as_element_backed() {
3381                    state.insert(SelectorParsingState::AFTER_PART_LIKE);
3382                } else {
3383                    state.insert(SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO);
3384                    if p.is_before_or_after() {
3385                        state.insert(SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO);
3386                    }
3387                }
3388                if !p.accepts_state_pseudo_classes() {
3389                    state.insert(SelectorParsingState::AFTER_NON_STATEFUL_PSEUDO_ELEMENT);
3390                }
3391                if p.is_in_pseudo_element_tree() {
3392                    state.insert(SelectorParsingState::IN_PSEUDO_ELEMENT_TREE);
3393                }
3394                builder.push_combinator(Combinator::PseudoElement);
3395                builder.push_simple_selector(Component::PseudoElement(p));
3396            },
3397        }
3398    }
3399    Ok(empty)
3400}
3401
3402fn parse_is_where<'i, 't, P, Impl>(
3403    parser: &P,
3404    input: &mut CssParser<'i, 't>,
3405    state: SelectorParsingState,
3406    component: impl FnOnce(SelectorList<Impl>) -> Component<Impl>,
3407) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3408where
3409    P: Parser<'i, Impl = Impl>,
3410    Impl: SelectorImpl,
3411{
3412    debug_assert!(parser.parse_is_and_where());
3413    // https://drafts.csswg.org/selectors/#matches-pseudo:
3414    //
3415    //     Pseudo-elements cannot be represented by the matches-any
3416    //     pseudo-class; they are not valid within :is().
3417    //
3418    let inner = SelectorList::parse_with_state(
3419        parser,
3420        input,
3421        state
3422            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3423            | SelectorParsingState::DISALLOW_PSEUDOS,
3424        ForgivingParsing::Yes,
3425        ParseRelative::No,
3426    )?;
3427    Ok(component(inner))
3428}
3429
3430fn parse_has<'i, 't, P, Impl>(
3431    parser: &P,
3432    input: &mut CssParser<'i, 't>,
3433    state: SelectorParsingState,
3434) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3435where
3436    P: Parser<'i, Impl = Impl>,
3437    Impl: SelectorImpl,
3438{
3439    debug_assert!(parser.parse_has());
3440    if state.intersects(
3441        SelectorParsingState::DISALLOW_RELATIVE_SELECTOR | SelectorParsingState::AFTER_PSEUDO,
3442    ) {
3443        return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3444    }
3445    // Nested `:has()` is disallowed, mark it as such.
3446    // Note: The spec defines ":has-allowed pseudo-element," but there's no
3447    // pseudo-element defined as such at the moment.
3448    // https://w3c.github.io/csswg-drafts/selectors-4/#has-allowed-pseudo-element
3449    let inner = SelectorList::parse_with_state(
3450        parser,
3451        input,
3452        state
3453            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3454            | SelectorParsingState::DISALLOW_PSEUDOS
3455            | SelectorParsingState::DISALLOW_RELATIVE_SELECTOR,
3456        ForgivingParsing::No,
3457        ParseRelative::ForHas,
3458    )?;
3459    Ok(Component::Has(RelativeSelector::from_selector_list(inner)))
3460}
3461
3462fn parse_functional_pseudo_class<'i, 't, P, Impl>(
3463    parser: &P,
3464    input: &mut CssParser<'i, 't>,
3465    name: CowRcStr<'i>,
3466    state: SelectorParsingState,
3467) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3468where
3469    P: Parser<'i, Impl = Impl>,
3470    Impl: SelectorImpl,
3471{
3472    match_ignore_ascii_case! { &name,
3473        "nth-child" => return parse_nth_pseudo_class(parser, input, state, NthType::Child),
3474        "nth-of-type" => return parse_nth_pseudo_class(parser, input, state, NthType::OfType),
3475        "nth-last-child" => return parse_nth_pseudo_class(parser, input, state, NthType::LastChild),
3476        "nth-last-of-type" => return parse_nth_pseudo_class(parser, input, state, NthType::LastOfType),
3477        "is" if parser.parse_is_and_where() => return parse_is_where(parser, input, state, Component::Is),
3478        "where" if parser.parse_is_and_where() => return parse_is_where(parser, input, state, Component::Where),
3479        "has" if parser.parse_has() => return parse_has(parser, input, state),
3480        "host" => {
3481            if !state.allows_tree_structural_pseudo_classes() {
3482                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3483            }
3484            return Ok(Component::Host(Some(parse_inner_compound_selector(parser, input, state)?)));
3485        },
3486        "not" => {
3487            return parse_negation(parser, input, state)
3488        },
3489        _ => {}
3490    }
3491
3492    if parser.parse_is_and_where() && parser.is_is_alias(&name) {
3493        return parse_is_where(parser, input, state, Component::Is);
3494    }
3495
3496    if state.intersects(
3497        SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO | SelectorParsingState::AFTER_SLOTTED,
3498    ) {
3499        return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3500    }
3501
3502    let after_part = state.intersects(SelectorParsingState::AFTER_PART_LIKE);
3503    P::parse_non_ts_functional_pseudo_class(parser, name, input, after_part)
3504        .map(Component::NonTSPseudoClass)
3505}
3506
3507fn parse_nth_pseudo_class<'i, 't, P, Impl>(
3508    parser: &P,
3509    input: &mut CssParser<'i, 't>,
3510    state: SelectorParsingState,
3511    ty: NthType,
3512) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3513where
3514    P: Parser<'i, Impl = Impl>,
3515    Impl: SelectorImpl,
3516{
3517    if !state.allows_tree_structural_pseudo_classes() {
3518        return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3519    }
3520    let (a, b) = parse_nth(input)?;
3521    let nth_data = NthSelectorData {
3522        ty,
3523        is_function: true,
3524        an_plus_b: AnPlusB(a, b),
3525    };
3526    if !parser.parse_nth_child_of() || ty.is_of_type() {
3527        return Ok(Component::Nth(nth_data));
3528    }
3529
3530    // Try to parse "of <selector-list>".
3531    if input.try_parse(|i| i.expect_ident_matching("of")).is_err() {
3532        return Ok(Component::Nth(nth_data));
3533    }
3534    // Whitespace between "of" and the selector list is optional
3535    // https://github.com/w3c/csswg-drafts/issues/8285
3536    let selectors = SelectorList::parse_with_state(
3537        parser,
3538        input,
3539        state
3540            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3541            | SelectorParsingState::DISALLOW_PSEUDOS,
3542        ForgivingParsing::No,
3543        ParseRelative::No,
3544    )?;
3545    Ok(Component::NthOf(NthOfSelectorData::new(
3546        &nth_data,
3547        selectors.slice().iter().cloned(),
3548    )))
3549}
3550
3551/// Returns whether the name corresponds to a CSS2 pseudo-element that
3552/// can be specified with the single colon syntax (in addition to the
3553/// double-colon syntax, which can be used for all pseudo-elements).
3554pub fn is_css2_pseudo_element(name: &str) -> bool {
3555    // ** Do not add to this list! **
3556    match_ignore_ascii_case! { name,
3557        "before" | "after" | "first-line" | "first-letter" => true,
3558        _ => false,
3559    }
3560}
3561
3562/// Parse a simple selector other than a type selector.
3563///
3564/// * `Err(())`: Invalid selector, abort
3565/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
3566/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
3567fn parse_one_simple_selector<'i, 't, P, Impl>(
3568    parser: &P,
3569    input: &mut CssParser<'i, 't>,
3570    state: SelectorParsingState,
3571) -> Result<Option<SimpleSelectorParseResult<Impl>>, ParseError<'i, P::Error>>
3572where
3573    P: Parser<'i, Impl = Impl>,
3574    Impl: SelectorImpl,
3575{
3576    let start = input.state();
3577    let token = match input.next_including_whitespace().map(|t| t.clone()) {
3578        Ok(t) => t,
3579        Err(..) => {
3580            input.reset(&start);
3581            return Ok(None);
3582        },
3583    };
3584
3585    Ok(Some(match token {
3586        Token::IDHash(id) => {
3587            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
3588                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3589            }
3590            let id = Component::ID(id.as_ref().into());
3591            SimpleSelectorParseResult::SimpleSelector(id)
3592        },
3593        Token::Delim(delim) if delim == '.' || (delim == '&' && parser.parse_parent_selector()) => {
3594            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
3595                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3596            }
3597            let location = input.current_source_location();
3598            SimpleSelectorParseResult::SimpleSelector(if delim == '&' {
3599                Component::ParentSelector
3600            } else {
3601                let class = match *input.next_including_whitespace()? {
3602                    Token::Ident(ref class) => class,
3603                    ref t => {
3604                        let e = SelectorParseErrorKind::ClassNeedsIdent(t.clone());
3605                        return Err(location.new_custom_error(e));
3606                    },
3607                };
3608                Component::Class(class.as_ref().into())
3609            })
3610        },
3611        Token::SquareBracketBlock => {
3612            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
3613                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3614            }
3615            let attr = input.parse_nested_block(|input| parse_attribute_selector(parser, input))?;
3616            SimpleSelectorParseResult::SimpleSelector(attr)
3617        },
3618        Token::Colon => {
3619            let location = input.current_source_location();
3620            let (is_single_colon, next_token) = match input.next_including_whitespace()?.clone() {
3621                Token::Colon => (false, input.next_including_whitespace()?.clone()),
3622                t => (true, t),
3623            };
3624            let (name, is_functional) = match next_token {
3625                Token::Ident(name) => (name, false),
3626                Token::Function(name) => (name, true),
3627                t => {
3628                    let e = SelectorParseErrorKind::PseudoElementExpectedIdent(t);
3629                    return Err(input.new_custom_error(e));
3630                },
3631            };
3632            let is_pseudo_element = !is_single_colon || is_css2_pseudo_element(&name);
3633            if is_pseudo_element {
3634                // Pseudos after pseudo elements are not allowed in some cases:
3635                // - Some states will disallow pseudos, such as the interiors of
3636                // :has/:is/:where/:not (DISALLOW_PSEUDOS).
3637                // - Non-element backed pseudos do not allow other pseudos to follow (AFTER_NON_ELEMENT_BACKED_PSEUDO)...
3638                // - ... except ::before and ::after, which allow _some_ pseudos.
3639                if state.intersects(SelectorParsingState::DISALLOW_PSEUDOS)
3640                    || (state.intersects(SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO)
3641                        && !state.intersects(SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO))
3642                {
3643                    return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3644                }
3645                let pseudo_element = if is_functional {
3646                    if P::parse_part(parser) && name.eq_ignore_ascii_case("part") {
3647                        if !state.allows_part() {
3648                            return Err(
3649                                input.new_custom_error(SelectorParseErrorKind::InvalidState)
3650                            );
3651                        }
3652                        let names = input.parse_nested_block(|input| {
3653                            let mut result = Vec::with_capacity(1);
3654                            result.push(input.expect_ident()?.as_ref().into());
3655                            while !input.is_exhausted() {
3656                                result.push(input.expect_ident()?.as_ref().into());
3657                            }
3658                            Ok(result.into_boxed_slice())
3659                        })?;
3660                        return Ok(Some(SimpleSelectorParseResult::PartPseudo(names)));
3661                    }
3662                    if P::parse_slotted(parser) && name.eq_ignore_ascii_case("slotted") {
3663                        if !state.allows_slotted() {
3664                            return Err(
3665                                input.new_custom_error(SelectorParseErrorKind::InvalidState)
3666                            );
3667                        }
3668                        let selector = input.parse_nested_block(|input| {
3669                            parse_inner_compound_selector(parser, input, state)
3670                        })?;
3671                        return Ok(Some(SimpleSelectorParseResult::SlottedPseudo(selector)));
3672                    }
3673                    input.parse_nested_block(|input| {
3674                        P::parse_functional_pseudo_element(parser, name, input)
3675                    })?
3676                } else {
3677                    P::parse_pseudo_element(parser, location, name)?
3678                };
3679
3680                if state.intersects(SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO)
3681                    && !pseudo_element.valid_after_before_or_after()
3682                {
3683                    return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3684                }
3685
3686                if state.intersects(SelectorParsingState::AFTER_SLOTTED)
3687                    && !pseudo_element.valid_after_slotted()
3688                {
3689                    return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3690                }
3691                SimpleSelectorParseResult::PseudoElement(pseudo_element)
3692            } else {
3693                let pseudo_class = if is_functional {
3694                    input.parse_nested_block(|input| {
3695                        parse_functional_pseudo_class(parser, input, name, state)
3696                    })?
3697                } else {
3698                    parse_simple_pseudo_class(parser, location, name, state)?
3699                };
3700                SimpleSelectorParseResult::SimpleSelector(pseudo_class)
3701            }
3702        },
3703        _ => {
3704            input.reset(&start);
3705            return Ok(None);
3706        },
3707    }))
3708}
3709
3710fn parse_simple_pseudo_class<'i, P, Impl>(
3711    parser: &P,
3712    location: SourceLocation,
3713    name: CowRcStr<'i>,
3714    state: SelectorParsingState,
3715) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3716where
3717    P: Parser<'i, Impl = Impl>,
3718    Impl: SelectorImpl,
3719{
3720    if !state.allows_non_functional_pseudo_classes() {
3721        return Err(location.new_custom_error(SelectorParseErrorKind::InvalidState));
3722    }
3723
3724    if state.allows_tree_structural_pseudo_classes() {
3725        // If a descendant pseudo of a pseudo-element root has no other siblings, then :only-child
3726        // matches that pseudo. Note that we don't accept other tree structural pseudo classes in
3727        // this case (to match other browsers). And the spec mentions only `:only-child` as well.
3728        // https://drafts.csswg.org/css-view-transitions-1/#pseudo-root
3729        if state.allows_only_child_pseudo_class_only() {
3730            if name.eq_ignore_ascii_case("only-child") {
3731                return Ok(Component::Nth(NthSelectorData::only(
3732                    /* of_type = */ false,
3733                )));
3734            }
3735            // Other non-functional pseudo classes are not allowed.
3736            // FIXME: Perhaps we can refactor this, e.g. distinguish tree-structural pseudo classes
3737            // from other non-ts pseudo classes. Otherwise, this special case looks weird.
3738            return Err(location.new_custom_error(SelectorParseErrorKind::InvalidState));
3739        }
3740
3741        match_ignore_ascii_case! { &name,
3742            "first-child" => return Ok(Component::Nth(NthSelectorData::first(/* of_type = */ false))),
3743            "last-child" => return Ok(Component::Nth(NthSelectorData::last(/* of_type = */ false))),
3744            "only-child" => return Ok(Component::Nth(NthSelectorData::only(/* of_type = */ false))),
3745            "root" => return Ok(Component::Root),
3746            "empty" => return Ok(Component::Empty),
3747            "scope" => return Ok(Component::Scope),
3748            "host" if P::parse_host(parser) => return Ok(Component::Host(None)),
3749            "first-of-type" => return Ok(Component::Nth(NthSelectorData::first(/* of_type = */ true))),
3750            "last-of-type" => return Ok(Component::Nth(NthSelectorData::last(/* of_type = */ true))),
3751            "only-of-type" => return Ok(Component::Nth(NthSelectorData::only(/* of_type = */ true))),
3752            _ => {},
3753        }
3754    }
3755
3756    let pseudo_class = P::parse_non_ts_pseudo_class(parser, location, name)?;
3757    if state.intersects(SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO)
3758        && !pseudo_class.is_user_action_state()
3759    {
3760        return Err(location.new_custom_error(SelectorParseErrorKind::InvalidState));
3761    }
3762    Ok(Component::NonTSPseudoClass(pseudo_class))
3763}
3764
3765// NB: pub module in order to access the DummyParser
3766#[cfg(test)]
3767pub mod tests {
3768    use super::*;
3769    use crate::builder::SelectorFlags;
3770    use crate::parser;
3771    use cssparser::{serialize_identifier, Parser as CssParser, ParserInput, ToCss};
3772    use std::collections::HashMap;
3773    use std::fmt;
3774
3775    #[derive(Clone, Debug, Eq, PartialEq)]
3776    pub enum PseudoClass {
3777        Hover,
3778        Active,
3779        Lang(String),
3780    }
3781
3782    #[derive(Clone, Debug, Eq, PartialEq)]
3783    pub enum PseudoElement {
3784        Before,
3785        After,
3786        Marker,
3787        DetailsContent,
3788        Highlight(String),
3789    }
3790
3791    impl parser::PseudoElement for PseudoElement {
3792        type Impl = DummySelectorImpl;
3793
3794        fn accepts_state_pseudo_classes(&self) -> bool {
3795            true
3796        }
3797
3798        fn valid_after_slotted(&self) -> bool {
3799            true
3800        }
3801
3802        fn valid_after_before_or_after(&self) -> bool {
3803            matches!(self, Self::Marker)
3804        }
3805
3806        fn is_before_or_after(&self) -> bool {
3807            matches!(self, Self::Before | Self::After)
3808        }
3809
3810        fn parses_as_element_backed(&self) -> bool {
3811            matches!(self, Self::DetailsContent)
3812        }
3813    }
3814
3815    impl parser::NonTSPseudoClass for PseudoClass {
3816        type Impl = DummySelectorImpl;
3817
3818        #[inline]
3819        fn is_active_or_hover(&self) -> bool {
3820            matches!(*self, PseudoClass::Active | PseudoClass::Hover)
3821        }
3822
3823        #[inline]
3824        fn is_user_action_state(&self) -> bool {
3825            self.is_active_or_hover()
3826        }
3827    }
3828
3829    impl ToCss for PseudoClass {
3830        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3831        where
3832            W: fmt::Write,
3833        {
3834            match *self {
3835                PseudoClass::Hover => dest.write_str(":hover"),
3836                PseudoClass::Active => dest.write_str(":active"),
3837                PseudoClass::Lang(ref lang) => {
3838                    dest.write_str(":lang(")?;
3839                    serialize_identifier(lang, dest)?;
3840                    dest.write_char(')')
3841                },
3842            }
3843        }
3844    }
3845
3846    impl ToCss for PseudoElement {
3847        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3848        where
3849            W: fmt::Write,
3850        {
3851            match *self {
3852                PseudoElement::Before => dest.write_str("::before"),
3853                PseudoElement::After => dest.write_str("::after"),
3854                PseudoElement::Marker => dest.write_str("::marker"),
3855                PseudoElement::DetailsContent => dest.write_str("::details-content"),
3856                PseudoElement::Highlight(ref name) => {
3857                    dest.write_str("::highlight(")?;
3858                    serialize_identifier(&name, dest)?;
3859                    dest.write_char(')')
3860                },
3861            }
3862        }
3863    }
3864
3865    #[derive(Clone, Debug, PartialEq)]
3866    pub struct DummySelectorImpl;
3867
3868    #[derive(Default)]
3869    pub struct DummyParser {
3870        default_ns: Option<DummyAtom>,
3871        ns_prefixes: HashMap<DummyAtom, DummyAtom>,
3872    }
3873
3874    impl DummyParser {
3875        fn default_with_namespace(default_ns: DummyAtom) -> DummyParser {
3876            DummyParser {
3877                default_ns: Some(default_ns),
3878                ns_prefixes: Default::default(),
3879            }
3880        }
3881    }
3882
3883    impl SelectorImpl for DummySelectorImpl {
3884        type ExtraMatchingData<'a> = std::marker::PhantomData<&'a ()>;
3885        type AttrValue = DummyAttrValue;
3886        type Identifier = DummyAtom;
3887        type LocalName = DummyAtom;
3888        type NamespaceUrl = DummyAtom;
3889        type NamespacePrefix = DummyAtom;
3890        type BorrowedLocalName = DummyAtom;
3891        type BorrowedNamespaceUrl = DummyAtom;
3892        type NonTSPseudoClass = PseudoClass;
3893        type PseudoElement = PseudoElement;
3894    }
3895
3896    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
3897    pub struct DummyAttrValue(String);
3898
3899    impl ToCss for DummyAttrValue {
3900        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3901        where
3902            W: fmt::Write,
3903        {
3904            use std::fmt::Write;
3905
3906            dest.write_char('"')?;
3907            write!(cssparser::CssStringWriter::new(dest), "{}", &self.0)?;
3908            dest.write_char('"')
3909        }
3910    }
3911
3912    impl<'a> From<&'a str> for DummyAttrValue {
3913        fn from(string: &'a str) -> Self {
3914            Self(string.into())
3915        }
3916    }
3917
3918    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
3919    pub struct DummyAtom(String);
3920
3921    impl ToCss for DummyAtom {
3922        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3923        where
3924            W: fmt::Write,
3925        {
3926            serialize_identifier(&self.0, dest)
3927        }
3928    }
3929
3930    impl From<String> for DummyAtom {
3931        fn from(string: String) -> Self {
3932            DummyAtom(string)
3933        }
3934    }
3935
3936    impl<'a> From<&'a str> for DummyAtom {
3937        fn from(string: &'a str) -> Self {
3938            DummyAtom(string.into())
3939        }
3940    }
3941
3942    impl PrecomputedHash for DummyAtom {
3943        fn precomputed_hash(&self) -> u32 {
3944            self.0.as_ptr() as u32
3945        }
3946    }
3947
3948    impl<'i> Parser<'i> for DummyParser {
3949        type Impl = DummySelectorImpl;
3950        type Error = SelectorParseErrorKind<'i>;
3951
3952        fn parse_slotted(&self) -> bool {
3953            true
3954        }
3955
3956        fn parse_nth_child_of(&self) -> bool {
3957            true
3958        }
3959
3960        fn parse_is_and_where(&self) -> bool {
3961            true
3962        }
3963
3964        fn parse_has(&self) -> bool {
3965            true
3966        }
3967
3968        fn parse_parent_selector(&self) -> bool {
3969            true
3970        }
3971
3972        fn parse_part(&self) -> bool {
3973            true
3974        }
3975
3976        fn parse_host(&self) -> bool {
3977            true
3978        }
3979
3980        fn parse_non_ts_pseudo_class(
3981            &self,
3982            location: SourceLocation,
3983            name: CowRcStr<'i>,
3984        ) -> Result<PseudoClass, SelectorParseError<'i>> {
3985            match_ignore_ascii_case! { &name,
3986                "hover" => return Ok(PseudoClass::Hover),
3987                "active" => return Ok(PseudoClass::Active),
3988                _ => {}
3989            }
3990            Err(
3991                location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
3992                    name,
3993                )),
3994            )
3995        }
3996
3997        fn parse_non_ts_functional_pseudo_class<'t>(
3998            &self,
3999            name: CowRcStr<'i>,
4000            parser: &mut CssParser<'i, 't>,
4001            after_part: bool,
4002        ) -> Result<PseudoClass, SelectorParseError<'i>> {
4003            match_ignore_ascii_case! { &name,
4004                "lang" if !after_part => {
4005                    let lang = parser.expect_ident_or_string()?.as_ref().to_owned();
4006                    return Ok(PseudoClass::Lang(lang));
4007                },
4008                _ => {}
4009            }
4010            Err(
4011                parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
4012                    name,
4013                )),
4014            )
4015        }
4016
4017        fn parse_pseudo_element(
4018            &self,
4019            location: SourceLocation,
4020            name: CowRcStr<'i>,
4021        ) -> Result<PseudoElement, SelectorParseError<'i>> {
4022            match_ignore_ascii_case! { &name,
4023                "before" => return Ok(PseudoElement::Before),
4024                "after" => return Ok(PseudoElement::After),
4025                "marker" => return Ok(PseudoElement::Marker),
4026                "details-content" => return Ok(PseudoElement::DetailsContent),
4027                _ => {}
4028            }
4029            Err(
4030                location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
4031                    name,
4032                )),
4033            )
4034        }
4035
4036        fn parse_functional_pseudo_element<'t>(
4037            &self,
4038            name: CowRcStr<'i>,
4039            parser: &mut CssParser<'i, 't>,
4040        ) -> Result<PseudoElement, SelectorParseError<'i>> {
4041            match_ignore_ascii_case! { &name,
4042                "highlight" => return Ok(PseudoElement::Highlight(parser.expect_ident()?.as_ref().to_owned())),
4043                _ => {}
4044            }
4045            Err(
4046                parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
4047                    name,
4048                )),
4049            )
4050        }
4051
4052        fn default_namespace(&self) -> Option<DummyAtom> {
4053            self.default_ns.clone()
4054        }
4055
4056        fn namespace_for_prefix(&self, prefix: &DummyAtom) -> Option<DummyAtom> {
4057            self.ns_prefixes.get(prefix).cloned()
4058        }
4059    }
4060
4061    fn parse<'i>(
4062        input: &'i str,
4063    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4064        parse_relative(input, ParseRelative::No)
4065    }
4066
4067    fn parse_relative<'i>(
4068        input: &'i str,
4069        parse_relative: ParseRelative,
4070    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4071        parse_ns_relative(input, &DummyParser::default(), parse_relative)
4072    }
4073
4074    fn parse_expected<'i, 'a>(
4075        input: &'i str,
4076        expected: Option<&'a str>,
4077    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4078        parse_ns_expected(input, &DummyParser::default(), expected)
4079    }
4080
4081    fn parse_relative_expected<'i, 'a>(
4082        input: &'i str,
4083        parse_relative: ParseRelative,
4084        expected: Option<&'a str>,
4085    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4086        parse_ns_relative_expected(input, &DummyParser::default(), parse_relative, expected)
4087    }
4088
4089    fn parse_ns<'i>(
4090        input: &'i str,
4091        parser: &DummyParser,
4092    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4093        parse_ns_relative(input, parser, ParseRelative::No)
4094    }
4095
4096    fn parse_ns_relative<'i>(
4097        input: &'i str,
4098        parser: &DummyParser,
4099        parse_relative: ParseRelative,
4100    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4101        parse_ns_relative_expected(input, parser, parse_relative, None)
4102    }
4103
4104    fn parse_ns_expected<'i, 'a>(
4105        input: &'i str,
4106        parser: &DummyParser,
4107        expected: Option<&'a str>,
4108    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4109        parse_ns_relative_expected(input, parser, ParseRelative::No, expected)
4110    }
4111
4112    fn parse_ns_relative_expected<'i, 'a>(
4113        input: &'i str,
4114        parser: &DummyParser,
4115        parse_relative: ParseRelative,
4116        expected: Option<&'a str>,
4117    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4118        let mut parser_input = ParserInput::new(input);
4119        let result = SelectorList::parse(
4120            parser,
4121            &mut CssParser::new(&mut parser_input),
4122            parse_relative,
4123        );
4124        if let Ok(ref selectors) = result {
4125            // We can't assume that the serialized parsed selector will equal
4126            // the input; for example, if there is no default namespace, '*|foo'
4127            // should serialize to 'foo'.
4128            assert_eq!(
4129                selectors.to_css_string(),
4130                match expected {
4131                    Some(x) => x,
4132                    None => input,
4133                }
4134            );
4135        }
4136        result
4137    }
4138
4139    fn specificity(a: u32, b: u32, c: u32) -> u32 {
4140        a << 20 | b << 10 | c
4141    }
4142
4143    #[test]
4144    fn test_ancestor_hashes_in_subject_position() {
4145        fn ancestor_hash_count(selector: &str) -> usize {
4146            let list = parse(selector).unwrap();
4147            assert_eq!(list.slice().len(), 1);
4148            let mut hashes = [0u32; 4];
4149            let mut len = 0;
4150            collect_ancestor_hashes(
4151                list.slice()[0].iter(),
4152                QuirksMode::NoQuirks,
4153                &mut hashes,
4154                &mut len,
4155            );
4156            len
4157        }
4158
4159        // Subject-only selectors don't contribute any ancestor hashes.
4160        assert_eq!(ancestor_hash_count(".subject"), 0);
4161        assert_eq!(ancestor_hash_count(":where(.subject)"), 0);
4162
4163        // An ancestor combinator inside :is() / :where() in subject position
4164        // should still contribute ancestor hashes (bug 2040922).
4165        assert_eq!(ancestor_hash_count(":where(.ancestor > .subject)"), 1);
4166        assert_eq!(ancestor_hash_count(":is(.ancestor .subject)"), 1);
4167        assert_eq!(
4168            ancestor_hash_count(":where(.ancestor > :not(:last-child))"),
4169            1
4170        );
4171
4172        // Real ancestors combine with ancestor combinators nested in a subject
4173        // :where().
4174        assert_eq!(
4175            ancestor_hash_count(".real-ancestor :where(.inner-ancestor > .subject)"),
4176            2
4177        );
4178
4179        // :is() / :where() with more than one selector OR their selectors, so no
4180        // hash can be collected from them, even when they contain ancestor
4181        // combinators.
4182        assert_eq!(ancestor_hash_count(":is(.a, .b) .subject"), 0);
4183        assert_eq!(
4184            ancestor_hash_count(":where(.ancestor > .subject, .other)"),
4185            0
4186        );
4187        // But a real ancestor next to a multi-selector subject :where() is still
4188        // collected.
4189        assert_eq!(ancestor_hash_count(".real-ancestor :where(.a > .b, .c)"), 1);
4190
4191        // Pseudo-elements match on their originating element, so simple
4192        // selectors in front of the pseudo-element combinator are part of the
4193        // subject and don't contribute ancestor hashes.
4194        assert_eq!(ancestor_hash_count(".subject::before"), 0);
4195        assert_eq!(ancestor_hash_count(".real-ancestor .subject::before"), 1);
4196        // An ancestor combinator nested in a subject :where() is still collected
4197        // even when the subject carries a pseudo-element.
4198        assert_eq!(
4199            ancestor_hash_count(":where(.ancestor > .subject)::before"),
4200            1
4201        );
4202    }
4203
4204    #[test]
4205    fn test_empty() {
4206        let mut input = ParserInput::new(":empty");
4207        let list = SelectorList::parse(
4208            &DummyParser::default(),
4209            &mut CssParser::new(&mut input),
4210            ParseRelative::No,
4211        );
4212        assert!(list.is_ok());
4213    }
4214
4215    const MATHML: &str = "http://www.w3.org/1998/Math/MathML";
4216    const SVG: &str = "http://www.w3.org/2000/svg";
4217
4218    #[test]
4219    fn test_parsing() {
4220        assert!(parse("").is_err());
4221        assert!(parse(":lang(4)").is_err());
4222        assert!(parse(":lang(en US)").is_err());
4223        assert_eq!(
4224            parse("EeÉ"),
4225            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4226                vec![Component::LocalName(LocalName {
4227                    name: DummyAtom::from("EeÉ"),
4228                    lower_name: DummyAtom::from("eeÉ"),
4229                })],
4230                specificity(0, 0, 1),
4231                SelectorFlags::empty(),
4232            )]))
4233        );
4234        assert_eq!(
4235            parse("|e"),
4236            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4237                vec![
4238                    Component::ExplicitNoNamespace,
4239                    Component::LocalName(LocalName {
4240                        name: DummyAtom::from("e"),
4241                        lower_name: DummyAtom::from("e"),
4242                    }),
4243                ],
4244                specificity(0, 0, 1),
4245                SelectorFlags::empty(),
4246            )]))
4247        );
4248        // When the default namespace is not set, *| should be elided.
4249        // https://github.com/servo/servo/pull/17537
4250        assert_eq!(
4251            parse_expected("*|e", Some("e")),
4252            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4253                vec![Component::LocalName(LocalName {
4254                    name: DummyAtom::from("e"),
4255                    lower_name: DummyAtom::from("e"),
4256                })],
4257                specificity(0, 0, 1),
4258                SelectorFlags::empty(),
4259            )]))
4260        );
4261        // When the default namespace is set, *| should _not_ be elided (as foo
4262        // is no longer equivalent to *|foo--the former is only for foo in the
4263        // default namespace).
4264        // https://github.com/servo/servo/issues/16020
4265        assert_eq!(
4266            parse_ns(
4267                "*|e",
4268                &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org"))
4269            ),
4270            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4271                vec![
4272                    Component::ExplicitAnyNamespace,
4273                    Component::LocalName(LocalName {
4274                        name: DummyAtom::from("e"),
4275                        lower_name: DummyAtom::from("e"),
4276                    }),
4277                ],
4278                specificity(0, 0, 1),
4279                SelectorFlags::empty(),
4280            )]))
4281        );
4282        assert_eq!(
4283            parse("*"),
4284            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4285                vec![Component::ExplicitUniversalType],
4286                specificity(0, 0, 0),
4287                SelectorFlags::empty(),
4288            )]))
4289        );
4290        assert_eq!(
4291            parse("|*"),
4292            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4293                vec![
4294                    Component::ExplicitNoNamespace,
4295                    Component::ExplicitUniversalType,
4296                ],
4297                specificity(0, 0, 0),
4298                SelectorFlags::empty(),
4299            )]))
4300        );
4301        assert_eq!(
4302            parse_expected("*|*", Some("*")),
4303            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4304                vec![Component::ExplicitUniversalType],
4305                specificity(0, 0, 0),
4306                SelectorFlags::empty(),
4307            )]))
4308        );
4309        assert_eq!(
4310            parse_ns(
4311                "*|*",
4312                &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org"))
4313            ),
4314            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4315                vec![
4316                    Component::ExplicitAnyNamespace,
4317                    Component::ExplicitUniversalType,
4318                ],
4319                specificity(0, 0, 0),
4320                SelectorFlags::empty(),
4321            )]))
4322        );
4323        assert_eq!(
4324            parse(".foo:lang(en-US)"),
4325            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4326                vec![
4327                    Component::Class(DummyAtom::from("foo")),
4328                    Component::NonTSPseudoClass(PseudoClass::Lang("en-US".to_owned())),
4329                ],
4330                specificity(0, 2, 0),
4331                SelectorFlags::empty(),
4332            )]))
4333        );
4334        assert_eq!(
4335            parse("#bar"),
4336            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4337                vec![Component::ID(DummyAtom::from("bar"))],
4338                specificity(1, 0, 0),
4339                SelectorFlags::empty(),
4340            )]))
4341        );
4342        assert_eq!(
4343            parse("e.foo#bar"),
4344            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4345                vec![
4346                    Component::LocalName(LocalName {
4347                        name: DummyAtom::from("e"),
4348                        lower_name: DummyAtom::from("e"),
4349                    }),
4350                    Component::Class(DummyAtom::from("foo")),
4351                    Component::ID(DummyAtom::from("bar")),
4352                ],
4353                specificity(1, 1, 1),
4354                SelectorFlags::empty(),
4355            )]))
4356        );
4357        assert_eq!(
4358            parse("e.foo #bar"),
4359            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4360                vec![
4361                    Component::LocalName(LocalName {
4362                        name: DummyAtom::from("e"),
4363                        lower_name: DummyAtom::from("e"),
4364                    }),
4365                    Component::Class(DummyAtom::from("foo")),
4366                    Component::Combinator(Combinator::Descendant),
4367                    Component::ID(DummyAtom::from("bar")),
4368                ],
4369                specificity(1, 1, 1),
4370                SelectorFlags::empty(),
4371            )]))
4372        );
4373        // Default namespace does not apply to attribute selectors
4374        // https://github.com/mozilla/servo/pull/1652
4375        let mut parser = DummyParser::default();
4376        assert_eq!(
4377            parse_ns("[Foo]", &parser),
4378            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4379                vec![Component::AttributeInNoNamespaceExists {
4380                    local_name: DummyAtom::from("Foo"),
4381                    local_name_lower: DummyAtom::from("foo"),
4382                }],
4383                specificity(0, 1, 0),
4384                SelectorFlags::empty(),
4385            )]))
4386        );
4387        assert!(parse_ns("svg|circle", &parser).is_err());
4388        parser
4389            .ns_prefixes
4390            .insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
4391        assert_eq!(
4392            parse_ns("svg|circle", &parser),
4393            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4394                vec![
4395                    Component::Namespace(DummyAtom("svg".into()), SVG.into()),
4396                    Component::LocalName(LocalName {
4397                        name: DummyAtom::from("circle"),
4398                        lower_name: DummyAtom::from("circle"),
4399                    }),
4400                ],
4401                specificity(0, 0, 1),
4402                SelectorFlags::empty(),
4403            )]))
4404        );
4405        assert_eq!(
4406            parse_ns("svg|*", &parser),
4407            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4408                vec![
4409                    Component::Namespace(DummyAtom("svg".into()), SVG.into()),
4410                    Component::ExplicitUniversalType,
4411                ],
4412                specificity(0, 0, 0),
4413                SelectorFlags::empty(),
4414            )]))
4415        );
4416        // Default namespace does not apply to attribute selectors
4417        // https://github.com/mozilla/servo/pull/1652
4418        // but it does apply to implicit type selectors
4419        // https://github.com/servo/rust-selectors/pull/82
4420        parser.default_ns = Some(MATHML.into());
4421        assert_eq!(
4422            parse_ns("[Foo]", &parser),
4423            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4424                vec![
4425                    Component::DefaultNamespace(MATHML.into()),
4426                    Component::AttributeInNoNamespaceExists {
4427                        local_name: DummyAtom::from("Foo"),
4428                        local_name_lower: DummyAtom::from("foo"),
4429                    },
4430                ],
4431                specificity(0, 1, 0),
4432                SelectorFlags::empty(),
4433            )]))
4434        );
4435        // Default namespace does apply to type selectors
4436        assert_eq!(
4437            parse_ns("e", &parser),
4438            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4439                vec![
4440                    Component::DefaultNamespace(MATHML.into()),
4441                    Component::LocalName(LocalName {
4442                        name: DummyAtom::from("e"),
4443                        lower_name: DummyAtom::from("e"),
4444                    }),
4445                ],
4446                specificity(0, 0, 1),
4447                SelectorFlags::empty(),
4448            )]))
4449        );
4450        assert_eq!(
4451            parse_ns("*", &parser),
4452            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4453                vec![
4454                    Component::DefaultNamespace(MATHML.into()),
4455                    Component::ExplicitUniversalType,
4456                ],
4457                specificity(0, 0, 0),
4458                SelectorFlags::empty(),
4459            )]))
4460        );
4461        assert_eq!(
4462            parse_ns("*|*", &parser),
4463            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4464                vec![
4465                    Component::ExplicitAnyNamespace,
4466                    Component::ExplicitUniversalType,
4467                ],
4468                specificity(0, 0, 0),
4469                SelectorFlags::empty(),
4470            )]))
4471        );
4472        // Default namespace applies to universal and type selectors inside :not and :matches,
4473        // but not otherwise.
4474        assert_eq!(
4475            parse_ns(":not(.cl)", &parser),
4476            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4477                vec![
4478                    Component::DefaultNamespace(MATHML.into()),
4479                    Component::Negation(SelectorList::from_vec(vec![Selector::from_vec(
4480                        vec![Component::Class(DummyAtom::from("cl"))],
4481                        specificity(0, 1, 0),
4482                        SelectorFlags::empty(),
4483                    )])),
4484                ],
4485                specificity(0, 1, 0),
4486                SelectorFlags::empty(),
4487            )]))
4488        );
4489        assert_eq!(
4490            parse_ns(":not(*)", &parser),
4491            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4492                vec![
4493                    Component::DefaultNamespace(MATHML.into()),
4494                    Component::Negation(SelectorList::from_vec(vec![Selector::from_vec(
4495                        vec![
4496                            Component::DefaultNamespace(MATHML.into()),
4497                            Component::ExplicitUniversalType,
4498                        ],
4499                        specificity(0, 0, 0),
4500                        SelectorFlags::empty(),
4501                    )]),),
4502                ],
4503                specificity(0, 0, 0),
4504                SelectorFlags::empty(),
4505            )]))
4506        );
4507        assert_eq!(
4508            parse_ns(":not(e)", &parser),
4509            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4510                vec![
4511                    Component::DefaultNamespace(MATHML.into()),
4512                    Component::Negation(SelectorList::from_vec(vec![Selector::from_vec(
4513                        vec![
4514                            Component::DefaultNamespace(MATHML.into()),
4515                            Component::LocalName(LocalName {
4516                                name: DummyAtom::from("e"),
4517                                lower_name: DummyAtom::from("e"),
4518                            }),
4519                        ],
4520                        specificity(0, 0, 1),
4521                        SelectorFlags::empty(),
4522                    )])),
4523                ],
4524                specificity(0, 0, 1),
4525                SelectorFlags::empty(),
4526            )]))
4527        );
4528        assert_eq!(
4529            parse("[attr|=\"foo\"]"),
4530            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4531                vec![Component::AttributeInNoNamespace {
4532                    local_name: DummyAtom::from("attr"),
4533                    operator: AttrSelectorOperator::DashMatch,
4534                    value: DummyAttrValue::from("foo"),
4535                    case_sensitivity: ParsedCaseSensitivity::CaseSensitive,
4536                }],
4537                specificity(0, 1, 0),
4538                SelectorFlags::empty(),
4539            )]))
4540        );
4541        // https://github.com/mozilla/servo/issues/1723
4542        assert_eq!(
4543            parse("::before"),
4544            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4545                vec![
4546                    Component::Combinator(Combinator::PseudoElement),
4547                    Component::PseudoElement(PseudoElement::Before),
4548                ],
4549                specificity(0, 0, 1),
4550                SelectorFlags::HAS_PSEUDO,
4551            )]))
4552        );
4553        assert_eq!(
4554            parse("::before:hover"),
4555            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4556                vec![
4557                    Component::Combinator(Combinator::PseudoElement),
4558                    Component::PseudoElement(PseudoElement::Before),
4559                    Component::NonTSPseudoClass(PseudoClass::Hover),
4560                ],
4561                specificity(0, 1, 1),
4562                SelectorFlags::HAS_PSEUDO,
4563            )]))
4564        );
4565        assert_eq!(
4566            parse("::before:hover:hover"),
4567            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4568                vec![
4569                    Component::Combinator(Combinator::PseudoElement),
4570                    Component::PseudoElement(PseudoElement::Before),
4571                    Component::NonTSPseudoClass(PseudoClass::Hover),
4572                    Component::NonTSPseudoClass(PseudoClass::Hover),
4573                ],
4574                specificity(0, 2, 1),
4575                SelectorFlags::HAS_PSEUDO,
4576            )]))
4577        );
4578        assert!(parse("::before:hover:lang(foo)").is_err());
4579        assert!(parse("::before:hover .foo").is_err());
4580        assert!(parse("::before .foo").is_err());
4581        assert!(parse("::before ~ bar").is_err());
4582        assert!(parse("::before:active").is_ok());
4583
4584        // https://github.com/servo/servo/issues/15335
4585        assert!(parse(":: before").is_err());
4586        assert_eq!(
4587            parse("div ::after"),
4588            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4589                vec![
4590                    Component::LocalName(LocalName {
4591                        name: DummyAtom::from("div"),
4592                        lower_name: DummyAtom::from("div"),
4593                    }),
4594                    Component::Combinator(Combinator::Descendant),
4595                    Component::Combinator(Combinator::PseudoElement),
4596                    Component::PseudoElement(PseudoElement::After),
4597                ],
4598                specificity(0, 0, 2),
4599                SelectorFlags::HAS_PSEUDO,
4600            )]))
4601        );
4602        assert_eq!(
4603            parse("#d1 > .ok"),
4604            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4605                vec![
4606                    Component::ID(DummyAtom::from("d1")),
4607                    Component::Combinator(Combinator::Child),
4608                    Component::Class(DummyAtom::from("ok")),
4609                ],
4610                specificity(1, 1, 0),
4611                SelectorFlags::empty(),
4612            )]))
4613        );
4614        parser.default_ns = None;
4615        assert!(parse(":not(#provel.old)").is_ok());
4616        assert!(parse(":not(#provel > old)").is_ok());
4617        assert!(parse("table[rules]:not([rules=\"none\"]):not([rules=\"\"])").is_ok());
4618        // https://github.com/servo/servo/issues/16017
4619        assert_eq!(
4620            parse_ns(":not(*)", &parser),
4621            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4622                vec![Component::Negation(SelectorList::from_vec(vec![
4623                    Selector::from_vec(
4624                        vec![Component::ExplicitUniversalType],
4625                        specificity(0, 0, 0),
4626                        SelectorFlags::empty(),
4627                    )
4628                ]))],
4629                specificity(0, 0, 0),
4630                SelectorFlags::empty(),
4631            )]))
4632        );
4633        assert_eq!(
4634            parse_ns(":not(|*)", &parser),
4635            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4636                vec![Component::Negation(SelectorList::from_vec(vec![
4637                    Selector::from_vec(
4638                        vec![
4639                            Component::ExplicitNoNamespace,
4640                            Component::ExplicitUniversalType,
4641                        ],
4642                        specificity(0, 0, 0),
4643                        SelectorFlags::empty(),
4644                    )
4645                ]))],
4646                specificity(0, 0, 0),
4647                SelectorFlags::empty(),
4648            )]))
4649        );
4650        // *| should be elided if there is no default namespace.
4651        // https://github.com/servo/servo/pull/17537
4652        assert_eq!(
4653            parse_ns_expected(":not(*|*)", &parser, Some(":not(*)")),
4654            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4655                vec![Component::Negation(SelectorList::from_vec(vec![
4656                    Selector::from_vec(
4657                        vec![Component::ExplicitUniversalType],
4658                        specificity(0, 0, 0),
4659                        SelectorFlags::empty(),
4660                    )
4661                ]))],
4662                specificity(0, 0, 0),
4663                SelectorFlags::empty(),
4664            )]))
4665        );
4666
4667        assert!(parse("::highlight(foo)").is_ok());
4668
4669        assert!(parse("::slotted()").is_err());
4670        assert!(parse("::slotted(div)").is_ok());
4671        assert!(parse("::slotted(div).foo").is_err());
4672        assert!(parse("::slotted(div + bar)").is_err());
4673        assert!(parse("::slotted(div) + foo").is_err());
4674
4675        assert!(parse("::part()").is_err());
4676        assert!(parse("::part(42)").is_err());
4677        assert!(parse("::part(foo bar)").is_ok());
4678        assert!(parse("::part(foo):hover").is_ok());
4679        assert!(parse("::part(foo) + bar").is_err());
4680
4681        assert!(parse("div ::slotted(div)").is_ok());
4682        assert!(parse("div + slot::slotted(div)").is_ok());
4683        assert!(parse("div + slot::slotted(div.foo)").is_ok());
4684        assert!(parse("slot::slotted(div,foo)::first-line").is_err());
4685        assert!(parse("::slotted(div)::before").is_ok());
4686        assert!(parse("slot::slotted(div,foo)").is_err());
4687
4688        assert!(parse("foo:where()").is_ok());
4689        assert!(parse("foo:where(div, foo, .bar baz)").is_ok());
4690        assert!(parse("foo:where(::before)").is_ok());
4691    }
4692
4693    #[test]
4694    fn parent_selector() {
4695        assert!(parse("foo &").is_ok());
4696        assert_eq!(
4697            parse("#foo &.bar"),
4698            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4699                vec![
4700                    Component::ID(DummyAtom::from("foo")),
4701                    Component::Combinator(Combinator::Descendant),
4702                    Component::ParentSelector,
4703                    Component::Class(DummyAtom::from("bar")),
4704                ],
4705                specificity(1, 1, 0),
4706                SelectorFlags::HAS_PARENT
4707            )]))
4708        );
4709
4710        let parent = parse(".bar, div .baz").unwrap();
4711        let child = parse("#foo &.bar").unwrap();
4712        assert_eq!(
4713            child.replace_parent_selector(&parent),
4714            parse("#foo :is(.bar, div .baz).bar").unwrap()
4715        );
4716
4717        let has_child = parse("#foo:has(&.bar)").unwrap();
4718        assert_eq!(
4719            has_child.replace_parent_selector(&parent),
4720            parse("#foo:has(:is(.bar, div .baz).bar)").unwrap()
4721        );
4722
4723        let child =
4724            parse_relative_expected("#foo", ParseRelative::ForNesting, Some("& #foo")).unwrap();
4725        assert_eq!(
4726            child.replace_parent_selector(&parent),
4727            parse(":is(.bar, div .baz) #foo").unwrap()
4728        );
4729
4730        let child =
4731            parse_relative_expected("+ #foo", ParseRelative::ForNesting, Some("& + #foo")).unwrap();
4732        assert_eq!(child, parse("& + #foo").unwrap());
4733    }
4734
4735    #[test]
4736    fn test_pseudo_iter() {
4737        let list = parse("q::before").unwrap();
4738        let selector = &list.slice()[0];
4739        assert!(!selector.is_universal());
4740        let mut iter = selector.iter();
4741        assert_eq!(
4742            iter.next(),
4743            Some(&Component::PseudoElement(PseudoElement::Before))
4744        );
4745        assert_eq!(iter.next(), None);
4746        let combinator = iter.next_sequence();
4747        assert_eq!(combinator, Some(Combinator::PseudoElement));
4748        assert_eq!(
4749            iter.next(),
4750            Some(&Component::LocalName(LocalName {
4751                name: DummyAtom::from("q"),
4752                lower_name: DummyAtom::from("q"),
4753            }))
4754        );
4755        assert_eq!(iter.next(), None);
4756        assert_eq!(iter.next_sequence(), None);
4757    }
4758
4759    #[test]
4760    fn test_pseudo_before_marker() {
4761        let list = parse("::before::marker").unwrap();
4762        let selector = &list.slice()[0];
4763        let mut iter = selector.iter();
4764        assert_eq!(
4765            iter.next(),
4766            Some(&Component::PseudoElement(PseudoElement::Marker))
4767        );
4768        assert_eq!(iter.next(), None);
4769        let combinator = iter.next_sequence();
4770        assert_eq!(combinator, Some(Combinator::PseudoElement));
4771        assert_eq!(
4772            iter.next(),
4773            Some(&Component::PseudoElement(PseudoElement::Before))
4774        );
4775        assert_eq!(iter.next(), None);
4776        let combinator = iter.next_sequence();
4777        assert_eq!(combinator, Some(Combinator::PseudoElement));
4778        assert_eq!(iter.next(), None);
4779        assert_eq!(iter.next_sequence(), None);
4780    }
4781
4782    #[test]
4783    fn test_pseudo_duplicate_before_after_or_marker() {
4784        assert!(parse("::before::before").is_err());
4785        assert!(parse("::after::after").is_err());
4786        assert!(parse("::marker::marker").is_err());
4787    }
4788
4789    #[test]
4790    fn test_pseudo_on_element_backed_pseudo() {
4791        let list = parse("::details-content::before").unwrap();
4792        let selector = &list.slice()[0];
4793        let mut iter = selector.iter();
4794        assert_eq!(
4795            iter.next(),
4796            Some(&Component::PseudoElement(PseudoElement::Before))
4797        );
4798        assert_eq!(iter.next(), None);
4799        let combinator = iter.next_sequence();
4800        assert_eq!(combinator, Some(Combinator::PseudoElement));
4801        assert_eq!(
4802            iter.next(),
4803            Some(&Component::PseudoElement(PseudoElement::DetailsContent))
4804        );
4805        assert_eq!(iter.next(), None);
4806        let combinator = iter.next_sequence();
4807        assert_eq!(combinator, Some(Combinator::PseudoElement));
4808        assert_eq!(iter.next(), None);
4809        assert_eq!(iter.next_sequence(), None);
4810    }
4811
4812    #[test]
4813    fn test_universal() {
4814        let list = parse_ns(
4815            "*|*::before",
4816            &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org")),
4817        )
4818        .unwrap();
4819        let selector = &list.slice()[0];
4820        assert!(selector.is_universal());
4821    }
4822
4823    #[test]
4824    fn test_empty_pseudo_iter() {
4825        let list = parse("::before").unwrap();
4826        let selector = &list.slice()[0];
4827        assert!(selector.is_universal());
4828        let mut iter = selector.iter();
4829        assert_eq!(
4830            iter.next(),
4831            Some(&Component::PseudoElement(PseudoElement::Before))
4832        );
4833        assert_eq!(iter.next(), None);
4834        assert_eq!(iter.next_sequence(), Some(Combinator::PseudoElement));
4835        assert_eq!(iter.next(), None);
4836        assert_eq!(iter.next_sequence(), None);
4837    }
4838
4839    #[test]
4840    fn test_parse_implicit_scope() {
4841        assert_eq!(
4842            parse_relative_expected(".foo", ParseRelative::ForScope, None).unwrap(),
4843            SelectorList::from_vec(vec![Selector::from_vec(
4844                vec![
4845                    Component::ImplicitScope,
4846                    Component::Combinator(Combinator::Descendant),
4847                    Component::Class(DummyAtom::from("foo")),
4848                ],
4849                specificity(0, 1, 0),
4850                SelectorFlags::HAS_SCOPE,
4851            )])
4852        );
4853
4854        assert_eq!(
4855            parse_relative_expected(":scope .foo", ParseRelative::ForScope, None).unwrap(),
4856            SelectorList::from_vec(vec![Selector::from_vec(
4857                vec![
4858                    Component::Scope,
4859                    Component::Combinator(Combinator::Descendant),
4860                    Component::Class(DummyAtom::from("foo")),
4861                ],
4862                specificity(0, 2, 0),
4863                SelectorFlags::HAS_SCOPE
4864            )])
4865        );
4866
4867        assert_eq!(
4868            parse_relative_expected("> .foo", ParseRelative::ForScope, Some("> .foo")).unwrap(),
4869            SelectorList::from_vec(vec![Selector::from_vec(
4870                vec![
4871                    Component::ImplicitScope,
4872                    Component::Combinator(Combinator::Child),
4873                    Component::Class(DummyAtom::from("foo")),
4874                ],
4875                specificity(0, 1, 0),
4876                SelectorFlags::HAS_SCOPE
4877            )])
4878        );
4879
4880        assert_eq!(
4881            parse_relative_expected(".foo :scope > .bar", ParseRelative::ForScope, None).unwrap(),
4882            SelectorList::from_vec(vec![Selector::from_vec(
4883                vec![
4884                    Component::Class(DummyAtom::from("foo")),
4885                    Component::Combinator(Combinator::Descendant),
4886                    Component::Scope,
4887                    Component::Combinator(Combinator::Child),
4888                    Component::Class(DummyAtom::from("bar")),
4889                ],
4890                specificity(0, 3, 0),
4891                SelectorFlags::HAS_SCOPE
4892            )])
4893        );
4894    }
4895
4896    struct TestVisitor {
4897        seen: Vec<String>,
4898    }
4899
4900    impl SelectorVisitor for TestVisitor {
4901        type Impl = DummySelectorImpl;
4902
4903        fn visit_simple_selector(&mut self, s: &Component<DummySelectorImpl>) -> bool {
4904            let mut dest = String::new();
4905            s.to_css(&mut dest).unwrap();
4906            self.seen.push(dest);
4907            true
4908        }
4909    }
4910
4911    #[test]
4912    fn visitor() {
4913        let mut test_visitor = TestVisitor { seen: vec![] };
4914        parse(":not(:hover) ~ label").unwrap().slice()[0].visit(&mut test_visitor);
4915        assert!(test_visitor.seen.contains(&":hover".into()));
4916
4917        let mut test_visitor = TestVisitor { seen: vec![] };
4918        parse("::before:hover").unwrap().slice()[0].visit(&mut test_visitor);
4919        assert!(test_visitor.seen.contains(&":hover".into()));
4920    }
4921}