1use crate::attr::{
6 AttrSelectorOperation, AttrSelectorWithOptionalNamespace, CaseSensitivity, NamespaceConstraint,
7 ParsedAttrSelectorOperation, ParsedCaseSensitivity,
8};
9use crate::bloom::{BloomFilter, BLOOM_HASH_MASK};
10use crate::kleene_value::KleeneValue;
11use crate::parser::{
12 AncestorHashes, Combinator, Component, LocalName, MatchesFeaturelessHost, NthSelectorData,
13 RelativeSelectorMatchHint,
14};
15use crate::parser::{
16 NonTSPseudoClass, RelativeSelector, Selector, SelectorImpl, SelectorIter, SelectorList,
17};
18use crate::relative_selector::cache::RelativeSelectorCachedMatch;
19use crate::tree::Element;
20use bitflags::bitflags;
21use debug_unreachable::debug_unreachable;
22use log::debug;
23use smallvec::SmallVec;
24use std::borrow::Borrow;
25
26pub use crate::context::*;
27
28pub static RECOMMENDED_SELECTOR_BLOOM_FILTER_SIZE: usize = 4096;
32
33bitflags! {
34 #[derive(Clone, Copy)]
37 pub struct ElementSelectorFlags: usize {
38 const HAS_SLOW_SELECTOR = 1 << 0;
42
43 const HAS_SLOW_SELECTOR_LATER_SIBLINGS = 1 << 1;
47
48 const HAS_SLOW_SELECTOR_NTH = 1 << 2;
50
51 const HAS_SLOW_SELECTOR_NTH_OF = 1 << 3;
60
61 const HAS_EDGE_CHILD_SELECTOR = 1 << 4;
65
66 const HAS_EMPTY_SELECTOR = 1 << 5;
69
70 const ANCHORS_RELATIVE_SELECTOR = 1 << 6;
72
73 const ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT = 1 << 7;
76
77 const RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING = 1 << 8;
79
80 const RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR = 1 << 9;
82
83 const RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING =
85 Self::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING.bits() |
86 Self::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR.bits();
87
88 const MAY_HAVE_TREE_COUNTING_FUNCTION = 1 << 11;
91 }
92}
93
94impl ElementSelectorFlags {
95 pub fn for_self(self) -> ElementSelectorFlags {
97 self & (ElementSelectorFlags::HAS_EMPTY_SELECTOR
98 | ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR
99 | ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT
100 | ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
101 | ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR)
102 }
103
104 pub fn for_parent(self) -> ElementSelectorFlags {
106 self & (ElementSelectorFlags::HAS_SLOW_SELECTOR
107 | ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS
108 | ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH
109 | ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF
110 | ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR
111 | ElementSelectorFlags::MAY_HAVE_TREE_COUNTING_FUNCTION)
112 }
113}
114
115struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
117 shared: &'a mut MatchingContext<'b, Impl>,
118 rightmost: SubjectOrPseudoElement,
119 quirks_data: Option<SelectorIter<'a, Impl>>,
120}
121
122#[inline(always)]
123pub fn matches_selector_list<E>(
124 selector_list: &SelectorList<E::Impl>,
125 element: &E,
126 context: &mut MatchingContext<E::Impl>,
127) -> bool
128where
129 E: Element,
130{
131 for selector in selector_list.slice() {
134 let matches = matches_selector(selector, 0, None, element, context);
135 if matches {
136 return true;
137 }
138 }
139
140 false
141}
142
143#[inline(always)]
146pub fn selector_may_match(hashes: &AncestorHashes, bf: &BloomFilter) -> bool {
147 for i in 0..3 {
155 let packed = hashes.packed_hashes[i];
156 if packed == 0 {
157 return true;
159 }
160
161 if !bf.might_contain_hash(packed & BLOOM_HASH_MASK) {
162 return false;
164 }
165 }
166
167 let fourth = hashes.fourth_hash();
170 fourth == 0 || bf.might_contain_hash(fourth)
171}
172
173#[derive(Clone, Copy, Eq, PartialEq)]
230enum SelectorMatchingResult {
231 Matched,
232 NotMatchedAndRestartFromClosestLaterSibling,
233 NotMatchedAndRestartFromClosestDescendant,
234 NotMatchedGlobally,
235 Unknown,
236}
237
238impl From<SelectorMatchingResult> for KleeneValue {
239 #[inline]
240 fn from(value: SelectorMatchingResult) -> Self {
241 match value {
242 SelectorMatchingResult::Matched => KleeneValue::True,
243 SelectorMatchingResult::Unknown => KleeneValue::Unknown,
244 SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling
245 | SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
246 | SelectorMatchingResult::NotMatchedGlobally => KleeneValue::False,
247 }
248 }
249}
250
251#[inline(always)]
260pub fn matches_selector<E>(
261 selector: &Selector<E::Impl>,
262 offset: usize,
263 hashes: Option<&AncestorHashes>,
264 element: &E,
265 context: &mut MatchingContext<E::Impl>,
266) -> bool
267where
268 E: Element,
269{
270 let result = matches_selector_kleene(selector, offset, hashes, element, context);
271 if cfg!(debug_assertions) && result == KleeneValue::Unknown {
272 debug_assert!(
273 context
274 .matching_for_invalidation_comparison()
275 .unwrap_or(false),
276 "How did we return unknown?"
277 );
278 }
279 result.to_bool(true)
280}
281
282#[inline(always)]
284pub fn matches_selector_kleene<E>(
285 selector: &Selector<E::Impl>,
286 offset: usize,
287 hashes: Option<&AncestorHashes>,
288 element: &E,
289 context: &mut MatchingContext<E::Impl>,
290) -> KleeneValue
291where
292 E: Element,
293{
294 if let Some(hashes) = hashes {
296 if let Some(filter) = context.bloom_filter {
297 if !selector_may_match(hashes, filter) {
298 return KleeneValue::False;
299 }
300 }
301 }
302 matches_complex_selector(
303 selector.iter_from(offset),
304 element,
305 context,
306 if selector.is_rightmost(offset) {
307 SubjectOrPseudoElement::Yes
308 } else {
309 SubjectOrPseudoElement::No
310 },
311 )
312}
313
314pub enum CompoundSelectorMatchingResult {
317 FullyMatched,
319 Matched { next_combinator_offset: usize },
322 NotMatched,
324}
325
326fn complex_selector_early_reject_by_local_name<E: Element>(
327 list: &SelectorList<E::Impl>,
328 element: &E,
329) -> bool {
330 list.slice()
331 .iter()
332 .all(|s| early_reject_by_local_name(s, 0, element))
333}
334
335pub fn early_reject_by_local_name<E: Element>(
338 selector: &Selector<E::Impl>,
339 from_offset: usize,
340 element: &E,
341) -> bool {
342 let iter = selector.iter_from(from_offset);
343 for component in iter {
344 if match component {
345 Component::LocalName(name) => !matches_local_name(element, name),
346 Component::Is(list) | Component::Where(list) => {
347 complex_selector_early_reject_by_local_name(list, element)
348 },
349 _ => continue,
350 } {
351 return true;
352 }
353 }
354 false
355}
356
357pub fn matches_compound_selector_from<E>(
365 selector: &Selector<E::Impl>,
366 mut from_offset: usize,
367 context: &mut MatchingContext<E::Impl>,
368 element: &E,
369) -> CompoundSelectorMatchingResult
370where
371 E: Element,
372{
373 debug_assert!(
374 !context
375 .matching_for_invalidation_comparison()
376 .unwrap_or(false),
377 "CompoundSelectorMatchingResult doesn't support unknown"
378 );
379 if cfg!(debug_assertions) && from_offset != 0 {
380 selector.combinator_at_parse_order(from_offset - 1); }
382
383 let mut local_context = LocalMatchingContext {
384 shared: context,
385 rightmost: SubjectOrPseudoElement::No,
389 quirks_data: None,
390 };
391
392 let start_offset = from_offset;
396 for component in selector.iter_raw_parse_order_from(from_offset) {
397 if matches!(*component, Component::Combinator(..)) {
398 debug_assert_ne!(from_offset, 0, "Selector started with a combinator?");
399 break;
400 }
401
402 from_offset += 1;
403 }
404
405 debug_assert!(from_offset >= 1);
406 debug_assert!(from_offset <= selector.len());
407
408 let iter = selector.iter_from(selector.len() - from_offset);
409 debug_assert!(
410 iter.clone().next().is_some() || from_offset != selector.len(),
411 "Got the math wrong: {:?} | {:?} | {} {}",
412 selector,
413 selector.iter_raw_match_order().as_slice(),
414 from_offset,
415 start_offset
416 );
417
418 debug_assert!(
419 !local_context.shared.featureless(),
420 "Invalidating featureless element somehow?"
421 );
422
423 for component in iter {
424 let result = matches_simple_selector(component, element, &mut local_context);
425 debug_assert!(
426 result != KleeneValue::Unknown,
427 "Returned unknown in non invalidation context?"
428 );
429 if !result.to_bool(true) {
430 return CompoundSelectorMatchingResult::NotMatched;
431 }
432 }
433
434 if from_offset != selector.len() {
435 return CompoundSelectorMatchingResult::Matched {
436 next_combinator_offset: from_offset,
437 };
438 }
439
440 CompoundSelectorMatchingResult::FullyMatched
441}
442
443#[inline(always)]
445fn matches_complex_selector<E>(
446 mut iter: SelectorIter<E::Impl>,
447 element: &E,
448 context: &mut MatchingContext<E::Impl>,
449 rightmost: SubjectOrPseudoElement,
450) -> KleeneValue
451where
452 E: Element,
453{
454 if context.matching_mode() == MatchingMode::ForStatelessPseudoElement && !context.is_nested() {
457 match *iter.next().unwrap() {
459 Component::PseudoElement(ref pseudo) => {
460 if let Some(ref f) = context.pseudo_element_matching_fn {
461 if !f(pseudo) {
462 return KleeneValue::False;
463 }
464 }
465 },
466 ref other => {
467 debug_assert!(
468 false,
469 "Used MatchingMode::ForStatelessPseudoElement \
470 in a non-pseudo selector {:?}",
471 other
472 );
473 return KleeneValue::False;
474 },
475 }
476
477 if !iter.matches_for_stateless_pseudo_element() {
478 return KleeneValue::False;
479 }
480
481 let next_sequence = iter.next_sequence().unwrap();
483 debug_assert_eq!(next_sequence, Combinator::PseudoElement);
484 }
485
486 matches_complex_selector_internal(
487 iter,
488 element,
489 context,
490 rightmost,
491 SubjectOrPseudoElement::Yes,
492 )
493 .into()
494}
495
496fn matches_complex_selector_list<E: Element>(
498 list: &[Selector<E::Impl>],
499 element: &E,
500 context: &mut MatchingContext<E::Impl>,
501 rightmost: SubjectOrPseudoElement,
502) -> KleeneValue {
503 KleeneValue::any(list.iter(), |selector| {
504 matches_complex_selector(selector.iter(), element, context, rightmost)
505 })
506}
507
508fn matches_relative_selector<E: Element>(
509 relative_selector: &RelativeSelector<E::Impl>,
510 element: &E,
511 context: &mut MatchingContext<E::Impl>,
512 rightmost: SubjectOrPseudoElement,
513) -> bool {
514 if relative_selector.match_hint.is_descendant_direction() {
517 if context.needs_selector_flags() {
518 element.apply_selector_flags(
519 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
520 );
521 }
522 let mut next_element = element.first_element_child();
523 while let Some(el) = next_element {
524 if context.needs_selector_flags() {
525 el.apply_selector_flags(
526 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
527 );
528 }
529 let mut matched = matches_complex_selector(
530 relative_selector.selector.iter(),
531 &el,
532 context,
533 rightmost,
534 )
535 .to_bool(true);
536 if !matched && relative_selector.match_hint.is_subtree() {
537 matched = matches_relative_selector_subtree(
538 &relative_selector.selector,
539 &el,
540 context,
541 rightmost,
542 );
543 }
544 if matched {
545 return true;
546 }
547 next_element = el.next_sibling_element();
548 }
549 } else {
550 debug_assert!(
551 matches!(
552 relative_selector.match_hint,
553 RelativeSelectorMatchHint::InNextSibling
554 | RelativeSelectorMatchHint::InNextSiblingSubtree
555 | RelativeSelectorMatchHint::InSibling
556 | RelativeSelectorMatchHint::InSiblingSubtree
557 ),
558 "Not descendant direction, but also not sibling direction?"
559 );
560 if context.needs_selector_flags() {
561 element.apply_selector_flags(
562 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
563 );
564 }
565 let sibling_flag = if relative_selector.match_hint.is_subtree() {
566 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING
567 } else {
568 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
569 };
570 let mut next_element = element.next_sibling_element();
571 while let Some(el) = next_element {
572 if context.needs_selector_flags() {
573 el.apply_selector_flags(sibling_flag);
574 }
575 let matched = if relative_selector.match_hint.is_subtree() {
576 matches_relative_selector_subtree(
577 &relative_selector.selector,
578 &el,
579 context,
580 rightmost,
581 )
582 } else {
583 matches_complex_selector(relative_selector.selector.iter(), &el, context, rightmost)
584 .to_bool(true)
585 };
586 if matched {
587 return true;
588 }
589 if relative_selector.match_hint.is_next_sibling() {
590 break;
591 }
592 next_element = el.next_sibling_element();
593 }
594 }
595 return false;
596}
597
598fn relative_selector_match_early<E: Element>(
599 selector: &RelativeSelector<E::Impl>,
600 element: &E,
601 context: &mut MatchingContext<E::Impl>,
602) -> Option<bool> {
603 if let Some(cached) = context
605 .selector_caches
606 .relative_selector
607 .lookup(element.opaque(), selector)
608 {
609 return Some(cached.matched());
610 }
611 if context
613 .selector_caches
614 .relative_selector_filter_map
615 .fast_reject(element, selector, context.quirks_mode())
616 {
617 context.selector_caches.relative_selector.add(
619 element.opaque(),
620 selector,
621 RelativeSelectorCachedMatch::NotMatched,
622 );
623 return Some(false);
624 }
625 None
626}
627
628fn match_relative_selectors<E: Element>(
629 selectors: &[RelativeSelector<E::Impl>],
630 element: &E,
631 context: &mut MatchingContext<E::Impl>,
632 rightmost: SubjectOrPseudoElement,
633) -> KleeneValue {
634 if context.relative_selector_anchor().is_some() {
635 return KleeneValue::False;
641 }
642 if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
643 return if may_return_unknown {
647 KleeneValue::Unknown
648 } else {
649 KleeneValue::from(!context.in_negation())
650 };
651 }
652 context
653 .nest_for_relative_selector(element.opaque(), |context| {
654 do_match_relative_selectors(selectors, element, context, rightmost)
655 })
656 .into()
657}
658
659fn do_match_relative_selectors<E: Element>(
661 selectors: &[RelativeSelector<E::Impl>],
662 element: &E,
663 context: &mut MatchingContext<E::Impl>,
664 rightmost: SubjectOrPseudoElement,
665) -> bool {
666 if rightmost == SubjectOrPseudoElement::Yes {
670 if context.needs_selector_flags() {
671 element.apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR);
672 }
673 } else {
674 if context.needs_selector_flags() {
675 element
676 .apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT);
677 }
678 }
679
680 for relative_selector in selectors.iter() {
681 if let Some(result) = relative_selector_match_early(relative_selector, element, context) {
682 if result {
683 return true;
684 }
685 continue;
687 }
688
689 let matched = matches_relative_selector(relative_selector, element, context, rightmost);
690 context.selector_caches.relative_selector.add(
691 element.opaque(),
692 relative_selector,
693 if matched {
694 RelativeSelectorCachedMatch::Matched
695 } else {
696 RelativeSelectorCachedMatch::NotMatched
697 },
698 );
699 if matched {
700 return true;
701 }
702 }
703
704 false
705}
706
707fn matches_relative_selector_subtree<E: Element>(
708 selector: &Selector<E::Impl>,
709 element: &E,
710 context: &mut MatchingContext<E::Impl>,
711 rightmost: SubjectOrPseudoElement,
712) -> bool {
713 let mut current = element.first_element_child();
714
715 while let Some(el) = current {
716 if context.needs_selector_flags() {
717 el.apply_selector_flags(
718 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
719 );
720 }
721 if matches_complex_selector(selector.iter(), &el, context, rightmost).to_bool(true) {
722 return true;
723 }
724
725 if matches_relative_selector_subtree(selector, &el, context, rightmost) {
726 return true;
727 }
728
729 current = el.next_sibling_element();
730 }
731
732 false
733}
734
735fn hover_and_active_quirk_applies<Impl: SelectorImpl>(
739 selector_iter: &SelectorIter<Impl>,
740 context: &MatchingContext<Impl>,
741 rightmost: SubjectOrPseudoElement,
742) -> bool {
743 debug_assert_eq!(context.quirks_mode(), QuirksMode::Quirks);
744
745 if context.is_nested() {
746 return false;
747 }
748
749 if rightmost == SubjectOrPseudoElement::Yes
752 && context.matching_mode() == MatchingMode::ForStatelessPseudoElement
753 {
754 return false;
755 }
756
757 selector_iter.clone().all(|simple| match *simple {
758 Component::NonTSPseudoClass(ref pseudo_class) => pseudo_class.is_active_or_hover(),
759 _ => false,
760 })
761}
762
763#[derive(Clone, Copy, PartialEq)]
764enum SubjectOrPseudoElement {
765 Yes,
766 No,
767}
768
769fn host_for_part<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
770where
771 E: Element,
772{
773 let scope = context.current_host;
774 let mut curr = element.containing_shadow_host()?;
775 if scope == Some(curr.opaque()) {
776 return Some(curr);
777 }
778 loop {
779 let parent = curr.containing_shadow_host();
780 if parent.as_ref().map(|h| h.opaque()) == scope {
781 return Some(curr);
782 }
783 curr = parent?;
784 }
785}
786
787fn assigned_slot<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
788where
789 E: Element,
790{
791 debug_assert!(element
792 .assigned_slot()
793 .map_or(true, |s| s.is_html_slot_element()));
794 let scope = context.current_host?;
795 let mut current_slot = element.assigned_slot()?;
796 while current_slot.containing_shadow_host().unwrap().opaque() != scope {
797 current_slot = current_slot.assigned_slot()?;
798 }
799 Some(current_slot)
800}
801
802struct NextElement<E> {
803 next_element: Option<E>,
804 featureless: bool,
805}
806
807impl<E> NextElement<E> {
808 #[inline(always)]
809 fn new(next_element: Option<E>, featureless: bool) -> Self {
810 Self {
811 next_element,
812 featureless,
813 }
814 }
815}
816
817#[inline(always)]
818fn next_element_for_combinator<E>(
819 element: &E,
820 combinator: Combinator,
821 context: &MatchingContext<E::Impl>,
822) -> NextElement<E>
823where
824 E: Element,
825{
826 match combinator {
827 Combinator::NextSibling | Combinator::LaterSibling => {
828 NextElement::new(element.prev_sibling_element(), false)
829 },
830 Combinator::Child | Combinator::Descendant => {
831 if let Some(parent) = element.parent_element() {
832 return NextElement::new(Some(parent), false);
833 }
834
835 let element = if element.parent_node_is_shadow_root() {
836 element.containing_shadow_host()
837 } else {
838 None
839 };
840 NextElement::new(element, true)
841 },
842 Combinator::Part => NextElement::new(host_for_part(element, context), false),
843 Combinator::SlotAssignment => NextElement::new(assigned_slot(element, context), false),
844 Combinator::PseudoElement => {
845 NextElement::new(element.pseudo_element_originating_element(), false)
846 },
847 }
848}
849
850fn matches_complex_selector_internal<E>(
851 mut selector_iter: SelectorIter<E::Impl>,
852 element: &E,
853 context: &mut MatchingContext<E::Impl>,
854 mut rightmost: SubjectOrPseudoElement,
855 mut first_subject_compound: SubjectOrPseudoElement,
856) -> SelectorMatchingResult
857where
858 E: Element,
859{
860 debug!(
861 "Matching complex selector {:?} for {:?}",
862 selector_iter, element
863 );
864
865 let matches_compound_selector =
866 matches_compound_selector(&mut selector_iter, element, context, rightmost);
867
868 let Some(combinator) = selector_iter.next_sequence() else {
869 return match matches_compound_selector {
870 KleeneValue::True => SelectorMatchingResult::Matched,
871 KleeneValue::Unknown => SelectorMatchingResult::Unknown,
872 KleeneValue::False => {
873 SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling
874 },
875 };
876 };
877
878 let is_pseudo_combinator = combinator.is_pseudo_element();
879 if context.featureless() && !is_pseudo_combinator {
880 return SelectorMatchingResult::NotMatchedGlobally;
883 }
884
885 let is_sibling_combinator = combinator.is_sibling();
886 if is_sibling_combinator && context.needs_selector_flags() {
887 element.apply_selector_flags(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS);
889 }
890
891 if matches_compound_selector == KleeneValue::False {
892 return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
895 }
896
897 if !is_pseudo_combinator {
898 rightmost = SubjectOrPseudoElement::No;
899 first_subject_compound = SubjectOrPseudoElement::No;
900 }
901
902 let mut visited_handling = if is_sibling_combinator {
905 VisitedHandlingMode::AllLinksUnvisited
906 } else {
907 context.visited_handling()
908 };
909
910 let candidate_not_found = if is_sibling_combinator {
911 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
912 } else {
913 SelectorMatchingResult::NotMatchedGlobally
914 };
915
916 let mut element = element.clone();
917 loop {
918 if element.is_link() {
919 visited_handling = VisitedHandlingMode::AllLinksUnvisited;
920 }
921
922 let NextElement {
923 next_element,
924 featureless,
925 } = next_element_for_combinator(&element, combinator, &context);
926 element = match next_element {
927 None => return candidate_not_found,
928 Some(e) => e,
929 };
930
931 let result = context.with_visited_handling_mode(visited_handling, |context| {
932 context.with_featureless(featureless, |context| {
933 matches_complex_selector_internal(
934 selector_iter.clone(),
935 &element,
936 context,
937 rightmost,
938 first_subject_compound,
939 )
940 })
941 });
942
943 match result {
945 SelectorMatchingResult::Matched => {
946 debug_assert!(
947 matches_compound_selector.to_bool(true),
948 "Compound didn't match?"
949 );
950 if !matches_compound_selector.to_bool(false) {
951 return SelectorMatchingResult::Unknown;
952 }
953 return result;
954 },
955 SelectorMatchingResult::Unknown | SelectorMatchingResult::NotMatchedGlobally => {
956 return result
957 },
958 _ => {},
959 }
960
961 match combinator {
962 Combinator::Descendant => {
963 },
969 Combinator::Child => {
970 return SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant;
972 },
973 Combinator::LaterSibling => {
974 if matches!(
978 result,
979 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
980 ) {
981 return result;
982 }
983 },
984 Combinator::NextSibling
985 | Combinator::PseudoElement
986 | Combinator::Part
987 | Combinator::SlotAssignment => {
988 return result;
993 },
994 }
995
996 if featureless {
997 return candidate_not_found;
1000 }
1001 }
1002}
1003
1004#[inline]
1005fn matches_local_name<E>(element: &E, local_name: &LocalName<E::Impl>) -> bool
1006where
1007 E: Element,
1008{
1009 let name = select_name(element, &local_name.name, &local_name.lower_name).borrow();
1010 element.has_local_name(name)
1011}
1012
1013fn matches_part<E>(
1014 element: &E,
1015 parts: &[<E::Impl as SelectorImpl>::Identifier],
1016 context: &mut MatchingContext<E::Impl>,
1017) -> bool
1018where
1019 E: Element,
1020{
1021 let mut hosts = SmallVec::<[E; 4]>::new();
1022
1023 let mut host = match element.containing_shadow_host() {
1024 Some(h) => h,
1025 None => return false,
1026 };
1027
1028 let current_host = context.current_host;
1029 if current_host != Some(host.opaque()) {
1030 loop {
1031 let outer_host = host.containing_shadow_host();
1032 if outer_host.as_ref().map(|h| h.opaque()) == current_host {
1033 break;
1034 }
1035 let outer_host = match outer_host {
1036 Some(h) => h,
1037 None => return false,
1038 };
1039 hosts.push(host);
1042 host = outer_host;
1043 }
1044 }
1045
1046 parts.iter().all(|part| {
1048 let mut part = part.clone();
1049 for host in hosts.iter().rev() {
1050 part = match host.imported_part(&part) {
1051 Some(p) => p,
1052 None => return false,
1053 };
1054 }
1055 element.is_part(&part)
1056 })
1057}
1058
1059fn matches_host<E>(
1060 element: &E,
1061 selector: Option<&Selector<E::Impl>>,
1062 context: &mut MatchingContext<E::Impl>,
1063 rightmost: SubjectOrPseudoElement,
1064) -> KleeneValue
1065where
1066 E: Element,
1067{
1068 let host = match context.shadow_host() {
1069 Some(h) => h,
1070 None => return KleeneValue::False,
1071 };
1072 if host != element.opaque() {
1073 return KleeneValue::False;
1074 }
1075 let Some(selector) = selector else {
1076 return KleeneValue::True;
1077 };
1078 context.nest(|context| {
1079 context.with_featureless(false, |context| {
1080 matches_complex_selector(selector.iter(), element, context, rightmost)
1081 })
1082 })
1083}
1084
1085fn matches_slotted<E>(
1086 element: &E,
1087 selector: &Selector<E::Impl>,
1088 context: &mut MatchingContext<E::Impl>,
1089 rightmost: SubjectOrPseudoElement,
1090) -> KleeneValue
1091where
1092 E: Element,
1093{
1094 if element.is_html_slot_element() {
1096 return KleeneValue::False;
1097 }
1098 context.nest(|context| matches_complex_selector(selector.iter(), element, context, rightmost))
1099}
1100
1101fn matches_rare_attribute_selector<E>(
1102 element: &E,
1103 attr_sel: &AttrSelectorWithOptionalNamespace<E::Impl>,
1104) -> bool
1105where
1106 E: Element,
1107{
1108 let empty_string;
1109 let namespace = match attr_sel.namespace() {
1110 Some(ns) => ns,
1111 None => {
1112 empty_string = crate::parser::namespace_empty_string::<E::Impl>();
1113 NamespaceConstraint::Specific(&empty_string)
1114 },
1115 };
1116 element.attr_matches(
1117 &namespace,
1118 select_name(element, &attr_sel.local_name, &attr_sel.local_name_lower),
1119 &match attr_sel.operation {
1120 ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
1121 ParsedAttrSelectorOperation::WithValue {
1122 operator,
1123 case_sensitivity,
1124 ref value,
1125 } => AttrSelectorOperation::WithValue {
1126 operator,
1127 case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
1128 value,
1129 },
1130 },
1131 )
1132}
1133
1134pub(crate) fn compound_matches_featureless_host<Impl: SelectorImpl>(
1138 iter: &mut SelectorIter<Impl>,
1139 scope_matches_featureless_host: bool,
1140) -> MatchesFeaturelessHost {
1141 let mut matches = MatchesFeaturelessHost::Only;
1142 for component in iter {
1143 match component {
1144 Component::Scope | Component::ImplicitScope if scope_matches_featureless_host => {},
1145 Component::Host(..) => {},
1147 Component::PseudoElement(..) => {},
1149 Component::Is(ref l) | Component::Where(ref l) => {
1152 let mut any_yes = false;
1153 let mut any_no = false;
1154 for selector in l.slice() {
1155 match selector.matches_featureless_host(scope_matches_featureless_host) {
1156 MatchesFeaturelessHost::Never => {
1157 any_no = true;
1158 },
1159 MatchesFeaturelessHost::Yes => {
1160 any_yes = true;
1161 any_no = true;
1162 },
1163 MatchesFeaturelessHost::Only => {
1164 any_yes = true;
1165 },
1166 }
1167 }
1168 if !any_yes {
1169 return MatchesFeaturelessHost::Never;
1170 }
1171 if any_no {
1172 matches = MatchesFeaturelessHost::Yes;
1174 }
1175 },
1176 Component::Negation(ref l) => {
1177 for selector in l.slice() {
1181 if selector.matches_featureless_host(scope_matches_featureless_host)
1182 != MatchesFeaturelessHost::Only
1183 {
1184 return MatchesFeaturelessHost::Never;
1185 }
1186 }
1187 },
1188 _ => return MatchesFeaturelessHost::Never,
1190 }
1191 }
1192 matches
1193}
1194
1195#[inline]
1197fn matches_compound_selector<E>(
1198 selector_iter: &mut SelectorIter<E::Impl>,
1199 element: &E,
1200 context: &mut MatchingContext<E::Impl>,
1201 rightmost: SubjectOrPseudoElement,
1202) -> KleeneValue
1203where
1204 E: Element,
1205{
1206 if context.featureless()
1207 && compound_matches_featureless_host(
1208 &mut selector_iter.clone(),
1209 true,
1210 ) == MatchesFeaturelessHost::Never
1211 {
1212 return KleeneValue::False;
1213 }
1214 let quirks_data = if context.quirks_mode() == QuirksMode::Quirks {
1215 Some(selector_iter.clone())
1216 } else {
1217 None
1218 };
1219 let mut local_context = LocalMatchingContext {
1220 shared: context,
1221 rightmost,
1222 quirks_data,
1223 };
1224 KleeneValue::any_false(selector_iter, |simple| {
1225 matches_simple_selector(simple, element, &mut local_context)
1226 })
1227}
1228
1229fn matches_simple_selector<E>(
1231 selector: &Component<E::Impl>,
1232 element: &E,
1233 context: &mut LocalMatchingContext<E::Impl>,
1234) -> KleeneValue
1235where
1236 E: Element,
1237{
1238 debug_assert!(context.shared.is_nested() || !context.shared.in_negation());
1239 let rightmost = context.rightmost;
1240 KleeneValue::from(match *selector {
1241 Component::ID(ref id) => {
1242 element.has_id(id, context.shared.classes_and_ids_case_sensitivity())
1243 },
1244 Component::Class(ref class) => {
1245 element.has_class(class, context.shared.classes_and_ids_case_sensitivity())
1246 },
1247 Component::LocalName(ref local_name) => matches_local_name(element, local_name),
1248 Component::AttributeInNoNamespaceExists {
1249 ref local_name,
1250 ref local_name_lower,
1251 } => element.has_attr_in_no_namespace(select_name(element, local_name, local_name_lower)),
1252 Component::AttributeInNoNamespace {
1253 ref local_name,
1254 ref value,
1255 operator,
1256 case_sensitivity,
1257 } => element.attr_matches(
1258 &NamespaceConstraint::Specific(&crate::parser::namespace_empty_string::<E::Impl>()),
1259 local_name,
1260 &AttrSelectorOperation::WithValue {
1261 operator,
1262 case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
1263 value,
1264 },
1265 ),
1266 Component::AttributeOther(ref attr_sel) => {
1267 matches_rare_attribute_selector(element, attr_sel)
1268 },
1269 Component::Part(ref parts) => matches_part(element, parts, &mut context.shared),
1270 Component::Slotted(ref selector) => {
1271 return matches_slotted(element, selector, &mut context.shared, rightmost);
1272 },
1273 Component::PseudoElement(ref pseudo) => {
1274 element.match_pseudo_element(pseudo, context.shared)
1275 },
1276 Component::ExplicitUniversalType | Component::ExplicitAnyNamespace => true,
1277 Component::Namespace(_, ref url) | Component::DefaultNamespace(ref url) => {
1278 element.has_namespace(&url.borrow())
1279 },
1280 Component::ExplicitNoNamespace => {
1281 let ns = crate::parser::namespace_empty_string::<E::Impl>();
1282 element.has_namespace(&ns.borrow())
1283 },
1284 Component::NonTSPseudoClass(ref pc) => {
1285 if let Some(ref iter) = context.quirks_data {
1286 if pc.is_active_or_hover()
1287 && !element.is_link()
1288 && hover_and_active_quirk_applies(iter, context.shared, context.rightmost)
1289 {
1290 return KleeneValue::False;
1291 }
1292 }
1293 element.match_non_ts_pseudo_class(pc, &mut context.shared)
1294 },
1295 Component::Root => element.is_root(),
1296 Component::Empty => {
1297 if context.shared.needs_selector_flags() {
1298 element.apply_selector_flags(ElementSelectorFlags::HAS_EMPTY_SELECTOR);
1299 }
1300 element.is_empty()
1301 },
1302 Component::Host(ref selector) => {
1303 return matches_host(element, selector.as_ref(), &mut context.shared, rightmost);
1304 },
1305 Component::ParentSelector => match context.shared.scope_element {
1306 Some(ref scope_element) => element.opaque() == *scope_element,
1307 None => element.is_root(),
1308 },
1309 Component::Scope | Component::ImplicitScope => {
1310 let matching_for_invalidation = context.shared.matching_for_invalidation_comparison();
1311 if context.shared.matching_for_revalidation() || matching_for_invalidation.is_some() {
1312 let may_return_unknown = matching_for_invalidation.unwrap_or(false);
1313 return if may_return_unknown {
1314 KleeneValue::Unknown
1315 } else {
1316 KleeneValue::from(!context.shared.in_negation())
1317 };
1318 }
1319 match context.shared.scope_element {
1320 Some(ref scope_element) => element.opaque() == *scope_element,
1321 None => element.is_root(),
1322 }
1323 },
1324 Component::Nth(ref nth_data) => {
1325 return matches_generic_nth_child(element, context.shared, nth_data, &[], rightmost);
1326 },
1327 Component::NthOf(ref nth_of_data) => {
1328 return context.shared.nest(|context| {
1329 matches_generic_nth_child(
1330 element,
1331 context,
1332 nth_of_data.nth_data(),
1333 nth_of_data.selectors(),
1334 rightmost,
1335 )
1336 })
1337 },
1338 Component::Is(ref list) | Component::Where(ref list) => {
1339 return context.shared.nest(|context| {
1340 matches_complex_selector_list(list.slice(), element, context, rightmost)
1341 })
1342 },
1343 Component::Negation(ref list) => {
1344 return context.shared.nest_for_negation(|context| {
1345 !matches_complex_selector_list(list.slice(), element, context, rightmost)
1346 })
1347 },
1348 Component::Has(ref relative_selectors) => {
1349 return match_relative_selectors(
1350 relative_selectors,
1351 element,
1352 context.shared,
1353 rightmost,
1354 );
1355 },
1356 Component::Combinator(_) => unsafe {
1357 debug_unreachable!("Shouldn't try to selector-match combinators")
1358 },
1359 Component::RelativeSelectorAnchor => {
1360 let anchor = context.shared.relative_selector_anchor();
1361 anchor.map_or(true, |a| a == element.opaque())
1363 },
1364 Component::Invalid(..) => false,
1365 })
1366}
1367
1368#[inline(always)]
1369pub fn select_name<'a, E: Element, T: PartialEq>(
1370 element: &E,
1371 local_name: &'a T,
1372 local_name_lower: &'a T,
1373) -> &'a T {
1374 if local_name == local_name_lower || element.is_html_element_in_html_document() {
1375 local_name_lower
1376 } else {
1377 local_name
1378 }
1379}
1380
1381#[inline(always)]
1382pub fn to_unconditional_case_sensitivity<'a, E: Element>(
1383 parsed: ParsedCaseSensitivity,
1384 element: &E,
1385) -> CaseSensitivity {
1386 match parsed {
1387 ParsedCaseSensitivity::CaseSensitive | ParsedCaseSensitivity::ExplicitCaseSensitive => {
1388 CaseSensitivity::CaseSensitive
1389 },
1390 ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
1391 ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
1392 if element.is_html_element_in_html_document() {
1393 CaseSensitivity::AsciiCaseInsensitive
1394 } else {
1395 CaseSensitivity::CaseSensitive
1396 }
1397 },
1398 }
1399}
1400
1401fn matches_generic_nth_child<E>(
1402 element: &E,
1403 context: &mut MatchingContext<E::Impl>,
1404 nth_data: &NthSelectorData,
1405 selectors: &[Selector<E::Impl>],
1406 rightmost: SubjectOrPseudoElement,
1407) -> KleeneValue
1408where
1409 E: Element,
1410{
1411 if element.ignores_nth_child_selectors() {
1412 return KleeneValue::False;
1413 }
1414 let has_selectors = !selectors.is_empty();
1415 let selectors_match = !has_selectors
1416 || matches_complex_selector_list(selectors, element, context, rightmost).to_bool(true);
1417 if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
1418 return if selectors_match && may_return_unknown {
1420 KleeneValue::Unknown
1421 } else {
1422 KleeneValue::from(selectors_match && !context.in_negation())
1423 };
1424 }
1425
1426 let NthSelectorData { ty, an_plus_b, .. } = *nth_data;
1427 let is_of_type = ty.is_of_type();
1428 if ty.is_only() {
1429 debug_assert!(
1430 !has_selectors,
1431 ":only-child and :only-of-type cannot have a selector list!"
1432 );
1433 return KleeneValue::from(
1434 matches_generic_nth_child(
1435 element,
1436 context,
1437 &NthSelectorData::first(is_of_type),
1438 selectors,
1439 rightmost,
1440 )
1441 .to_bool(true)
1442 && matches_generic_nth_child(
1443 element,
1444 context,
1445 &NthSelectorData::last(is_of_type),
1446 selectors,
1447 rightmost,
1448 )
1449 .to_bool(true),
1450 );
1451 }
1452
1453 let is_from_end = ty.is_from_end();
1454
1455 let is_edge_child_selector = nth_data.is_simple_edge() && !has_selectors;
1458
1459 if context.needs_selector_flags() {
1460 let mut flags = if is_edge_child_selector {
1461 ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR
1462 } else if is_from_end {
1463 ElementSelectorFlags::HAS_SLOW_SELECTOR
1464 } else {
1465 ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS
1466 };
1467 flags |= if has_selectors {
1468 ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF
1469 } else {
1470 ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH
1471 };
1472 element.apply_selector_flags(flags);
1473 }
1474
1475 if !selectors_match {
1476 return KleeneValue::False;
1477 }
1478
1479 if is_edge_child_selector {
1482 return if is_from_end {
1483 element.next_sibling_element()
1484 } else {
1485 element.prev_sibling_element()
1486 }
1487 .is_none()
1488 .into();
1489 }
1490
1491 let index = if let Some(i) = context
1493 .nth_index_cache(is_of_type, is_from_end, selectors)
1494 .lookup(element.opaque())
1495 {
1496 i
1497 } else {
1498 let i = nth_child_index(
1499 element,
1500 context,
1501 selectors,
1502 is_of_type,
1503 is_from_end,
1504 true,
1505 rightmost,
1506 );
1507 context
1508 .nth_index_cache(is_of_type, is_from_end, selectors)
1509 .insert(element.opaque(), i);
1510 i
1511 };
1512 debug_assert_eq!(
1513 index,
1514 nth_child_index(
1515 element,
1516 context,
1517 selectors,
1518 is_of_type,
1519 is_from_end,
1520 false,
1521 rightmost,
1522 ),
1523 "invalid cache"
1524 );
1525
1526 an_plus_b.matches_index(index).into()
1527}
1528
1529#[inline]
1530fn nth_child_index<E>(
1531 element: &E,
1532 context: &mut MatchingContext<E::Impl>,
1533 selectors: &[Selector<E::Impl>],
1534 is_of_type: bool,
1535 is_from_end: bool,
1536 check_cache: bool,
1537 rightmost: SubjectOrPseudoElement,
1538) -> i32
1539where
1540 E: Element,
1541{
1542 if check_cache
1549 && is_from_end
1550 && !context
1551 .nth_index_cache(is_of_type, is_from_end, selectors)
1552 .is_empty()
1553 {
1554 let mut index: i32 = 1;
1555 let mut curr = element.clone();
1556 while let Some(e) = curr.prev_sibling_element() {
1557 curr = e;
1558 let matches = if is_of_type {
1559 element.is_same_type(&curr)
1560 } else if !selectors.is_empty() {
1561 matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
1562 } else {
1563 true
1564 };
1565 if !matches {
1566 continue;
1567 }
1568 if let Some(i) = context
1569 .nth_index_cache(is_of_type, is_from_end, selectors)
1570 .lookup(curr.opaque())
1571 {
1572 return i - index;
1573 }
1574 index += 1;
1575 }
1576 }
1577
1578 let mut index: i32 = 1;
1579 let mut curr = element.clone();
1580 let next = |e: E| {
1581 if is_from_end {
1582 e.next_sibling_element()
1583 } else {
1584 e.prev_sibling_element()
1585 }
1586 };
1587 while let Some(e) = next(curr) {
1588 curr = e;
1589 let matches = if is_of_type {
1590 element.is_same_type(&curr)
1591 } else if !selectors.is_empty() {
1592 matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
1593 } else {
1594 true
1595 };
1596 if !matches {
1597 continue;
1598 }
1599 if !is_from_end && check_cache {
1603 if let Some(i) = context
1604 .nth_index_cache(is_of_type, is_from_end, selectors)
1605 .lookup(curr.opaque())
1606 {
1607 return i + index;
1608 }
1609 }
1610 index += 1;
1611 }
1612
1613 index
1614}