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