Skip to main content

selectors/
parser.rs

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