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