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