selectors/
parser.rs

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