lewp_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
5pub use crate::visitor::SelectorVisitor;
6use {
7    crate::{
8        attr::{
9            AttrSelectorOperator,
10            AttrSelectorWithOptionalNamespace,
11            NamespaceConstraint,
12            ParsedAttrSelectorOperation,
13            ParsedCaseSensitivity,
14            SELECTOR_WHITESPACE,
15        },
16        bloom::BLOOM_HASH_MASK,
17        builder::{SelectorBuilder, SelectorFlags, SpecificityAndFlags},
18        context::QuirksMode,
19        sink::Push,
20    },
21    cssparser::{
22        parse_nth,
23        BasicParseError,
24        BasicParseErrorKind,
25        CowRcStr,
26        Delimiter,
27        ParseError,
28        ParseErrorKind,
29        Parser as CssParser,
30        SourceLocation,
31        ToCss,
32        Token,
33    },
34    precomputed_hash::PrecomputedHash,
35    servo_arc::ThinArc,
36    smallvec::SmallVec,
37    std::{
38        borrow::{Borrow, Cow},
39        fmt::{self, Debug},
40        iter::Rev,
41        slice,
42    },
43};
44
45/// A trait that represents a pseudo-element.
46pub trait PseudoElement: Sized + ToCss {
47    /// The `SelectorImpl` this pseudo-element is used for.
48    type Impl: SelectorImpl;
49
50    /// Whether the pseudo-element supports a given state selector to the right
51    /// of it.
52    fn accepts_state_pseudo_classes(&self) -> bool {
53        false
54    }
55
56    /// Whether this pseudo-element is valid after a ::slotted(..) pseudo.
57    fn valid_after_slotted(&self) -> bool {
58        false
59    }
60}
61
62/// A trait that represents a pseudo-class.
63pub trait NonTSPseudoClass: Sized + ToCss {
64    /// The `SelectorImpl` this pseudo-element is used for.
65    type Impl: SelectorImpl;
66
67    /// Whether this pseudo-class is :active or :hover.
68    fn is_active_or_hover(&self) -> bool;
69
70    /// Whether this pseudo-class belongs to:
71    ///
72    /// https://drafts.csswg.org/selectors-4/#useraction-pseudos
73    fn is_user_action_state(&self) -> bool;
74
75    fn visit<V>(&self, _visitor: &mut V) -> bool
76    where
77        V: SelectorVisitor<Impl = Self::Impl>,
78    {
79        true
80    }
81}
82
83/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a
84/// Cow::Owned if `s` had to be converted into ASCII lowercase.
85fn to_ascii_lowercase(s: &str) -> Cow<str> {
86    if let Some(first_uppercase) =
87        s.bytes().position(|byte| byte >= b'A' && byte <= b'Z')
88    {
89        let mut string = s.to_owned();
90        string[first_uppercase..].make_ascii_lowercase();
91        string.into()
92    } else {
93        s.into()
94    }
95}
96
97bitflags! {
98    /// Flags that indicate at which point of parsing a selector are we.
99    struct SelectorParsingState: u8 {
100        /// Whether we should avoid adding default namespaces to selectors that
101        /// aren't type or universal selectors.
102        const SKIP_DEFAULT_NAMESPACE = 1 << 0;
103
104        /// Whether we've parsed a ::slotted() pseudo-element already.
105        ///
106        /// If so, then we can only parse a subset of pseudo-elements, and
107        /// whatever comes after them if so.
108        const AFTER_SLOTTED = 1 << 1;
109        /// Whether we've parsed a ::part() pseudo-element already.
110        ///
111        /// If so, then we can only parse a subset of pseudo-elements, and
112        /// whatever comes after them if so.
113        const AFTER_PART = 1 << 2;
114        /// Whether we've parsed a pseudo-element (as in, an
115        /// `Impl::PseudoElement` thus not accounting for `::slotted` or
116        /// `::part`) already.
117        ///
118        /// If so, then other pseudo-elements and most other selectors are
119        /// disallowed.
120        const AFTER_PSEUDO_ELEMENT = 1 << 3;
121        /// Whether we've parsed a non-stateful pseudo-element (again, as-in
122        /// `Impl::PseudoElement`) already. If so, then other pseudo-classes are
123        /// disallowed. If this flag is set, `AFTER_PSEUDO_ELEMENT` must be set
124        /// as well.
125        const AFTER_NON_STATEFUL_PSEUDO_ELEMENT = 1 << 4;
126
127        /// Whether we are after any of the pseudo-like things.
128        const AFTER_PSEUDO = Self::AFTER_PART.bits | Self::AFTER_SLOTTED.bits | Self::AFTER_PSEUDO_ELEMENT.bits;
129
130        /// Whether we explicitly disallow combinators.
131        const DISALLOW_COMBINATORS = 1 << 5;
132
133        /// Whether we explicitly disallow pseudo-element-like things.
134        const DISALLOW_PSEUDOS = 1 << 6;
135    }
136}
137
138impl SelectorParsingState {
139    #[inline]
140    fn allows_pseudos(self) -> bool {
141        // NOTE(emilio): We allow pseudos after ::part and such.
142        !self.intersects(Self::AFTER_PSEUDO_ELEMENT | Self::DISALLOW_PSEUDOS)
143    }
144
145    #[inline]
146    fn allows_slotted(self) -> bool {
147        !self.intersects(Self::AFTER_PSEUDO | Self::DISALLOW_PSEUDOS)
148    }
149
150    #[inline]
151    fn allows_part(self) -> bool {
152        !self.intersects(Self::AFTER_PSEUDO | Self::DISALLOW_PSEUDOS)
153    }
154
155    // TODO(emilio): Maybe some of these should be allowed, but this gets us on
156    // the safe side for now, matching previous behavior. Gotta be careful with
157    // the ones like :-moz-any, which allow nested selectors but don't carry the
158    // state, and so on.
159    #[inline]
160    fn allows_custom_functional_pseudo_classes(self) -> bool {
161        !self.intersects(Self::AFTER_PSEUDO)
162    }
163
164    #[inline]
165    fn allows_non_functional_pseudo_classes(self) -> bool {
166        !self.intersects(
167            Self::AFTER_SLOTTED | Self::AFTER_NON_STATEFUL_PSEUDO_ELEMENT,
168        )
169    }
170
171    #[inline]
172    fn allows_tree_structural_pseudo_classes(self) -> bool {
173        !self.intersects(Self::AFTER_PSEUDO)
174    }
175
176    #[inline]
177    fn allows_combinators(self) -> bool {
178        !self.intersects(Self::DISALLOW_COMBINATORS)
179    }
180}
181
182pub type SelectorParseError<'i> = ParseError<'i, SelectorParseErrorKind<'i>>;
183
184#[derive(Clone, Debug, PartialEq)]
185pub enum SelectorParseErrorKind<'i> {
186    NoQualifiedNameInAttributeSelector(Token<'i>),
187    EmptySelector,
188    DanglingCombinator,
189    NonCompoundSelector,
190    NonPseudoElementAfterSlotted,
191    InvalidPseudoElementAfterSlotted,
192    InvalidPseudoElementInsideWhere,
193    InvalidState,
194    UnexpectedTokenInAttributeSelector(Token<'i>),
195    PseudoElementExpectedColon(Token<'i>),
196    PseudoElementExpectedIdent(Token<'i>),
197    NoIdentForPseudo(Token<'i>),
198    UnsupportedPseudoClassOrElement(CowRcStr<'i>),
199    UnexpectedIdent(CowRcStr<'i>),
200    ExpectedNamespace(CowRcStr<'i>),
201    ExpectedBarInAttr(Token<'i>),
202    BadValueInAttr(Token<'i>),
203    InvalidQualNameInAttr(Token<'i>),
204    ExplicitNamespaceUnexpectedToken(Token<'i>),
205    ClassNeedsIdent(Token<'i>),
206}
207
208macro_rules! with_all_bounds {
209    (
210        [ $( $InSelector: tt )* ]
211        [ $( $CommonBounds: tt )* ]
212        [ $( $FromStr: tt )* ]
213    ) => {
214        /// This trait allows to define the parser implementation in regards
215        /// of pseudo-classes/elements
216        ///
217        /// NB: We need Clone so that we can derive(Clone) on struct with that
218        /// are parameterized on SelectorImpl. See
219        /// <https://github.com/rust-lang/rust/issues/26925>
220        pub trait SelectorImpl: Clone + Debug + Sized + 'static {
221            type ExtraMatchingData: Sized + Default + 'static;
222            type AttrValue: $($InSelector)*;
223            type Identifier: $($InSelector)*;
224            type LocalName: $($InSelector)* + Borrow<Self::BorrowedLocalName>;
225            type NamespaceUrl: $($CommonBounds)* + Default + Borrow<Self::BorrowedNamespaceUrl>;
226            type NamespacePrefix: $($InSelector)* + Default;
227            type BorrowedNamespaceUrl: ?Sized + Eq;
228            type BorrowedLocalName: ?Sized + Eq;
229
230            /// non tree-structural pseudo-classes
231            /// (see: https://drafts.csswg.org/selectors/#structural-pseudos)
232            type NonTSPseudoClass: $($CommonBounds)* + NonTSPseudoClass<Impl = Self>;
233
234            /// pseudo-elements
235            type PseudoElement: $($CommonBounds)* + PseudoElement<Impl = Self>;
236        }
237    }
238}
239
240macro_rules! with_bounds {
241    ( [ $( $CommonBounds: tt )* ] [ $( $FromStr: tt )* ]) => {
242        with_all_bounds! {
243            [$($CommonBounds)* + $($FromStr)* + ToCss]
244            [$($CommonBounds)*]
245            [$($FromStr)*]
246        }
247    }
248}
249
250with_bounds! {
251    [Clone + Eq]
252    [for<'a> From<&'a str>]
253}
254
255pub trait Parser<'i> {
256    type Impl: SelectorImpl;
257    type Error: 'i + From<SelectorParseErrorKind<'i>>;
258
259    /// Whether to parse the `::slotted()` pseudo-element.
260    fn parse_slotted(&self) -> bool {
261        false
262    }
263
264    /// Whether to parse the `::part()` pseudo-element.
265    fn parse_part(&self) -> bool {
266        false
267    }
268
269    /// Whether to parse the `:where` pseudo-class.
270    fn parse_is_and_where(&self) -> bool {
271        true
272    }
273
274    /// The error recovery that selector lists inside :is() and :where() have.
275    fn is_and_where_error_recovery(&self) -> ParseErrorRecovery {
276        ParseErrorRecovery::IgnoreInvalidSelector
277    }
278
279    /// Whether the given function name is an alias for the `:is()` function.
280    fn is_is_alias(&self, _name: &str) -> bool {
281        false
282    }
283
284    /// Whether to parse the `:host` pseudo-class.
285    fn parse_host(&self) -> bool {
286        false
287    }
288
289    /// Parses non-tree-structural pseudo-classes. Tree structural pseudo-classes,
290    /// like `:first-child`, are built into this library.
291    ///
292    /// This function can return an "Err" pseudo-element in order to support CSS2.1
293    /// pseudo-elements.
294    fn parse_non_ts_pseudo_class(
295        &self,
296        location: SourceLocation,
297        name: CowRcStr<'i>,
298    ) -> Result<
299        <Self::Impl as SelectorImpl>::NonTSPseudoClass,
300        ParseError<'i, Self::Error>,
301    > {
302        Err(location.new_custom_error(
303            SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
304        ))
305    }
306
307    fn parse_non_ts_functional_pseudo_class<'t>(
308        &self,
309        name: CowRcStr<'i>,
310        arguments: &mut CssParser<'i, 't>,
311    ) -> Result<
312        <Self::Impl as SelectorImpl>::NonTSPseudoClass,
313        ParseError<'i, Self::Error>,
314    > {
315        Err(arguments.new_custom_error(
316            SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
317        ))
318    }
319
320    fn parse_pseudo_element(
321        &self,
322        location: SourceLocation,
323        name: CowRcStr<'i>,
324    ) -> Result<
325        <Self::Impl as SelectorImpl>::PseudoElement,
326        ParseError<'i, Self::Error>,
327    > {
328        Err(location.new_custom_error(
329            SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
330        ))
331    }
332
333    fn parse_functional_pseudo_element<'t>(
334        &self,
335        name: CowRcStr<'i>,
336        arguments: &mut CssParser<'i, 't>,
337    ) -> Result<
338        <Self::Impl as SelectorImpl>::PseudoElement,
339        ParseError<'i, Self::Error>,
340    > {
341        Err(arguments.new_custom_error(
342            SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
343        ))
344    }
345
346    fn default_namespace(
347        &self,
348    ) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
349        None
350    }
351
352    fn namespace_for_prefix(
353        &self,
354        _prefix: &<Self::Impl as SelectorImpl>::NamespacePrefix,
355    ) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
356        None
357    }
358}
359
360#[derive(Clone, Debug, Eq, PartialEq)]
361pub struct SelectorList<Impl: SelectorImpl>(pub SmallVec<[Selector<Impl>; 1]>);
362
363/// How to treat invalid selectors in a selector list.
364pub enum ParseErrorRecovery {
365    /// Discard the entire selector list, this is the default behavior for
366    /// almost all of CSS.
367    DiscardList,
368    /// Ignore invalid selectors, potentially creating an empty selector list.
369    ///
370    /// This is the error recovery mode of :is() and :where()
371    IgnoreInvalidSelector,
372}
373
374impl<Impl: SelectorImpl> SelectorList<Impl> {
375    /// Parse a comma-separated list of Selectors.
376    /// <https://drafts.csswg.org/selectors/#grouping>
377    ///
378    /// Return the Selectors or Err if there is an invalid selector.
379    pub fn parse<'i, 't, P>(
380        parser: &P,
381        input: &mut CssParser<'i, 't>,
382    ) -> Result<Self, ParseError<'i, P::Error>>
383    where
384        P: Parser<'i, Impl = Impl>,
385    {
386        Self::parse_with_state(
387            parser,
388            input,
389            SelectorParsingState::empty(),
390            ParseErrorRecovery::DiscardList,
391        )
392    }
393
394    #[inline]
395    fn parse_with_state<'i, 't, P>(
396        parser: &P,
397        input: &mut CssParser<'i, 't>,
398        state: SelectorParsingState,
399        recovery: ParseErrorRecovery,
400    ) -> Result<Self, ParseError<'i, P::Error>>
401    where
402        P: Parser<'i, Impl = Impl>,
403    {
404        let mut values = SmallVec::new();
405        loop {
406            let selector = input
407                .parse_until_before(Delimiter::Comma, |input| {
408                    parse_selector(parser, input, state)
409                });
410
411            let was_ok = selector.is_ok();
412            match selector {
413                Ok(selector) => values.push(selector),
414                Err(err) => match recovery {
415                    ParseErrorRecovery::DiscardList => return Err(err),
416                    ParseErrorRecovery::IgnoreInvalidSelector => {}
417                },
418            }
419
420            loop {
421                match input.next() {
422                    Err(_) => return Ok(SelectorList(values)),
423                    Ok(&Token::Comma) => break,
424                    Ok(_) => {
425                        debug_assert!(
426                            !was_ok,
427                            "Shouldn't have got a selector if getting here"
428                        );
429                    }
430                }
431            }
432        }
433    }
434
435    /// Creates a SelectorList from a Vec of selectors. Used in tests.
436    pub fn from_vec(v: Vec<Selector<Impl>>) -> Self {
437        SelectorList(SmallVec::from_vec(v))
438    }
439}
440
441/// Parses one compound selector suitable for nested stuff like :-moz-any, etc.
442fn parse_inner_compound_selector<'i, 't, P, Impl>(
443    parser: &P,
444    input: &mut CssParser<'i, 't>,
445    state: SelectorParsingState,
446) -> Result<Selector<Impl>, ParseError<'i, P::Error>>
447where
448    P: Parser<'i, Impl = Impl>,
449    Impl: SelectorImpl,
450{
451    parse_selector(
452        parser,
453        input,
454        state
455            | SelectorParsingState::DISALLOW_PSEUDOS
456            | SelectorParsingState::DISALLOW_COMBINATORS,
457    )
458}
459
460/// Ancestor hashes for the bloom filter. We precompute these and store them
461/// inline with selectors to optimize cache performance during matching.
462/// This matters a lot.
463///
464/// We use 4 hashes, which is copied from Gecko, who copied it from WebKit.
465/// Note that increasing the number of hashes here will adversely affect the
466/// cache hit when fast-rejecting long lists of Rules with inline hashes.
467///
468/// Because the bloom filter only uses the bottom 24 bits of the hash, we pack
469/// the fourth hash into the upper bits of the first three hashes in order to
470/// shrink Rule (whose size matters a lot). This scheme minimizes the runtime
471/// overhead of the packing for the first three hashes (we just need to mask
472/// off the upper bits) at the expense of making the fourth somewhat more
473/// complicated to assemble, because we often bail out before checking all the
474/// hashes.
475#[derive(Clone, Debug, Eq, PartialEq)]
476pub struct AncestorHashes {
477    pub packed_hashes: [u32; 3],
478}
479
480fn collect_ancestor_hashes<Impl: SelectorImpl>(
481    iter: SelectorIter<Impl>,
482    quirks_mode: QuirksMode,
483    hashes: &mut [u32; 4],
484    len: &mut usize,
485) -> bool
486where
487    Impl::Identifier: PrecomputedHash,
488    Impl::LocalName: PrecomputedHash,
489    Impl::NamespaceUrl: PrecomputedHash,
490{
491    for component in AncestorIter::new(iter) {
492        let hash = match *component {
493            Component::LocalName(LocalName {
494                ref name,
495                ref lower_name,
496            }) => {
497                // Only insert the local-name into the filter if it's all
498                // lowercase.  Otherwise we would need to test both hashes, and
499                // our data structures aren't really set up for that.
500                if name != lower_name {
501                    continue;
502                }
503                name.precomputed_hash()
504            }
505            Component::DefaultNamespace(ref url)
506            | Component::Namespace(_, ref url) => url.precomputed_hash(),
507            // In quirks mode, class and id selectors should match
508            // case-insensitively, so just avoid inserting them into the filter.
509            Component::ID(ref id) if quirks_mode != QuirksMode::Quirks => {
510                id.precomputed_hash()
511            }
512            Component::Class(ref class)
513                if quirks_mode != QuirksMode::Quirks =>
514            {
515                class.precomputed_hash()
516            }
517            Component::Is(ref list) | Component::Where(ref list) => {
518                // :where and :is OR their selectors, so we can't put any hash
519                // in the filter if there's more than one selector, as that'd
520                // exclude elements that may match one of the other selectors.
521                if list.len() == 1
522                    && !collect_ancestor_hashes(
523                        list[0].iter(),
524                        quirks_mode,
525                        hashes,
526                        len,
527                    )
528                {
529                    return false;
530                }
531                continue;
532            }
533            _ => continue,
534        };
535
536        hashes[*len] = hash & BLOOM_HASH_MASK;
537        *len += 1;
538        if *len == hashes.len() {
539            return false;
540        }
541    }
542    true
543}
544
545impl AncestorHashes {
546    pub fn new<Impl: SelectorImpl>(
547        selector: &Selector<Impl>,
548        quirks_mode: QuirksMode,
549    ) -> Self
550    where
551        Impl::Identifier: PrecomputedHash,
552        Impl::LocalName: PrecomputedHash,
553        Impl::NamespaceUrl: PrecomputedHash,
554    {
555        // Compute ancestor hashes for the bloom filter.
556        let mut hashes = [0u32; 4];
557        let mut len = 0;
558        collect_ancestor_hashes(
559            selector.iter(),
560            quirks_mode,
561            &mut hashes,
562            &mut len,
563        );
564        debug_assert!(len <= 4);
565
566        // Now, pack the fourth hash (if it exists) into the upper byte of each of
567        // the other three hashes.
568        if len == 4 {
569            let fourth = hashes[3];
570            hashes[0] |= (fourth & 0x000000ff) << 24;
571            hashes[1] |= (fourth & 0x0000ff00) << 16;
572            hashes[2] |= (fourth & 0x00ff0000) << 8;
573        }
574
575        AncestorHashes {
576            packed_hashes: [hashes[0], hashes[1], hashes[2]],
577        }
578    }
579
580    /// Returns the fourth hash, reassembled from parts.
581    pub fn fourth_hash(&self) -> u32 {
582        ((self.packed_hashes[0] & 0xff000000) >> 24)
583            | ((self.packed_hashes[1] & 0xff000000) >> 16)
584            | ((self.packed_hashes[2] & 0xff000000) >> 8)
585    }
586}
587
588pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
589    // Rust type’s default, not default namespace
590    Impl::NamespaceUrl::default()
591}
592
593/// A Selector stores a sequence of simple selectors and combinators. The
594/// iterator classes allow callers to iterate at either the raw sequence level or
595/// at the level of sequences of simple selectors separated by combinators. Most
596/// callers want the higher-level iterator.
597///
598/// We store compound selectors internally right-to-left (in matching order).
599/// Additionally, we invert the order of top-level compound selectors so that
600/// each one matches left-to-right. This is because matching namespace, local name,
601/// id, and class are all relatively cheap, whereas matching pseudo-classes might
602/// be expensive (depending on the pseudo-class). Since authors tend to put the
603/// pseudo-classes on the right, it's faster to start matching on the left.
604///
605/// This reordering doesn't change the semantics of selector matching, and we
606/// handle it in to_css to make it invisible to serialization.
607#[derive(Clone, Eq, PartialEq)]
608pub struct Selector<Impl: SelectorImpl>(
609    ThinArc<SpecificityAndFlags, Component<Impl>>,
610);
611
612impl<Impl: SelectorImpl> Selector<Impl> {
613    #[inline]
614    pub fn specificity(&self) -> u32 {
615        self.0.header.header.specificity()
616    }
617
618    #[inline]
619    pub fn has_pseudo_element(&self) -> bool {
620        self.0.header.header.has_pseudo_element()
621    }
622
623    #[inline]
624    pub fn is_slotted(&self) -> bool {
625        self.0.header.header.is_slotted()
626    }
627
628    #[inline]
629    pub fn is_part(&self) -> bool {
630        self.0.header.header.is_part()
631    }
632
633    #[inline]
634    pub fn parts(&self) -> Option<&[Impl::Identifier]> {
635        if !self.is_part() {
636            return None;
637        }
638
639        let mut iter = self.iter();
640        if self.has_pseudo_element() {
641            // Skip the pseudo-element.
642            for _ in &mut iter {}
643
644            let combinator = iter.next_sequence()?;
645            debug_assert_eq!(combinator, Combinator::PseudoElement);
646        }
647
648        for component in iter {
649            if let Component::Part(ref part) = *component {
650                return Some(part);
651            }
652        }
653
654        debug_assert!(false, "is_part() lied somehow?");
655        None
656    }
657
658    #[inline]
659    pub fn pseudo_element(&self) -> Option<&Impl::PseudoElement> {
660        if !self.has_pseudo_element() {
661            return None;
662        }
663
664        for component in self.iter() {
665            if let Component::PseudoElement(ref pseudo) = *component {
666                return Some(pseudo);
667            }
668        }
669
670        debug_assert!(false, "has_pseudo_element lied!");
671        None
672    }
673
674    /// Whether this selector (pseudo-element part excluded) matches every element.
675    ///
676    /// Used for "pre-computed" pseudo-elements in components/style/stylist.rs
677    #[inline]
678    pub fn is_universal(&self) -> bool {
679        self.iter_raw_match_order().all(|c| {
680            matches!(
681                *c,
682                Component::ExplicitUniversalType
683                    | Component::ExplicitAnyNamespace
684                    | Component::Combinator(Combinator::PseudoElement)
685                    | Component::PseudoElement(..)
686            )
687        })
688    }
689
690    /// Returns an iterator over this selector in matching order (right-to-left).
691    /// When a combinator is reached, the iterator will return None, and
692    /// next_sequence() may be called to continue to the next sequence.
693    #[inline]
694    pub fn iter(&self) -> SelectorIter<Impl> {
695        SelectorIter {
696            iter: self.iter_raw_match_order(),
697            next_combinator: None,
698        }
699    }
700
701    /// Whether this selector is a featureless :host selector, with no
702    /// combinators to the left, and optionally has a pseudo-element to the
703    /// right.
704    #[inline]
705    pub fn is_featureless_host_selector_or_pseudo_element(&self) -> bool {
706        let mut iter = self.iter();
707        if !self.has_pseudo_element() {
708            return iter.is_featureless_host_selector();
709        }
710
711        // Skip the pseudo-element.
712        for _ in &mut iter {}
713
714        match iter.next_sequence() {
715            None => return false,
716            Some(combinator) => {
717                debug_assert_eq!(combinator, Combinator::PseudoElement);
718            }
719        }
720
721        iter.is_featureless_host_selector()
722    }
723
724    /// Returns an iterator over this selector in matching order (right-to-left),
725    /// skipping the rightmost |offset| Components.
726    #[inline]
727    pub fn iter_from(&self, offset: usize) -> SelectorIter<Impl> {
728        let iter = self.0.slice[offset..].iter();
729        SelectorIter {
730            iter,
731            next_combinator: None,
732        }
733    }
734
735    /// Returns the combinator at index `index` (zero-indexed from the right),
736    /// or panics if the component is not a combinator.
737    #[inline]
738    pub fn combinator_at_match_order(&self, index: usize) -> Combinator {
739        match self.0.slice[index] {
740            Component::Combinator(c) => c,
741            ref other => panic!(
742                "Not a combinator: {:?}, {:?}, index: {}",
743                other, self, index
744            ),
745        }
746    }
747
748    /// Returns an iterator over the entire sequence of simple selectors and
749    /// combinators, in matching order (from right to left).
750    #[inline]
751    pub fn iter_raw_match_order(&self) -> slice::Iter<Component<Impl>> {
752        self.0.slice.iter()
753    }
754
755    /// Returns the combinator at index `index` (zero-indexed from the left),
756    /// or panics if the component is not a combinator.
757    #[inline]
758    pub fn combinator_at_parse_order(&self, index: usize) -> Combinator {
759        match self.0.slice[self.len() - index - 1] {
760            Component::Combinator(c) => c,
761            ref other => panic!(
762                "Not a combinator: {:?}, {:?}, index: {}",
763                other, self, index
764            ),
765        }
766    }
767
768    /// Returns an iterator over the sequence of simple selectors and
769    /// combinators, in parse order (from left to right), starting from
770    /// `offset`.
771    #[inline]
772    pub fn iter_raw_parse_order_from(
773        &self,
774        offset: usize,
775    ) -> Rev<slice::Iter<Component<Impl>>> {
776        self.0.slice[..self.len() - offset].iter().rev()
777    }
778
779    /// Creates a Selector from a vec of Components, specified in parse order. Used in tests.
780    #[allow(unused)]
781    pub(crate) fn from_vec(
782        vec: Vec<Component<Impl>>,
783        specificity: u32,
784        flags: SelectorFlags,
785    ) -> Self {
786        let mut builder = SelectorBuilder::default();
787        for component in vec.into_iter() {
788            if let Some(combinator) = component.as_combinator() {
789                builder.push_combinator(combinator);
790            } else {
791                builder.push_simple_selector(component);
792            }
793        }
794        let spec = SpecificityAndFlags { specificity, flags };
795        Selector(builder.build_with_specificity_and_flags(spec))
796    }
797
798    /// Returns count of simple selectors and combinators in the Selector.
799    #[inline]
800    pub fn len(&self) -> usize {
801        self.0.slice.len()
802    }
803
804    /// Returns the address on the heap of the ThinArc for memory reporting.
805    pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
806        self.0.heap_ptr()
807    }
808
809    /// Traverse selector components inside `self`.
810    ///
811    /// Implementations of this method should call `SelectorVisitor` methods
812    /// or other impls of `Visit` as appropriate based on the fields of `Self`.
813    ///
814    /// A return value of `false` indicates terminating the traversal.
815    /// It should be propagated with an early return.
816    /// On the contrary, `true` indicates that all fields of `self` have been traversed:
817    ///
818    /// ```rust,ignore
819    /// if !visitor.visit_simple_selector(&self.some_simple_selector) {
820    ///     return false;
821    /// }
822    /// if !self.some_component.visit(visitor) {
823    ///     return false;
824    /// }
825    /// true
826    /// ```
827    pub fn visit<V>(&self, visitor: &mut V) -> bool
828    where
829        V: SelectorVisitor<Impl = Impl>,
830    {
831        let mut current = self.iter();
832        let mut combinator = None;
833        loop {
834            if !visitor.visit_complex_selector(combinator) {
835                return false;
836            }
837
838            for selector in &mut current {
839                if !selector.visit(visitor) {
840                    return false;
841                }
842            }
843
844            combinator = current.next_sequence();
845            if combinator.is_none() {
846                break;
847            }
848        }
849
850        true
851    }
852}
853
854#[derive(Clone)]
855pub struct SelectorIter<'a, Impl: 'a + SelectorImpl> {
856    iter: slice::Iter<'a, Component<Impl>>,
857    next_combinator: Option<Combinator>,
858}
859
860impl<'a, Impl: 'a + SelectorImpl> SelectorIter<'a, Impl> {
861    /// Prepares this iterator to point to the next sequence to the left,
862    /// returning the combinator if the sequence was found.
863    #[inline]
864    pub fn next_sequence(&mut self) -> Option<Combinator> {
865        self.next_combinator.take()
866    }
867
868    /// Whether this selector is a featureless host selector, with no
869    /// combinators to the left.
870    #[inline]
871    pub(crate) fn is_featureless_host_selector(&mut self) -> bool {
872        self.selector_length() > 0
873            && self.all(|component| matches!(*component, Component::Host(..)))
874            && self.next_sequence().is_none()
875    }
876
877    #[inline]
878    pub(crate) fn matches_for_stateless_pseudo_element(&mut self) -> bool {
879        let first = match self.next() {
880            Some(c) => c,
881            // Note that this is the common path that we keep inline: the
882            // pseudo-element not having anything to its right.
883            None => return true,
884        };
885        self.matches_for_stateless_pseudo_element_internal(first)
886    }
887
888    #[inline(never)]
889    fn matches_for_stateless_pseudo_element_internal(
890        &mut self,
891        first: &Component<Impl>,
892    ) -> bool {
893        if !first.matches_for_stateless_pseudo_element() {
894            return false;
895        }
896        for component in self {
897            // The only other parser-allowed Components in this sequence are
898            // state pseudo-classes, or one of the other things that can contain
899            // them.
900            if !component.matches_for_stateless_pseudo_element() {
901                return false;
902            }
903        }
904        true
905    }
906
907    /// Returns remaining count of the simple selectors and combinators in the Selector.
908    #[inline]
909    pub fn selector_length(&self) -> usize {
910        self.iter.len()
911    }
912}
913
914impl<'a, Impl: SelectorImpl> Iterator for SelectorIter<'a, Impl> {
915    type Item = &'a Component<Impl>;
916
917    #[inline]
918    fn next(&mut self) -> Option<Self::Item> {
919        debug_assert!(
920            self.next_combinator.is_none(),
921            "You should call next_sequence!"
922        );
923        match *self.iter.next()? {
924            Component::Combinator(c) => {
925                self.next_combinator = Some(c);
926                None
927            }
928            ref x => Some(x),
929        }
930    }
931}
932
933impl<'a, Impl: SelectorImpl> fmt::Debug for SelectorIter<'a, Impl> {
934    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
935        let iter = self.iter.clone().rev();
936        for component in iter {
937            component.to_css(f)?
938        }
939        Ok(())
940    }
941}
942
943/// An iterator over all simple selectors belonging to ancestors.
944struct AncestorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
945impl<'a, Impl: 'a + SelectorImpl> AncestorIter<'a, Impl> {
946    /// Creates an AncestorIter. The passed-in iterator is assumed to point to
947    /// the beginning of the child sequence, which will be skipped.
948    fn new(inner: SelectorIter<'a, Impl>) -> Self {
949        let mut result = AncestorIter(inner);
950        result.skip_until_ancestor();
951        result
952    }
953
954    /// Skips a sequence of simple selectors and all subsequent sequences until
955    /// a non-pseudo-element ancestor combinator is reached.
956    fn skip_until_ancestor(&mut self) {
957        loop {
958            while self.0.next().is_some() {}
959            // If this is ever changed to stop at the "pseudo-element"
960            // combinator, we will need to fix the way we compute hashes for
961            // revalidation selectors.
962            if self.0.next_sequence().map_or(true, |x| {
963                matches!(x, Combinator::Child | Combinator::Descendant)
964            }) {
965                break;
966            }
967        }
968    }
969}
970
971impl<'a, Impl: SelectorImpl> Iterator for AncestorIter<'a, Impl> {
972    type Item = &'a Component<Impl>;
973    fn next(&mut self) -> Option<Self::Item> {
974        // Grab the next simple selector in the sequence if available.
975        let next = self.0.next();
976        if next.is_some() {
977            return next;
978        }
979
980        // See if there are more sequences. If so, skip any non-ancestor sequences.
981        if let Some(combinator) = self.0.next_sequence() {
982            if !matches!(combinator, Combinator::Child | Combinator::Descendant)
983            {
984                self.skip_until_ancestor();
985            }
986        }
987
988        self.0.next()
989    }
990}
991
992#[derive(Clone, Copy, Debug, Eq, PartialEq)]
993pub enum Combinator {
994    Child,        //  >
995    Descendant,   // space
996    NextSibling,  // +
997    LaterSibling, // ~
998    /// A dummy combinator we use to the left of pseudo-elements.
999    ///
1000    /// It serializes as the empty string, and acts effectively as a child
1001    /// combinator in most cases.  If we ever actually start using a child
1002    /// combinator for this, we will need to fix up the way hashes are computed
1003    /// for revalidation selectors.
1004    PseudoElement,
1005    /// Another combinator used for ::slotted(), which represent the jump from
1006    /// a node to its assigned slot.
1007    SlotAssignment,
1008    /// Another combinator used for `::part()`, which represents the jump from
1009    /// the part to the containing shadow host.
1010    Part,
1011}
1012
1013impl Combinator {
1014    /// Returns true if this combinator is a child or descendant combinator.
1015    #[inline]
1016    pub fn is_ancestor(&self) -> bool {
1017        matches!(
1018            *self,
1019            Combinator::Child
1020                | Combinator::Descendant
1021                | Combinator::PseudoElement
1022                | Combinator::SlotAssignment
1023        )
1024    }
1025
1026    /// Returns true if this combinator is a pseudo-element combinator.
1027    #[inline]
1028    pub fn is_pseudo_element(&self) -> bool {
1029        matches!(*self, Combinator::PseudoElement)
1030    }
1031
1032    /// Returns true if this combinator is a next- or later-sibling combinator.
1033    #[inline]
1034    pub fn is_sibling(&self) -> bool {
1035        matches!(*self, Combinator::NextSibling | Combinator::LaterSibling)
1036    }
1037}
1038
1039/// A CSS simple selector or combinator. We store both in the same enum for
1040/// optimal packing and cache performance, see [1].
1041///
1042/// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973
1043#[derive(Clone, Eq, PartialEq)]
1044pub enum Component<Impl: SelectorImpl> {
1045    Combinator(Combinator),
1046
1047    ExplicitAnyNamespace,
1048    ExplicitNoNamespace,
1049    DefaultNamespace(Impl::NamespaceUrl),
1050    Namespace(Impl::NamespacePrefix, Impl::NamespaceUrl),
1051
1052    ExplicitUniversalType,
1053    LocalName(LocalName<Impl>),
1054
1055    ID(Impl::Identifier),
1056    Class(Impl::Identifier),
1057
1058    AttributeInNoNamespaceExists {
1059        local_name: Impl::LocalName,
1060        local_name_lower: Impl::LocalName,
1061    },
1062    // Used only when local_name is already lowercase.
1063    AttributeInNoNamespace {
1064        local_name: Impl::LocalName,
1065        operator: AttrSelectorOperator,
1066        value: Impl::AttrValue,
1067        case_sensitivity: ParsedCaseSensitivity,
1068        never_matches: bool,
1069    },
1070    // Use a Box in the less common cases with more data to keep size_of::<Component>() small.
1071    AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>),
1072
1073    /// Pseudo-classes
1074    Negation(Box<[Selector<Impl>]>),
1075    FirstChild,
1076    LastChild,
1077    OnlyChild,
1078    Root,
1079    Empty,
1080    Scope,
1081    NthChild(i32, i32),
1082    NthLastChild(i32, i32),
1083    NthOfType(i32, i32),
1084    NthLastOfType(i32, i32),
1085    FirstOfType,
1086    LastOfType,
1087    OnlyOfType,
1088    NonTSPseudoClass(Impl::NonTSPseudoClass),
1089    /// The ::slotted() pseudo-element:
1090    ///
1091    /// https://drafts.csswg.org/css-scoping/#slotted-pseudo
1092    ///
1093    /// The selector here is a compound selector, that is, no combinators.
1094    ///
1095    /// NOTE(emilio): This should support a list of selectors, but as of this
1096    /// writing no other browser does, and that allows them to put ::slotted()
1097    /// in the rule hash, so we do that too.
1098    ///
1099    /// See https://github.com/w3c/csswg-drafts/issues/2158
1100    Slotted(Selector<Impl>),
1101    /// The `::part` pseudo-element.
1102    ///   https://drafts.csswg.org/css-shadow-parts/#part
1103    Part(Box<[Impl::Identifier]>),
1104    /// The `:host` pseudo-class:
1105    ///
1106    /// https://drafts.csswg.org/css-scoping/#host-selector
1107    ///
1108    /// NOTE(emilio): This should support a list of selectors, but as of this
1109    /// writing no other browser does, and that allows them to put :host()
1110    /// in the rule hash, so we do that too.
1111    ///
1112    /// See https://github.com/w3c/csswg-drafts/issues/2158
1113    Host(Option<Selector<Impl>>),
1114    /// The `:where` pseudo-class.
1115    ///
1116    /// https://drafts.csswg.org/selectors/#zero-matches
1117    ///
1118    /// The inner argument is conceptually a SelectorList, but we move the
1119    /// selectors to the heap to keep Component small.
1120    Where(Box<[Selector<Impl>]>),
1121    /// The `:is` pseudo-class.
1122    ///
1123    /// https://drafts.csswg.org/selectors/#matches-pseudo
1124    ///
1125    /// Same comment as above re. the argument.
1126    Is(Box<[Selector<Impl>]>),
1127    /// An implementation-dependent pseudo-element selector.
1128    PseudoElement(Impl::PseudoElement),
1129}
1130
1131impl<Impl: SelectorImpl> Component<Impl> {
1132    /// Returns true if this is a combinator.
1133    pub fn is_combinator(&self) -> bool {
1134        matches!(*self, Component::Combinator(_))
1135    }
1136
1137    /// Returns the value as a combinator if applicable, None otherwise.
1138    pub fn as_combinator(&self) -> Option<Combinator> {
1139        match *self {
1140            Component::Combinator(c) => Some(c),
1141            _ => None,
1142        }
1143    }
1144
1145    /// Whether this component is valid after a pseudo-element. Only intended
1146    /// for sanity-checking.
1147    pub fn maybe_allowed_after_pseudo_element(&self) -> bool {
1148        match *self {
1149            Component::NonTSPseudoClass(..) => true,
1150            Component::Negation(ref selectors)
1151            | Component::Is(ref selectors)
1152            | Component::Where(ref selectors) => {
1153                selectors.iter().all(|selector| {
1154                    selector
1155                        .iter_raw_match_order()
1156                        .all(|c| c.maybe_allowed_after_pseudo_element())
1157                })
1158            }
1159            _ => false,
1160        }
1161    }
1162
1163    /// Whether a given selector should match for stateless pseudo-elements.
1164    ///
1165    /// This is a bit subtle: Only selectors that return true in
1166    /// `maybe_allowed_after_pseudo_element` should end up here, and
1167    /// `NonTSPseudoClass` never matches (as it is a stateless pseudo after
1168    /// all).
1169    fn matches_for_stateless_pseudo_element(&self) -> bool {
1170        debug_assert!(
1171            self.maybe_allowed_after_pseudo_element(),
1172            "Someone messed up pseudo-element parsing: {:?}",
1173            *self
1174        );
1175        match *self {
1176            Component::Negation(ref selectors) => {
1177                !selectors.iter().all(|selector| {
1178                    selector
1179                        .iter_raw_match_order()
1180                        .all(|c| c.matches_for_stateless_pseudo_element())
1181                })
1182            }
1183            Component::Is(ref selectors) | Component::Where(ref selectors) => {
1184                selectors.iter().any(|selector| {
1185                    selector
1186                        .iter_raw_match_order()
1187                        .all(|c| c.matches_for_stateless_pseudo_element())
1188                })
1189            }
1190            _ => false,
1191        }
1192    }
1193
1194    pub fn visit<V>(&self, visitor: &mut V) -> bool
1195    where
1196        V: SelectorVisitor<Impl = Impl>,
1197    {
1198        use self::Component::*;
1199        if !visitor.visit_simple_selector(self) {
1200            return false;
1201        }
1202
1203        match *self {
1204            Slotted(ref selector) => {
1205                if !selector.visit(visitor) {
1206                    return false;
1207                }
1208            }
1209            Host(Some(ref selector)) => {
1210                if !selector.visit(visitor) {
1211                    return false;
1212                }
1213            }
1214            AttributeInNoNamespaceExists {
1215                ref local_name,
1216                ref local_name_lower,
1217            } => {
1218                if !visitor.visit_attribute_selector(
1219                    &NamespaceConstraint::Specific(&namespace_empty_string::<
1220                        Impl,
1221                    >()),
1222                    local_name,
1223                    local_name_lower,
1224                ) {
1225                    return false;
1226                }
1227            }
1228            AttributeInNoNamespace {
1229                ref local_name,
1230                never_matches,
1231                ..
1232            } if !never_matches => {
1233                if !visitor.visit_attribute_selector(
1234                    &NamespaceConstraint::Specific(&namespace_empty_string::<
1235                        Impl,
1236                    >()),
1237                    local_name,
1238                    local_name,
1239                ) {
1240                    return false;
1241                }
1242            }
1243            AttributeOther(ref attr_selector)
1244                if !attr_selector.never_matches =>
1245            {
1246                let empty_string;
1247                let namespace = match attr_selector.namespace() {
1248                    Some(ns) => ns,
1249                    None => {
1250                        empty_string =
1251                            crate::parser::namespace_empty_string::<Impl>();
1252                        NamespaceConstraint::Specific(&empty_string)
1253                    }
1254                };
1255                if !visitor.visit_attribute_selector(
1256                    &namespace,
1257                    &attr_selector.local_name,
1258                    &attr_selector.local_name_lower,
1259                ) {
1260                    return false;
1261                }
1262            }
1263
1264            NonTSPseudoClass(ref pseudo_class) => {
1265                if !pseudo_class.visit(visitor) {
1266                    return false;
1267                }
1268            }
1269
1270            Negation(ref list) | Is(ref list) | Where(ref list) => {
1271                if !visitor.visit_selector_list(&list) {
1272                    return false;
1273                }
1274            }
1275            _ => {}
1276        }
1277
1278        true
1279    }
1280}
1281
1282#[derive(Clone, Eq, PartialEq)]
1283pub struct LocalName<Impl: SelectorImpl> {
1284    pub name: Impl::LocalName,
1285    pub lower_name: Impl::LocalName,
1286}
1287
1288impl<Impl: SelectorImpl> Debug for Selector<Impl> {
1289    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1290        f.write_str("Selector(")?;
1291        self.to_css(f)?;
1292        write!(f, ", specificity = 0x{:x})", self.specificity())
1293    }
1294}
1295
1296impl<Impl: SelectorImpl> Debug for Component<Impl> {
1297    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1298        self.to_css(f)
1299    }
1300}
1301impl<Impl: SelectorImpl> Debug for AttrSelectorWithOptionalNamespace<Impl> {
1302    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1303        self.to_css(f)
1304    }
1305}
1306impl<Impl: SelectorImpl> Debug for LocalName<Impl> {
1307    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1308        self.to_css(f)
1309    }
1310}
1311
1312fn serialize_selector_list<'a, Impl, I, W>(iter: I, dest: &mut W) -> fmt::Result
1313where
1314    Impl: SelectorImpl,
1315    I: Iterator<Item = &'a Selector<Impl>>,
1316    W: fmt::Write,
1317{
1318    let mut first = true;
1319    for selector in iter {
1320        if !first {
1321            dest.write_str(", ")?;
1322        }
1323        first = false;
1324        selector.to_css(dest)?;
1325    }
1326    Ok(())
1327}
1328
1329impl<Impl: SelectorImpl> ToCss for SelectorList<Impl> {
1330    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1331    where
1332        W: fmt::Write,
1333    {
1334        serialize_selector_list(self.0.iter(), dest)
1335    }
1336}
1337
1338impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
1339    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1340    where
1341        W: fmt::Write,
1342    {
1343        // Compound selectors invert the order of their contents, so we need to
1344        // undo that during serialization.
1345        //
1346        // This two-iterator strategy involves walking over the selector twice.
1347        // We could do something more clever, but selector serialization probably
1348        // isn't hot enough to justify it, and the stringification likely
1349        // dominates anyway.
1350        //
1351        // NB: A parse-order iterator is a Rev<>, which doesn't expose as_slice(),
1352        // which we need for |split|. So we split by combinators on a match-order
1353        // sequence and then reverse.
1354
1355        let mut combinators = self
1356            .iter_raw_match_order()
1357            .rev()
1358            .filter_map(|x| x.as_combinator());
1359        let compound_selectors = self
1360            .iter_raw_match_order()
1361            .as_slice()
1362            .split(|x| x.is_combinator())
1363            .rev();
1364
1365        let mut combinators_exhausted = false;
1366        for compound in compound_selectors {
1367            debug_assert!(!combinators_exhausted);
1368
1369            // https://drafts.csswg.org/cssom/#serializing-selectors
1370            if compound.is_empty() {
1371                continue;
1372            }
1373
1374            // 1. If there is only one simple selector in the compound selectors
1375            //    which is a universal selector, append the result of
1376            //    serializing the universal selector to s.
1377            //
1378            // Check if `!compound.empty()` first--this can happen if we have
1379            // something like `... > ::before`, because we store `>` and `::`
1380            // both as combinators internally.
1381            //
1382            // If we are in this case, after we have serialized the universal
1383            // selector, we skip Step 2 and continue with the algorithm.
1384            let (can_elide_namespace, first_non_namespace) = match compound[0] {
1385                Component::ExplicitAnyNamespace
1386                | Component::ExplicitNoNamespace
1387                | Component::Namespace(..) => (false, 1),
1388                Component::DefaultNamespace(..) => (true, 1),
1389                _ => (true, 0),
1390            };
1391            let mut perform_step_2 = true;
1392            let next_combinator = combinators.next();
1393            if first_non_namespace == compound.len() - 1 {
1394                match (next_combinator, &compound[first_non_namespace]) {
1395                    // We have to be careful here, because if there is a
1396                    // pseudo element "combinator" there isn't really just
1397                    // the one simple selector. Technically this compound
1398                    // selector contains the pseudo element selector as well
1399                    // -- Combinator::PseudoElement, just like
1400                    // Combinator::SlotAssignment, don't exist in the
1401                    // spec.
1402                    (Some(Combinator::PseudoElement), _)
1403                    | (Some(Combinator::SlotAssignment), _) => (),
1404                    (_, &Component::ExplicitUniversalType) => {
1405                        // Iterate over everything so we serialize the namespace
1406                        // too.
1407                        for simple in compound.iter() {
1408                            simple.to_css(dest)?;
1409                        }
1410                        // Skip step 2, which is an "otherwise".
1411                        perform_step_2 = false;
1412                    }
1413                    _ => (),
1414                }
1415            }
1416
1417            // 2. Otherwise, for each simple selector in the compound selectors
1418            //    that is not a universal selector of which the namespace prefix
1419            //    maps to a namespace that is not the default namespace
1420            //    serialize the simple selector and append the result to s.
1421            //
1422            // See https://github.com/w3c/csswg-drafts/issues/1606, which is
1423            // proposing to change this to match up with the behavior asserted
1424            // in cssom/serialize-namespaced-type-selectors.html, which the
1425            // following code tries to match.
1426            if perform_step_2 {
1427                for simple in compound.iter() {
1428                    if let Component::ExplicitUniversalType = *simple {
1429                        // Can't have a namespace followed by a pseudo-element
1430                        // selector followed by a universal selector in the same
1431                        // compound selector, so we don't have to worry about the
1432                        // real namespace being in a different `compound`.
1433                        if can_elide_namespace {
1434                            continue;
1435                        }
1436                    }
1437                    simple.to_css(dest)?;
1438                }
1439            }
1440
1441            // 3. If this is not the last part of the chain of the selector
1442            //    append a single SPACE (U+0020), followed by the combinator
1443            //    ">", "+", "~", ">>", "||", as appropriate, followed by another
1444            //    single SPACE (U+0020) if the combinator was not whitespace, to
1445            //    s.
1446            match next_combinator {
1447                Some(c) => c.to_css(dest)?,
1448                None => combinators_exhausted = true,
1449            };
1450
1451            // 4. If this is the last part of the chain of the selector and
1452            //    there is a pseudo-element, append "::" followed by the name of
1453            //    the pseudo-element, to s.
1454            //
1455            // (we handle this above)
1456        }
1457
1458        Ok(())
1459    }
1460}
1461
1462impl ToCss for Combinator {
1463    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1464    where
1465        W: fmt::Write,
1466    {
1467        match *self {
1468            Combinator::Child => dest.write_str(" > "),
1469            Combinator::Descendant => dest.write_str(" "),
1470            Combinator::NextSibling => dest.write_str(" + "),
1471            Combinator::LaterSibling => dest.write_str(" ~ "),
1472            Combinator::PseudoElement
1473            | Combinator::Part
1474            | Combinator::SlotAssignment => Ok(()),
1475        }
1476    }
1477}
1478
1479impl<Impl: SelectorImpl> ToCss for Component<Impl> {
1480    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1481    where
1482        W: fmt::Write,
1483    {
1484        use self::Component::*;
1485
1486        /// Serialize <an+b> values (part of the CSS Syntax spec, but currently only used here).
1487        /// <https://drafts.csswg.org/css-syntax-3/#serialize-an-anb-value>
1488        fn write_affine<W>(dest: &mut W, a: i32, b: i32) -> fmt::Result
1489        where
1490            W: fmt::Write,
1491        {
1492            match (a, b) {
1493                (0, 0) => dest.write_char('0'),
1494
1495                (1, 0) => dest.write_char('n'),
1496                (-1, 0) => dest.write_str("-n"),
1497                (_, 0) => write!(dest, "{}n", a),
1498
1499                (0, _) => write!(dest, "{}", b),
1500                (1, _) => write!(dest, "n{:+}", b),
1501                (-1, _) => write!(dest, "-n{:+}", b),
1502                (_, _) => write!(dest, "{}n{:+}", a, b),
1503            }
1504        }
1505
1506        match *self {
1507            Combinator(ref c) => c.to_css(dest),
1508            Slotted(ref selector) => {
1509                dest.write_str("::slotted(")?;
1510                selector.to_css(dest)?;
1511                dest.write_char(')')
1512            }
1513            Part(ref part_names) => {
1514                dest.write_str("::part(")?;
1515                for (i, name) in part_names.iter().enumerate() {
1516                    if i != 0 {
1517                        dest.write_char(' ')?;
1518                    }
1519                    name.to_css(dest)?;
1520                }
1521                dest.write_char(')')
1522            }
1523            PseudoElement(ref p) => p.to_css(dest),
1524            ID(ref s) => {
1525                dest.write_char('#')?;
1526                s.to_css(dest)
1527            }
1528            Class(ref s) => {
1529                dest.write_char('.')?;
1530                s.to_css(dest)
1531            }
1532            LocalName(ref s) => s.to_css(dest),
1533            ExplicitUniversalType => dest.write_char('*'),
1534
1535            DefaultNamespace(_) => Ok(()),
1536            ExplicitNoNamespace => dest.write_char('|'),
1537            ExplicitAnyNamespace => dest.write_str("*|"),
1538            Namespace(ref prefix, _) => {
1539                prefix.to_css(dest)?;
1540                dest.write_char('|')
1541            }
1542
1543            AttributeInNoNamespaceExists { ref local_name, .. } => {
1544                dest.write_char('[')?;
1545                local_name.to_css(dest)?;
1546                dest.write_char(']')
1547            }
1548            AttributeInNoNamespace {
1549                ref local_name,
1550                operator,
1551                ref value,
1552                case_sensitivity,
1553                ..
1554            } => {
1555                dest.write_char('[')?;
1556                local_name.to_css(dest)?;
1557                operator.to_css(dest)?;
1558                dest.write_char('"')?;
1559                value.to_css(dest)?;
1560                dest.write_char('"')?;
1561                match case_sensitivity {
1562                    ParsedCaseSensitivity::CaseSensitive |
1563                    ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
1564                    ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
1565                    ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
1566                }
1567                dest.write_char(']')
1568            }
1569            AttributeOther(ref attr_selector) => attr_selector.to_css(dest),
1570
1571            // Pseudo-classes
1572            FirstChild => dest.write_str(":first-child"),
1573            LastChild => dest.write_str(":last-child"),
1574            OnlyChild => dest.write_str(":only-child"),
1575            Root => dest.write_str(":root"),
1576            Empty => dest.write_str(":empty"),
1577            Scope => dest.write_str(":scope"),
1578            Host(ref selector) => {
1579                dest.write_str(":host")?;
1580                if let Some(ref selector) = *selector {
1581                    dest.write_char('(')?;
1582                    selector.to_css(dest)?;
1583                    dest.write_char(')')?;
1584                }
1585                Ok(())
1586            }
1587            FirstOfType => dest.write_str(":first-of-type"),
1588            LastOfType => dest.write_str(":last-of-type"),
1589            OnlyOfType => dest.write_str(":only-of-type"),
1590            NthChild(a, b)
1591            | NthLastChild(a, b)
1592            | NthOfType(a, b)
1593            | NthLastOfType(a, b) => {
1594                match *self {
1595                    NthChild(_, _) => dest.write_str(":nth-child(")?,
1596                    NthLastChild(_, _) => dest.write_str(":nth-last-child(")?,
1597                    NthOfType(_, _) => dest.write_str(":nth-of-type(")?,
1598                    NthLastOfType(_, _) => {
1599                        dest.write_str(":nth-last-of-type(")?
1600                    }
1601                    _ => unreachable!(),
1602                }
1603                write_affine(dest, a, b)?;
1604                dest.write_char(')')
1605            }
1606            Is(ref list) | Where(ref list) | Negation(ref list) => {
1607                match *self {
1608                    Where(..) => dest.write_str(":where(")?,
1609                    Is(..) => dest.write_str(":is(")?,
1610                    Negation(..) => dest.write_str(":not(")?,
1611                    _ => unreachable!(),
1612                }
1613                serialize_selector_list(list.iter(), dest)?;
1614                dest.write_str(")")
1615            }
1616            NonTSPseudoClass(ref pseudo) => pseudo.to_css(dest),
1617        }
1618    }
1619}
1620
1621impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> {
1622    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1623    where
1624        W: fmt::Write,
1625    {
1626        dest.write_char('[')?;
1627        match self.namespace {
1628            Some(NamespaceConstraint::Specific((ref prefix, _))) => {
1629                prefix.to_css(dest)?;
1630                dest.write_char('|')?
1631            }
1632            Some(NamespaceConstraint::Any) => dest.write_str("*|")?,
1633            None => {}
1634        }
1635        self.local_name.to_css(dest)?;
1636        match self.operation {
1637            ParsedAttrSelectorOperation::Exists => {}
1638            ParsedAttrSelectorOperation::WithValue {
1639                operator,
1640                case_sensitivity,
1641                ref expected_value,
1642            } => {
1643                operator.to_css(dest)?;
1644                dest.write_char('"')?;
1645                expected_value.to_css(dest)?;
1646                dest.write_char('"')?;
1647                match case_sensitivity {
1648                    ParsedCaseSensitivity::CaseSensitive |
1649                    ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
1650                    ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
1651                    ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
1652                }
1653            }
1654        }
1655        dest.write_char(']')
1656    }
1657}
1658
1659impl<Impl: SelectorImpl> ToCss for LocalName<Impl> {
1660    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
1661    where
1662        W: fmt::Write,
1663    {
1664        self.name.to_css(dest)
1665    }
1666}
1667
1668/// Build up a Selector.
1669/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
1670///
1671/// `Err` means invalid selector.
1672fn parse_selector<'i, 't, P, Impl>(
1673    parser: &P,
1674    input: &mut CssParser<'i, 't>,
1675    mut state: SelectorParsingState,
1676) -> Result<Selector<Impl>, ParseError<'i, P::Error>>
1677where
1678    P: Parser<'i, Impl = Impl>,
1679    Impl: SelectorImpl,
1680{
1681    let mut builder = SelectorBuilder::default();
1682
1683    let mut has_pseudo_element = false;
1684    let mut slotted = false;
1685    let mut part = false;
1686    'outer_loop: loop {
1687        // Parse a sequence of simple selectors.
1688        let empty =
1689            parse_compound_selector(parser, &mut state, input, &mut builder)?;
1690        if empty {
1691            return Err(input.new_custom_error(if builder.has_combinators() {
1692                SelectorParseErrorKind::DanglingCombinator
1693            } else {
1694                SelectorParseErrorKind::EmptySelector
1695            }));
1696        }
1697
1698        if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
1699            has_pseudo_element =
1700                state.intersects(SelectorParsingState::AFTER_PSEUDO_ELEMENT);
1701            slotted = state.intersects(SelectorParsingState::AFTER_SLOTTED);
1702            part = state.intersects(SelectorParsingState::AFTER_PART);
1703            debug_assert!(has_pseudo_element || slotted || part);
1704            break;
1705        }
1706
1707        // Parse a combinator.
1708        let combinator;
1709        let mut any_whitespace = false;
1710        loop {
1711            let before_this_token = input.state();
1712            match input.next_including_whitespace() {
1713                Err(_e) => break 'outer_loop,
1714                Ok(&Token::WhiteSpace(_)) => any_whitespace = true,
1715                Ok(&Token::Delim('>')) => {
1716                    combinator = Combinator::Child;
1717                    break;
1718                }
1719                Ok(&Token::Delim('+')) => {
1720                    combinator = Combinator::NextSibling;
1721                    break;
1722                }
1723                Ok(&Token::Delim('~')) => {
1724                    combinator = Combinator::LaterSibling;
1725                    break;
1726                }
1727                Ok(_) => {
1728                    input.reset(&before_this_token);
1729                    if any_whitespace {
1730                        combinator = Combinator::Descendant;
1731                        break;
1732                    } else {
1733                        break 'outer_loop;
1734                    }
1735                }
1736            }
1737        }
1738
1739        if !state.allows_combinators() {
1740            return Err(
1741                input.new_custom_error(SelectorParseErrorKind::InvalidState)
1742            );
1743        }
1744
1745        builder.push_combinator(combinator);
1746    }
1747
1748    Ok(Selector(builder.build(has_pseudo_element, slotted, part)))
1749}
1750
1751impl<Impl: SelectorImpl> Selector<Impl> {
1752    /// Parse a selector, without any pseudo-element.
1753    #[inline]
1754    pub fn parse<'i, 't, P>(
1755        parser: &P,
1756        input: &mut CssParser<'i, 't>,
1757    ) -> Result<Self, ParseError<'i, P::Error>>
1758    where
1759        P: Parser<'i, Impl = Impl>,
1760    {
1761        parse_selector(parser, input, SelectorParsingState::empty())
1762    }
1763}
1764
1765/// * `Err(())`: Invalid selector, abort
1766/// * `Ok(false)`: Not a type selector, could be something else. `input` was not consumed.
1767/// * `Ok(true)`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
1768fn parse_type_selector<'i, 't, P, Impl, S>(
1769    parser: &P,
1770    input: &mut CssParser<'i, 't>,
1771    state: SelectorParsingState,
1772    sink: &mut S,
1773) -> Result<bool, ParseError<'i, P::Error>>
1774where
1775    P: Parser<'i, Impl = Impl>,
1776    Impl: SelectorImpl,
1777    S: Push<Component<Impl>>,
1778{
1779    match parse_qualified_name(
1780        parser, input, /* in_attr_selector = */ false,
1781    ) {
1782        Err(ParseError {
1783            kind: ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput),
1784            ..
1785        })
1786        | Ok(OptionalQName::None(_)) => Ok(false),
1787        Ok(OptionalQName::Some(namespace, local_name)) => {
1788            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
1789                return Err(input
1790                    .new_custom_error(SelectorParseErrorKind::InvalidState));
1791            }
1792            match namespace {
1793                QNamePrefix::ImplicitAnyNamespace => {}
1794                QNamePrefix::ImplicitDefaultNamespace(url) => {
1795                    sink.push(Component::DefaultNamespace(url))
1796                }
1797                QNamePrefix::ExplicitNamespace(prefix, url) => {
1798                    sink.push(match parser.default_namespace() {
1799                        Some(ref default_url) if url == *default_url => {
1800                            Component::DefaultNamespace(url)
1801                        }
1802                        _ => Component::Namespace(prefix, url),
1803                    })
1804                }
1805                QNamePrefix::ExplicitNoNamespace => {
1806                    sink.push(Component::ExplicitNoNamespace)
1807                }
1808                QNamePrefix::ExplicitAnyNamespace => {
1809                    match parser.default_namespace() {
1810                        // Element type selectors that have no namespace
1811                        // component (no namespace separator) represent elements
1812                        // without regard to the element's namespace (equivalent
1813                        // to "*|") unless a default namespace has been declared
1814                        // for namespaced selectors (e.g. in CSS, in the style
1815                        // sheet). If a default namespace has been declared,
1816                        // such selectors will represent only elements in the
1817                        // default namespace.
1818                        // -- Selectors § 6.1.1
1819                        // So we'll have this act the same as the
1820                        // QNamePrefix::ImplicitAnyNamespace case.
1821                        None => {}
1822                        Some(_) => sink.push(Component::ExplicitAnyNamespace),
1823                    }
1824                }
1825                QNamePrefix::ImplicitNoNamespace => {
1826                    unreachable!() // Not returned with in_attr_selector = false
1827                }
1828            }
1829            match local_name {
1830                Some(name) => sink.push(Component::LocalName(LocalName {
1831                    lower_name: to_ascii_lowercase(&name).as_ref().into(),
1832                    name: name.as_ref().into(),
1833                })),
1834                None => sink.push(Component::ExplicitUniversalType),
1835            }
1836            Ok(true)
1837        }
1838        Err(e) => Err(e),
1839    }
1840}
1841
1842#[derive(Debug)]
1843enum SimpleSelectorParseResult<Impl: SelectorImpl> {
1844    SimpleSelector(Component<Impl>),
1845    PseudoElement(Impl::PseudoElement),
1846    SlottedPseudo(Selector<Impl>),
1847    PartPseudo(Box<[Impl::Identifier]>),
1848}
1849
1850#[derive(Debug)]
1851enum QNamePrefix<Impl: SelectorImpl> {
1852    ImplicitNoNamespace,  // `foo` in attr selectors
1853    ImplicitAnyNamespace, // `foo` in type selectors, without a default ns
1854    ImplicitDefaultNamespace(Impl::NamespaceUrl), // `foo` in type selectors, with a default ns
1855    ExplicitNoNamespace,                          // `|foo`
1856    ExplicitAnyNamespace,                         // `*|foo`
1857    ExplicitNamespace(Impl::NamespacePrefix, Impl::NamespaceUrl), // `prefix|foo`
1858}
1859
1860enum OptionalQName<'i, Impl: SelectorImpl> {
1861    Some(QNamePrefix<Impl>, Option<CowRcStr<'i>>),
1862    None(Token<'i>),
1863}
1864
1865/// * `Err(())`: Invalid selector, abort
1866/// * `Ok(None(token))`: Not a simple selector, could be something else. `input` was not consumed,
1867///                      but the token is still returned.
1868/// * `Ok(Some(namespace, local_name))`: `None` for the local name means a `*` universal selector
1869fn parse_qualified_name<'i, 't, P, Impl>(
1870    parser: &P,
1871    input: &mut CssParser<'i, 't>,
1872    in_attr_selector: bool,
1873) -> Result<OptionalQName<'i, Impl>, ParseError<'i, P::Error>>
1874where
1875    P: Parser<'i, Impl = Impl>,
1876    Impl: SelectorImpl,
1877{
1878    let default_namespace = |local_name| {
1879        let namespace = match parser.default_namespace() {
1880            Some(url) => QNamePrefix::ImplicitDefaultNamespace(url),
1881            None => QNamePrefix::ImplicitAnyNamespace,
1882        };
1883        Ok(OptionalQName::Some(namespace, local_name))
1884    };
1885
1886    let explicit_namespace = |input: &mut CssParser<'i, 't>, namespace| {
1887        let location = input.current_source_location();
1888        match input.next_including_whitespace() {
1889            Ok(&Token::Delim('*')) if !in_attr_selector => {
1890                Ok(OptionalQName::Some(namespace, None))
1891            }
1892            Ok(&Token::Ident(ref local_name)) => {
1893                Ok(OptionalQName::Some(namespace, Some(local_name.clone())))
1894            }
1895            Ok(t) if in_attr_selector => {
1896                let e =
1897                    SelectorParseErrorKind::InvalidQualNameInAttr(t.clone());
1898                Err(location.new_custom_error(e))
1899            }
1900            Ok(t) => Err(location.new_custom_error(
1901                SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(
1902                    t.clone(),
1903                ),
1904            )),
1905            Err(e) => Err(e.into()),
1906        }
1907    };
1908
1909    let start = input.state();
1910    // FIXME: remove clone() when lifetimes are non-lexical
1911    match input.next_including_whitespace().map(|t| t.clone()) {
1912        Ok(Token::Ident(value)) => {
1913            let after_ident = input.state();
1914            match input.next_including_whitespace() {
1915                Ok(&Token::Delim('|')) => {
1916                    let prefix = value.as_ref().into();
1917                    let result = parser.namespace_for_prefix(&prefix);
1918                    let url = result.ok_or(
1919                        after_ident.source_location().new_custom_error(
1920                            SelectorParseErrorKind::ExpectedNamespace(value),
1921                        ),
1922                    )?;
1923                    explicit_namespace(
1924                        input,
1925                        QNamePrefix::ExplicitNamespace(prefix, url),
1926                    )
1927                }
1928                _ => {
1929                    input.reset(&after_ident);
1930                    if in_attr_selector {
1931                        Ok(OptionalQName::Some(
1932                            QNamePrefix::ImplicitNoNamespace,
1933                            Some(value),
1934                        ))
1935                    } else {
1936                        default_namespace(Some(value))
1937                    }
1938                }
1939            }
1940        }
1941        Ok(Token::Delim('*')) => {
1942            let after_star = input.state();
1943            // FIXME: remove clone() when lifetimes are non-lexical
1944            match input.next_including_whitespace().map(|t| t.clone()) {
1945                Ok(Token::Delim('|')) => {
1946                    explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
1947                }
1948                result => {
1949                    input.reset(&after_star);
1950                    if in_attr_selector {
1951                        match result {
1952                            Ok(t) => Err(after_star
1953                                .source_location()
1954                                .new_custom_error(
1955                                    SelectorParseErrorKind::ExpectedBarInAttr(
1956                                        t,
1957                                    ),
1958                                )),
1959                            Err(e) => Err(e.into()),
1960                        }
1961                    } else {
1962                        default_namespace(None)
1963                    }
1964                }
1965            }
1966        }
1967        Ok(Token::Delim('|')) => {
1968            explicit_namespace(input, QNamePrefix::ExplicitNoNamespace)
1969        }
1970        Ok(t) => {
1971            input.reset(&start);
1972            Ok(OptionalQName::None(t))
1973        }
1974        Err(e) => {
1975            input.reset(&start);
1976            Err(e.into())
1977        }
1978    }
1979}
1980
1981fn parse_attribute_selector<'i, 't, P, Impl>(
1982    parser: &P,
1983    input: &mut CssParser<'i, 't>,
1984) -> Result<Component<Impl>, ParseError<'i, P::Error>>
1985where
1986    P: Parser<'i, Impl = Impl>,
1987    Impl: SelectorImpl,
1988{
1989    let namespace;
1990    let local_name;
1991
1992    input.skip_whitespace();
1993
1994    match parse_qualified_name(
1995        parser, input, /* in_attr_selector = */ true,
1996    )? {
1997        OptionalQName::None(t) => {
1998            return Err(input.new_custom_error(
1999                SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(t),
2000            ));
2001        }
2002        OptionalQName::Some(_, None) => unreachable!(),
2003        OptionalQName::Some(ns, Some(ln)) => {
2004            local_name = ln;
2005            namespace = match ns {
2006                QNamePrefix::ImplicitNoNamespace
2007                | QNamePrefix::ExplicitNoNamespace => None,
2008                QNamePrefix::ExplicitNamespace(prefix, url) => {
2009                    Some(NamespaceConstraint::Specific((prefix, url)))
2010                }
2011                QNamePrefix::ExplicitAnyNamespace => {
2012                    Some(NamespaceConstraint::Any)
2013                }
2014                QNamePrefix::ImplicitAnyNamespace
2015                | QNamePrefix::ImplicitDefaultNamespace(_) => {
2016                    unreachable!() // Not returned with in_attr_selector = true
2017                }
2018            }
2019        }
2020    }
2021
2022    let location = input.current_source_location();
2023    let operator = match input.next() {
2024        // [foo]
2025        Err(_) => {
2026            let local_name_lower =
2027                to_ascii_lowercase(&local_name).as_ref().into();
2028            let local_name = local_name.as_ref().into();
2029            if let Some(namespace) = namespace {
2030                return Ok(Component::AttributeOther(Box::new(
2031                    AttrSelectorWithOptionalNamespace {
2032                        namespace: Some(namespace),
2033                        local_name,
2034                        local_name_lower,
2035                        operation: ParsedAttrSelectorOperation::Exists,
2036                        never_matches: false,
2037                    },
2038                )));
2039            } else {
2040                return Ok(Component::AttributeInNoNamespaceExists {
2041                    local_name,
2042                    local_name_lower,
2043                });
2044            }
2045        }
2046
2047        // [foo=bar]
2048        Ok(&Token::Delim('=')) => AttrSelectorOperator::Equal,
2049        // [foo~=bar]
2050        Ok(&Token::IncludeMatch) => AttrSelectorOperator::Includes,
2051        // [foo|=bar]
2052        Ok(&Token::DashMatch) => AttrSelectorOperator::DashMatch,
2053        // [foo^=bar]
2054        Ok(&Token::PrefixMatch) => AttrSelectorOperator::Prefix,
2055        // [foo*=bar]
2056        Ok(&Token::SubstringMatch) => AttrSelectorOperator::Substring,
2057        // [foo$=bar]
2058        Ok(&Token::SuffixMatch) => AttrSelectorOperator::Suffix,
2059        Ok(t) => {
2060            return Err(location.new_custom_error(
2061                SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(
2062                    t.clone(),
2063                ),
2064            ));
2065        }
2066    };
2067
2068    let value = match input.expect_ident_or_string() {
2069        Ok(t) => t.clone(),
2070        Err(BasicParseError {
2071            kind: BasicParseErrorKind::UnexpectedToken(t),
2072            location,
2073        }) => {
2074            return Err(location
2075                .new_custom_error(SelectorParseErrorKind::BadValueInAttr(t)))
2076        }
2077        Err(e) => return Err(e.into()),
2078    };
2079    let never_matches = match operator {
2080        AttrSelectorOperator::Equal | AttrSelectorOperator::DashMatch => false,
2081
2082        AttrSelectorOperator::Includes => {
2083            value.is_empty() || value.contains(SELECTOR_WHITESPACE)
2084        }
2085
2086        AttrSelectorOperator::Prefix
2087        | AttrSelectorOperator::Substring
2088        | AttrSelectorOperator::Suffix => value.is_empty(),
2089    };
2090
2091    let attribute_flags = parse_attribute_flags(input)?;
2092
2093    let value = value.as_ref().into();
2094    let local_name_lower;
2095    let local_name_is_ascii_lowercase;
2096    let case_sensitivity;
2097    {
2098        let local_name_lower_cow = to_ascii_lowercase(&local_name);
2099        case_sensitivity = attribute_flags.to_case_sensitivity(
2100            local_name_lower_cow.as_ref(),
2101            namespace.is_some(),
2102        );
2103        local_name_lower = local_name_lower_cow.as_ref().into();
2104        local_name_is_ascii_lowercase =
2105            matches!(local_name_lower_cow, Cow::Borrowed(..));
2106    }
2107    let local_name = local_name.as_ref().into();
2108    if namespace.is_some() || !local_name_is_ascii_lowercase {
2109        Ok(Component::AttributeOther(Box::new(
2110            AttrSelectorWithOptionalNamespace {
2111                namespace,
2112                local_name,
2113                local_name_lower,
2114                never_matches,
2115                operation: ParsedAttrSelectorOperation::WithValue {
2116                    operator,
2117                    case_sensitivity,
2118                    expected_value: value,
2119                },
2120            },
2121        )))
2122    } else {
2123        Ok(Component::AttributeInNoNamespace {
2124            local_name,
2125            operator,
2126            value,
2127            case_sensitivity,
2128            never_matches,
2129        })
2130    }
2131}
2132
2133/// An attribute selector can have 's' or 'i' as flags, or no flags at all.
2134enum AttributeFlags {
2135    // Matching should be case-sensitive ('s' flag).
2136    CaseSensitive,
2137    // Matching should be case-insensitive ('i' flag).
2138    AsciiCaseInsensitive,
2139    // No flags.  Matching behavior depends on the name of the attribute.
2140    CaseSensitivityDependsOnName,
2141}
2142
2143impl AttributeFlags {
2144    fn to_case_sensitivity(
2145        self,
2146        local_name: &str,
2147        have_namespace: bool,
2148    ) -> ParsedCaseSensitivity {
2149        match self {
2150            AttributeFlags::CaseSensitive => {
2151                ParsedCaseSensitivity::ExplicitCaseSensitive
2152            }
2153            AttributeFlags::AsciiCaseInsensitive => {
2154                ParsedCaseSensitivity::AsciiCaseInsensitive
2155            }
2156            AttributeFlags::CaseSensitivityDependsOnName => {
2157                if !have_namespace
2158                    && include!(concat!(
2159                        env!("OUT_DIR"),
2160                        "/ascii_case_insensitive_html_attributes.rs"
2161                    ))
2162                    .contains(local_name)
2163                {
2164                    ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
2165                } else {
2166                    ParsedCaseSensitivity::CaseSensitive
2167                }
2168            }
2169        }
2170    }
2171}
2172
2173fn parse_attribute_flags<'i, 't>(
2174    input: &mut CssParser<'i, 't>,
2175) -> Result<AttributeFlags, BasicParseError<'i>> {
2176    let location = input.current_source_location();
2177    let token = match input.next() {
2178        Ok(t) => t,
2179        Err(..) => {
2180            // Selectors spec says language-defined; HTML says it depends on the
2181            // exact attribute name.
2182            return Ok(AttributeFlags::CaseSensitivityDependsOnName);
2183        }
2184    };
2185
2186    let ident = match *token {
2187        Token::Ident(ref i) => i,
2188        ref other => {
2189            return Err(location.new_basic_unexpected_token_error(other.clone()))
2190        }
2191    };
2192
2193    Ok(match_ignore_ascii_case! {
2194        ident,
2195        "i" => AttributeFlags::AsciiCaseInsensitive,
2196        "s" => AttributeFlags::CaseSensitive,
2197        _ => return Err(location.new_basic_unexpected_token_error(token.clone())),
2198    })
2199}
2200
2201/// Level 3: Parse **one** simple_selector.  (Though we might insert a second
2202/// implied "<defaultns>|*" type selector.)
2203fn parse_negation<'i, 't, P, Impl>(
2204    parser: &P,
2205    input: &mut CssParser<'i, 't>,
2206    state: SelectorParsingState,
2207) -> Result<Component<Impl>, ParseError<'i, P::Error>>
2208where
2209    P: Parser<'i, Impl = Impl>,
2210    Impl: SelectorImpl,
2211{
2212    let list = SelectorList::parse_with_state(
2213        parser,
2214        input,
2215        state
2216            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
2217            | SelectorParsingState::DISALLOW_PSEUDOS,
2218        ParseErrorRecovery::DiscardList,
2219    )?;
2220
2221    Ok(Component::Negation(list.0.into_vec().into_boxed_slice()))
2222}
2223
2224/// simple_selector_sequence
2225/// : [ type_selector | universal ] [ HASH | class | attrib | pseudo | negation ]*
2226/// | [ HASH | class | attrib | pseudo | negation ]+
2227///
2228/// `Err(())` means invalid selector.
2229/// `Ok(true)` is an empty selector
2230fn parse_compound_selector<'i, 't, P, Impl>(
2231    parser: &P,
2232    state: &mut SelectorParsingState,
2233    input: &mut CssParser<'i, 't>,
2234    builder: &mut SelectorBuilder<Impl>,
2235) -> Result<bool, ParseError<'i, P::Error>>
2236where
2237    P: Parser<'i, Impl = Impl>,
2238    Impl: SelectorImpl,
2239{
2240    input.skip_whitespace();
2241
2242    let mut empty = true;
2243    if parse_type_selector(parser, input, *state, builder)? {
2244        empty = false;
2245    }
2246
2247    loop {
2248        let result = match parse_one_simple_selector(parser, input, *state)? {
2249            None => break,
2250            Some(result) => result,
2251        };
2252
2253        if empty {
2254            if let Some(url) = parser.default_namespace() {
2255                // If there was no explicit type selector, but there is a
2256                // default namespace, there is an implicit "<defaultns>|*" type
2257                // selector. Except for :host() or :not() / :is() / :where(),
2258                // where we ignore it.
2259                //
2260                // https://drafts.csswg.org/css-scoping/#host-element-in-tree:
2261                //
2262                //     When considered within its own shadow trees, the shadow
2263                //     host is featureless. Only the :host, :host(), and
2264                //     :host-context() pseudo-classes are allowed to match it.
2265                //
2266                // https://drafts.csswg.org/selectors-4/#featureless:
2267                //
2268                //     A featureless element does not match any selector at all,
2269                //     except those it is explicitly defined to match. If a
2270                //     given selector is allowed to match a featureless element,
2271                //     it must do so while ignoring the default namespace.
2272                //
2273                // https://drafts.csswg.org/selectors-4/#matches
2274                //
2275                //     Default namespace declarations do not affect the compound
2276                //     selector representing the subject of any selector within
2277                //     a :is() pseudo-class, unless that compound selector
2278                //     contains an explicit universal selector or type selector.
2279                //
2280                //     (Similar quotes for :where() / :not())
2281                //
2282                let ignore_default_ns = state
2283                    .intersects(SelectorParsingState::SKIP_DEFAULT_NAMESPACE)
2284                    || matches!(
2285                        result,
2286                        SimpleSelectorParseResult::SimpleSelector(
2287                            Component::Host(..)
2288                        )
2289                    );
2290                if !ignore_default_ns {
2291                    builder
2292                        .push_simple_selector(Component::DefaultNamespace(url));
2293                }
2294            }
2295        }
2296
2297        empty = false;
2298
2299        match result {
2300            SimpleSelectorParseResult::SimpleSelector(s) => {
2301                builder.push_simple_selector(s);
2302            }
2303            SimpleSelectorParseResult::PartPseudo(part_names) => {
2304                state.insert(SelectorParsingState::AFTER_PART);
2305                builder.push_combinator(Combinator::Part);
2306                builder.push_simple_selector(Component::Part(part_names));
2307            }
2308            SimpleSelectorParseResult::SlottedPseudo(selector) => {
2309                state.insert(SelectorParsingState::AFTER_SLOTTED);
2310                builder.push_combinator(Combinator::SlotAssignment);
2311                builder.push_simple_selector(Component::Slotted(selector));
2312            }
2313            SimpleSelectorParseResult::PseudoElement(p) => {
2314                state.insert(SelectorParsingState::AFTER_PSEUDO_ELEMENT);
2315                if !p.accepts_state_pseudo_classes() {
2316                    state.insert(
2317                        SelectorParsingState::AFTER_NON_STATEFUL_PSEUDO_ELEMENT,
2318                    );
2319                }
2320                builder.push_combinator(Combinator::PseudoElement);
2321                builder.push_simple_selector(Component::PseudoElement(p));
2322            }
2323        }
2324    }
2325    Ok(empty)
2326}
2327
2328fn parse_is_or_where<'i, 't, P, Impl>(
2329    parser: &P,
2330    input: &mut CssParser<'i, 't>,
2331    state: SelectorParsingState,
2332    component: impl FnOnce(Box<[Selector<Impl>]>) -> Component<Impl>,
2333) -> Result<Component<Impl>, ParseError<'i, P::Error>>
2334where
2335    P: Parser<'i, Impl = Impl>,
2336    Impl: SelectorImpl,
2337{
2338    debug_assert!(parser.parse_is_and_where());
2339    // https://drafts.csswg.org/selectors/#matches-pseudo:
2340    //
2341    //     Pseudo-elements cannot be represented by the matches-any
2342    //     pseudo-class; they are not valid within :is().
2343    //
2344    let inner = SelectorList::parse_with_state(
2345        parser,
2346        input,
2347        state
2348            | SelectorParsingState::SKIP_DEFAULT_NAMESPACE
2349            | SelectorParsingState::DISALLOW_PSEUDOS,
2350        parser.is_and_where_error_recovery(),
2351    )?;
2352    Ok(component(inner.0.into_vec().into_boxed_slice()))
2353}
2354
2355fn parse_functional_pseudo_class<'i, 't, P, Impl>(
2356    parser: &P,
2357    input: &mut CssParser<'i, 't>,
2358    name: CowRcStr<'i>,
2359    state: SelectorParsingState,
2360) -> Result<Component<Impl>, ParseError<'i, P::Error>>
2361where
2362    P: Parser<'i, Impl = Impl>,
2363    Impl: SelectorImpl,
2364{
2365    match_ignore_ascii_case! { &name,
2366        "nth-child" => return parse_nth_pseudo_class(parser, input, state, Component::NthChild),
2367        "nth-of-type" => return parse_nth_pseudo_class(parser, input, state, Component::NthOfType),
2368        "nth-last-child" => return parse_nth_pseudo_class(parser, input, state, Component::NthLastChild),
2369        "nth-last-of-type" => return parse_nth_pseudo_class(parser, input, state, Component::NthLastOfType),
2370        "is" if parser.parse_is_and_where() => return parse_is_or_where(parser, input, state, Component::Is),
2371        "where" if parser.parse_is_and_where() => return parse_is_or_where(parser, input, state, Component::Where),
2372        "host" => {
2373            if !state.allows_tree_structural_pseudo_classes() {
2374                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
2375            }
2376            return Ok(Component::Host(Some(parse_inner_compound_selector(parser, input, state)?)));
2377        },
2378        "not" => {
2379            return parse_negation(parser, input, state)
2380        },
2381        _ => {}
2382    }
2383
2384    if parser.parse_is_and_where() && parser.is_is_alias(&name) {
2385        return parse_is_or_where(parser, input, state, Component::Is);
2386    }
2387
2388    if !state.allows_custom_functional_pseudo_classes() {
2389        return Err(
2390            input.new_custom_error(SelectorParseErrorKind::InvalidState)
2391        );
2392    }
2393
2394    P::parse_non_ts_functional_pseudo_class(parser, name, input)
2395        .map(Component::NonTSPseudoClass)
2396}
2397
2398fn parse_nth_pseudo_class<'i, 't, P, Impl, F>(
2399    _: &P,
2400    input: &mut CssParser<'i, 't>,
2401    state: SelectorParsingState,
2402    selector: F,
2403) -> Result<Component<Impl>, ParseError<'i, P::Error>>
2404where
2405    P: Parser<'i, Impl = Impl>,
2406    Impl: SelectorImpl,
2407    F: FnOnce(i32, i32) -> Component<Impl>,
2408{
2409    if !state.allows_tree_structural_pseudo_classes() {
2410        return Err(
2411            input.new_custom_error(SelectorParseErrorKind::InvalidState)
2412        );
2413    }
2414    let (a, b) = parse_nth(input)?;
2415    Ok(selector(a, b))
2416}
2417
2418/// Returns whether the name corresponds to a CSS2 pseudo-element that
2419/// can be specified with the single colon syntax (in addition to the
2420/// double-colon syntax, which can be used for all pseudo-elements).
2421fn is_css2_pseudo_element(name: &str) -> bool {
2422    // ** Do not add to this list! **
2423    match_ignore_ascii_case! { name,
2424        "before" | "after" | "first-line" | "first-letter" => true,
2425        _ => false,
2426    }
2427}
2428
2429/// Parse a simple selector other than a type selector.
2430///
2431/// * `Err(())`: Invalid selector, abort
2432/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
2433/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
2434fn parse_one_simple_selector<'i, 't, P, Impl>(
2435    parser: &P,
2436    input: &mut CssParser<'i, 't>,
2437    state: SelectorParsingState,
2438) -> Result<Option<SimpleSelectorParseResult<Impl>>, ParseError<'i, P::Error>>
2439where
2440    P: Parser<'i, Impl = Impl>,
2441    Impl: SelectorImpl,
2442{
2443    let start = input.state();
2444    let token = match input.next_including_whitespace().map(|t| t.clone()) {
2445        Ok(t) => t,
2446        Err(..) => {
2447            input.reset(&start);
2448            return Ok(None);
2449        }
2450    };
2451
2452    Ok(Some(match token {
2453        Token::IDHash(id) => {
2454            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2455                return Err(input
2456                    .new_custom_error(SelectorParseErrorKind::InvalidState));
2457            }
2458            let id = Component::ID(id.as_ref().into());
2459            SimpleSelectorParseResult::SimpleSelector(id)
2460        }
2461        Token::Delim('.') => {
2462            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2463                return Err(input
2464                    .new_custom_error(SelectorParseErrorKind::InvalidState));
2465            }
2466            let location = input.current_source_location();
2467            let class = match *input.next_including_whitespace()? {
2468                Token::Ident(ref class) => class,
2469                ref t => {
2470                    let e = SelectorParseErrorKind::ClassNeedsIdent(t.clone());
2471                    return Err(location.new_custom_error(e));
2472                }
2473            };
2474            let class = Component::Class(class.as_ref().into());
2475            SimpleSelectorParseResult::SimpleSelector(class)
2476        }
2477        Token::SquareBracketBlock => {
2478            if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
2479                return Err(input
2480                    .new_custom_error(SelectorParseErrorKind::InvalidState));
2481            }
2482            let attr = input.parse_nested_block(|input| {
2483                parse_attribute_selector(parser, input)
2484            })?;
2485            SimpleSelectorParseResult::SimpleSelector(attr)
2486        }
2487        Token::Colon => {
2488            let location = input.current_source_location();
2489            let (is_single_colon, next_token) =
2490                match input.next_including_whitespace()?.clone() {
2491                    Token::Colon => {
2492                        (false, input.next_including_whitespace()?.clone())
2493                    }
2494                    t => (true, t),
2495                };
2496            let (name, is_functional) = match next_token {
2497                Token::Ident(name) => (name, false),
2498                Token::Function(name) => (name, true),
2499                t => {
2500                    let e =
2501                        SelectorParseErrorKind::PseudoElementExpectedIdent(t);
2502                    return Err(input.new_custom_error(e));
2503                }
2504            };
2505            let is_pseudo_element =
2506                !is_single_colon || is_css2_pseudo_element(&name);
2507            if is_pseudo_element {
2508                if !state.allows_pseudos() {
2509                    return Err(input.new_custom_error(
2510                        SelectorParseErrorKind::InvalidState,
2511                    ));
2512                }
2513                let pseudo_element = if is_functional {
2514                    if P::parse_part(parser)
2515                        && name.eq_ignore_ascii_case("part")
2516                    {
2517                        if !state.allows_part() {
2518                            return Err(input.new_custom_error(
2519                                SelectorParseErrorKind::InvalidState,
2520                            ));
2521                        }
2522                        let names = input.parse_nested_block(|input| {
2523                            let mut result = Vec::with_capacity(1);
2524                            result.push(input.expect_ident()?.as_ref().into());
2525                            while !input.is_exhausted() {
2526                                result.push(
2527                                    input.expect_ident()?.as_ref().into(),
2528                                );
2529                            }
2530                            Ok(result.into_boxed_slice())
2531                        })?;
2532                        return Ok(Some(
2533                            SimpleSelectorParseResult::PartPseudo(names),
2534                        ));
2535                    }
2536                    if P::parse_slotted(parser)
2537                        && name.eq_ignore_ascii_case("slotted")
2538                    {
2539                        if !state.allows_slotted() {
2540                            return Err(input.new_custom_error(
2541                                SelectorParseErrorKind::InvalidState,
2542                            ));
2543                        }
2544                        let selector = input.parse_nested_block(|input| {
2545                            parse_inner_compound_selector(parser, input, state)
2546                        })?;
2547                        return Ok(Some(
2548                            SimpleSelectorParseResult::SlottedPseudo(selector),
2549                        ));
2550                    }
2551                    input.parse_nested_block(|input| {
2552                        P::parse_functional_pseudo_element(parser, name, input)
2553                    })?
2554                } else {
2555                    P::parse_pseudo_element(parser, location, name)?
2556                };
2557
2558                if state.intersects(SelectorParsingState::AFTER_SLOTTED)
2559                    && !pseudo_element.valid_after_slotted()
2560                {
2561                    return Err(input.new_custom_error(
2562                        SelectorParseErrorKind::InvalidState,
2563                    ));
2564                }
2565                SimpleSelectorParseResult::PseudoElement(pseudo_element)
2566            } else {
2567                let pseudo_class = if is_functional {
2568                    input.parse_nested_block(|input| {
2569                        parse_functional_pseudo_class(
2570                            parser, input, name, state,
2571                        )
2572                    })?
2573                } else {
2574                    parse_simple_pseudo_class(parser, location, name, state)?
2575                };
2576                SimpleSelectorParseResult::SimpleSelector(pseudo_class)
2577            }
2578        }
2579        _ => {
2580            input.reset(&start);
2581            return Ok(None);
2582        }
2583    }))
2584}
2585
2586fn parse_simple_pseudo_class<'i, P, Impl>(
2587    parser: &P,
2588    location: SourceLocation,
2589    name: CowRcStr<'i>,
2590    state: SelectorParsingState,
2591) -> Result<Component<Impl>, ParseError<'i, P::Error>>
2592where
2593    P: Parser<'i, Impl = Impl>,
2594    Impl: SelectorImpl,
2595{
2596    if !state.allows_non_functional_pseudo_classes() {
2597        return Err(
2598            location.new_custom_error(SelectorParseErrorKind::InvalidState)
2599        );
2600    }
2601
2602    if state.allows_tree_structural_pseudo_classes() {
2603        match_ignore_ascii_case! { &name,
2604            "first-child" => return Ok(Component::FirstChild),
2605            "last-child" => return Ok(Component::LastChild),
2606            "only-child" => return Ok(Component::OnlyChild),
2607            "root" => return Ok(Component::Root),
2608            "empty" => return Ok(Component::Empty),
2609            "scope" => return Ok(Component::Scope),
2610            "host" if P::parse_host(parser) => return Ok(Component::Host(None)),
2611            "first-of-type" => return Ok(Component::FirstOfType),
2612            "last-of-type" => return Ok(Component::LastOfType),
2613            "only-of-type" => return Ok(Component::OnlyOfType),
2614            _ => {},
2615        }
2616    }
2617
2618    let pseudo_class = P::parse_non_ts_pseudo_class(parser, location, name)?;
2619    if state.intersects(SelectorParsingState::AFTER_PSEUDO_ELEMENT)
2620        && !pseudo_class.is_user_action_state()
2621    {
2622        return Err(
2623            location.new_custom_error(SelectorParseErrorKind::InvalidState)
2624        );
2625    }
2626    Ok(Component::NonTSPseudoClass(pseudo_class))
2627}
2628
2629// NB: pub module in order to access the DummyParser
2630#[cfg(test)]
2631pub mod tests {
2632    use {
2633        super::*,
2634        crate::{builder::SelectorFlags, parser},
2635        cssparser::{
2636            serialize_identifier,
2637            Parser as CssParser,
2638            ParserInput,
2639            ToCss,
2640        },
2641        std::{collections::HashMap, fmt},
2642    };
2643
2644    #[derive(Clone, Debug, Eq, PartialEq)]
2645    pub enum PseudoClass {
2646        Hover,
2647        Active,
2648        Lang(String),
2649    }
2650
2651    #[derive(Clone, Debug, Eq, PartialEq)]
2652    pub enum PseudoElement {
2653        Before,
2654        After,
2655    }
2656
2657    impl parser::PseudoElement for PseudoElement {
2658        type Impl = DummySelectorImpl;
2659
2660        fn accepts_state_pseudo_classes(&self) -> bool {
2661            true
2662        }
2663
2664        fn valid_after_slotted(&self) -> bool {
2665            true
2666        }
2667    }
2668
2669    impl parser::NonTSPseudoClass for PseudoClass {
2670        type Impl = DummySelectorImpl;
2671
2672        #[inline]
2673        fn is_active_or_hover(&self) -> bool {
2674            matches!(*self, PseudoClass::Active | PseudoClass::Hover)
2675        }
2676
2677        #[inline]
2678        fn is_user_action_state(&self) -> bool {
2679            self.is_active_or_hover()
2680        }
2681    }
2682
2683    impl ToCss for PseudoClass {
2684        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2685        where
2686            W: fmt::Write,
2687        {
2688            match *self {
2689                PseudoClass::Hover => dest.write_str(":hover"),
2690                PseudoClass::Active => dest.write_str(":active"),
2691                PseudoClass::Lang(ref lang) => {
2692                    dest.write_str(":lang(")?;
2693                    serialize_identifier(lang, dest)?;
2694                    dest.write_char(')')
2695                }
2696            }
2697        }
2698    }
2699
2700    impl ToCss for PseudoElement {
2701        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2702        where
2703            W: fmt::Write,
2704        {
2705            match *self {
2706                PseudoElement::Before => dest.write_str("::before"),
2707                PseudoElement::After => dest.write_str("::after"),
2708            }
2709        }
2710    }
2711
2712    #[derive(Clone, Debug, PartialEq)]
2713    pub struct DummySelectorImpl;
2714
2715    #[derive(Default)]
2716    pub struct DummyParser {
2717        default_ns: Option<DummyAtom>,
2718        ns_prefixes: HashMap<DummyAtom, DummyAtom>,
2719    }
2720
2721    impl DummyParser {
2722        fn default_with_namespace(default_ns: DummyAtom) -> DummyParser {
2723            DummyParser {
2724                default_ns: Some(default_ns),
2725                ns_prefixes: Default::default(),
2726            }
2727        }
2728    }
2729
2730    impl SelectorImpl for DummySelectorImpl {
2731        type ExtraMatchingData = ();
2732        type AttrValue = DummyAttrValue;
2733        type Identifier = DummyAtom;
2734        type LocalName = DummyAtom;
2735        type NamespaceUrl = DummyAtom;
2736        type NamespacePrefix = DummyAtom;
2737        type BorrowedLocalName = DummyAtom;
2738        type BorrowedNamespaceUrl = DummyAtom;
2739        type NonTSPseudoClass = PseudoClass;
2740        type PseudoElement = PseudoElement;
2741    }
2742
2743    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
2744    pub struct DummyAttrValue(String);
2745
2746    impl ToCss for DummyAttrValue {
2747        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2748        where
2749            W: fmt::Write,
2750        {
2751            use std::fmt::Write;
2752
2753            write!(cssparser::CssStringWriter::new(dest), "{}", &self.0)
2754        }
2755    }
2756
2757    impl<'a> From<&'a str> for DummyAttrValue {
2758        fn from(string: &'a str) -> Self {
2759            Self(string.into())
2760        }
2761    }
2762
2763    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
2764    pub struct DummyAtom(String);
2765
2766    impl ToCss for DummyAtom {
2767        fn to_css<W>(&self, dest: &mut W) -> fmt::Result
2768        where
2769            W: fmt::Write,
2770        {
2771            serialize_identifier(&self.0, dest)
2772        }
2773    }
2774
2775    impl From<String> for DummyAtom {
2776        fn from(string: String) -> Self {
2777            DummyAtom(string)
2778        }
2779    }
2780
2781    impl<'a> From<&'a str> for DummyAtom {
2782        fn from(string: &'a str) -> Self {
2783            DummyAtom(string.into())
2784        }
2785    }
2786
2787    impl<'i> Parser<'i> for DummyParser {
2788        type Impl = DummySelectorImpl;
2789        type Error = SelectorParseErrorKind<'i>;
2790
2791        fn parse_slotted(&self) -> bool {
2792            true
2793        }
2794
2795        fn parse_is_and_where(&self) -> bool {
2796            true
2797        }
2798
2799        fn is_and_where_error_recovery(&self) -> ParseErrorRecovery {
2800            ParseErrorRecovery::DiscardList
2801        }
2802
2803        fn parse_part(&self) -> bool {
2804            true
2805        }
2806
2807        fn parse_non_ts_pseudo_class(
2808            &self,
2809            location: SourceLocation,
2810            name: CowRcStr<'i>,
2811        ) -> Result<PseudoClass, SelectorParseError<'i>> {
2812            match_ignore_ascii_case! { &name,
2813                "hover" => return Ok(PseudoClass::Hover),
2814                "active" => return Ok(PseudoClass::Active),
2815                _ => {}
2816            }
2817            Err(location.new_custom_error(
2818                SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
2819            ))
2820        }
2821
2822        fn parse_non_ts_functional_pseudo_class<'t>(
2823            &self,
2824            name: CowRcStr<'i>,
2825            parser: &mut CssParser<'i, 't>,
2826        ) -> Result<PseudoClass, SelectorParseError<'i>> {
2827            match_ignore_ascii_case! { &name,
2828                "lang" => {
2829                    let lang = parser.expect_ident_or_string()?.as_ref().to_owned();
2830                    return Ok(PseudoClass::Lang(lang));
2831                },
2832                _ => {}
2833            }
2834            Err(parser.new_custom_error(
2835                SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
2836            ))
2837        }
2838
2839        fn parse_pseudo_element(
2840            &self,
2841            location: SourceLocation,
2842            name: CowRcStr<'i>,
2843        ) -> Result<PseudoElement, SelectorParseError<'i>> {
2844            match_ignore_ascii_case! { &name,
2845                "before" => return Ok(PseudoElement::Before),
2846                "after" => return Ok(PseudoElement::After),
2847                _ => {}
2848            }
2849            Err(location.new_custom_error(
2850                SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name),
2851            ))
2852        }
2853
2854        fn default_namespace(&self) -> Option<DummyAtom> {
2855            self.default_ns.clone()
2856        }
2857
2858        fn namespace_for_prefix(
2859            &self,
2860            prefix: &DummyAtom,
2861        ) -> Option<DummyAtom> {
2862            self.ns_prefixes.get(prefix).cloned()
2863        }
2864    }
2865
2866    fn parse<'i>(
2867        input: &'i str,
2868    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
2869        parse_ns(input, &DummyParser::default())
2870    }
2871
2872    fn parse_expected<'i, 'a>(
2873        input: &'i str,
2874        expected: Option<&'a str>,
2875    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
2876        parse_ns_expected(input, &DummyParser::default(), expected)
2877    }
2878
2879    fn parse_ns<'i>(
2880        input: &'i str,
2881        parser: &DummyParser,
2882    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
2883        parse_ns_expected(input, parser, None)
2884    }
2885
2886    fn parse_ns_expected<'i, 'a>(
2887        input: &'i str,
2888        parser: &DummyParser,
2889        expected: Option<&'a str>,
2890    ) -> Result<SelectorList<DummySelectorImpl>, SelectorParseError<'i>> {
2891        let mut parser_input = ParserInput::new(input);
2892        let result =
2893            SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
2894        if let Ok(ref selectors) = result {
2895            assert_eq!(selectors.0.len(), 1);
2896            // We can't assume that the serialized parsed selector will equal
2897            // the input; for example, if there is no default namespace, '*|foo'
2898            // should serialize to 'foo'.
2899            assert_eq!(
2900                selectors.0[0].to_css_string(),
2901                match expected {
2902                    Some(x) => x,
2903                    None => input,
2904                }
2905            );
2906        }
2907        result
2908    }
2909
2910    fn specificity(a: u32, b: u32, c: u32) -> u32 {
2911        a << 20 | b << 10 | c
2912    }
2913
2914    #[test]
2915    fn test_empty() {
2916        let mut input = ParserInput::new(":empty");
2917        let list = SelectorList::parse(
2918            &DummyParser::default(),
2919            &mut CssParser::new(&mut input),
2920        );
2921        assert!(list.is_ok());
2922    }
2923
2924    const MATHML: &str = "http://www.w3.org/1998/Math/MathML";
2925    const SVG: &str = "http://www.w3.org/2000/svg";
2926
2927    #[test]
2928    fn test_parsing() {
2929        assert!(parse("").is_err());
2930        assert!(parse(":lang(4)").is_err());
2931        assert!(parse(":lang(en US)").is_err());
2932        assert_eq!(
2933            parse("EeÉ"),
2934            Ok(SelectorList::from_vec(vec![Selector::from_vec(
2935                vec![Component::LocalName(LocalName {
2936                    name: DummyAtom::from("EeÉ"),
2937                    lower_name: DummyAtom::from("eeÉ"),
2938                })],
2939                specificity(0, 0, 1),
2940                Default::default(),
2941            )]))
2942        );
2943        assert_eq!(
2944            parse("|e"),
2945            Ok(SelectorList::from_vec(vec![Selector::from_vec(
2946                vec![
2947                    Component::ExplicitNoNamespace,
2948                    Component::LocalName(LocalName {
2949                        name: DummyAtom::from("e"),
2950                        lower_name: DummyAtom::from("e"),
2951                    }),
2952                ],
2953                specificity(0, 0, 1),
2954                Default::default(),
2955            )]))
2956        );
2957        // When the default namespace is not set, *| should be elided.
2958        // https://github.com/servo/servo/pull/17537
2959        assert_eq!(
2960            parse_expected("*|e", Some("e")),
2961            Ok(SelectorList::from_vec(vec![Selector::from_vec(
2962                vec![Component::LocalName(LocalName {
2963                    name: DummyAtom::from("e"),
2964                    lower_name: DummyAtom::from("e"),
2965                })],
2966                specificity(0, 0, 1),
2967                Default::default(),
2968            )]))
2969        );
2970        // When the default namespace is set, *| should _not_ be elided (as foo
2971        // is no longer equivalent to *|foo--the former is only for foo in the
2972        // default namespace).
2973        // https://github.com/servo/servo/issues/16020
2974        assert_eq!(
2975            parse_ns(
2976                "*|e",
2977                &DummyParser::default_with_namespace(DummyAtom::from(
2978                    "https://mozilla.org"
2979                ))
2980            ),
2981            Ok(SelectorList::from_vec(vec![Selector::from_vec(
2982                vec![
2983                    Component::ExplicitAnyNamespace,
2984                    Component::LocalName(LocalName {
2985                        name: DummyAtom::from("e"),
2986                        lower_name: DummyAtom::from("e"),
2987                    }),
2988                ],
2989                specificity(0, 0, 1),
2990                Default::default(),
2991            )]))
2992        );
2993        assert_eq!(
2994            parse("*"),
2995            Ok(SelectorList::from_vec(vec![Selector::from_vec(
2996                vec![Component::ExplicitUniversalType],
2997                specificity(0, 0, 0),
2998                Default::default(),
2999            )]))
3000        );
3001        assert_eq!(
3002            parse("|*"),
3003            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3004                vec![
3005                    Component::ExplicitNoNamespace,
3006                    Component::ExplicitUniversalType,
3007                ],
3008                specificity(0, 0, 0),
3009                Default::default(),
3010            )]))
3011        );
3012        assert_eq!(
3013            parse_expected("*|*", Some("*")),
3014            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3015                vec![Component::ExplicitUniversalType],
3016                specificity(0, 0, 0),
3017                Default::default(),
3018            )]))
3019        );
3020        assert_eq!(
3021            parse_ns(
3022                "*|*",
3023                &DummyParser::default_with_namespace(DummyAtom::from(
3024                    "https://mozilla.org"
3025                ))
3026            ),
3027            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3028                vec![
3029                    Component::ExplicitAnyNamespace,
3030                    Component::ExplicitUniversalType,
3031                ],
3032                specificity(0, 0, 0),
3033                Default::default(),
3034            )]))
3035        );
3036        assert_eq!(
3037            parse(".foo:lang(en-US)"),
3038            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3039                vec![
3040                    Component::Class(DummyAtom::from("foo")),
3041                    Component::NonTSPseudoClass(PseudoClass::Lang(
3042                        "en-US".to_owned()
3043                    )),
3044                ],
3045                specificity(0, 2, 0),
3046                Default::default(),
3047            )]))
3048        );
3049        assert_eq!(
3050            parse("#bar"),
3051            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3052                vec![Component::ID(DummyAtom::from("bar"))],
3053                specificity(1, 0, 0),
3054                Default::default(),
3055            )]))
3056        );
3057        assert_eq!(
3058            parse("e.foo#bar"),
3059            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3060                vec![
3061                    Component::LocalName(LocalName {
3062                        name: DummyAtom::from("e"),
3063                        lower_name: DummyAtom::from("e"),
3064                    }),
3065                    Component::Class(DummyAtom::from("foo")),
3066                    Component::ID(DummyAtom::from("bar")),
3067                ],
3068                specificity(1, 1, 1),
3069                Default::default(),
3070            )]))
3071        );
3072        assert_eq!(
3073            parse("e.foo #bar"),
3074            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3075                vec![
3076                    Component::LocalName(LocalName {
3077                        name: DummyAtom::from("e"),
3078                        lower_name: DummyAtom::from("e"),
3079                    }),
3080                    Component::Class(DummyAtom::from("foo")),
3081                    Component::Combinator(Combinator::Descendant),
3082                    Component::ID(DummyAtom::from("bar")),
3083                ],
3084                specificity(1, 1, 1),
3085                Default::default(),
3086            )]))
3087        );
3088        // Default namespace does not apply to attribute selectors
3089        // https://github.com/mozilla/servo/pull/1652
3090        let mut parser = DummyParser::default();
3091        assert_eq!(
3092            parse_ns("[Foo]", &parser),
3093            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3094                vec![Component::AttributeInNoNamespaceExists {
3095                    local_name: DummyAtom::from("Foo"),
3096                    local_name_lower: DummyAtom::from("foo"),
3097                }],
3098                specificity(0, 1, 0),
3099                Default::default(),
3100            )]))
3101        );
3102        assert!(parse_ns("svg|circle", &parser).is_err());
3103        parser
3104            .ns_prefixes
3105            .insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
3106        assert_eq!(
3107            parse_ns("svg|circle", &parser),
3108            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3109                vec![
3110                    Component::Namespace(DummyAtom("svg".into()), SVG.into()),
3111                    Component::LocalName(LocalName {
3112                        name: DummyAtom::from("circle"),
3113                        lower_name: DummyAtom::from("circle"),
3114                    }),
3115                ],
3116                specificity(0, 0, 1),
3117                Default::default(),
3118            )]))
3119        );
3120        assert_eq!(
3121            parse_ns("svg|*", &parser),
3122            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3123                vec![
3124                    Component::Namespace(DummyAtom("svg".into()), SVG.into()),
3125                    Component::ExplicitUniversalType,
3126                ],
3127                specificity(0, 0, 0),
3128                Default::default(),
3129            )]))
3130        );
3131        // Default namespace does not apply to attribute selectors
3132        // https://github.com/mozilla/servo/pull/1652
3133        // but it does apply to implicit type selectors
3134        // https://github.com/servo/rust-selectors/pull/82
3135        parser.default_ns = Some(MATHML.into());
3136        assert_eq!(
3137            parse_ns("[Foo]", &parser),
3138            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3139                vec![
3140                    Component::DefaultNamespace(MATHML.into()),
3141                    Component::AttributeInNoNamespaceExists {
3142                        local_name: DummyAtom::from("Foo"),
3143                        local_name_lower: DummyAtom::from("foo"),
3144                    },
3145                ],
3146                specificity(0, 1, 0),
3147                Default::default(),
3148            )]))
3149        );
3150        // Default namespace does apply to type selectors
3151        assert_eq!(
3152            parse_ns("e", &parser),
3153            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3154                vec![
3155                    Component::DefaultNamespace(MATHML.into()),
3156                    Component::LocalName(LocalName {
3157                        name: DummyAtom::from("e"),
3158                        lower_name: DummyAtom::from("e"),
3159                    }),
3160                ],
3161                specificity(0, 0, 1),
3162                Default::default(),
3163            )]))
3164        );
3165        assert_eq!(
3166            parse_ns("*", &parser),
3167            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3168                vec![
3169                    Component::DefaultNamespace(MATHML.into()),
3170                    Component::ExplicitUniversalType,
3171                ],
3172                specificity(0, 0, 0),
3173                Default::default(),
3174            )]))
3175        );
3176        assert_eq!(
3177            parse_ns("*|*", &parser),
3178            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3179                vec![
3180                    Component::ExplicitAnyNamespace,
3181                    Component::ExplicitUniversalType,
3182                ],
3183                specificity(0, 0, 0),
3184                Default::default(),
3185            )]))
3186        );
3187        // Default namespace applies to universal and type selectors inside :not and :matches,
3188        // but not otherwise.
3189        assert_eq!(
3190            parse_ns(":not(.cl)", &parser),
3191            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3192                vec![
3193                    Component::DefaultNamespace(MATHML.into()),
3194                    Component::Negation(
3195                        vec![Selector::from_vec(
3196                            vec![Component::Class(DummyAtom::from("cl"))],
3197                            specificity(0, 1, 0),
3198                            Default::default(),
3199                        )]
3200                        .into_boxed_slice()
3201                    ),
3202                ],
3203                specificity(0, 1, 0),
3204                Default::default(),
3205            )]))
3206        );
3207        assert_eq!(
3208            parse_ns(":not(*)", &parser),
3209            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3210                vec![
3211                    Component::DefaultNamespace(MATHML.into()),
3212                    Component::Negation(
3213                        vec![Selector::from_vec(
3214                            vec![
3215                                Component::DefaultNamespace(MATHML.into()),
3216                                Component::ExplicitUniversalType,
3217                            ],
3218                            specificity(0, 0, 0),
3219                            Default::default(),
3220                        )]
3221                        .into_boxed_slice(),
3222                    ),
3223                ],
3224                specificity(0, 0, 0),
3225                Default::default(),
3226            )]))
3227        );
3228        assert_eq!(
3229            parse_ns(":not(e)", &parser),
3230            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3231                vec![
3232                    Component::DefaultNamespace(MATHML.into()),
3233                    Component::Negation(
3234                        vec![Selector::from_vec(
3235                            vec![
3236                                Component::DefaultNamespace(MATHML.into()),
3237                                Component::LocalName(LocalName {
3238                                    name: DummyAtom::from("e"),
3239                                    lower_name: DummyAtom::from("e"),
3240                                }),
3241                            ],
3242                            specificity(0, 0, 1),
3243                            Default::default(),
3244                        ),]
3245                        .into_boxed_slice()
3246                    ),
3247                ],
3248                specificity(0, 0, 1),
3249                Default::default(),
3250            )]))
3251        );
3252        assert_eq!(
3253            parse("[attr|=\"foo\"]"),
3254            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3255                vec![Component::AttributeInNoNamespace {
3256                    local_name: DummyAtom::from("attr"),
3257                    operator: AttrSelectorOperator::DashMatch,
3258                    value: DummyAttrValue::from("foo"),
3259                    never_matches: false,
3260                    case_sensitivity: ParsedCaseSensitivity::CaseSensitive,
3261                }],
3262                specificity(0, 1, 0),
3263                Default::default(),
3264            )]))
3265        );
3266        // https://github.com/mozilla/servo/issues/1723
3267        assert_eq!(
3268            parse("::before"),
3269            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3270                vec![
3271                    Component::Combinator(Combinator::PseudoElement),
3272                    Component::PseudoElement(PseudoElement::Before),
3273                ],
3274                specificity(0, 0, 1),
3275                SelectorFlags::HAS_PSEUDO,
3276            )]))
3277        );
3278        assert_eq!(
3279            parse("::before:hover"),
3280            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3281                vec![
3282                    Component::Combinator(Combinator::PseudoElement),
3283                    Component::PseudoElement(PseudoElement::Before),
3284                    Component::NonTSPseudoClass(PseudoClass::Hover),
3285                ],
3286                specificity(0, 1, 1),
3287                SelectorFlags::HAS_PSEUDO,
3288            )]))
3289        );
3290        assert_eq!(
3291            parse("::before:hover:hover"),
3292            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3293                vec![
3294                    Component::Combinator(Combinator::PseudoElement),
3295                    Component::PseudoElement(PseudoElement::Before),
3296                    Component::NonTSPseudoClass(PseudoClass::Hover),
3297                    Component::NonTSPseudoClass(PseudoClass::Hover),
3298                ],
3299                specificity(0, 2, 1),
3300                SelectorFlags::HAS_PSEUDO,
3301            )]))
3302        );
3303        assert!(parse("::before:hover:lang(foo)").is_err());
3304        assert!(parse("::before:hover .foo").is_err());
3305        assert!(parse("::before .foo").is_err());
3306        assert!(parse("::before ~ bar").is_err());
3307        assert!(parse("::before:active").is_ok());
3308
3309        // https://github.com/servo/servo/issues/15335
3310        assert!(parse(":: before").is_err());
3311        assert_eq!(
3312            parse("div ::after"),
3313            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3314                vec![
3315                    Component::LocalName(LocalName {
3316                        name: DummyAtom::from("div"),
3317                        lower_name: DummyAtom::from("div"),
3318                    }),
3319                    Component::Combinator(Combinator::Descendant),
3320                    Component::Combinator(Combinator::PseudoElement),
3321                    Component::PseudoElement(PseudoElement::After),
3322                ],
3323                specificity(0, 0, 2),
3324                SelectorFlags::HAS_PSEUDO,
3325            )]))
3326        );
3327        assert_eq!(
3328            parse("#d1 > .ok"),
3329            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3330                vec![
3331                    Component::ID(DummyAtom::from("d1")),
3332                    Component::Combinator(Combinator::Child),
3333                    Component::Class(DummyAtom::from("ok")),
3334                ],
3335                (1 << 20) + (1 << 10) + (0 << 0),
3336                Default::default(),
3337            )]))
3338        );
3339        parser.default_ns = None;
3340        assert!(parse(":not(#provel.old)").is_ok());
3341        assert!(parse(":not(#provel > old)").is_ok());
3342        assert!(
3343            parse("table[rules]:not([rules=\"none\"]):not([rules=\"\"])")
3344                .is_ok()
3345        );
3346        // https://github.com/servo/servo/issues/16017
3347        assert_eq!(
3348            parse_ns(":not(*)", &parser),
3349            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3350                vec![Component::Negation(
3351                    vec![Selector::from_vec(
3352                        vec![Component::ExplicitUniversalType],
3353                        specificity(0, 0, 0),
3354                        Default::default(),
3355                    )]
3356                    .into_boxed_slice()
3357                )],
3358                specificity(0, 0, 0),
3359                Default::default(),
3360            )]))
3361        );
3362        assert_eq!(
3363            parse_ns(":not(|*)", &parser),
3364            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3365                vec![Component::Negation(
3366                    vec![Selector::from_vec(
3367                        vec![
3368                            Component::ExplicitNoNamespace,
3369                            Component::ExplicitUniversalType,
3370                        ],
3371                        specificity(0, 0, 0),
3372                        Default::default(),
3373                    )]
3374                    .into_boxed_slice(),
3375                )],
3376                specificity(0, 0, 0),
3377                Default::default(),
3378            )]))
3379        );
3380        // *| should be elided if there is no default namespace.
3381        // https://github.com/servo/servo/pull/17537
3382        assert_eq!(
3383            parse_ns_expected(":not(*|*)", &parser, Some(":not(*)")),
3384            Ok(SelectorList::from_vec(vec![Selector::from_vec(
3385                vec![Component::Negation(
3386                    vec![Selector::from_vec(
3387                        vec![Component::ExplicitUniversalType],
3388                        specificity(0, 0, 0),
3389                        Default::default()
3390                    )]
3391                    .into_boxed_slice()
3392                )],
3393                specificity(0, 0, 0),
3394                Default::default(),
3395            )]))
3396        );
3397
3398        assert!(parse("::slotted()").is_err());
3399        assert!(parse("::slotted(div)").is_ok());
3400        assert!(parse("::slotted(div).foo").is_err());
3401        assert!(parse("::slotted(div + bar)").is_err());
3402        assert!(parse("::slotted(div) + foo").is_err());
3403
3404        assert!(parse("::part()").is_err());
3405        assert!(parse("::part(42)").is_err());
3406        assert!(parse("::part(foo bar)").is_ok());
3407        assert!(parse("::part(foo):hover").is_ok());
3408        assert!(parse("::part(foo) + bar").is_err());
3409
3410        assert!(parse("div ::slotted(div)").is_ok());
3411        assert!(parse("div + slot::slotted(div)").is_ok());
3412        assert!(parse("div + slot::slotted(div.foo)").is_ok());
3413        assert!(parse("slot::slotted(div,foo)::first-line").is_err());
3414        assert!(parse("::slotted(div)::before").is_ok());
3415        assert!(parse("slot::slotted(div,foo)").is_err());
3416
3417        assert!(parse("foo:where()").is_err());
3418        assert!(parse("foo:where(div, foo, .bar baz)").is_ok());
3419        assert!(parse("foo:where(::before)").is_err());
3420    }
3421
3422    #[test]
3423    fn test_pseudo_iter() {
3424        let selector = &parse("q::before").unwrap().0[0];
3425        assert!(!selector.is_universal());
3426        let mut iter = selector.iter();
3427        assert_eq!(
3428            iter.next(),
3429            Some(&Component::PseudoElement(PseudoElement::Before))
3430        );
3431        assert_eq!(iter.next(), None);
3432        let combinator = iter.next_sequence();
3433        assert_eq!(combinator, Some(Combinator::PseudoElement));
3434        assert!(matches!(iter.next(), Some(&Component::LocalName(..))));
3435        assert_eq!(iter.next(), None);
3436        assert_eq!(iter.next_sequence(), None);
3437    }
3438
3439    #[test]
3440    fn test_universal() {
3441        let selector = &parse_ns(
3442            "*|*::before",
3443            &DummyParser::default_with_namespace(DummyAtom::from(
3444                "https://mozilla.org",
3445            )),
3446        )
3447        .unwrap()
3448        .0[0];
3449        assert!(selector.is_universal());
3450    }
3451
3452    #[test]
3453    fn test_empty_pseudo_iter() {
3454        let selector = &parse("::before").unwrap().0[0];
3455        assert!(selector.is_universal());
3456        let mut iter = selector.iter();
3457        assert_eq!(
3458            iter.next(),
3459            Some(&Component::PseudoElement(PseudoElement::Before))
3460        );
3461        assert_eq!(iter.next(), None);
3462        assert_eq!(iter.next_sequence(), Some(Combinator::PseudoElement));
3463        assert_eq!(iter.next(), None);
3464        assert_eq!(iter.next_sequence(), None);
3465    }
3466
3467    struct TestVisitor {
3468        seen: Vec<String>,
3469    }
3470
3471    impl SelectorVisitor for TestVisitor {
3472        type Impl = DummySelectorImpl;
3473
3474        fn visit_simple_selector(
3475            &mut self,
3476            s: &Component<DummySelectorImpl>,
3477        ) -> bool {
3478            let mut dest = String::new();
3479            s.to_css(&mut dest).unwrap();
3480            self.seen.push(dest);
3481            true
3482        }
3483    }
3484
3485    #[test]
3486    fn visitor() {
3487        let mut test_visitor = TestVisitor { seen: vec![] };
3488        parse(":not(:hover) ~ label").unwrap().0[0].visit(&mut test_visitor);
3489        assert!(test_visitor.seen.contains(&":hover".into()));
3490
3491        let mut test_visitor = TestVisitor { seen: vec![] };
3492        parse("::before:hover").unwrap().0[0].visit(&mut test_visitor);
3493        assert!(test_visitor.seen.contains(&":hover".into()));
3494    }
3495}