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        ) -> Vec<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                .into_boxed_slice()),
1341
1342                Host(Some(ref selector)) => Host(Some(replace_parent_on_selector(
1343                    selector,
1344                    parent,
1345                    &mut specificity,
1346                    &mut flags,
1347                    forbidden_flags,
1348                ))),
1349                NthOf(ref data) => {
1350                    let selectors = replace_parent_on_selector_list(
1351                        data.selectors(),
1352                        parent,
1353                        &mut specificity,
1354                        &mut flags,
1355                        /* propagate_specificity = */ true,
1356                        forbidden_flags,
1357                    );
1358                    NthOf(match selectors {
1359                        Some(s) => {
1360                            NthOfSelectorData::new(data.nth_data(), s.slice().iter().cloned())
1361                        },
1362                        None => data.clone(),
1363                    })
1364                },
1365                Slotted(ref selector) => Slotted(replace_parent_on_selector(
1366                    selector,
1367                    parent,
1368                    &mut specificity,
1369                    &mut flags,
1370                    forbidden_flags,
1371                )),
1372            }
1373        });
1374        let mut items = UniqueArc::from_header_and_iter(Default::default(), iter);
1375        *items.header_mut() = SpecificityAndFlags {
1376            specificity: specificity.into(),
1377            flags,
1378        };
1379        Selector(items.shareable())
1380    }
1381
1382    /// Returns count of simple selectors and combinators in the Selector.
1383    #[inline]
1384    pub fn len(&self) -> usize {
1385        self.0.len()
1386    }
1387
1388    /// Returns the address on the heap of the ThinArc for memory reporting.
1389    pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
1390        self.0.heap_ptr()
1391    }
1392
1393    /// Traverse selector components inside `self`.
1394    ///
1395    /// Implementations of this method should call `SelectorVisitor` methods
1396    /// or other impls of `Visit` as appropriate based on the fields of `Self`.
1397    ///
1398    /// A return value of `false` indicates terminating the traversal.
1399    /// It should be propagated with an early return.
1400    /// On the contrary, `true` indicates that all fields of `self` have been traversed:
1401    ///
1402    /// ```rust,ignore
1403    /// if !visitor.visit_simple_selector(&self.some_simple_selector) {
1404    ///     return false;
1405    /// }
1406    /// if !self.some_component.visit(visitor) {
1407    ///     return false;
1408    /// }
1409    /// true
1410    /// ```
1411    pub fn visit<V>(&self, visitor: &mut V) -> bool
1412    where
1413        V: SelectorVisitor<Impl = Impl>,
1414    {
1415        let mut current = self.iter();
1416        let mut combinator = None;
1417        loop {
1418            if !visitor.visit_complex_selector(combinator) {
1419                return false;
1420            }
1421
1422            for selector in &mut current {
1423                if !selector.visit(visitor) {
1424                    return false;
1425                }
1426            }
1427
1428            combinator = current.next_sequence();
1429            if combinator.is_none() {
1430                break;
1431            }
1432        }
1433
1434        true
1435    }
1436
1437    /// Parse a selector, without any pseudo-element.
1438    #[inline]
1439    pub fn parse<'i, 't, P>(
1440        parser: &P,
1441        input: &mut CssParser<'i, 't>,
1442    ) -> Result<Self, ParseError<'i, P::Error>>
1443    where
1444        P: Parser<'i, Impl = Impl>,
1445    {
1446        parse_selector(
1447            parser,
1448            input,
1449            SelectorParsingState::empty(),
1450            ParseRelative::No,
1451        )
1452    }
1453
1454    pub fn new_invalid(s: &str) -> Self {
1455        fn check_for_parent(input: &mut CssParser, has_parent: &mut bool) {
1456            while let Ok(t) = input.next() {
1457                match *t {
1458                    Token::Function(_)
1459                    | Token::ParenthesisBlock
1460                    | Token::CurlyBracketBlock
1461                    | Token::SquareBracketBlock => {
1462                        let _ = input.parse_nested_block(
1463                            |i| -> Result<(), ParseError<'_, BasicParseError>> {
1464                                check_for_parent(i, has_parent);
1465                                Ok(())
1466                            },
1467                        );
1468                    },
1469                    Token::Delim('&') => {
1470                        *has_parent = true;
1471                    },
1472                    _ => {},
1473                }
1474                if *has_parent {
1475                    break;
1476                }
1477            }
1478        }
1479        let mut has_parent = false;
1480        {
1481            let mut parser = cssparser::ParserInput::new(s);
1482            let mut parser = CssParser::new(&mut parser);
1483            check_for_parent(&mut parser, &mut has_parent);
1484        }
1485        Self(ThinArc::from_header_and_iter(
1486            SpecificityAndFlags {
1487                specificity: 0,
1488                flags: if has_parent {
1489                    SelectorFlags::HAS_PARENT
1490                } else {
1491                    SelectorFlags::empty()
1492                },
1493            },
1494            std::iter::once(Component::Invalid(Arc::new(String::from(s.trim())))),
1495        ))
1496    }
1497
1498    /// Is the compound starting at the offset the subject compound, or referring to its pseudo-element?
1499    pub fn is_rightmost(&self, offset: usize) -> bool {
1500        // There can really be only one pseudo-element, and it's not really valid for anything else to
1501        // follow it.
1502        offset == 0
1503            || matches!(
1504                self.combinator_at_match_order(offset - 1),
1505                Combinator::PseudoElement
1506            )
1507    }
1508}
1509
1510#[derive(Clone)]
1511pub struct SelectorIter<'a, Impl: 'a + SelectorImpl> {
1512    iter: slice::Iter<'a, Component<Impl>>,
1513    next_combinator: Option<Combinator>,
1514}
1515
1516impl<'a, Impl: 'a + SelectorImpl> SelectorIter<'a, Impl> {
1517    /// Prepares this iterator to point to the next sequence to the left,
1518    /// returning the combinator if the sequence was found.
1519    #[inline]
1520    pub fn next_sequence(&mut self) -> Option<Combinator> {
1521        self.next_combinator.take()
1522    }
1523
1524    /// Skips a sequence of simple selectors and all subsequent sequences until
1525    /// a non-pseudo-element ancestor combinator is reached.
1526    fn skip_until_ancestor(&mut self) {
1527        loop {
1528            while self.next().is_some() {}
1529            if self.next_sequence().is_none_or(|c| c.is_ancestor()) {
1530                break;
1531            }
1532        }
1533    }
1534
1535    #[inline]
1536    pub(crate) fn matches_for_stateless_pseudo_element(&mut self) -> bool {
1537        let first = match self.next() {
1538            Some(c) => c,
1539            // Note that this is the common path that we keep inline: the
1540            // pseudo-element not having anything to its right.
1541            None => return true,
1542        };
1543        self.matches_for_stateless_pseudo_element_internal(first)
1544    }
1545
1546    #[inline(never)]
1547    fn matches_for_stateless_pseudo_element_internal(&mut self, first: &Component<Impl>) -> bool {
1548        if !first.matches_for_stateless_pseudo_element() {
1549            return false;
1550        }
1551        for component in self {
1552            // The only other parser-allowed Components in this sequence are
1553            // state pseudo-classes, or one of the other things that can contain
1554            // them.
1555            if !component.matches_for_stateless_pseudo_element() {
1556                return false;
1557            }
1558        }
1559        true
1560    }
1561
1562    /// Returns remaining count of the simple selectors and combinators in the Selector.
1563    #[inline]
1564    pub fn selector_length(&self) -> usize {
1565        self.iter.len()
1566    }
1567}
1568
1569impl<'a, Impl: SelectorImpl> Iterator for SelectorIter<'a, Impl> {
1570    type Item = &'a Component<Impl>;
1571
1572    #[inline]
1573    fn next(&mut self) -> Option<Self::Item> {
1574        debug_assert!(
1575            self.next_combinator.is_none(),
1576            "You should call next_sequence!"
1577        );
1578        match *self.iter.next()? {
1579            Component::Combinator(c) => {
1580                self.next_combinator = Some(c);
1581                None
1582            },
1583            ref x => Some(x),
1584        }
1585    }
1586}
1587
1588impl<'a, Impl: SelectorImpl> fmt::Debug for SelectorIter<'a, Impl> {
1589    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1590        let iter = self.iter.clone().rev();
1591        for component in iter {
1592            component.to_css(f)?
1593        }
1594        Ok(())
1595    }
1596}
1597
1598/// An iterator over all combinators in a selector. Does not traverse selectors within psuedoclasses.
1599struct CombinatorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
1600impl<'a, Impl: 'a + SelectorImpl> CombinatorIter<'a, Impl> {
1601    fn new(inner: SelectorIter<'a, Impl>) -> Self {
1602        let mut result = CombinatorIter(inner);
1603        result.consume_non_combinators();
1604        result
1605    }
1606
1607    fn consume_non_combinators(&mut self) {
1608        while self.0.next().is_some() {}
1609    }
1610}
1611
1612impl<'a, Impl: SelectorImpl> Iterator for CombinatorIter<'a, Impl> {
1613    type Item = Combinator;
1614    fn next(&mut self) -> Option<Self::Item> {
1615        let result = self.0.next_sequence();
1616        self.consume_non_combinators();
1617        result
1618    }
1619}
1620
1621/// An iterator over all simple selectors belonging to ancestors.
1622struct AncestorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
1623impl<'a, Impl: SelectorImpl> Iterator for AncestorIter<'a, Impl> {
1624    type Item = &'a Component<Impl>;
1625    fn next(&mut self) -> Option<Self::Item> {
1626        // Grab the next simple selector in the sequence if available.
1627        let next = self.0.next();
1628        if next.is_some() {
1629            return next;
1630        }
1631        // See if there are more sequences. If so, skip any non-ancestor sequences.
1632        if !self.0.next_sequence()?.is_ancestor() {
1633            self.0.skip_until_ancestor();
1634        }
1635        self.0.next()
1636    }
1637}
1638
1639#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1640#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1641pub enum Combinator {
1642    Child,        //  >
1643    Descendant,   // space
1644    NextSibling,  // +
1645    LaterSibling, // ~
1646    /// A dummy combinator we use to the left of pseudo-elements.
1647    ///
1648    /// It serializes as the empty string, and acts effectively as a child
1649    /// combinator in most cases.  If we ever actually start using a child
1650    /// combinator for this, we will need to fix up the way hashes are computed
1651    /// for revalidation selectors.
1652    PseudoElement,
1653    /// Another combinator used for ::slotted(), which represent the jump from
1654    /// a node to its assigned slot.
1655    SlotAssignment,
1656    /// Another combinator used for `::part()`, which represents the jump from
1657    /// the part to the containing shadow host.
1658    Part,
1659}
1660
1661impl Combinator {
1662    /// Returns true if this combinator is a pseudo-element combinator.
1663    #[inline]
1664    pub fn is_pseudo_element(&self) -> bool {
1665        matches!(*self, Combinator::PseudoElement)
1666    }
1667
1668    /// Returns true if this combinator is a next- or later-sibling combinator.
1669    #[inline]
1670    pub fn is_sibling(&self) -> bool {
1671        matches!(*self, Combinator::NextSibling | Combinator::LaterSibling)
1672    }
1673
1674    /// Returns true if this combinator represents a jump to an ancestor. Note that this includes
1675    /// combinators like ::part() / ::slotted() and pseudo-elements!
1676    #[inline]
1677    pub fn is_ancestor(&self) -> bool {
1678        !self.is_sibling()
1679    }
1680}
1681
1682/// An enum for the different types of :nth- pseudoclasses
1683#[derive(Copy, Clone, Eq, PartialEq)]
1684#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1685#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1686pub enum NthType {
1687    Child,
1688    LastChild,
1689    OnlyChild,
1690    OfType,
1691    LastOfType,
1692    OnlyOfType,
1693}
1694
1695impl NthType {
1696    pub fn is_only(self) -> bool {
1697        self == Self::OnlyChild || self == Self::OnlyOfType
1698    }
1699
1700    pub fn is_of_type(self) -> bool {
1701        self == Self::OfType || self == Self::LastOfType || self == Self::OnlyOfType
1702    }
1703
1704    pub fn is_from_end(self) -> bool {
1705        self == Self::LastChild || self == Self::LastOfType
1706    }
1707}
1708
1709/// The properties that comprise an An+B syntax
1710#[derive(Copy, Clone, Eq, PartialEq, Debug)]
1711#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1712#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1713pub struct AnPlusB(pub i32, pub i32);
1714
1715impl AnPlusB {
1716    #[inline]
1717    pub fn matches_index(&self, i: i32) -> bool {
1718        // Is there a non-negative integer n such that An+B=i?
1719        match i.checked_sub(self.1) {
1720            None => false,
1721            Some(an) => match an.checked_div(self.0) {
1722                Some(n) => n >= 0 && self.0 * n == an,
1723                None /* a == 0 */ => an == 0,
1724            },
1725        }
1726    }
1727}
1728
1729impl ToCss for AnPlusB {
1730    /// Serialize <an+b> (part of the CSS Syntax spec).
1731    /// <https://drafts.csswg.org/css-syntax-3/#serialize-an-anb-value>
1732    #[inline]
1733    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1734    where
1735        W: fmt::Write,
1736    {
1737        match (self.0, self.1) {
1738            (0, 0) => dest.write_char('0'),
1739
1740            (1, 0) => dest.write_char('n'),
1741            (-1, 0) => dest.write_str("-n"),
1742            (_, 0) => write!(dest, "{}n", self.0),
1743
1744            (0, _) => write!(dest, "{}", self.1),
1745            (1, _) => write!(dest, "n{:+}", self.1),
1746            (-1, _) => write!(dest, "-n{:+}", self.1),
1747            (_, _) => write!(dest, "{}n{:+}", self.0, self.1),
1748        }
1749    }
1750}
1751
1752/// The properties that comprise an :nth- pseudoclass as of Selectors 3 (e.g.,
1753/// nth-child(An+B)).
1754/// https://www.w3.org/TR/selectors-3/#nth-child-pseudo
1755#[derive(Copy, Clone, Eq, PartialEq)]
1756#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1757#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1758pub struct NthSelectorData {
1759    pub ty: NthType,
1760    pub is_function: bool,
1761    pub an_plus_b: AnPlusB,
1762}
1763
1764impl NthSelectorData {
1765    /// Returns selector data for :only-{child,of-type}
1766    #[inline]
1767    pub const fn only(of_type: bool) -> Self {
1768        Self {
1769            ty: if of_type {
1770                NthType::OnlyOfType
1771            } else {
1772                NthType::OnlyChild
1773            },
1774            is_function: false,
1775            an_plus_b: AnPlusB(0, 1),
1776        }
1777    }
1778
1779    /// Returns selector data for :first-{child,of-type}
1780    #[inline]
1781    pub const fn first(of_type: bool) -> Self {
1782        Self {
1783            ty: if of_type {
1784                NthType::OfType
1785            } else {
1786                NthType::Child
1787            },
1788            is_function: false,
1789            an_plus_b: AnPlusB(0, 1),
1790        }
1791    }
1792
1793    /// Returns selector data for :last-{child,of-type}
1794    #[inline]
1795    pub const fn last(of_type: bool) -> Self {
1796        Self {
1797            ty: if of_type {
1798                NthType::LastOfType
1799            } else {
1800                NthType::LastChild
1801            },
1802            is_function: false,
1803            an_plus_b: AnPlusB(0, 1),
1804        }
1805    }
1806
1807    /// Returns true if this is an edge selector that is not `:*-of-type``
1808    #[inline]
1809    pub fn is_simple_edge(&self) -> bool {
1810        self.an_plus_b.0 == 0
1811            && self.an_plus_b.1 == 1
1812            && !self.ty.is_of_type()
1813            && !self.ty.is_only()
1814    }
1815
1816    /// Writes the beginning of the selector.
1817    #[inline]
1818    fn write_start<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
1819        dest.write_str(match self.ty {
1820            NthType::Child if self.is_function => ":nth-child(",
1821            NthType::Child => ":first-child",
1822            NthType::LastChild if self.is_function => ":nth-last-child(",
1823            NthType::LastChild => ":last-child",
1824            NthType::OfType if self.is_function => ":nth-of-type(",
1825            NthType::OfType => ":first-of-type",
1826            NthType::LastOfType if self.is_function => ":nth-last-of-type(",
1827            NthType::LastOfType => ":last-of-type",
1828            NthType::OnlyChild => ":only-child",
1829            NthType::OnlyOfType => ":only-of-type",
1830        })
1831    }
1832
1833    #[inline]
1834    fn write_affine<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
1835        self.an_plus_b.to_css(dest)
1836    }
1837}
1838
1839/// The properties that comprise an :nth- pseudoclass as of Selectors 4 (e.g.,
1840/// nth-child(An+B [of S]?)).
1841/// https://www.w3.org/TR/selectors-4/#nth-child-pseudo
1842#[derive(Clone, Eq, PartialEq)]
1843#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1844#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
1845pub struct NthOfSelectorData<Impl: SelectorImpl>(
1846    #[cfg_attr(feature = "to_shmem", shmem(field_bound))] ThinArc<NthSelectorData, Selector<Impl>>,
1847);
1848
1849impl<Impl: SelectorImpl> NthOfSelectorData<Impl> {
1850    /// Returns selector data for :nth-{,last-}{child,of-type}(An+B [of S])
1851    #[inline]
1852    pub fn new<I>(nth_data: &NthSelectorData, selectors: I) -> Self
1853    where
1854        I: Iterator<Item = Selector<Impl>> + ExactSizeIterator,
1855    {
1856        Self(ThinArc::from_header_and_iter(*nth_data, selectors))
1857    }
1858
1859    /// Returns the An+B part of the selector
1860    #[inline]
1861    pub fn nth_data(&self) -> &NthSelectorData {
1862        &self.0.header
1863    }
1864
1865    /// Returns the selector list part of the selector
1866    #[inline]
1867    pub fn selectors(&self) -> &[Selector<Impl>] {
1868        self.0.slice()
1869    }
1870}
1871
1872/// Flag indicating where a given relative selector's match would be contained.
1873#[derive(Clone, Copy, Eq, PartialEq)]
1874#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
1875pub enum RelativeSelectorMatchHint {
1876    /// Within this element's subtree.
1877    InSubtree,
1878    /// Within this element's direct children.
1879    InChild,
1880    /// This element's next sibling.
1881    InNextSibling,
1882    /// Within this element's next sibling's subtree.
1883    InNextSiblingSubtree,
1884    /// Within this element's subsequent siblings.
1885    InSibling,
1886    /// Across this element's subsequent siblings and their subtrees.
1887    InSiblingSubtree,
1888}
1889
1890impl RelativeSelectorMatchHint {
1891    /// Create a new relative selector match hint based on its composition.
1892    pub fn new(
1893        relative_combinator: Combinator,
1894        has_child_or_descendants: bool,
1895        has_adjacent_or_next_siblings: bool,
1896    ) -> Self {
1897        match relative_combinator {
1898            Combinator::Descendant => RelativeSelectorMatchHint::InSubtree,
1899            Combinator::Child => {
1900                if !has_child_or_descendants {
1901                    RelativeSelectorMatchHint::InChild
1902                } else {
1903                    // Technically, for any composition that consists of child combinators only,
1904                    // the search space is depth-constrained, but it's probably not worth optimizing for.
1905                    RelativeSelectorMatchHint::InSubtree
1906                }
1907            },
1908            Combinator::NextSibling => {
1909                if !has_child_or_descendants && !has_adjacent_or_next_siblings {
1910                    RelativeSelectorMatchHint::InNextSibling
1911                } else if !has_child_or_descendants && has_adjacent_or_next_siblings {
1912                    RelativeSelectorMatchHint::InSibling
1913                } else if has_child_or_descendants && !has_adjacent_or_next_siblings {
1914                    // Match won't cross multiple siblings.
1915                    RelativeSelectorMatchHint::InNextSiblingSubtree
1916                } else {
1917                    RelativeSelectorMatchHint::InSiblingSubtree
1918                }
1919            },
1920            Combinator::LaterSibling => {
1921                if !has_child_or_descendants {
1922                    RelativeSelectorMatchHint::InSibling
1923                } else {
1924                    // Even if the match may not cross multiple siblings, we have to look until
1925                    // we find a match anyway.
1926                    RelativeSelectorMatchHint::InSiblingSubtree
1927                }
1928            },
1929            Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
1930                debug_assert!(false, "Unexpected relative combinator");
1931                RelativeSelectorMatchHint::InSubtree
1932            },
1933        }
1934    }
1935
1936    /// Is the match traversal direction towards the descendant of this element (As opposed to siblings)?
1937    pub fn is_descendant_direction(&self) -> bool {
1938        matches!(*self, Self::InChild | Self::InSubtree)
1939    }
1940
1941    /// Is the match traversal terminated at the next sibling?
1942    pub fn is_next_sibling(&self) -> bool {
1943        matches!(*self, Self::InNextSibling | Self::InNextSiblingSubtree)
1944    }
1945
1946    /// Does the match involve matching the subtree?
1947    pub fn is_subtree(&self) -> bool {
1948        matches!(
1949            *self,
1950            Self::InSubtree | Self::InSiblingSubtree | Self::InNextSiblingSubtree
1951        )
1952    }
1953}
1954
1955/// Count of combinators in a given relative selector, not traversing selectors of pseudoclasses.
1956#[derive(Clone, Copy)]
1957pub struct RelativeSelectorCombinatorCount {
1958    relative_combinator: Combinator,
1959    pub child_or_descendants: usize,
1960    pub adjacent_or_next_siblings: usize,
1961}
1962
1963impl RelativeSelectorCombinatorCount {
1964    /// Create a new relative selector combinator count from a given relative selector.
1965    pub fn new<Impl: SelectorImpl>(relative_selector: &RelativeSelector<Impl>) -> Self {
1966        let mut result = RelativeSelectorCombinatorCount {
1967            relative_combinator: relative_selector.selector.combinator_at_parse_order(1),
1968            child_or_descendants: 0,
1969            adjacent_or_next_siblings: 0,
1970        };
1971
1972        for combinator in CombinatorIter::new(
1973            relative_selector
1974                .selector
1975                .iter_skip_relative_selector_anchor(),
1976        ) {
1977            match combinator {
1978                Combinator::Descendant | Combinator::Child => {
1979                    result.child_or_descendants += 1;
1980                },
1981                Combinator::NextSibling | Combinator::LaterSibling => {
1982                    result.adjacent_or_next_siblings += 1;
1983                },
1984                Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
1985                    continue;
1986                },
1987            };
1988        }
1989        result
1990    }
1991
1992    /// Get the match hint based on the current combinator count.
1993    pub fn get_match_hint(&self) -> RelativeSelectorMatchHint {
1994        RelativeSelectorMatchHint::new(
1995            self.relative_combinator,
1996            self.child_or_descendants != 0,
1997            self.adjacent_or_next_siblings != 0,
1998        )
1999    }
2000}
2001
2002/// Storage for a relative selector.
2003#[derive(Clone, Eq, PartialEq)]
2004#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
2005#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
2006pub struct RelativeSelector<Impl: SelectorImpl> {
2007    /// Match space constraining hint.
2008    pub match_hint: RelativeSelectorMatchHint,
2009    /// The selector. Guaranteed to contain `RelativeSelectorAnchor` and the relative combinator in parse order.
2010    #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2011    pub selector: Selector<Impl>,
2012}
2013
2014bitflags! {
2015    /// Composition of combinators in a given selector, not traversing selectors of pseudoclasses.
2016    #[derive(Clone, Debug, Eq, PartialEq)]
2017    struct CombinatorComposition: u8 {
2018        const DESCENDANTS = 1 << 0;
2019        const SIBLINGS = 1 << 1;
2020    }
2021}
2022
2023impl CombinatorComposition {
2024    fn for_relative_selector<Impl: SelectorImpl>(inner_selector: &Selector<Impl>) -> Self {
2025        let mut result = CombinatorComposition::empty();
2026        for combinator in CombinatorIter::new(inner_selector.iter_skip_relative_selector_anchor()) {
2027            match combinator {
2028                Combinator::Descendant | Combinator::Child => {
2029                    result.insert(Self::DESCENDANTS);
2030                },
2031                Combinator::NextSibling | Combinator::LaterSibling => {
2032                    result.insert(Self::SIBLINGS);
2033                },
2034                Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => {
2035                    continue;
2036                },
2037            };
2038            if result.is_all() {
2039                break;
2040            }
2041        }
2042        return result;
2043    }
2044}
2045
2046impl<Impl: SelectorImpl> RelativeSelector<Impl> {
2047    fn from_selector_list(selector_list: SelectorList<Impl>) -> Box<[Self]> {
2048        selector_list
2049            .slice()
2050            .iter()
2051            .map(|selector| {
2052                // It's more efficient to keep track of all this during the parse time, but that seems like a lot of special
2053                // case handling for what it's worth.
2054                if cfg!(debug_assertions) {
2055                    let relative_selector_anchor = selector.iter_raw_parse_order_from(0).next();
2056                    debug_assert!(
2057                        relative_selector_anchor.is_some(),
2058                        "Relative selector is empty"
2059                    );
2060                    debug_assert!(
2061                        matches!(
2062                            relative_selector_anchor.unwrap(),
2063                            Component::RelativeSelectorAnchor
2064                        ),
2065                        "Relative selector anchor is missing"
2066                    );
2067                }
2068                // Leave a hint for narrowing down the search space when we're matching.
2069                let composition = CombinatorComposition::for_relative_selector(&selector);
2070                let match_hint = RelativeSelectorMatchHint::new(
2071                    selector.combinator_at_parse_order(1),
2072                    composition.intersects(CombinatorComposition::DESCENDANTS),
2073                    composition.intersects(CombinatorComposition::SIBLINGS),
2074                );
2075                RelativeSelector {
2076                    match_hint,
2077                    selector: selector.clone(),
2078                }
2079            })
2080            .collect()
2081    }
2082}
2083
2084/// A CSS simple selector or combinator. We store both in the same enum for
2085/// optimal packing and cache performance, see [1].
2086///
2087/// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973
2088#[derive(Clone, Eq, PartialEq)]
2089#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
2090#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
2091pub enum Component<Impl: SelectorImpl> {
2092    LocalName(LocalName<Impl>),
2093
2094    ID(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::Identifier),
2095    Class(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::Identifier),
2096
2097    AttributeInNoNamespaceExists {
2098        #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2099        local_name: Impl::LocalName,
2100        local_name_lower: Impl::LocalName,
2101    },
2102    // Used only when local_name is already lowercase.
2103    AttributeInNoNamespace {
2104        local_name: Impl::LocalName,
2105        operator: AttrSelectorOperator,
2106        #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2107        value: Impl::AttrValue,
2108        case_sensitivity: ParsedCaseSensitivity,
2109    },
2110    // Use a Box in the less common cases with more data to keep size_of::<Component>() small.
2111    AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>),
2112
2113    ExplicitUniversalType,
2114    ExplicitAnyNamespace,
2115
2116    ExplicitNoNamespace,
2117    DefaultNamespace(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NamespaceUrl),
2118    Namespace(
2119        #[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NamespacePrefix,
2120        #[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NamespaceUrl,
2121    ),
2122
2123    /// Pseudo-classes
2124    Negation(SelectorList<Impl>),
2125    Root,
2126    Empty,
2127    Scope,
2128    /// :scope added implicitly into scoped rules (i.e. In `@scope`) not
2129    /// explicitly using `:scope` or `&` selectors.
2130    ///
2131    /// https://drafts.csswg.org/css-cascade-6/#scoped-rules
2132    ///
2133    /// Unlike the normal `:scope` selector, this does not add any specificity.
2134    /// See https://github.com/w3c/csswg-drafts/issues/10196
2135    ImplicitScope,
2136    ParentSelector,
2137    Nth(NthSelectorData),
2138    NthOf(NthOfSelectorData<Impl>),
2139    NonTSPseudoClass(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::NonTSPseudoClass),
2140    /// The ::slotted() pseudo-element:
2141    ///
2142    /// https://drafts.csswg.org/css-scoping/#slotted-pseudo
2143    ///
2144    /// The selector here is a compound selector, that is, no combinators.
2145    ///
2146    /// NOTE(emilio): This should support a list of selectors, but as of this
2147    /// writing no other browser does, and that allows them to put ::slotted()
2148    /// in the rule hash, so we do that too.
2149    ///
2150    /// See https://github.com/w3c/csswg-drafts/issues/2158
2151    Slotted(Selector<Impl>),
2152    /// The `::part` pseudo-element.
2153    ///   https://drafts.csswg.org/css-shadow-parts/#part
2154    Part(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Box<[Impl::Identifier]>),
2155    /// The `:host` pseudo-class:
2156    ///
2157    /// https://drafts.csswg.org/css-scoping/#host-selector
2158    ///
2159    /// NOTE(emilio): This should support a list of selectors, but as of this
2160    /// writing no other browser does, and that allows them to put :host()
2161    /// in the rule hash, so we do that too.
2162    ///
2163    /// See https://github.com/w3c/csswg-drafts/issues/2158
2164    Host(Option<Selector<Impl>>),
2165    /// The `:where` pseudo-class.
2166    ///
2167    /// https://drafts.csswg.org/selectors/#zero-matches
2168    ///
2169    /// The inner argument is conceptually a SelectorList, but we move the
2170    /// selectors to the heap to keep Component small.
2171    Where(SelectorList<Impl>),
2172    /// The `:is` pseudo-class.
2173    ///
2174    /// https://drafts.csswg.org/selectors/#matches-pseudo
2175    ///
2176    /// Same comment as above re. the argument.
2177    Is(SelectorList<Impl>),
2178    /// The `:has` pseudo-class.
2179    ///
2180    /// https://drafts.csswg.org/selectors/#has-pseudo
2181    ///
2182    /// Same comment as above re. the argument.
2183    Has(Box<[RelativeSelector<Impl>]>),
2184    /// An invalid selector inside :is() / :where().
2185    Invalid(Arc<String>),
2186    /// An implementation-dependent pseudo-element selector.
2187    PseudoElement(#[cfg_attr(feature = "to_shmem", shmem(field_bound))] Impl::PseudoElement),
2188
2189    Combinator(Combinator),
2190
2191    /// Used only for relative selectors, which starts with a combinator
2192    /// (With an implied descendant combinator if not specified).
2193    ///
2194    /// https://drafts.csswg.org/selectors-4/#typedef-relative-selector
2195    RelativeSelectorAnchor,
2196}
2197
2198impl<Impl: SelectorImpl> Component<Impl> {
2199    /// Returns true if this is a combinator.
2200    #[inline]
2201    pub fn is_combinator(&self) -> bool {
2202        matches!(*self, Component::Combinator(_))
2203    }
2204
2205    /// Returns true if this is a :host() selector.
2206    #[inline]
2207    pub fn is_host(&self) -> bool {
2208        matches!(*self, Component::Host(..))
2209    }
2210
2211    /// Returns the value as a combinator if applicable, None otherwise.
2212    pub fn as_combinator(&self) -> Option<Combinator> {
2213        match *self {
2214            Component::Combinator(c) => Some(c),
2215            _ => None,
2216        }
2217    }
2218
2219    /// Whether a given selector (to the right of a pseudo-element) should match for stateless
2220    /// pseudo-elements. Note that generally nothing matches for those, but since we have :not(),
2221    /// we still need to traverse nested selector lists.
2222    fn matches_for_stateless_pseudo_element(&self) -> bool {
2223        match *self {
2224            Component::Negation(ref selectors) => !selectors.slice().iter().all(|selector| {
2225                selector
2226                    .iter_raw_match_order()
2227                    .all(|c| c.matches_for_stateless_pseudo_element())
2228            }),
2229            Component::Is(ref selectors) | Component::Where(ref selectors) => {
2230                selectors.slice().iter().any(|selector| {
2231                    selector
2232                        .iter_raw_match_order()
2233                        .all(|c| c.matches_for_stateless_pseudo_element())
2234                })
2235            },
2236            _ => false,
2237        }
2238    }
2239
2240    pub fn visit<V>(&self, visitor: &mut V) -> bool
2241    where
2242        V: SelectorVisitor<Impl = Impl>,
2243    {
2244        use self::Component::*;
2245        if !visitor.visit_simple_selector(self) {
2246            return false;
2247        }
2248
2249        match *self {
2250            Slotted(ref selector) => {
2251                if !selector.visit(visitor) {
2252                    return false;
2253                }
2254            },
2255            Host(Some(ref selector)) => {
2256                if !selector.visit(visitor) {
2257                    return false;
2258                }
2259            },
2260            AttributeInNoNamespaceExists {
2261                ref local_name,
2262                ref local_name_lower,
2263            } => {
2264                if !visitor.visit_attribute_selector(
2265                    &NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
2266                    local_name,
2267                    local_name_lower,
2268                ) {
2269                    return false;
2270                }
2271            },
2272            AttributeInNoNamespace { ref local_name, .. } => {
2273                if !visitor.visit_attribute_selector(
2274                    &NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
2275                    local_name,
2276                    local_name,
2277                ) {
2278                    return false;
2279                }
2280            },
2281            AttributeOther(ref attr_selector) => {
2282                let empty_string;
2283                let namespace = match attr_selector.namespace() {
2284                    Some(ns) => ns,
2285                    None => {
2286                        empty_string = crate::parser::namespace_empty_string::<Impl>();
2287                        NamespaceConstraint::Specific(&empty_string)
2288                    },
2289                };
2290                if !visitor.visit_attribute_selector(
2291                    &namespace,
2292                    &attr_selector.local_name,
2293                    &attr_selector.local_name_lower,
2294                ) {
2295                    return false;
2296                }
2297            },
2298
2299            NonTSPseudoClass(ref pseudo_class) => {
2300                if !pseudo_class.visit(visitor) {
2301                    return false;
2302                }
2303            },
2304            Negation(ref list) | Is(ref list) | Where(ref list) => {
2305                let list_kind = SelectorListKind::from_component(self);
2306                debug_assert!(!list_kind.is_empty());
2307                if !visitor.visit_selector_list(list_kind, list.slice()) {
2308                    return false;
2309                }
2310            },
2311            NthOf(ref nth_of_data) => {
2312                if !visitor.visit_selector_list(SelectorListKind::NTH_OF, nth_of_data.selectors()) {
2313                    return false;
2314                }
2315            },
2316            Has(ref list) => {
2317                if !visitor.visit_relative_selector_list(list) {
2318                    return false;
2319                }
2320            },
2321            _ => {},
2322        }
2323
2324        true
2325    }
2326
2327    // Returns true if this has any selector that requires an index calculation. e.g.
2328    // :nth-child, :first-child, etc. For nested selectors, return true only if the
2329    // indexed selector is in its subject compound.
2330    pub fn has_indexed_selector_in_subject(&self) -> bool {
2331        match *self {
2332            Component::NthOf(..) | Component::Nth(..) => return true,
2333            Component::Is(ref selectors)
2334            | Component::Where(ref selectors)
2335            | Component::Negation(ref selectors) => {
2336                // Check the subject compound.
2337                for selector in selectors.slice() {
2338                    let mut iter = selector.iter();
2339                    while let Some(c) = iter.next() {
2340                        if c.has_indexed_selector_in_subject() {
2341                            return true;
2342                        }
2343                    }
2344                }
2345            },
2346            _ => (),
2347        };
2348        false
2349    }
2350}
2351
2352#[derive(Clone, Eq, PartialEq)]
2353#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
2354#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
2355pub struct LocalName<Impl: SelectorImpl> {
2356    #[cfg_attr(feature = "to_shmem", shmem(field_bound))]
2357    pub name: Impl::LocalName,
2358    pub lower_name: Impl::LocalName,
2359}
2360
2361impl<Impl: SelectorImpl> Debug for Selector<Impl> {
2362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2363        f.write_str("Selector(")?;
2364        self.to_css(f)?;
2365        write!(
2366            f,
2367            ", specificity = {:#x}, flags = {:?})",
2368            self.specificity(),
2369            self.flags()
2370        )
2371    }
2372}
2373
2374impl<Impl: SelectorImpl> Debug for Component<Impl> {
2375    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2376        self.to_css(f)
2377    }
2378}
2379impl<Impl: SelectorImpl> Debug for AttrSelectorWithOptionalNamespace<Impl> {
2380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2381        self.to_css(f)
2382    }
2383}
2384impl<Impl: SelectorImpl> Debug for LocalName<Impl> {
2385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2386        self.to_css(f)
2387    }
2388}
2389
2390fn serialize_selector_list<'a, Impl, I, W>(iter: I, dest: &mut W) -> fmt::Result
2391where
2392    Impl: SelectorImpl,
2393    I: Iterator<Item = &'a Selector<Impl>>,
2394    W: fmt::Write,
2395{
2396    let mut first = true;
2397    for selector in iter {
2398        if !first {
2399            dest.write_str(", ")?;
2400        }
2401        first = false;
2402        selector.to_css(dest)?;
2403    }
2404    Ok(())
2405}
2406
2407impl<Impl: SelectorImpl> ToCss for SelectorList<Impl> {
2408    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2409    where
2410        W: fmt::Write,
2411    {
2412        serialize_selector_list(self.slice().iter(), dest)
2413    }
2414}
2415
2416impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
2417    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2418    where
2419        W: fmt::Write,
2420    {
2421        // Compound selectors invert the order of their contents, so we need to
2422        // undo that during serialization.
2423        //
2424        // This two-iterator strategy involves walking over the selector twice.
2425        // We could do something more clever, but selector serialization probably
2426        // isn't hot enough to justify it, and the stringification likely
2427        // dominates anyway.
2428        //
2429        // NB: A parse-order iterator is a Rev<>, which doesn't expose as_slice(),
2430        // which we need for |split|. So we split by combinators on a match-order
2431        // sequence and then reverse.
2432
2433        let mut combinators = self
2434            .iter_raw_match_order()
2435            .rev()
2436            .filter_map(|x| x.as_combinator());
2437        let compound_selectors = self
2438            .iter_raw_match_order()
2439            .as_slice()
2440            .split(|x| x.is_combinator())
2441            .rev();
2442
2443        let mut combinators_exhausted = false;
2444        for compound in compound_selectors {
2445            debug_assert!(!combinators_exhausted);
2446
2447            // https://drafts.csswg.org/cssom/#serializing-selectors
2448            let first_compound = match compound.first() {
2449                None => continue,
2450                Some(c) => c,
2451            };
2452            if matches!(
2453                first_compound,
2454                Component::RelativeSelectorAnchor | Component::ImplicitScope
2455            ) {
2456                debug_assert!(
2457                    compound.len() == 1,
2458                    "RelativeSelectorAnchor/ImplicitScope should only be a simple selector"
2459                );
2460                if let Some(c) = combinators.next() {
2461                    c.to_css_relative(dest)?;
2462                } else {
2463                    // Direct property declarations in `@scope` does not have
2464                    // combinators, since its selector is `:implicit-scope`.
2465                    debug_assert!(
2466                        matches!(first_compound, Component::ImplicitScope),
2467                        "Only implicit :scope may not have any combinator"
2468                    );
2469                }
2470                continue;
2471            }
2472
2473            // 1. If there is only one simple selector in the compound selectors
2474            //    which is a universal selector, append the result of
2475            //    serializing the universal selector to s.
2476            //
2477            // Check if `!compound.empty()` first--this can happen if we have
2478            // something like `... > ::before`, because we store `>` and `::`
2479            // both as combinators internally.
2480            //
2481            // If we are in this case, after we have serialized the universal
2482            // selector, we skip Step 2 and continue with the algorithm.
2483            let (can_elide_namespace, first_non_namespace) = match compound[0] {
2484                Component::ExplicitAnyNamespace
2485                | Component::ExplicitNoNamespace
2486                | Component::Namespace(..) => (false, 1),
2487                Component::DefaultNamespace(..) => (true, 1),
2488                _ => (true, 0),
2489            };
2490            let mut perform_step_2 = true;
2491            let next_combinator = combinators.next();
2492            if first_non_namespace == compound.len() - 1 {
2493                match (next_combinator, &compound[first_non_namespace]) {
2494                    // We have to be careful here, because if there is a
2495                    // pseudo element "combinator" there isn't really just
2496                    // the one simple selector. Technically this compound
2497                    // selector contains the pseudo element selector as well
2498                    // -- Combinator::PseudoElement, just like
2499                    // Combinator::SlotAssignment, don't exist in the
2500                    // spec.
2501                    (Some(Combinator::PseudoElement), _)
2502                    | (Some(Combinator::SlotAssignment), _) => (),
2503                    (_, &Component::ExplicitUniversalType) => {
2504                        // Iterate over everything so we serialize the namespace
2505                        // too.
2506                        for simple in compound.iter() {
2507                            simple.to_css(dest)?;
2508                        }
2509                        // Skip step 2, which is an "otherwise".
2510                        perform_step_2 = false;
2511                    },
2512                    _ => (),
2513                }
2514            }
2515
2516            // 2. Otherwise, for each simple selector in the compound selectors
2517            //    that is not a universal selector of which the namespace prefix
2518            //    maps to a namespace that is not the default namespace
2519            //    serialize the simple selector and append the result to s.
2520            //
2521            // See https://github.com/w3c/csswg-drafts/issues/1606, which is
2522            // proposing to change this to match up with the behavior asserted
2523            // in cssom/serialize-namespaced-type-selectors.html, which the
2524            // following code tries to match.
2525            if perform_step_2 {
2526                for simple in compound.iter() {
2527                    if let Component::ExplicitUniversalType = *simple {
2528                        // Can't have a namespace followed by a pseudo-element
2529                        // selector followed by a universal selector in the same
2530                        // compound selector, so we don't have to worry about the
2531                        // real namespace being in a different `compound`.
2532                        if can_elide_namespace {
2533                            continue;
2534                        }
2535                    }
2536                    simple.to_css(dest)?;
2537                }
2538            }
2539
2540            // 3. If this is not the last part of the chain of the selector
2541            //    append a single SPACE (U+0020), followed by the combinator
2542            //    ">", "+", "~", ">>", "||", as appropriate, followed by another
2543            //    single SPACE (U+0020) if the combinator was not whitespace, to
2544            //    s.
2545            match next_combinator {
2546                Some(c) => c.to_css(dest)?,
2547                None => combinators_exhausted = true,
2548            };
2549
2550            // 4. If this is the last part of the chain of the selector and
2551            //    there is a pseudo-element, append "::" followed by the name of
2552            //    the pseudo-element, to s.
2553            //
2554            // (we handle this above)
2555        }
2556
2557        Ok(())
2558    }
2559}
2560
2561impl Combinator {
2562    fn to_css_internal<W>(&self, dest: &mut W, prefix_space: bool) -> fmt::Result
2563    where
2564        W: fmt::Write,
2565    {
2566        if matches!(
2567            *self,
2568            Combinator::PseudoElement | Combinator::Part | Combinator::SlotAssignment
2569        ) {
2570            return Ok(());
2571        }
2572        if prefix_space {
2573            dest.write_char(' ')?;
2574        }
2575        match *self {
2576            Combinator::Child => dest.write_str("> "),
2577            Combinator::Descendant => Ok(()),
2578            Combinator::NextSibling => dest.write_str("+ "),
2579            Combinator::LaterSibling => dest.write_str("~ "),
2580            Combinator::PseudoElement | Combinator::Part | Combinator::SlotAssignment => unsafe {
2581                debug_unreachable!("Already handled")
2582            },
2583        }
2584    }
2585
2586    fn to_css_relative<W>(&self, dest: &mut W) -> fmt::Result
2587    where
2588        W: fmt::Write,
2589    {
2590        self.to_css_internal(dest, false)
2591    }
2592}
2593
2594impl ToCss for Combinator {
2595    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2596    where
2597        W: fmt::Write,
2598    {
2599        self.to_css_internal(dest, true)
2600    }
2601}
2602
2603impl<Impl: SelectorImpl> ToCss for Component<Impl> {
2604    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2605    where
2606        W: fmt::Write,
2607    {
2608        use self::Component::*;
2609
2610        match *self {
2611            Combinator(ref c) => c.to_css(dest),
2612            Slotted(ref selector) => {
2613                dest.write_str("::slotted(")?;
2614                selector.to_css(dest)?;
2615                dest.write_char(')')
2616            },
2617            Part(ref part_names) => {
2618                dest.write_str("::part(")?;
2619                for (i, name) in part_names.iter().enumerate() {
2620                    if i != 0 {
2621                        dest.write_char(' ')?;
2622                    }
2623                    name.to_css(dest)?;
2624                }
2625                dest.write_char(')')
2626            },
2627            PseudoElement(ref p) => p.to_css(dest),
2628            ID(ref s) => {
2629                dest.write_char('#')?;
2630                s.to_css(dest)
2631            },
2632            Class(ref s) => {
2633                dest.write_char('.')?;
2634                s.to_css(dest)
2635            },
2636            LocalName(ref s) => s.to_css(dest),
2637            ExplicitUniversalType => dest.write_char('*'),
2638
2639            DefaultNamespace(_) => Ok(()),
2640            ExplicitNoNamespace => dest.write_char('|'),
2641            ExplicitAnyNamespace => dest.write_str("*|"),
2642            Namespace(ref prefix, _) => {
2643                prefix.to_css(dest)?;
2644                dest.write_char('|')
2645            },
2646
2647            AttributeInNoNamespaceExists { ref local_name, .. } => {
2648                dest.write_char('[')?;
2649                local_name.to_css(dest)?;
2650                dest.write_char(']')
2651            },
2652            AttributeInNoNamespace {
2653                ref local_name,
2654                operator,
2655                ref value,
2656                case_sensitivity,
2657                ..
2658            } => {
2659                dest.write_char('[')?;
2660                local_name.to_css(dest)?;
2661                operator.to_css(dest)?;
2662                value.to_css(dest)?;
2663                match case_sensitivity {
2664                    ParsedCaseSensitivity::CaseSensitive
2665                    | ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
2666                    },
2667                    ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
2668                    ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
2669                }
2670                dest.write_char(']')
2671            },
2672            AttributeOther(ref attr_selector) => attr_selector.to_css(dest),
2673
2674            // Pseudo-classes
2675            Root => dest.write_str(":root"),
2676            Empty => dest.write_str(":empty"),
2677            Scope => dest.write_str(":scope"),
2678            ParentSelector => dest.write_char('&'),
2679            Host(ref selector) => {
2680                dest.write_str(":host")?;
2681                if let Some(ref selector) = *selector {
2682                    dest.write_char('(')?;
2683                    selector.to_css(dest)?;
2684                    dest.write_char(')')?;
2685                }
2686                Ok(())
2687            },
2688            Nth(ref nth_data) => {
2689                nth_data.write_start(dest)?;
2690                if nth_data.is_function {
2691                    nth_data.write_affine(dest)?;
2692                    dest.write_char(')')?;
2693                }
2694                Ok(())
2695            },
2696            NthOf(ref nth_of_data) => {
2697                let nth_data = nth_of_data.nth_data();
2698                nth_data.write_start(dest)?;
2699                debug_assert!(
2700                    nth_data.is_function,
2701                    "A selector must be a function to hold An+B notation"
2702                );
2703                nth_data.write_affine(dest)?;
2704                debug_assert!(
2705                    matches!(nth_data.ty, NthType::Child | NthType::LastChild),
2706                    "Only :nth-child or :nth-last-child can be of a selector list"
2707                );
2708                debug_assert!(
2709                    !nth_of_data.selectors().is_empty(),
2710                    "The selector list should not be empty"
2711                );
2712                dest.write_str(" of ")?;
2713                serialize_selector_list(nth_of_data.selectors().iter(), dest)?;
2714                dest.write_char(')')
2715            },
2716            Is(ref list) | Where(ref list) | Negation(ref list) => {
2717                match *self {
2718                    Where(..) => dest.write_str(":where(")?,
2719                    Is(..) => dest.write_str(":is(")?,
2720                    Negation(..) => dest.write_str(":not(")?,
2721                    _ => unreachable!(),
2722                }
2723                serialize_selector_list(list.slice().iter(), dest)?;
2724                dest.write_str(")")
2725            },
2726            Has(ref list) => {
2727                dest.write_str(":has(")?;
2728                serialize_selector_list(list.iter().map(|rel| &rel.selector), dest)?;
2729                dest.write_str(")")
2730            },
2731            NonTSPseudoClass(ref pseudo) => pseudo.to_css(dest),
2732            Invalid(ref css) => dest.write_str(css),
2733            RelativeSelectorAnchor | ImplicitScope => Ok(()),
2734        }
2735    }
2736}
2737
2738impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> {
2739    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2740    where
2741        W: fmt::Write,
2742    {
2743        dest.write_char('[')?;
2744        match self.namespace {
2745            Some(NamespaceConstraint::Specific((ref prefix, _))) => {
2746                prefix.to_css(dest)?;
2747                dest.write_char('|')?
2748            },
2749            Some(NamespaceConstraint::Any) => dest.write_str("*|")?,
2750            None => {},
2751        }
2752        self.local_name.to_css(dest)?;
2753        match self.operation {
2754            ParsedAttrSelectorOperation::Exists => {},
2755            ParsedAttrSelectorOperation::WithValue {
2756                operator,
2757                case_sensitivity,
2758                ref value,
2759            } => {
2760                operator.to_css(dest)?;
2761                value.to_css(dest)?;
2762                match case_sensitivity {
2763                    ParsedCaseSensitivity::CaseSensitive
2764                    | ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
2765                    },
2766                    ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
2767                    ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
2768                }
2769            },
2770        }
2771        dest.write_char(']')
2772    }
2773}
2774
2775impl<Impl: SelectorImpl> ToCss for LocalName<Impl> {
2776    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2777    where
2778        W: fmt::Write,
2779    {
2780        self.name.to_css(dest)
2781    }
2782}
2783
2784/// Build up a Selector.
2785/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
2786///
2787/// `Err` means invalid selector.
2788fn parse_selector<'i, 't, P, Impl>(
2789    parser: &P,
2790    input: &mut CssParser<'i, 't>,
2791    mut state: SelectorParsingState,
2792    parse_relative: ParseRelative,
2793) -> Result<Selector<Impl>, ParseError<'i, P::Error>>
2794where
2795    P: Parser<'i, Impl = Impl>,
2796    Impl: SelectorImpl,
2797{
2798    let mut builder = SelectorBuilder::default();
2799
2800    // Helps rewind less, but also simplifies dealing with relative combinators below.
2801    input.skip_whitespace();
2802
2803    if parse_relative != ParseRelative::No {
2804        let combinator = try_parse_combinator(input);
2805        match parse_relative {
2806            ParseRelative::ForHas => {
2807                builder.push_simple_selector(Component::RelativeSelectorAnchor);
2808                // Do we see a combinator? If so, push that. Otherwise, push a descendant
2809                // combinator.
2810                builder.push_combinator(combinator.unwrap_or(Combinator::Descendant));
2811            },
2812            ParseRelative::ForNesting | ParseRelative::ForScope => {
2813                if let Ok(combinator) = combinator {
2814                    let selector = match parse_relative {
2815                        ParseRelative::ForHas | ParseRelative::No => unreachable!(),
2816                        ParseRelative::ForNesting => Component::ParentSelector,
2817                        // See https://github.com/w3c/csswg-drafts/issues/10196
2818                        // Implicitly added `:scope` does not add specificity
2819                        // for non-relative selectors, so do the same.
2820                        ParseRelative::ForScope => Component::ImplicitScope,
2821                    };
2822                    builder.push_simple_selector(selector);
2823                    builder.push_combinator(combinator);
2824                }
2825            },
2826            ParseRelative::No => unreachable!(),
2827        }
2828    }
2829    loop {
2830        // Parse a sequence of simple selectors.
2831        let empty = parse_compound_selector(parser, &mut state, input, &mut builder)?;
2832        if empty {
2833            return Err(input.new_custom_error(if builder.has_combinators() {
2834                SelectorParseErrorKind::DanglingCombinator
2835            } else {
2836                SelectorParseErrorKind::EmptySelector
2837            }));
2838        }
2839
2840        if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2841            debug_assert!(state.intersects(
2842                SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO
2843                    | SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO
2844                    | SelectorParsingState::AFTER_SLOTTED
2845                    | SelectorParsingState::AFTER_PART_LIKE
2846            ));
2847            break;
2848        }
2849
2850        let combinator = if let Ok(c) = try_parse_combinator(input) {
2851            c
2852        } else {
2853            break;
2854        };
2855
2856        if !state.allows_combinators() {
2857            return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
2858        }
2859
2860        builder.push_combinator(combinator);
2861    }
2862    return Ok(Selector(builder.build(parse_relative)));
2863}
2864
2865fn try_parse_combinator<'i, 't>(input: &mut CssParser<'i, 't>) -> Result<Combinator, ()> {
2866    let mut any_whitespace = false;
2867    loop {
2868        let before_this_token = input.state();
2869        match input.next_including_whitespace() {
2870            Err(_e) => return Err(()),
2871            Ok(&Token::WhiteSpace(_)) => any_whitespace = true,
2872            Ok(&Token::Delim('>')) => {
2873                return Ok(Combinator::Child);
2874            },
2875            Ok(&Token::Delim('+')) => {
2876                return Ok(Combinator::NextSibling);
2877            },
2878            Ok(&Token::Delim('~')) => {
2879                return Ok(Combinator::LaterSibling);
2880            },
2881            Ok(_) => {
2882                input.reset(&before_this_token);
2883                if any_whitespace {
2884                    return Ok(Combinator::Descendant);
2885                } else {
2886                    return Err(());
2887                }
2888            },
2889        }
2890    }
2891}
2892
2893/// * `Err(())`: Invalid selector, abort
2894/// * `Ok(false)`: Not a type selector, could be something else. `input` was not consumed.
2895/// * `Ok(true)`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
2896fn parse_type_selector<'i, 't, P, Impl, S>(
2897    parser: &P,
2898    input: &mut CssParser<'i, 't>,
2899    state: SelectorParsingState,
2900    sink: &mut S,
2901) -> Result<bool, ParseError<'i, P::Error>>
2902where
2903    P: Parser<'i, Impl = Impl>,
2904    Impl: SelectorImpl,
2905    S: Push<Component<Impl>>,
2906{
2907    match parse_qualified_name(parser, input, /* in_attr_selector = */ false) {
2908        Err(ParseError {
2909            kind: ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput),
2910            ..
2911        })
2912        | Ok(OptionalQName::None(_)) => Ok(false),
2913        Ok(OptionalQName::Some(namespace, local_name)) => {
2914            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2915                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
2916            }
2917            match namespace {
2918                QNamePrefix::ImplicitAnyNamespace => {},
2919                QNamePrefix::ImplicitDefaultNamespace(url) => {
2920                    sink.push(Component::DefaultNamespace(url))
2921                },
2922                QNamePrefix::ExplicitNamespace(prefix, url) => {
2923                    sink.push(match parser.default_namespace() {
2924                        Some(ref default_url) if url == *default_url => {
2925                            Component::DefaultNamespace(url)
2926                        },
2927                        _ => Component::Namespace(prefix, url),
2928                    })
2929                },
2930                QNamePrefix::ExplicitNoNamespace => sink.push(Component::ExplicitNoNamespace),
2931                QNamePrefix::ExplicitAnyNamespace => {
2932                    match parser.default_namespace() {
2933                        // Element type selectors that have no namespace
2934                        // component (no namespace separator) represent elements
2935                        // without regard to the element's namespace (equivalent
2936                        // to "*|") unless a default namespace has been declared
2937                        // for namespaced selectors (e.g. in CSS, in the style
2938                        // sheet). If a default namespace has been declared,
2939                        // such selectors will represent only elements in the
2940                        // default namespace.
2941                        // -- Selectors § 6.1.1
2942                        // So we'll have this act the same as the
2943                        // QNamePrefix::ImplicitAnyNamespace case.
2944                        None => {},
2945                        Some(_) => sink.push(Component::ExplicitAnyNamespace),
2946                    }
2947                },
2948                QNamePrefix::ImplicitNoNamespace => {
2949                    unreachable!() // Not returned with in_attr_selector = false
2950                },
2951            }
2952            match local_name {
2953                Some(name) => sink.push(Component::LocalName(LocalName {
2954                    lower_name: to_ascii_lowercase(&name).as_ref().into(),
2955                    name: name.as_ref().into(),
2956                })),
2957                None => sink.push(Component::ExplicitUniversalType),
2958            }
2959            Ok(true)
2960        },
2961        Err(e) => Err(e),
2962    }
2963}
2964
2965#[derive(Debug)]
2966enum SimpleSelectorParseResult<Impl: SelectorImpl> {
2967    SimpleSelector(Component<Impl>),
2968    PseudoElement(Impl::PseudoElement),
2969    SlottedPseudo(Selector<Impl>),
2970    PartPseudo(Box<[Impl::Identifier]>),
2971}
2972
2973#[derive(Debug)]
2974enum QNamePrefix<Impl: SelectorImpl> {
2975    ImplicitNoNamespace,                          // `foo` in attr selectors
2976    ImplicitAnyNamespace,                         // `foo` in type selectors, without a default ns
2977    ImplicitDefaultNamespace(Impl::NamespaceUrl), // `foo` in type selectors, with a default ns
2978    ExplicitNoNamespace,                          // `|foo`
2979    ExplicitAnyNamespace,                         // `*|foo`
2980    ExplicitNamespace(Impl::NamespacePrefix, Impl::NamespaceUrl), // `prefix|foo`
2981}
2982
2983enum OptionalQName<'i, Impl: SelectorImpl> {
2984    Some(QNamePrefix<Impl>, Option<CowRcStr<'i>>),
2985    None(Token<'i>),
2986}
2987
2988/// * `Err(())`: Invalid selector, abort
2989/// * `Ok(None(token))`: Not a simple selector, could be something else. `input` was not consumed,
2990///                      but the token is still returned.
2991/// * `Ok(Some(namespace, local_name))`: `None` for the local name means a `*` universal selector
2992fn parse_qualified_name<'i, 't, P, Impl>(
2993    parser: &P,
2994    input: &mut CssParser<'i, 't>,
2995    in_attr_selector: bool,
2996) -> Result<OptionalQName<'i, Impl>, ParseError<'i, P::Error>>
2997where
2998    P: Parser<'i, Impl = Impl>,
2999    Impl: SelectorImpl,
3000{
3001    let default_namespace = |local_name| {
3002        let namespace = match parser.default_namespace() {
3003            Some(url) => QNamePrefix::ImplicitDefaultNamespace(url),
3004            None => QNamePrefix::ImplicitAnyNamespace,
3005        };
3006        Ok(OptionalQName::Some(namespace, local_name))
3007    };
3008
3009    let explicit_namespace = |input: &mut CssParser<'i, 't>, namespace| {
3010        let location = input.current_source_location();
3011        match input.next_including_whitespace() {
3012            Ok(&Token::Delim('*')) if !in_attr_selector => Ok(OptionalQName::Some(namespace, None)),
3013            Ok(&Token::Ident(ref local_name)) => {
3014                Ok(OptionalQName::Some(namespace, Some(local_name.clone())))
3015            },
3016            Ok(t) if in_attr_selector => {
3017                let e = SelectorParseErrorKind::InvalidQualNameInAttr(t.clone());
3018                Err(location.new_custom_error(e))
3019            },
3020            Ok(t) => Err(location.new_custom_error(
3021                SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(t.clone()),
3022            )),
3023            Err(e) => Err(e.into()),
3024        }
3025    };
3026
3027    let start = input.state();
3028    match input.next_including_whitespace() {
3029        Ok(Token::Ident(value)) => {
3030            let value = value.clone();
3031            let after_ident = input.state();
3032            match input.next_including_whitespace() {
3033                Ok(&Token::Delim('|')) => {
3034                    let prefix = value.as_ref().into();
3035                    let result = parser.namespace_for_prefix(&prefix);
3036                    let url = result.ok_or(
3037                        after_ident
3038                            .source_location()
3039                            .new_custom_error(SelectorParseErrorKind::ExpectedNamespace(value)),
3040                    )?;
3041                    explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
3042                },
3043                _ => {
3044                    input.reset(&after_ident);
3045                    if in_attr_selector {
3046                        Ok(OptionalQName::Some(
3047                            QNamePrefix::ImplicitNoNamespace,
3048                            Some(value),
3049                        ))
3050                    } else {
3051                        default_namespace(Some(value))
3052                    }
3053                },
3054            }
3055        },
3056        Ok(Token::Delim('*')) => {
3057            let after_star = input.state();
3058            match input.next_including_whitespace() {
3059                Ok(&Token::Delim('|')) => {
3060                    explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
3061                },
3062                _ if !in_attr_selector => {
3063                    input.reset(&after_star);
3064                    default_namespace(None)
3065                },
3066                result => {
3067                    let t = result?;
3068                    Err(after_star
3069                        .source_location()
3070                        .new_custom_error(SelectorParseErrorKind::ExpectedBarInAttr(t.clone())))
3071                },
3072            }
3073        },
3074        Ok(Token::Delim('|')) => explicit_namespace(input, QNamePrefix::ExplicitNoNamespace),
3075        Ok(t) => {
3076            let t = t.clone();
3077            input.reset(&start);
3078            Ok(OptionalQName::None(t))
3079        },
3080        Err(e) => {
3081            input.reset(&start);
3082            Err(e.into())
3083        },
3084    }
3085}
3086
3087fn parse_attribute_selector<'i, 't, P, Impl>(
3088    parser: &P,
3089    input: &mut CssParser<'i, 't>,
3090) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3091where
3092    P: Parser<'i, Impl = Impl>,
3093    Impl: SelectorImpl,
3094{
3095    let namespace;
3096    let local_name;
3097
3098    input.skip_whitespace();
3099
3100    match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
3101        OptionalQName::None(t) => {
3102            return Err(input.new_custom_error(
3103                SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(t),
3104            ));
3105        },
3106        OptionalQName::Some(_, None) => unreachable!(),
3107        OptionalQName::Some(ns, Some(ln)) => {
3108            local_name = ln;
3109            namespace = match ns {
3110                QNamePrefix::ImplicitNoNamespace | QNamePrefix::ExplicitNoNamespace => None,
3111                QNamePrefix::ExplicitNamespace(prefix, url) => {
3112                    Some(NamespaceConstraint::Specific((prefix, url)))
3113                },
3114                QNamePrefix::ExplicitAnyNamespace => Some(NamespaceConstraint::Any),
3115                QNamePrefix::ImplicitAnyNamespace | QNamePrefix::ImplicitDefaultNamespace(_) => {
3116                    unreachable!() // Not returned with in_attr_selector = true
3117                },
3118            }
3119        },
3120    }
3121
3122    let location = input.current_source_location();
3123    let operator = match input.next() {
3124        // [foo]
3125        Err(_) => {
3126            let local_name_lower = to_ascii_lowercase(&local_name).as_ref().into();
3127            let local_name = local_name.as_ref().into();
3128            if let Some(namespace) = namespace {
3129                return Ok(Component::AttributeOther(Box::new(
3130                    AttrSelectorWithOptionalNamespace {
3131                        namespace: Some(namespace),
3132                        local_name,
3133                        local_name_lower,
3134                        operation: ParsedAttrSelectorOperation::Exists,
3135                    },
3136                )));
3137            } else {
3138                return Ok(Component::AttributeInNoNamespaceExists {
3139                    local_name,
3140                    local_name_lower,
3141                });
3142            }
3143        },
3144
3145        // [foo=bar]
3146        Ok(&Token::Delim('=')) => AttrSelectorOperator::Equal,
3147        // [foo~=bar]
3148        Ok(&Token::IncludeMatch) => AttrSelectorOperator::Includes,
3149        // [foo|=bar]
3150        Ok(&Token::DashMatch) => AttrSelectorOperator::DashMatch,
3151        // [foo^=bar]
3152        Ok(&Token::PrefixMatch) => AttrSelectorOperator::Prefix,
3153        // [foo*=bar]
3154        Ok(&Token::SubstringMatch) => AttrSelectorOperator::Substring,
3155        // [foo$=bar]
3156        Ok(&Token::SuffixMatch) => AttrSelectorOperator::Suffix,
3157        Ok(t) => {
3158            return Err(location.new_custom_error(
3159                SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(t.clone()),
3160            ));
3161        },
3162    };
3163
3164    let value = match input.expect_ident_or_string() {
3165        Ok(t) => t.clone(),
3166        Err(BasicParseError {
3167            kind: BasicParseErrorKind::UnexpectedToken(t),
3168            location,
3169        }) => return Err(location.new_custom_error(SelectorParseErrorKind::BadValueInAttr(t))),
3170        Err(e) => return Err(e.into()),
3171    };
3172
3173    let attribute_flags = parse_attribute_flags(input)?;
3174    let value = value.as_ref().into();
3175    let local_name_lower;
3176    let local_name_is_ascii_lowercase;
3177    let case_sensitivity;
3178    {
3179        let local_name_lower_cow = to_ascii_lowercase(&local_name);
3180        case_sensitivity =
3181            attribute_flags.to_case_sensitivity(local_name_lower_cow.as_ref(), namespace.is_some());
3182        local_name_lower = local_name_lower_cow.as_ref().into();
3183        local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..));
3184    }
3185    let local_name = local_name.as_ref().into();
3186    if namespace.is_some() || !local_name_is_ascii_lowercase {
3187        Ok(Component::AttributeOther(Box::new(
3188            AttrSelectorWithOptionalNamespace {
3189                namespace,
3190                local_name,
3191                local_name_lower,
3192                operation: ParsedAttrSelectorOperation::WithValue {
3193                    operator,
3194                    case_sensitivity,
3195                    value,
3196                },
3197            },
3198        )))
3199    } else {
3200        Ok(Component::AttributeInNoNamespace {
3201            local_name,
3202            operator,
3203            value,
3204            case_sensitivity,
3205        })
3206    }
3207}
3208
3209/// An attribute selector can have 's' or 'i' as flags, or no flags at all.
3210enum AttributeFlags {
3211    // Matching should be case-sensitive ('s' flag).
3212    CaseSensitive,
3213    // Matching should be case-insensitive ('i' flag).
3214    AsciiCaseInsensitive,
3215    // No flags.  Matching behavior depends on the name of the attribute.
3216    CaseSensitivityDependsOnName,
3217}
3218
3219impl AttributeFlags {
3220    fn to_case_sensitivity(
3221        self,
3222        local_name_lower: &str,
3223        have_namespace: bool,
3224    ) -> ParsedCaseSensitivity {
3225        match self {
3226            AttributeFlags::CaseSensitive => ParsedCaseSensitivity::ExplicitCaseSensitive,
3227            AttributeFlags::AsciiCaseInsensitive => ParsedCaseSensitivity::AsciiCaseInsensitive,
3228            AttributeFlags::CaseSensitivityDependsOnName => {
3229                if !have_namespace
3230                    && include!(concat!(
3231                        env!("OUT_DIR"),
3232                        "/ascii_case_insensitive_html_attributes.rs"
3233                    ))
3234                    .contains(local_name_lower)
3235                {
3236                    ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
3237                } else {
3238                    ParsedCaseSensitivity::CaseSensitive
3239                }
3240            },
3241        }
3242    }
3243}
3244
3245fn parse_attribute_flags<'i, 't>(
3246    input: &mut CssParser<'i, 't>,
3247) -> Result<AttributeFlags, BasicParseError<'i>> {
3248    let location = input.current_source_location();
3249    let token = match input.next() {
3250        Ok(t) => t,
3251        Err(..) => {
3252            // Selectors spec says language-defined; HTML says it depends on the
3253            // exact attribute name.
3254            return Ok(AttributeFlags::CaseSensitivityDependsOnName);
3255        },
3256    };
3257
3258    let ident = match *token {
3259        Token::Ident(ref i) => i,
3260        ref other => return Err(location.new_basic_unexpected_token_error(other.clone())),
3261    };
3262
3263    Ok(match_ignore_ascii_case! {
3264        ident,
3265        "i" => AttributeFlags::AsciiCaseInsensitive,
3266        "s" => AttributeFlags::CaseSensitive,
3267        _ => return Err(location.new_basic_unexpected_token_error(token.clone())),
3268    })
3269}
3270
3271/// Level 3: Parse **one** simple_selector.  (Though we might insert a second
3272/// implied "<defaultns>|*" type selector.)
3273fn parse_negation<'i, 't, P, Impl>(
3274    parser: &P,
3275    input: &mut CssParser<'i, 't>,
3276    state: SelectorParsingState,
3277) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3278where
3279    P: Parser<'i, Impl = Impl>,
3280    Impl: SelectorImpl,
3281{
3282    let list = SelectorList::parse_with_state(
3283        parser,
3284        input,
3285        state
3286            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3287            | SelectorParsingState::DISALLOW_PSEUDOS,
3288        ForgivingParsing::No,
3289        ParseRelative::No,
3290    )?;
3291
3292    Ok(Component::Negation(list))
3293}
3294
3295/// simple_selector_sequence
3296/// : [ type_selector | universal ] [ HASH | class | attrib | pseudo | negation ]*
3297/// | [ HASH | class | attrib | pseudo | negation ]+
3298///
3299/// `Err(())` means invalid selector.
3300/// `Ok(true)` is an empty selector
3301fn parse_compound_selector<'i, 't, P, Impl>(
3302    parser: &P,
3303    state: &mut SelectorParsingState,
3304    input: &mut CssParser<'i, 't>,
3305    builder: &mut SelectorBuilder<Impl>,
3306) -> Result<bool, ParseError<'i, P::Error>>
3307where
3308    P: Parser<'i, Impl = Impl>,
3309    Impl: SelectorImpl,
3310{
3311    input.skip_whitespace();
3312
3313    let mut empty = true;
3314    if parse_type_selector(parser, input, *state, builder)? {
3315        empty = false;
3316    }
3317
3318    loop {
3319        let result = match parse_one_simple_selector(parser, input, *state)? {
3320            None => break,
3321            Some(result) => result,
3322        };
3323
3324        if empty {
3325            if let Some(url) = parser.default_namespace() {
3326                // If there was no explicit type selector, but there is a
3327                // default namespace, there is an implicit "<defaultns>|*" type
3328                // selector. Except for :host() or :not() / :is() / :where(),
3329                // where we ignore it.
3330                //
3331                // https://drafts.csswg.org/css-scoping/#host-element-in-tree:
3332                //
3333                //     When considered within its own shadow trees, the shadow
3334                //     host is featureless. Only the :host, :host(), and
3335                //     :host-context() pseudo-classes are allowed to match it.
3336                //
3337                // https://drafts.csswg.org/selectors-4/#featureless:
3338                //
3339                //     A featureless element does not match any selector at all,
3340                //     except those it is explicitly defined to match. If a
3341                //     given selector is allowed to match a featureless element,
3342                //     it must do so while ignoring the default namespace.
3343                //
3344                // https://drafts.csswg.org/selectors-4/#matches
3345                //
3346                //     Default namespace declarations do not affect the compound
3347                //     selector representing the subject of any selector within
3348                //     a :is() pseudo-class, unless that compound selector
3349                //     contains an explicit universal selector or type selector.
3350                //
3351                //     (Similar quotes for :where() / :not())
3352                //
3353                let ignore_default_ns = state
3354                    .intersects(SelectorParsingState::SKIP_DEFAULT_NAMESPACE)
3355                    || matches!(
3356                        result,
3357                        SimpleSelectorParseResult::SimpleSelector(Component::Host(..))
3358                    );
3359                if !ignore_default_ns {
3360                    builder.push_simple_selector(Component::DefaultNamespace(url));
3361                }
3362            }
3363        }
3364
3365        empty = false;
3366
3367        match result {
3368            SimpleSelectorParseResult::SimpleSelector(s) => {
3369                builder.push_simple_selector(s);
3370            },
3371            SimpleSelectorParseResult::PartPseudo(part_names) => {
3372                state.insert(SelectorParsingState::AFTER_PART_LIKE);
3373                builder.push_combinator(Combinator::Part);
3374                builder.push_simple_selector(Component::Part(part_names));
3375            },
3376            SimpleSelectorParseResult::SlottedPseudo(selector) => {
3377                state.insert(SelectorParsingState::AFTER_SLOTTED);
3378                builder.push_combinator(Combinator::SlotAssignment);
3379                builder.push_simple_selector(Component::Slotted(selector));
3380            },
3381            SimpleSelectorParseResult::PseudoElement(p) => {
3382                if p.parses_as_element_backed() {
3383                    state.insert(SelectorParsingState::AFTER_PART_LIKE);
3384                } else {
3385                    state.insert(SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO);
3386                    if p.is_before_or_after() {
3387                        state.insert(SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO);
3388                    }
3389                }
3390                if !p.accepts_state_pseudo_classes() {
3391                    state.insert(SelectorParsingState::AFTER_NON_STATEFUL_PSEUDO_ELEMENT);
3392                }
3393                if p.is_in_pseudo_element_tree() {
3394                    state.insert(SelectorParsingState::IN_PSEUDO_ELEMENT_TREE);
3395                }
3396                builder.push_combinator(Combinator::PseudoElement);
3397                builder.push_simple_selector(Component::PseudoElement(p));
3398            },
3399        }
3400    }
3401    Ok(empty)
3402}
3403
3404fn parse_is_where<'i, 't, P, Impl>(
3405    parser: &P,
3406    input: &mut CssParser<'i, 't>,
3407    state: SelectorParsingState,
3408    component: impl FnOnce(SelectorList<Impl>) -> Component<Impl>,
3409) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3410where
3411    P: Parser<'i, Impl = Impl>,
3412    Impl: SelectorImpl,
3413{
3414    debug_assert!(parser.parse_is_and_where());
3415    // https://drafts.csswg.org/selectors/#matches-pseudo:
3416    //
3417    //     Pseudo-elements cannot be represented by the matches-any
3418    //     pseudo-class; they are not valid within :is().
3419    //
3420    let inner = SelectorList::parse_with_state(
3421        parser,
3422        input,
3423        state
3424            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3425            | SelectorParsingState::DISALLOW_PSEUDOS,
3426        ForgivingParsing::Yes,
3427        ParseRelative::No,
3428    )?;
3429    Ok(component(inner))
3430}
3431
3432fn parse_has<'i, 't, P, Impl>(
3433    parser: &P,
3434    input: &mut CssParser<'i, 't>,
3435    state: SelectorParsingState,
3436) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3437where
3438    P: Parser<'i, Impl = Impl>,
3439    Impl: SelectorImpl,
3440{
3441    debug_assert!(parser.parse_has());
3442    if state.intersects(
3443        SelectorParsingState::DISALLOW_RELATIVE_SELECTOR | SelectorParsingState::AFTER_PSEUDO,
3444    ) {
3445        return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3446    }
3447    // Nested `:has()` is disallowed, mark it as such.
3448    // Note: The spec defines ":has-allowed pseudo-element," but there's no
3449    // pseudo-element defined as such at the moment.
3450    // https://w3c.github.io/csswg-drafts/selectors-4/#has-allowed-pseudo-element
3451    let inner = SelectorList::parse_with_state(
3452        parser,
3453        input,
3454        state
3455            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3456            | SelectorParsingState::DISALLOW_PSEUDOS
3457            | SelectorParsingState::DISALLOW_RELATIVE_SELECTOR,
3458        ForgivingParsing::No,
3459        ParseRelative::ForHas,
3460    )?;
3461    Ok(Component::Has(RelativeSelector::from_selector_list(inner)))
3462}
3463
3464fn parse_functional_pseudo_class<'i, 't, P, Impl>(
3465    parser: &P,
3466    input: &mut CssParser<'i, 't>,
3467    name: CowRcStr<'i>,
3468    state: SelectorParsingState,
3469) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3470where
3471    P: Parser<'i, Impl = Impl>,
3472    Impl: SelectorImpl,
3473{
3474    match_ignore_ascii_case! { &name,
3475        "nth-child" => return parse_nth_pseudo_class(parser, input, state, NthType::Child),
3476        "nth-of-type" => return parse_nth_pseudo_class(parser, input, state, NthType::OfType),
3477        "nth-last-child" => return parse_nth_pseudo_class(parser, input, state, NthType::LastChild),
3478        "nth-last-of-type" => return parse_nth_pseudo_class(parser, input, state, NthType::LastOfType),
3479        "is" if parser.parse_is_and_where() => return parse_is_where(parser, input, state, Component::Is),
3480        "where" if parser.parse_is_and_where() => return parse_is_where(parser, input, state, Component::Where),
3481        "has" if parser.parse_has() => return parse_has(parser, input, state),
3482        "host" => {
3483            if !state.allows_tree_structural_pseudo_classes() {
3484                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3485            }
3486            return Ok(Component::Host(Some(parse_inner_compound_selector(parser, input, state)?)));
3487        },
3488        "not" => {
3489            return parse_negation(parser, input, state)
3490        },
3491        _ => {}
3492    }
3493
3494    if parser.parse_is_and_where() && parser.is_is_alias(&name) {
3495        return parse_is_where(parser, input, state, Component::Is);
3496    }
3497
3498    if state.intersects(
3499        SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO | SelectorParsingState::AFTER_SLOTTED,
3500    ) {
3501        return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3502    }
3503
3504    let after_part = state.intersects(SelectorParsingState::AFTER_PART_LIKE);
3505    P::parse_non_ts_functional_pseudo_class(parser, name, input, after_part)
3506        .map(Component::NonTSPseudoClass)
3507}
3508
3509fn parse_nth_pseudo_class<'i, 't, P, Impl>(
3510    parser: &P,
3511    input: &mut CssParser<'i, 't>,
3512    state: SelectorParsingState,
3513    ty: NthType,
3514) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3515where
3516    P: Parser<'i, Impl = Impl>,
3517    Impl: SelectorImpl,
3518{
3519    if !state.allows_tree_structural_pseudo_classes() {
3520        return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3521    }
3522    let (a, b) = parse_nth(input)?;
3523    let nth_data = NthSelectorData {
3524        ty,
3525        is_function: true,
3526        an_plus_b: AnPlusB(a, b),
3527    };
3528    if !parser.parse_nth_child_of() || ty.is_of_type() {
3529        return Ok(Component::Nth(nth_data));
3530    }
3531
3532    // Try to parse "of <selector-list>".
3533    if input.try_parse(|i| i.expect_ident_matching("of")).is_err() {
3534        return Ok(Component::Nth(nth_data));
3535    }
3536    // Whitespace between "of" and the selector list is optional
3537    // https://github.com/w3c/csswg-drafts/issues/8285
3538    let selectors = SelectorList::parse_with_state(
3539        parser,
3540        input,
3541        state
3542            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
3543            | SelectorParsingState::DISALLOW_PSEUDOS,
3544        ForgivingParsing::No,
3545        ParseRelative::No,
3546    )?;
3547    Ok(Component::NthOf(NthOfSelectorData::new(
3548        &nth_data,
3549        selectors.slice().iter().cloned(),
3550    )))
3551}
3552
3553/// Returns whether the name corresponds to a CSS2 pseudo-element that
3554/// can be specified with the single colon syntax (in addition to the
3555/// double-colon syntax, which can be used for all pseudo-elements).
3556pub fn is_css2_pseudo_element(name: &str) -> bool {
3557    // ** Do not add to this list! **
3558    match_ignore_ascii_case! { name,
3559        "before" | "after" | "first-line" | "first-letter" => true,
3560        _ => false,
3561    }
3562}
3563
3564/// Parse a simple selector other than a type selector.
3565///
3566/// * `Err(())`: Invalid selector, abort
3567/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
3568/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
3569fn parse_one_simple_selector<'i, 't, P, Impl>(
3570    parser: &P,
3571    input: &mut CssParser<'i, 't>,
3572    state: SelectorParsingState,
3573) -> Result<Option<SimpleSelectorParseResult<Impl>>, ParseError<'i, P::Error>>
3574where
3575    P: Parser<'i, Impl = Impl>,
3576    Impl: SelectorImpl,
3577{
3578    let start = input.state();
3579    let token = match input.next_including_whitespace().map(|t| t.clone()) {
3580        Ok(t) => t,
3581        Err(..) => {
3582            input.reset(&start);
3583            return Ok(None);
3584        },
3585    };
3586
3587    Ok(Some(match token {
3588        Token::IDHash(id) => {
3589            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
3590                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3591            }
3592            let id = Component::ID(id.as_ref().into());
3593            SimpleSelectorParseResult::SimpleSelector(id)
3594        },
3595        Token::Delim(delim) if delim == '.' || (delim == '&' && parser.parse_parent_selector()) => {
3596            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
3597                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3598            }
3599            let location = input.current_source_location();
3600            SimpleSelectorParseResult::SimpleSelector(if delim == '&' {
3601                Component::ParentSelector
3602            } else {
3603                let class = match *input.next_including_whitespace()? {
3604                    Token::Ident(ref class) => class,
3605                    ref t => {
3606                        let e = SelectorParseErrorKind::ClassNeedsIdent(t.clone());
3607                        return Err(location.new_custom_error(e));
3608                    },
3609                };
3610                Component::Class(class.as_ref().into())
3611            })
3612        },
3613        Token::SquareBracketBlock => {
3614            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
3615                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3616            }
3617            let attr = input.parse_nested_block(|input| parse_attribute_selector(parser, input))?;
3618            SimpleSelectorParseResult::SimpleSelector(attr)
3619        },
3620        Token::Colon => {
3621            let location = input.current_source_location();
3622            let (is_single_colon, next_token) = match input.next_including_whitespace()?.clone() {
3623                Token::Colon => (false, input.next_including_whitespace()?.clone()),
3624                t => (true, t),
3625            };
3626            let (name, is_functional) = match next_token {
3627                Token::Ident(name) => (name, false),
3628                Token::Function(name) => (name, true),
3629                t => {
3630                    let e = SelectorParseErrorKind::PseudoElementExpectedIdent(t);
3631                    return Err(input.new_custom_error(e));
3632                },
3633            };
3634            let is_pseudo_element = !is_single_colon || is_css2_pseudo_element(&name);
3635            if is_pseudo_element {
3636                // Pseudos after pseudo elements are not allowed in some cases:
3637                // - Some states will disallow pseudos, such as the interiors of
3638                // :has/:is/:where/:not (DISALLOW_PSEUDOS).
3639                // - Non-element backed pseudos do not allow other pseudos to follow (AFTER_NON_ELEMENT_BACKED_PSEUDO)...
3640                // - ... except ::before and ::after, which allow _some_ pseudos.
3641                if state.intersects(SelectorParsingState::DISALLOW_PSEUDOS)
3642                    || (state.intersects(SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO)
3643                        && !state.intersects(SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO))
3644                {
3645                    return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3646                }
3647                let pseudo_element = if is_functional {
3648                    if P::parse_part(parser) && name.eq_ignore_ascii_case("part") {
3649                        if !state.allows_part() {
3650                            return Err(
3651                                input.new_custom_error(SelectorParseErrorKind::InvalidState)
3652                            );
3653                        }
3654                        let names = input.parse_nested_block(|input| {
3655                            let mut result = Vec::with_capacity(1);
3656                            result.push(input.expect_ident()?.as_ref().into());
3657                            while !input.is_exhausted() {
3658                                result.push(input.expect_ident()?.as_ref().into());
3659                            }
3660                            Ok(result.into_boxed_slice())
3661                        })?;
3662                        return Ok(Some(SimpleSelectorParseResult::PartPseudo(names)));
3663                    }
3664                    if P::parse_slotted(parser) && name.eq_ignore_ascii_case("slotted") {
3665                        if !state.allows_slotted() {
3666                            return Err(
3667                                input.new_custom_error(SelectorParseErrorKind::InvalidState)
3668                            );
3669                        }
3670                        let selector = input.parse_nested_block(|input| {
3671                            parse_inner_compound_selector(parser, input, state)
3672                        })?;
3673                        return Ok(Some(SimpleSelectorParseResult::SlottedPseudo(selector)));
3674                    }
3675                    input.parse_nested_block(|input| {
3676                        P::parse_functional_pseudo_element(parser, name, input)
3677                    })?
3678                } else {
3679                    P::parse_pseudo_element(parser, location, name)?
3680                };
3681
3682                if state.intersects(SelectorParsingState::AFTER_BEFORE_OR_AFTER_PSEUDO)
3683                    && !pseudo_element.valid_after_before_or_after()
3684                {
3685                    return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3686                }
3687
3688                if state.intersects(SelectorParsingState::AFTER_SLOTTED)
3689                    && !pseudo_element.valid_after_slotted()
3690                {
3691                    return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
3692                }
3693                SimpleSelectorParseResult::PseudoElement(pseudo_element)
3694            } else {
3695                let pseudo_class = if is_functional {
3696                    input.parse_nested_block(|input| {
3697                        parse_functional_pseudo_class(parser, input, name, state)
3698                    })?
3699                } else {
3700                    parse_simple_pseudo_class(parser, location, name, state)?
3701                };
3702                SimpleSelectorParseResult::SimpleSelector(pseudo_class)
3703            }
3704        },
3705        _ => {
3706            input.reset(&start);
3707            return Ok(None);
3708        },
3709    }))
3710}
3711
3712fn parse_simple_pseudo_class<'i, P, Impl>(
3713    parser: &P,
3714    location: SourceLocation,
3715    name: CowRcStr<'i>,
3716    state: SelectorParsingState,
3717) -> Result<Component<Impl>, ParseError<'i, P::Error>>
3718where
3719    P: Parser<'i, Impl = Impl>,
3720    Impl: SelectorImpl,
3721{
3722    if !state.allows_non_functional_pseudo_classes() {
3723        return Err(location.new_custom_error(SelectorParseErrorKind::InvalidState));
3724    }
3725
3726    if state.allows_tree_structural_pseudo_classes() {
3727        // If a descendant pseudo of a pseudo-element root has no other siblings, then :only-child
3728        // matches that pseudo. Note that we don't accept other tree structural pseudo classes in
3729        // this case (to match other browsers). And the spec mentions only `:only-child` as well.
3730        // https://drafts.csswg.org/css-view-transitions-1/#pseudo-root
3731        if state.allows_only_child_pseudo_class_only() {
3732            if name.eq_ignore_ascii_case("only-child") {
3733                return Ok(Component::Nth(NthSelectorData::only(
3734                    /* of_type = */ false,
3735                )));
3736            }
3737            // Other non-functional pseudo classes are not allowed.
3738            // FIXME: Perhaps we can refactor this, e.g. distinguish tree-structural pseudo classes
3739            // from other non-ts pseudo classes. Otherwise, this special case looks weird.
3740            return Err(location.new_custom_error(SelectorParseErrorKind::InvalidState));
3741        }
3742
3743        match_ignore_ascii_case! { &name,
3744            "first-child" => return Ok(Component::Nth(NthSelectorData::first(/* of_type = */ false))),
3745            "last-child" => return Ok(Component::Nth(NthSelectorData::last(/* of_type = */ false))),
3746            "only-child" => return Ok(Component::Nth(NthSelectorData::only(/* of_type = */ false))),
3747            "root" => return Ok(Component::Root),
3748            "empty" => return Ok(Component::Empty),
3749            "scope" => return Ok(Component::Scope),
3750            "host" if P::parse_host(parser) => return Ok(Component::Host(None)),
3751            "first-of-type" => return Ok(Component::Nth(NthSelectorData::first(/* of_type = */ true))),
3752            "last-of-type" => return Ok(Component::Nth(NthSelectorData::last(/* of_type = */ true))),
3753            "only-of-type" => return Ok(Component::Nth(NthSelectorData::only(/* of_type = */ true))),
3754            _ => {},
3755        }
3756    }
3757
3758    let pseudo_class = P::parse_non_ts_pseudo_class(parser, location, name)?;
3759    if state.intersects(SelectorParsingState::AFTER_NON_ELEMENT_BACKED_PSEUDO)
3760        && !pseudo_class.is_user_action_state()
3761    {
3762        return Err(location.new_custom_error(SelectorParseErrorKind::InvalidState));
3763    }
3764    Ok(Component::NonTSPseudoClass(pseudo_class))
3765}
3766
3767// NB: pub module in order to access the DummyParser
3768#[cfg(test)]
3769pub mod tests {
3770    use super::*;
3771    use crate::builder::SelectorFlags;
3772    use crate::parser;
3773    use cssparser::{serialize_identifier, Parser as CssParser, ParserInput, ToCss};
3774    use std::collections::HashMap;
3775    use std::fmt;
3776
3777    #[derive(Clone, Debug, Eq, PartialEq)]
3778    pub enum PseudoClass {
3779        Hover,
3780        Active,
3781        Lang(String),
3782    }
3783
3784    #[derive(Clone, Debug, Eq, PartialEq)]
3785    pub enum PseudoElement {
3786        Before,
3787        After,
3788        Marker,
3789        DetailsContent,
3790        Highlight(String),
3791    }
3792
3793    impl parser::PseudoElement for PseudoElement {
3794        type Impl = DummySelectorImpl;
3795
3796        fn accepts_state_pseudo_classes(&self) -> bool {
3797            true
3798        }
3799
3800        fn valid_after_slotted(&self) -> bool {
3801            true
3802        }
3803
3804        fn valid_after_before_or_after(&self) -> bool {
3805            matches!(self, Self::Marker)
3806        }
3807
3808        fn is_before_or_after(&self) -> bool {
3809            matches!(self, Self::Before | Self::After)
3810        }
3811
3812        fn parses_as_element_backed(&self) -> bool {
3813            matches!(self, Self::DetailsContent)
3814        }
3815    }
3816
3817    impl parser::NonTSPseudoClass for PseudoClass {
3818        type Impl = DummySelectorImpl;
3819
3820        #[inline]
3821        fn is_active_or_hover(&self) -> bool {
3822            matches!(*self, PseudoClass::Active | PseudoClass::Hover)
3823        }
3824
3825        #[inline]
3826        fn is_user_action_state(&self) -> bool {
3827            self.is_active_or_hover()
3828        }
3829    }
3830
3831    impl ToCss for PseudoClass {
3832        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3833        where
3834            W: fmt::Write,
3835        {
3836            match *self {
3837                PseudoClass::Hover => dest.write_str(":hover"),
3838                PseudoClass::Active => dest.write_str(":active"),
3839                PseudoClass::Lang(ref lang) => {
3840                    dest.write_str(":lang(")?;
3841                    serialize_identifier(lang, dest)?;
3842                    dest.write_char(')')
3843                },
3844            }
3845        }
3846    }
3847
3848    impl ToCss for PseudoElement {
3849        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3850        where
3851            W: fmt::Write,
3852        {
3853            match *self {
3854                PseudoElement::Before => dest.write_str("::before"),
3855                PseudoElement::After => dest.write_str("::after"),
3856                PseudoElement::Marker => dest.write_str("::marker"),
3857                PseudoElement::DetailsContent => dest.write_str("::details-content"),
3858                PseudoElement::Highlight(ref name) => {
3859                    dest.write_str("::highlight(")?;
3860                    serialize_identifier(&name, dest)?;
3861                    dest.write_char(')')
3862                },
3863            }
3864        }
3865    }
3866
3867    #[derive(Clone, Debug, PartialEq)]
3868    pub struct DummySelectorImpl;
3869
3870    #[derive(Default)]
3871    pub struct DummyParser {
3872        default_ns: Option<DummyAtom>,
3873        ns_prefixes: HashMap<DummyAtom, DummyAtom>,
3874    }
3875
3876    impl DummyParser {
3877        fn default_with_namespace(default_ns: DummyAtom) -> DummyParser {
3878            DummyParser {
3879                default_ns: Some(default_ns),
3880                ns_prefixes: Default::default(),
3881            }
3882        }
3883    }
3884
3885    impl SelectorImpl for DummySelectorImpl {
3886        type ExtraMatchingData<'a> = std::marker::PhantomData<&'a ()>;
3887        type AttrValue = DummyAttrValue;
3888        type Identifier = DummyAtom;
3889        type LocalName = DummyAtom;
3890        type NamespaceUrl = DummyAtom;
3891        type NamespacePrefix = DummyAtom;
3892        type BorrowedLocalName = DummyAtom;
3893        type BorrowedNamespaceUrl = DummyAtom;
3894        type NonTSPseudoClass = PseudoClass;
3895        type PseudoElement = PseudoElement;
3896    }
3897
3898    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
3899    pub struct DummyAttrValue(String);
3900
3901    impl ToCss for DummyAttrValue {
3902        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3903        where
3904            W: fmt::Write,
3905        {
3906            use std::fmt::Write;
3907
3908            dest.write_char('"')?;
3909            write!(cssparser::CssStringWriter::new(dest), "{}", &self.0)?;
3910            dest.write_char('"')
3911        }
3912    }
3913
3914    impl<'a> From<&'a str> for DummyAttrValue {
3915        fn from(string: &'a str) -> Self {
3916            Self(string.into())
3917        }
3918    }
3919
3920    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
3921    pub struct DummyAtom(String);
3922
3923    impl ToCss for DummyAtom {
3924        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
3925        where
3926            W: fmt::Write,
3927        {
3928            serialize_identifier(&self.0, dest)
3929        }
3930    }
3931
3932    impl From<String> for DummyAtom {
3933        fn from(string: String) -> Self {
3934            DummyAtom(string)
3935        }
3936    }
3937
3938    impl<'a> From<&'a str> for DummyAtom {
3939        fn from(string: &'a str) -> Self {
3940            DummyAtom(string.into())
3941        }
3942    }
3943
3944    impl PrecomputedHash for DummyAtom {
3945        fn precomputed_hash(&self) -> u32 {
3946            self.0.as_ptr() as u32
3947        }
3948    }
3949
3950    impl<'i> Parser<'i> for DummyParser {
3951        type Impl = DummySelectorImpl;
3952        type Error = SelectorParseErrorKind<'i>;
3953
3954        fn parse_slotted(&self) -> bool {
3955            true
3956        }
3957
3958        fn parse_nth_child_of(&self) -> bool {
3959            true
3960        }
3961
3962        fn parse_is_and_where(&self) -> bool {
3963            true
3964        }
3965
3966        fn parse_has(&self) -> bool {
3967            true
3968        }
3969
3970        fn parse_parent_selector(&self) -> bool {
3971            true
3972        }
3973
3974        fn parse_part(&self) -> bool {
3975            true
3976        }
3977
3978        fn parse_host(&self) -> bool {
3979            true
3980        }
3981
3982        fn parse_non_ts_pseudo_class(
3983            &self,
3984            location: SourceLocation,
3985            name: CowRcStr<'i>,
3986        ) -> Result<PseudoClass, SelectorParseError<'i>> {
3987            match_ignore_ascii_case! { &name,
3988                "hover" => return Ok(PseudoClass::Hover),
3989                "active" => return Ok(PseudoClass::Active),
3990                _ => {}
3991            }
3992            Err(
3993                location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
3994                    name,
3995                )),
3996            )
3997        }
3998
3999        fn parse_non_ts_functional_pseudo_class<'t>(
4000            &self,
4001            name: CowRcStr<'i>,
4002            parser: &mut CssParser<'i, 't>,
4003            after_part: bool,
4004        ) -> Result<PseudoClass, SelectorParseError<'i>> {
4005            match_ignore_ascii_case! { &name,
4006                "lang" if !after_part => {
4007                    let lang = parser.expect_ident_or_string()?.as_ref().to_owned();
4008                    return Ok(PseudoClass::Lang(lang));
4009                },
4010                _ => {}
4011            }
4012            Err(
4013                parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
4014                    name,
4015                )),
4016            )
4017        }
4018
4019        fn parse_pseudo_element(
4020            &self,
4021            location: SourceLocation,
4022            name: CowRcStr<'i>,
4023        ) -> Result<PseudoElement, SelectorParseError<'i>> {
4024            match_ignore_ascii_case! { &name,
4025                "before" => return Ok(PseudoElement::Before),
4026                "after" => return Ok(PseudoElement::After),
4027                "marker" => return Ok(PseudoElement::Marker),
4028                "details-content" => return Ok(PseudoElement::DetailsContent),
4029                _ => {}
4030            }
4031            Err(
4032                location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
4033                    name,
4034                )),
4035            )
4036        }
4037
4038        fn parse_functional_pseudo_element<'t>(
4039            &self,
4040            name: CowRcStr<'i>,
4041            parser: &mut CssParser<'i, 't>,
4042        ) -> Result<PseudoElement, SelectorParseError<'i>> {
4043            match_ignore_ascii_case! { &name,
4044                "highlight" => return Ok(PseudoElement::Highlight(parser.expect_ident()?.as_ref().to_owned())),
4045                _ => {}
4046            }
4047            Err(
4048                parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
4049                    name,
4050                )),
4051            )
4052        }
4053
4054        fn default_namespace(&self) -> Option<DummyAtom> {
4055            self.default_ns.clone()
4056        }
4057
4058        fn namespace_for_prefix(&self, prefix: &DummyAtom) -> Option<DummyAtom> {
4059            self.ns_prefixes.get(prefix).cloned()
4060        }
4061    }
4062
4063    fn parse<'i>(
4064        input: &'i str,
4065    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4066        parse_relative(input, ParseRelative::No)
4067    }
4068
4069    fn parse_relative<'i>(
4070        input: &'i str,
4071        parse_relative: ParseRelative,
4072    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4073        parse_ns_relative(input, &DummyParser::default(), parse_relative)
4074    }
4075
4076    fn parse_expected<'i, 'a>(
4077        input: &'i str,
4078        expected: Option<&'a str>,
4079    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4080        parse_ns_expected(input, &DummyParser::default(), expected)
4081    }
4082
4083    fn parse_relative_expected<'i, 'a>(
4084        input: &'i str,
4085        parse_relative: ParseRelative,
4086        expected: Option<&'a str>,
4087    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4088        parse_ns_relative_expected(input, &DummyParser::default(), parse_relative, expected)
4089    }
4090
4091    fn parse_ns<'i>(
4092        input: &'i str,
4093        parser: &DummyParser,
4094    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4095        parse_ns_relative(input, parser, ParseRelative::No)
4096    }
4097
4098    fn parse_ns_relative<'i>(
4099        input: &'i str,
4100        parser: &DummyParser,
4101        parse_relative: ParseRelative,
4102    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4103        parse_ns_relative_expected(input, parser, parse_relative, None)
4104    }
4105
4106    fn parse_ns_expected<'i, 'a>(
4107        input: &'i str,
4108        parser: &DummyParser,
4109        expected: Option<&'a str>,
4110    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4111        parse_ns_relative_expected(input, parser, ParseRelative::No, expected)
4112    }
4113
4114    fn parse_ns_relative_expected<'i, 'a>(
4115        input: &'i str,
4116        parser: &DummyParser,
4117        parse_relative: ParseRelative,
4118        expected: Option<&'a str>,
4119    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
4120        let mut parser_input = ParserInput::new(input);
4121        let result = SelectorList::parse(
4122            parser,
4123            &mut CssParser::new(&mut parser_input),
4124            parse_relative,
4125        );
4126        if let Ok(ref selectors) = result {
4127            // We can't assume that the serialized parsed selector will equal
4128            // the input; for example, if there is no default namespace, '*|foo'
4129            // should serialize to 'foo'.
4130            assert_eq!(
4131                selectors.to_css_string(),
4132                match expected {
4133                    Some(x) => x,
4134                    None => input,
4135                }
4136            );
4137        }
4138        result
4139    }
4140
4141    fn specificity(a: u32, b: u32, c: u32) -> u32 {
4142        a << 20 | b << 10 | c
4143    }
4144
4145    #[test]
4146    fn test_ancestor_hashes_in_subject_position() {
4147        fn ancestor_hash_count(selector: &str) -> usize {
4148            let list = parse(selector).unwrap();
4149            assert_eq!(list.slice().len(), 1);
4150            let mut hashes = [0u32; 4];
4151            let mut len = 0;
4152            collect_ancestor_hashes(
4153                list.slice()[0].iter(),
4154                QuirksMode::NoQuirks,
4155                &mut hashes,
4156                &mut len,
4157            );
4158            len
4159        }
4160
4161        // Subject-only selectors don't contribute any ancestor hashes.
4162        assert_eq!(ancestor_hash_count(".subject"), 0);
4163        assert_eq!(ancestor_hash_count(":where(.subject)"), 0);
4164
4165        // An ancestor combinator inside :is() / :where() in subject position
4166        // should still contribute ancestor hashes (bug 2040922).
4167        assert_eq!(ancestor_hash_count(":where(.ancestor > .subject)"), 1);
4168        assert_eq!(ancestor_hash_count(":is(.ancestor .subject)"), 1);
4169        assert_eq!(
4170            ancestor_hash_count(":where(.ancestor > :not(:last-child))"),
4171            1
4172        );
4173
4174        // Real ancestors combine with ancestor combinators nested in a subject
4175        // :where().
4176        assert_eq!(
4177            ancestor_hash_count(".real-ancestor :where(.inner-ancestor > .subject)"),
4178            2
4179        );
4180
4181        // :is() / :where() with more than one selector OR their selectors, so no
4182        // hash can be collected from them, even when they contain ancestor
4183        // combinators.
4184        assert_eq!(ancestor_hash_count(":is(.a, .b) .subject"), 0);
4185        assert_eq!(
4186            ancestor_hash_count(":where(.ancestor > .subject, .other)"),
4187            0
4188        );
4189        // But a real ancestor next to a multi-selector subject :where() is still
4190        // collected.
4191        assert_eq!(ancestor_hash_count(".real-ancestor :where(.a > .b, .c)"), 1);
4192
4193        // Pseudo-elements match on their originating element, so simple
4194        // selectors in front of the pseudo-element combinator are part of the
4195        // subject and don't contribute ancestor hashes.
4196        assert_eq!(ancestor_hash_count(".subject::before"), 0);
4197        assert_eq!(ancestor_hash_count(".real-ancestor .subject::before"), 1);
4198        // An ancestor combinator nested in a subject :where() is still collected
4199        // even when the subject carries a pseudo-element.
4200        assert_eq!(
4201            ancestor_hash_count(":where(.ancestor > .subject)::before"),
4202            1
4203        );
4204    }
4205
4206    #[test]
4207    fn test_empty() {
4208        let mut input = ParserInput::new(":empty");
4209        let list = SelectorList::parse(
4210            &DummyParser::default(),
4211            &mut CssParser::new(&mut input),
4212            ParseRelative::No,
4213        );
4214        assert!(list.is_ok());
4215    }
4216
4217    const MATHML: &str = "http://www.w3.org/1998/Math/MathML";
4218    const SVG: &str = "http://www.w3.org/2000/svg";
4219
4220    #[test]
4221    fn test_parsing() {
4222        assert!(parse("").is_err());
4223        assert!(parse(":lang(4)").is_err());
4224        assert!(parse(":lang(en US)").is_err());
4225        assert_eq!(
4226            parse("EeÉ"),
4227            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4228                vec![Component::LocalName(LocalName {
4229                    name: DummyAtom::from("EeÉ"),
4230                    lower_name: DummyAtom::from("eeÉ"),
4231                })],
4232                specificity(0, 0, 1),
4233                SelectorFlags::empty(),
4234            )]))
4235        );
4236        assert_eq!(
4237            parse("|e"),
4238            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4239                vec![
4240                    Component::ExplicitNoNamespace,
4241                    Component::LocalName(LocalName {
4242                        name: DummyAtom::from("e"),
4243                        lower_name: DummyAtom::from("e"),
4244                    }),
4245                ],
4246                specificity(0, 0, 1),
4247                SelectorFlags::empty(),
4248            )]))
4249        );
4250        // When the default namespace is not set, *| should be elided.
4251        // https://github.com/servo/servo/pull/17537
4252        assert_eq!(
4253            parse_expected("*|e", Some("e")),
4254            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4255                vec![Component::LocalName(LocalName {
4256                    name: DummyAtom::from("e"),
4257                    lower_name: DummyAtom::from("e"),
4258                })],
4259                specificity(0, 0, 1),
4260                SelectorFlags::empty(),
4261            )]))
4262        );
4263        // When the default namespace is set, *| should _not_ be elided (as foo
4264        // is no longer equivalent to *|foo--the former is only for foo in the
4265        // default namespace).
4266        // https://github.com/servo/servo/issues/16020
4267        assert_eq!(
4268            parse_ns(
4269                "*|e",
4270                &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org"))
4271            ),
4272            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4273                vec![
4274                    Component::ExplicitAnyNamespace,
4275                    Component::LocalName(LocalName {
4276                        name: DummyAtom::from("e"),
4277                        lower_name: DummyAtom::from("e"),
4278                    }),
4279                ],
4280                specificity(0, 0, 1),
4281                SelectorFlags::empty(),
4282            )]))
4283        );
4284        assert_eq!(
4285            parse("*"),
4286            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4287                vec![Component::ExplicitUniversalType],
4288                specificity(0, 0, 0),
4289                SelectorFlags::empty(),
4290            )]))
4291        );
4292        assert_eq!(
4293            parse("|*"),
4294            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4295                vec![
4296                    Component::ExplicitNoNamespace,
4297                    Component::ExplicitUniversalType,
4298                ],
4299                specificity(0, 0, 0),
4300                SelectorFlags::empty(),
4301            )]))
4302        );
4303        assert_eq!(
4304            parse_expected("*|*", Some("*")),
4305            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4306                vec![Component::ExplicitUniversalType],
4307                specificity(0, 0, 0),
4308                SelectorFlags::empty(),
4309            )]))
4310        );
4311        assert_eq!(
4312            parse_ns(
4313                "*|*",
4314                &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org"))
4315            ),
4316            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4317                vec![
4318                    Component::ExplicitAnyNamespace,
4319                    Component::ExplicitUniversalType,
4320                ],
4321                specificity(0, 0, 0),
4322                SelectorFlags::empty(),
4323            )]))
4324        );
4325        assert_eq!(
4326            parse(".foo:lang(en-US)"),
4327            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4328                vec![
4329                    Component::Class(DummyAtom::from("foo")),
4330                    Component::NonTSPseudoClass(PseudoClass::Lang("en-US".to_owned())),
4331                ],
4332                specificity(0, 2, 0),
4333                SelectorFlags::empty(),
4334            )]))
4335        );
4336        assert_eq!(
4337            parse("#bar"),
4338            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4339                vec![Component::ID(DummyAtom::from("bar"))],
4340                specificity(1, 0, 0),
4341                SelectorFlags::empty(),
4342            )]))
4343        );
4344        assert_eq!(
4345            parse("e.foo#bar"),
4346            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4347                vec![
4348                    Component::LocalName(LocalName {
4349                        name: DummyAtom::from("e"),
4350                        lower_name: DummyAtom::from("e"),
4351                    }),
4352                    Component::Class(DummyAtom::from("foo")),
4353                    Component::ID(DummyAtom::from("bar")),
4354                ],
4355                specificity(1, 1, 1),
4356                SelectorFlags::empty(),
4357            )]))
4358        );
4359        assert_eq!(
4360            parse("e.foo #bar"),
4361            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4362                vec![
4363                    Component::LocalName(LocalName {
4364                        name: DummyAtom::from("e"),
4365                        lower_name: DummyAtom::from("e"),
4366                    }),
4367                    Component::Class(DummyAtom::from("foo")),
4368                    Component::Combinator(Combinator::Descendant),
4369                    Component::ID(DummyAtom::from("bar")),
4370                ],
4371                specificity(1, 1, 1),
4372                SelectorFlags::empty(),
4373            )]))
4374        );
4375        // Default namespace does not apply to attribute selectors
4376        // https://github.com/mozilla/servo/pull/1652
4377        let mut parser = DummyParser::default();
4378        assert_eq!(
4379            parse_ns("[Foo]", &parser),
4380            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4381                vec![Component::AttributeInNoNamespaceExists {
4382                    local_name: DummyAtom::from("Foo"),
4383                    local_name_lower: DummyAtom::from("foo"),
4384                }],
4385                specificity(0, 1, 0),
4386                SelectorFlags::empty(),
4387            )]))
4388        );
4389        assert!(parse_ns("svg|circle", &parser).is_err());
4390        parser
4391            .ns_prefixes
4392            .insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
4393        assert_eq!(
4394            parse_ns("svg|circle", &parser),
4395            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4396                vec![
4397                    Component::Namespace(DummyAtom("svg".into()), SVG.into()),
4398                    Component::LocalName(LocalName {
4399                        name: DummyAtom::from("circle"),
4400                        lower_name: DummyAtom::from("circle"),
4401                    }),
4402                ],
4403                specificity(0, 0, 1),
4404                SelectorFlags::empty(),
4405            )]))
4406        );
4407        assert_eq!(
4408            parse_ns("svg|*", &parser),
4409            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4410                vec![
4411                    Component::Namespace(DummyAtom("svg".into()), SVG.into()),
4412                    Component::ExplicitUniversalType,
4413                ],
4414                specificity(0, 0, 0),
4415                SelectorFlags::empty(),
4416            )]))
4417        );
4418        // Default namespace does not apply to attribute selectors
4419        // https://github.com/mozilla/servo/pull/1652
4420        // but it does apply to implicit type selectors
4421        // https://github.com/servo/rust-selectors/pull/82
4422        parser.default_ns = Some(MATHML.into());
4423        assert_eq!(
4424            parse_ns("[Foo]", &parser),
4425            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4426                vec![
4427                    Component::DefaultNamespace(MATHML.into()),
4428                    Component::AttributeInNoNamespaceExists {
4429                        local_name: DummyAtom::from("Foo"),
4430                        local_name_lower: DummyAtom::from("foo"),
4431                    },
4432                ],
4433                specificity(0, 1, 0),
4434                SelectorFlags::empty(),
4435            )]))
4436        );
4437        // Default namespace does apply to type selectors
4438        assert_eq!(
4439            parse_ns("e", &parser),
4440            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4441                vec![
4442                    Component::DefaultNamespace(MATHML.into()),
4443                    Component::LocalName(LocalName {
4444                        name: DummyAtom::from("e"),
4445                        lower_name: DummyAtom::from("e"),
4446                    }),
4447                ],
4448                specificity(0, 0, 1),
4449                SelectorFlags::empty(),
4450            )]))
4451        );
4452        assert_eq!(
4453            parse_ns("*", &parser),
4454            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4455                vec![
4456                    Component::DefaultNamespace(MATHML.into()),
4457                    Component::ExplicitUniversalType,
4458                ],
4459                specificity(0, 0, 0),
4460                SelectorFlags::empty(),
4461            )]))
4462        );
4463        assert_eq!(
4464            parse_ns("*|*", &parser),
4465            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4466                vec![
4467                    Component::ExplicitAnyNamespace,
4468                    Component::ExplicitUniversalType,
4469                ],
4470                specificity(0, 0, 0),
4471                SelectorFlags::empty(),
4472            )]))
4473        );
4474        // Default namespace applies to universal and type selectors inside :not and :matches,
4475        // but not otherwise.
4476        assert_eq!(
4477            parse_ns(":not(.cl)", &parser),
4478            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4479                vec![
4480                    Component::DefaultNamespace(MATHML.into()),
4481                    Component::Negation(SelectorList::from_vec(vec![Selector::from_vec(
4482                        vec![Component::Class(DummyAtom::from("cl"))],
4483                        specificity(0, 1, 0),
4484                        SelectorFlags::empty(),
4485                    )])),
4486                ],
4487                specificity(0, 1, 0),
4488                SelectorFlags::empty(),
4489            )]))
4490        );
4491        assert_eq!(
4492            parse_ns(":not(*)", &parser),
4493            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4494                vec![
4495                    Component::DefaultNamespace(MATHML.into()),
4496                    Component::Negation(SelectorList::from_vec(vec![Selector::from_vec(
4497                        vec![
4498                            Component::DefaultNamespace(MATHML.into()),
4499                            Component::ExplicitUniversalType,
4500                        ],
4501                        specificity(0, 0, 0),
4502                        SelectorFlags::empty(),
4503                    )]),),
4504                ],
4505                specificity(0, 0, 0),
4506                SelectorFlags::empty(),
4507            )]))
4508        );
4509        assert_eq!(
4510            parse_ns(":not(e)", &parser),
4511            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4512                vec![
4513                    Component::DefaultNamespace(MATHML.into()),
4514                    Component::Negation(SelectorList::from_vec(vec![Selector::from_vec(
4515                        vec![
4516                            Component::DefaultNamespace(MATHML.into()),
4517                            Component::LocalName(LocalName {
4518                                name: DummyAtom::from("e"),
4519                                lower_name: DummyAtom::from("e"),
4520                            }),
4521                        ],
4522                        specificity(0, 0, 1),
4523                        SelectorFlags::empty(),
4524                    )])),
4525                ],
4526                specificity(0, 0, 1),
4527                SelectorFlags::empty(),
4528            )]))
4529        );
4530        assert_eq!(
4531            parse("[attr|=\"foo\"]"),
4532            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4533                vec![Component::AttributeInNoNamespace {
4534                    local_name: DummyAtom::from("attr"),
4535                    operator: AttrSelectorOperator::DashMatch,
4536                    value: DummyAttrValue::from("foo"),
4537                    case_sensitivity: ParsedCaseSensitivity::CaseSensitive,
4538                }],
4539                specificity(0, 1, 0),
4540                SelectorFlags::empty(),
4541            )]))
4542        );
4543        // https://github.com/mozilla/servo/issues/1723
4544        assert_eq!(
4545            parse("::before"),
4546            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4547                vec![
4548                    Component::Combinator(Combinator::PseudoElement),
4549                    Component::PseudoElement(PseudoElement::Before),
4550                ],
4551                specificity(0, 0, 1),
4552                SelectorFlags::HAS_PSEUDO,
4553            )]))
4554        );
4555        assert_eq!(
4556            parse("::before:hover"),
4557            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4558                vec![
4559                    Component::Combinator(Combinator::PseudoElement),
4560                    Component::PseudoElement(PseudoElement::Before),
4561                    Component::NonTSPseudoClass(PseudoClass::Hover),
4562                ],
4563                specificity(0, 1, 1),
4564                SelectorFlags::HAS_PSEUDO,
4565            )]))
4566        );
4567        assert_eq!(
4568            parse("::before:hover:hover"),
4569            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4570                vec![
4571                    Component::Combinator(Combinator::PseudoElement),
4572                    Component::PseudoElement(PseudoElement::Before),
4573                    Component::NonTSPseudoClass(PseudoClass::Hover),
4574                    Component::NonTSPseudoClass(PseudoClass::Hover),
4575                ],
4576                specificity(0, 2, 1),
4577                SelectorFlags::HAS_PSEUDO,
4578            )]))
4579        );
4580        assert!(parse("::before:hover:lang(foo)").is_err());
4581        assert!(parse("::before:hover .foo").is_err());
4582        assert!(parse("::before .foo").is_err());
4583        assert!(parse("::before ~ bar").is_err());
4584        assert!(parse("::before:active").is_ok());
4585
4586        // https://github.com/servo/servo/issues/15335
4587        assert!(parse(":: before").is_err());
4588        assert_eq!(
4589            parse("div ::after"),
4590            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4591                vec![
4592                    Component::LocalName(LocalName {
4593                        name: DummyAtom::from("div"),
4594                        lower_name: DummyAtom::from("div"),
4595                    }),
4596                    Component::Combinator(Combinator::Descendant),
4597                    Component::Combinator(Combinator::PseudoElement),
4598                    Component::PseudoElement(PseudoElement::After),
4599                ],
4600                specificity(0, 0, 2),
4601                SelectorFlags::HAS_PSEUDO,
4602            )]))
4603        );
4604        assert_eq!(
4605            parse("#d1 > .ok"),
4606            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4607                vec![
4608                    Component::ID(DummyAtom::from("d1")),
4609                    Component::Combinator(Combinator::Child),
4610                    Component::Class(DummyAtom::from("ok")),
4611                ],
4612                specificity(1, 1, 0),
4613                SelectorFlags::empty(),
4614            )]))
4615        );
4616        parser.default_ns = None;
4617        assert!(parse(":not(#provel.old)").is_ok());
4618        assert!(parse(":not(#provel > old)").is_ok());
4619        assert!(parse("table[rules]:not([rules=\"none\"]):not([rules=\"\"])").is_ok());
4620        // https://github.com/servo/servo/issues/16017
4621        assert_eq!(
4622            parse_ns(":not(*)", &parser),
4623            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4624                vec![Component::Negation(SelectorList::from_vec(vec![
4625                    Selector::from_vec(
4626                        vec![Component::ExplicitUniversalType],
4627                        specificity(0, 0, 0),
4628                        SelectorFlags::empty(),
4629                    )
4630                ]))],
4631                specificity(0, 0, 0),
4632                SelectorFlags::empty(),
4633            )]))
4634        );
4635        assert_eq!(
4636            parse_ns(":not(|*)", &parser),
4637            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4638                vec![Component::Negation(SelectorList::from_vec(vec![
4639                    Selector::from_vec(
4640                        vec![
4641                            Component::ExplicitNoNamespace,
4642                            Component::ExplicitUniversalType,
4643                        ],
4644                        specificity(0, 0, 0),
4645                        SelectorFlags::empty(),
4646                    )
4647                ]))],
4648                specificity(0, 0, 0),
4649                SelectorFlags::empty(),
4650            )]))
4651        );
4652        // *| should be elided if there is no default namespace.
4653        // https://github.com/servo/servo/pull/17537
4654        assert_eq!(
4655            parse_ns_expected(":not(*|*)", &parser, Some(":not(*)")),
4656            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4657                vec![Component::Negation(SelectorList::from_vec(vec![
4658                    Selector::from_vec(
4659                        vec![Component::ExplicitUniversalType],
4660                        specificity(0, 0, 0),
4661                        SelectorFlags::empty(),
4662                    )
4663                ]))],
4664                specificity(0, 0, 0),
4665                SelectorFlags::empty(),
4666            )]))
4667        );
4668
4669        assert!(parse("::highlight(foo)").is_ok());
4670
4671        assert!(parse("::slotted()").is_err());
4672        assert!(parse("::slotted(div)").is_ok());
4673        assert!(parse("::slotted(div).foo").is_err());
4674        assert!(parse("::slotted(div + bar)").is_err());
4675        assert!(parse("::slotted(div) + foo").is_err());
4676
4677        assert!(parse("::part()").is_err());
4678        assert!(parse("::part(42)").is_err());
4679        assert!(parse("::part(foo bar)").is_ok());
4680        assert!(parse("::part(foo):hover").is_ok());
4681        assert!(parse("::part(foo) + bar").is_err());
4682
4683        assert!(parse("div ::slotted(div)").is_ok());
4684        assert!(parse("div + slot::slotted(div)").is_ok());
4685        assert!(parse("div + slot::slotted(div.foo)").is_ok());
4686        assert!(parse("slot::slotted(div,foo)::first-line").is_err());
4687        assert!(parse("::slotted(div)::before").is_ok());
4688        assert!(parse("slot::slotted(div,foo)").is_err());
4689
4690        assert!(parse("foo:where()").is_ok());
4691        assert!(parse("foo:where(div, foo, .bar baz)").is_ok());
4692        assert!(parse("foo:where(::before)").is_ok());
4693    }
4694
4695    #[test]
4696    fn parent_selector() {
4697        assert!(parse("foo &").is_ok());
4698        assert_eq!(
4699            parse("#foo &.bar"),
4700            Ok(SelectorList::from_vec(vec![Selector::from_vec(
4701                vec![
4702                    Component::ID(DummyAtom::from("foo")),
4703                    Component::Combinator(Combinator::Descendant),
4704                    Component::ParentSelector,
4705                    Component::Class(DummyAtom::from("bar")),
4706                ],
4707                specificity(1, 1, 0),
4708                SelectorFlags::HAS_PARENT
4709            )]))
4710        );
4711
4712        let parent = parse(".bar, div .baz").unwrap();
4713        let child = parse("#foo &.bar").unwrap();
4714        assert_eq!(
4715            child.replace_parent_selector(&parent),
4716            parse("#foo :is(.bar, div .baz).bar").unwrap()
4717        );
4718
4719        let has_child = parse("#foo:has(&.bar)").unwrap();
4720        assert_eq!(
4721            has_child.replace_parent_selector(&parent),
4722            parse("#foo:has(:is(.bar, div .baz).bar)").unwrap()
4723        );
4724
4725        let child =
4726            parse_relative_expected("#foo", ParseRelative::ForNesting, Some("& #foo")).unwrap();
4727        assert_eq!(
4728            child.replace_parent_selector(&parent),
4729            parse(":is(.bar, div .baz) #foo").unwrap()
4730        );
4731
4732        let child =
4733            parse_relative_expected("+ #foo", ParseRelative::ForNesting, Some("& + #foo")).unwrap();
4734        assert_eq!(child, parse("& + #foo").unwrap());
4735    }
4736
4737    #[test]
4738    fn test_pseudo_iter() {
4739        let list = parse("q::before").unwrap();
4740        let selector = &list.slice()[0];
4741        assert!(!selector.is_universal());
4742        let mut iter = selector.iter();
4743        assert_eq!(
4744            iter.next(),
4745            Some(&Component::PseudoElement(PseudoElement::Before))
4746        );
4747        assert_eq!(iter.next(), None);
4748        let combinator = iter.next_sequence();
4749        assert_eq!(combinator, Some(Combinator::PseudoElement));
4750        assert_eq!(
4751            iter.next(),
4752            Some(&Component::LocalName(LocalName {
4753                name: DummyAtom::from("q"),
4754                lower_name: DummyAtom::from("q"),
4755            }))
4756        );
4757        assert_eq!(iter.next(), None);
4758        assert_eq!(iter.next_sequence(), None);
4759    }
4760
4761    #[test]
4762    fn test_pseudo_before_marker() {
4763        let list = parse("::before::marker").unwrap();
4764        let selector = &list.slice()[0];
4765        let mut iter = selector.iter();
4766        assert_eq!(
4767            iter.next(),
4768            Some(&Component::PseudoElement(PseudoElement::Marker))
4769        );
4770        assert_eq!(iter.next(), None);
4771        let combinator = iter.next_sequence();
4772        assert_eq!(combinator, Some(Combinator::PseudoElement));
4773        assert_eq!(
4774            iter.next(),
4775            Some(&Component::PseudoElement(PseudoElement::Before))
4776        );
4777        assert_eq!(iter.next(), None);
4778        let combinator = iter.next_sequence();
4779        assert_eq!(combinator, Some(Combinator::PseudoElement));
4780        assert_eq!(iter.next(), None);
4781        assert_eq!(iter.next_sequence(), None);
4782    }
4783
4784    #[test]
4785    fn test_pseudo_duplicate_before_after_or_marker() {
4786        assert!(parse("::before::before").is_err());
4787        assert!(parse("::after::after").is_err());
4788        assert!(parse("::marker::marker").is_err());
4789    }
4790
4791    #[test]
4792    fn test_pseudo_on_element_backed_pseudo() {
4793        let list = parse("::details-content::before").unwrap();
4794        let selector = &list.slice()[0];
4795        let mut iter = selector.iter();
4796        assert_eq!(
4797            iter.next(),
4798            Some(&Component::PseudoElement(PseudoElement::Before))
4799        );
4800        assert_eq!(iter.next(), None);
4801        let combinator = iter.next_sequence();
4802        assert_eq!(combinator, Some(Combinator::PseudoElement));
4803        assert_eq!(
4804            iter.next(),
4805            Some(&Component::PseudoElement(PseudoElement::DetailsContent))
4806        );
4807        assert_eq!(iter.next(), None);
4808        let combinator = iter.next_sequence();
4809        assert_eq!(combinator, Some(Combinator::PseudoElement));
4810        assert_eq!(iter.next(), None);
4811        assert_eq!(iter.next_sequence(), None);
4812    }
4813
4814    #[test]
4815    fn test_universal() {
4816        let list = parse_ns(
4817            "*|*::before",
4818            &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org")),
4819        )
4820        .unwrap();
4821        let selector = &list.slice()[0];
4822        assert!(selector.is_universal());
4823    }
4824
4825    #[test]
4826    fn test_empty_pseudo_iter() {
4827        let list = parse("::before").unwrap();
4828        let selector = &list.slice()[0];
4829        assert!(selector.is_universal());
4830        let mut iter = selector.iter();
4831        assert_eq!(
4832            iter.next(),
4833            Some(&Component::PseudoElement(PseudoElement::Before))
4834        );
4835        assert_eq!(iter.next(), None);
4836        assert_eq!(iter.next_sequence(), Some(Combinator::PseudoElement));
4837        assert_eq!(iter.next(), None);
4838        assert_eq!(iter.next_sequence(), None);
4839    }
4840
4841    #[test]
4842    fn test_parse_implicit_scope() {
4843        assert_eq!(
4844            parse_relative_expected(".foo", ParseRelative::ForScope, None).unwrap(),
4845            SelectorList::from_vec(vec![Selector::from_vec(
4846                vec![
4847                    Component::ImplicitScope,
4848                    Component::Combinator(Combinator::Descendant),
4849                    Component::Class(DummyAtom::from("foo")),
4850                ],
4851                specificity(0, 1, 0),
4852                SelectorFlags::HAS_SCOPE,
4853            )])
4854        );
4855
4856        assert_eq!(
4857            parse_relative_expected(":scope .foo", ParseRelative::ForScope, None).unwrap(),
4858            SelectorList::from_vec(vec![Selector::from_vec(
4859                vec![
4860                    Component::Scope,
4861                    Component::Combinator(Combinator::Descendant),
4862                    Component::Class(DummyAtom::from("foo")),
4863                ],
4864                specificity(0, 2, 0),
4865                SelectorFlags::HAS_SCOPE
4866            )])
4867        );
4868
4869        assert_eq!(
4870            parse_relative_expected("> .foo", ParseRelative::ForScope, Some("> .foo")).unwrap(),
4871            SelectorList::from_vec(vec![Selector::from_vec(
4872                vec![
4873                    Component::ImplicitScope,
4874                    Component::Combinator(Combinator::Child),
4875                    Component::Class(DummyAtom::from("foo")),
4876                ],
4877                specificity(0, 1, 0),
4878                SelectorFlags::HAS_SCOPE
4879            )])
4880        );
4881
4882        assert_eq!(
4883            parse_relative_expected(".foo :scope > .bar", ParseRelative::ForScope, None).unwrap(),
4884            SelectorList::from_vec(vec![Selector::from_vec(
4885                vec![
4886                    Component::Class(DummyAtom::from("foo")),
4887                    Component::Combinator(Combinator::Descendant),
4888                    Component::Scope,
4889                    Component::Combinator(Combinator::Child),
4890                    Component::Class(DummyAtom::from("bar")),
4891                ],
4892                specificity(0, 3, 0),
4893                SelectorFlags::HAS_SCOPE
4894            )])
4895        );
4896    }
4897
4898    struct TestVisitor {
4899        seen: Vec<String>,
4900    }
4901
4902    impl SelectorVisitor for TestVisitor {
4903        type Impl = DummySelectorImpl;
4904
4905        fn visit_simple_selector(&mut self, s: &Component<DummySelectorImpl>) -> bool {
4906            let mut dest = String::new();
4907            s.to_css(&mut dest).unwrap();
4908            self.seen.push(dest);
4909            true
4910        }
4911    }
4912
4913    #[test]
4914    fn visitor() {
4915        let mut test_visitor = TestVisitor { seen: vec![] };
4916        parse(":not(:hover) ~ label").unwrap().slice()[0].visit(&mut test_visitor);
4917        assert!(test_visitor.seen.contains(&":hover".into()));
4918
4919        let mut test_visitor = TestVisitor { seen: vec![] };
4920        parse("::before:hover").unwrap().slice()[0].visit(&mut test_visitor);
4921        assert!(test_visitor.seen.contains(&":hover".into()));
4922    }
4923}