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)]
445pub fn 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
457 && !context.is_nested()
458 && rightmost == SubjectOrPseudoElement::Yes
459 {
460 match *iter.next().unwrap() {
462 Component::PseudoElement(ref pseudo) => {
463 if let Some(ref f) = context.pseudo_element_matching_fn {
464 if !f(pseudo) {
465 return KleeneValue::False;
466 }
467 }
468 },
469 ref other => {
470 debug_assert!(
471 false,
472 "Used MatchingMode::ForStatelessPseudoElement \
473 in a non-pseudo selector {:?}",
474 other
475 );
476 return KleeneValue::False;
477 },
478 }
479
480 if !iter.matches_for_stateless_pseudo_element() {
481 return KleeneValue::False;
482 }
483
484 let next_sequence = iter.next_sequence().unwrap();
486 debug_assert_eq!(next_sequence, Combinator::PseudoElement);
487 }
488
489 matches_complex_selector_internal(
490 iter,
491 element,
492 context,
493 rightmost,
494 SubjectOrPseudoElement::Yes,
495 )
496 .into()
497}
498
499fn matches_complex_selector_list<E: Element>(
501 list: &[Selector<E::Impl>],
502 element: &E,
503 context: &mut MatchingContext<E::Impl>,
504 rightmost: SubjectOrPseudoElement,
505) -> KleeneValue {
506 KleeneValue::any(list.iter(), |selector| {
507 matches_complex_selector(selector.iter(), element, context, rightmost)
508 })
509}
510
511fn matches_relative_selector<E: Element>(
512 relative_selector: &RelativeSelector<E::Impl>,
513 element: &E,
514 context: &mut MatchingContext<E::Impl>,
515 rightmost: SubjectOrPseudoElement,
516) -> bool {
517 if relative_selector.match_hint.is_descendant_direction() {
520 if context.needs_selector_flags() {
521 element.apply_selector_flags(
522 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
523 );
524 }
525 let mut next_element = element.first_element_child();
526 while let Some(el) = next_element {
527 if context.needs_selector_flags() {
528 el.apply_selector_flags(
529 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
530 );
531 }
532 let mut matched = matches_complex_selector(
533 relative_selector.selector.iter(),
534 &el,
535 context,
536 rightmost,
537 )
538 .to_bool(true);
539 if !matched && relative_selector.match_hint.is_subtree() {
540 matched = matches_relative_selector_subtree(
541 &relative_selector.selector,
542 &el,
543 context,
544 rightmost,
545 );
546 }
547 if matched {
548 return true;
549 }
550 next_element = el.next_sibling_element();
551 }
552 } else {
553 debug_assert!(
554 matches!(
555 relative_selector.match_hint,
556 RelativeSelectorMatchHint::InNextSibling
557 | RelativeSelectorMatchHint::InNextSiblingSubtree
558 | RelativeSelectorMatchHint::InSibling
559 | RelativeSelectorMatchHint::InSiblingSubtree
560 ),
561 "Not descendant direction, but also not sibling direction?"
562 );
563 if context.needs_selector_flags() {
564 element.apply_selector_flags(
565 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
566 );
567 }
568 let sibling_flag = if relative_selector.match_hint.is_subtree() {
569 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING
570 } else {
571 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
572 };
573 let mut next_element = element.next_sibling_element();
574 while let Some(el) = next_element {
575 if context.needs_selector_flags() {
576 el.apply_selector_flags(sibling_flag);
577 }
578 let matched = if relative_selector.match_hint.is_subtree() {
579 matches_relative_selector_subtree(
580 &relative_selector.selector,
581 &el,
582 context,
583 rightmost,
584 )
585 } else {
586 matches_complex_selector(relative_selector.selector.iter(), &el, context, rightmost)
587 .to_bool(true)
588 };
589 if matched {
590 return true;
591 }
592 if relative_selector.match_hint.is_next_sibling() {
593 break;
594 }
595 next_element = el.next_sibling_element();
596 }
597 }
598 return false;
599}
600
601fn relative_selector_match_early<E: Element>(
602 selector: &RelativeSelector<E::Impl>,
603 element: &E,
604 context: &mut MatchingContext<E::Impl>,
605) -> Option<bool> {
606 if let Some(cached) = context
608 .selector_caches
609 .relative_selector
610 .lookup(element.opaque(), selector)
611 {
612 return Some(cached.matched());
613 }
614 if context
616 .selector_caches
617 .relative_selector_filter_map
618 .fast_reject(element, selector, context.quirks_mode())
619 {
620 context.selector_caches.relative_selector.add(
622 element.opaque(),
623 selector,
624 RelativeSelectorCachedMatch::NotMatched,
625 );
626 return Some(false);
627 }
628 None
629}
630
631fn match_relative_selectors<E: Element>(
632 selectors: &[RelativeSelector<E::Impl>],
633 element: &E,
634 context: &mut MatchingContext<E::Impl>,
635 rightmost: SubjectOrPseudoElement,
636) -> KleeneValue {
637 if context.relative_selector_anchor().is_some() {
638 return KleeneValue::False;
644 }
645 if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
646 return if may_return_unknown {
650 KleeneValue::Unknown
651 } else {
652 KleeneValue::from(!context.in_negation())
653 };
654 }
655 context
656 .nest_for_relative_selector(element.opaque(), |context| {
657 do_match_relative_selectors(selectors, element, context, rightmost)
658 })
659 .into()
660}
661
662fn do_match_relative_selectors<E: Element>(
664 selectors: &[RelativeSelector<E::Impl>],
665 element: &E,
666 context: &mut MatchingContext<E::Impl>,
667 rightmost: SubjectOrPseudoElement,
668) -> bool {
669 if rightmost == SubjectOrPseudoElement::Yes {
673 if context.needs_selector_flags() {
674 element.apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR);
675 }
676 } else {
677 if context.needs_selector_flags() {
678 element
679 .apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT);
680 }
681 }
682
683 for relative_selector in selectors.iter() {
684 if let Some(result) = relative_selector_match_early(relative_selector, element, context) {
685 if result {
686 return true;
687 }
688 continue;
690 }
691
692 let matched = matches_relative_selector(relative_selector, element, context, rightmost);
693 context.selector_caches.relative_selector.add(
694 element.opaque(),
695 relative_selector,
696 if matched {
697 RelativeSelectorCachedMatch::Matched
698 } else {
699 RelativeSelectorCachedMatch::NotMatched
700 },
701 );
702 if matched {
703 return true;
704 }
705 }
706
707 false
708}
709
710fn matches_relative_selector_subtree<E: Element>(
711 selector: &Selector<E::Impl>,
712 element: &E,
713 context: &mut MatchingContext<E::Impl>,
714 rightmost: SubjectOrPseudoElement,
715) -> bool {
716 let mut current = element.first_element_child();
717
718 while let Some(el) = current {
719 if context.needs_selector_flags() {
720 el.apply_selector_flags(
721 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
722 );
723 }
724 if matches_complex_selector(selector.iter(), &el, context, rightmost).to_bool(true) {
725 return true;
726 }
727
728 if matches_relative_selector_subtree(selector, &el, context, rightmost) {
729 return true;
730 }
731
732 current = el.next_sibling_element();
733 }
734
735 false
736}
737
738fn hover_and_active_quirk_applies<Impl: SelectorImpl>(
742 selector_iter: &SelectorIter<Impl>,
743 context: &MatchingContext<Impl>,
744 rightmost: SubjectOrPseudoElement,
745) -> bool {
746 debug_assert_eq!(context.quirks_mode(), QuirksMode::Quirks);
747
748 if context.is_nested() {
749 return false;
750 }
751
752 if rightmost == SubjectOrPseudoElement::Yes
755 && context.matching_mode() == MatchingMode::ForStatelessPseudoElement
756 {
757 return false;
758 }
759
760 selector_iter.clone().all(|simple| match *simple {
761 Component::NonTSPseudoClass(ref pseudo_class) => pseudo_class.is_active_or_hover(),
762 _ => false,
763 })
764}
765
766#[derive(Clone, Copy, PartialEq)]
768pub enum SubjectOrPseudoElement {
769 Yes,
770 No,
771}
772
773fn host_for_part<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
774where
775 E: Element,
776{
777 let scope = context.current_host;
778 let mut curr = element.containing_shadow_host()?;
779 if scope == Some(curr.opaque()) {
780 return Some(curr);
781 }
782 loop {
783 let parent = curr.containing_shadow_host();
784 if parent.as_ref().map(|h| h.opaque()) == scope {
785 return Some(curr);
786 }
787 curr = parent?;
788 }
789}
790
791fn assigned_slot<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
792where
793 E: Element,
794{
795 debug_assert!(element
796 .assigned_slot()
797 .map_or(true, |s| s.is_html_slot_element()));
798 let scope = context.current_host?;
799 let mut current_slot = element.assigned_slot()?;
800 while current_slot.containing_shadow_host().unwrap().opaque() != scope {
801 current_slot = current_slot.assigned_slot()?;
802 }
803 Some(current_slot)
804}
805
806struct NextElement<E> {
807 next_element: Option<E>,
808 featureless: bool,
809}
810
811impl<E> NextElement<E> {
812 #[inline(always)]
813 fn new(next_element: Option<E>, featureless: bool) -> Self {
814 Self {
815 next_element,
816 featureless,
817 }
818 }
819}
820
821#[inline(always)]
822fn next_element_for_combinator<E>(
823 element: &E,
824 combinator: Combinator,
825 context: &MatchingContext<E::Impl>,
826) -> NextElement<E>
827where
828 E: Element,
829{
830 match combinator {
831 Combinator::NextSibling | Combinator::LaterSibling => {
832 NextElement::new(element.prev_sibling_element(), false)
833 },
834 Combinator::Child | Combinator::Descendant => {
835 if let Some(parent) = element.parent_element() {
836 return NextElement::new(Some(parent), false);
837 }
838
839 let element = if element.parent_node_is_shadow_root() {
840 element.containing_shadow_host()
841 } else {
842 None
843 };
844 NextElement::new(element, true)
845 },
846 Combinator::Part => NextElement::new(host_for_part(element, context), false),
847 Combinator::SlotAssignment => NextElement::new(assigned_slot(element, context), false),
848 Combinator::PseudoElement => {
849 NextElement::new(element.pseudo_element_originating_element(), false)
850 },
851 }
852}
853
854fn matches_complex_selector_internal<E>(
855 mut selector_iter: SelectorIter<E::Impl>,
856 element: &E,
857 context: &mut MatchingContext<E::Impl>,
858 mut rightmost: SubjectOrPseudoElement,
859 mut first_subject_compound: SubjectOrPseudoElement,
860) -> SelectorMatchingResult
861where
862 E: Element,
863{
864 debug!(
865 "Matching complex selector {:?} for {:?}",
866 selector_iter, element
867 );
868
869 let matches_compound_selector =
870 matches_compound_selector(&mut selector_iter, element, context, rightmost);
871
872 let Some(combinator) = selector_iter.next_sequence() else {
873 return match matches_compound_selector {
874 KleeneValue::True => SelectorMatchingResult::Matched,
875 KleeneValue::Unknown => SelectorMatchingResult::Unknown,
876 KleeneValue::False => {
877 SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling
878 },
879 };
880 };
881
882 let is_pseudo_combinator = combinator.is_pseudo_element();
883 if context.featureless() && !is_pseudo_combinator {
884 return SelectorMatchingResult::NotMatchedGlobally;
887 }
888
889 let is_sibling_combinator = combinator.is_sibling();
890 if is_sibling_combinator && context.needs_selector_flags() {
891 element.apply_selector_flags(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS);
893 }
894
895 if matches_compound_selector == KleeneValue::False {
896 return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
899 }
900
901 if !is_pseudo_combinator {
902 rightmost = SubjectOrPseudoElement::No;
903 first_subject_compound = SubjectOrPseudoElement::No;
904 }
905
906 let mut visited_handling = if is_sibling_combinator {
909 VisitedHandlingMode::AllLinksUnvisited
910 } else {
911 context.visited_handling()
912 };
913
914 let candidate_not_found = if is_sibling_combinator {
915 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
916 } else {
917 SelectorMatchingResult::NotMatchedGlobally
918 };
919
920 let mut element = element.clone();
921 loop {
922 if element.is_link() {
923 visited_handling = VisitedHandlingMode::AllLinksUnvisited;
924 }
925
926 let NextElement {
927 next_element,
928 featureless,
929 } = next_element_for_combinator(&element, combinator, &context);
930 element = match next_element {
931 None => return candidate_not_found,
932 Some(e) => e,
933 };
934
935 let result = context.with_visited_handling_mode(visited_handling, |context| {
936 context.with_featureless(featureless, |context| {
937 matches_complex_selector_internal(
938 selector_iter.clone(),
939 &element,
940 context,
941 rightmost,
942 first_subject_compound,
943 )
944 })
945 });
946
947 match result {
949 SelectorMatchingResult::Matched => {
950 debug_assert!(
951 matches_compound_selector.to_bool(true),
952 "Compound didn't match?"
953 );
954 if !matches_compound_selector.to_bool(false) {
955 return SelectorMatchingResult::Unknown;
956 }
957 return result;
958 },
959 SelectorMatchingResult::Unknown | SelectorMatchingResult::NotMatchedGlobally => {
960 return result
961 },
962 _ => {},
963 }
964
965 match combinator {
966 Combinator::Descendant => {
967 },
973 Combinator::Child => {
974 return SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant;
976 },
977 Combinator::LaterSibling => {
978 if matches!(
982 result,
983 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
984 ) {
985 return result;
986 }
987 },
988 Combinator::NextSibling
989 | Combinator::PseudoElement
990 | Combinator::Part
991 | Combinator::SlotAssignment => {
992 return result;
997 },
998 }
999
1000 if featureless {
1001 return candidate_not_found;
1004 }
1005 }
1006}
1007
1008#[inline]
1009fn matches_local_name<E>(element: &E, local_name: &LocalName<E::Impl>) -> bool
1010where
1011 E: Element,
1012{
1013 let name = select_name(element, &local_name.name, &local_name.lower_name).borrow();
1014 element.has_local_name(name)
1015}
1016
1017fn matches_part<E>(
1018 element: &E,
1019 parts: &[<E::Impl as SelectorImpl>::Identifier],
1020 context: &mut MatchingContext<E::Impl>,
1021) -> bool
1022where
1023 E: Element,
1024{
1025 let mut hosts = SmallVec::<[E; 4]>::new();
1026
1027 let mut host = match element.containing_shadow_host() {
1028 Some(h) => h,
1029 None => return false,
1030 };
1031
1032 let current_host = context.current_host;
1033 if current_host != Some(host.opaque()) {
1034 loop {
1035 let outer_host = host.containing_shadow_host();
1036 if outer_host.as_ref().map(|h| h.opaque()) == current_host {
1037 break;
1038 }
1039 let outer_host = match outer_host {
1040 Some(h) => h,
1041 None => return false,
1042 };
1043 hosts.push(host);
1046 host = outer_host;
1047 }
1048 }
1049
1050 parts.iter().all(|part| {
1052 let mut part = part.clone();
1053 for host in hosts.iter().rev() {
1054 part = match host.imported_part(&part) {
1055 Some(p) => p,
1056 None => return false,
1057 };
1058 }
1059 element.is_part(&part)
1060 })
1061}
1062
1063fn matches_host<E>(
1064 element: &E,
1065 selector: Option<&Selector<E::Impl>>,
1066 context: &mut MatchingContext<E::Impl>,
1067 rightmost: SubjectOrPseudoElement,
1068) -> KleeneValue
1069where
1070 E: Element,
1071{
1072 let host = match context.shadow_host() {
1073 Some(h) => h,
1074 None => return KleeneValue::False,
1075 };
1076 if host != element.opaque() {
1077 return KleeneValue::False;
1078 }
1079 let Some(selector) = selector else {
1080 return KleeneValue::True;
1081 };
1082 context.nest(|context| {
1083 context.with_featureless(false, |context| {
1084 matches_complex_selector(selector.iter(), element, context, rightmost)
1085 })
1086 })
1087}
1088
1089fn matches_slotted<E>(
1090 element: &E,
1091 selector: &Selector<E::Impl>,
1092 context: &mut MatchingContext<E::Impl>,
1093 rightmost: SubjectOrPseudoElement,
1094) -> KleeneValue
1095where
1096 E: Element,
1097{
1098 if element.is_html_slot_element() {
1100 return KleeneValue::False;
1101 }
1102 context.nest(|context| matches_complex_selector(selector.iter(), element, context, rightmost))
1103}
1104
1105fn matches_rare_attribute_selector<E>(
1106 element: &E,
1107 attr_sel: &AttrSelectorWithOptionalNamespace<E::Impl>,
1108) -> bool
1109where
1110 E: Element,
1111{
1112 let empty_string;
1113 let namespace = match attr_sel.namespace() {
1114 Some(ns) => ns,
1115 None => {
1116 empty_string = crate::parser::namespace_empty_string::<E::Impl>();
1117 NamespaceConstraint::Specific(&empty_string)
1118 },
1119 };
1120 element.attr_matches(
1121 &namespace,
1122 select_name(element, &attr_sel.local_name, &attr_sel.local_name_lower),
1123 &match attr_sel.operation {
1124 ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
1125 ParsedAttrSelectorOperation::WithValue {
1126 operator,
1127 case_sensitivity,
1128 ref value,
1129 } => AttrSelectorOperation::WithValue {
1130 operator,
1131 case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
1132 value,
1133 },
1134 },
1135 )
1136}
1137
1138pub(crate) fn compound_matches_featureless_host<Impl: SelectorImpl>(
1142 iter: &mut SelectorIter<Impl>,
1143 scope_matches_featureless_host: bool,
1144) -> MatchesFeaturelessHost {
1145 let mut matches = MatchesFeaturelessHost::Only;
1146 for component in iter {
1147 match component {
1148 Component::Scope | Component::ImplicitScope if scope_matches_featureless_host => {},
1149 Component::Host(..) => {},
1151 Component::PseudoElement(..) => {},
1153 Component::Is(l) | Component::Where(l) => {
1156 let mut any_yes = false;
1157 let mut any_no = false;
1158 for selector in l.slice() {
1159 match selector.matches_featureless_host(scope_matches_featureless_host) {
1160 MatchesFeaturelessHost::Never => {
1161 any_no = true;
1162 },
1163 MatchesFeaturelessHost::Yes => {
1164 any_yes = true;
1165 any_no = true;
1166 },
1167 MatchesFeaturelessHost::Only => {
1168 any_yes = true;
1169 },
1170 }
1171 }
1172 if !any_yes {
1173 return MatchesFeaturelessHost::Never;
1174 }
1175 if any_no {
1176 matches = MatchesFeaturelessHost::Yes;
1178 }
1179 },
1180 Component::Negation(l) => {
1181 for selector in l.slice() {
1185 if selector.matches_featureless_host(scope_matches_featureless_host)
1186 != MatchesFeaturelessHost::Only
1187 {
1188 return MatchesFeaturelessHost::Never;
1189 }
1190 }
1191 },
1192 _ => return MatchesFeaturelessHost::Never,
1194 }
1195 }
1196 matches
1197}
1198
1199#[inline]
1201fn matches_compound_selector<E>(
1202 selector_iter: &mut SelectorIter<E::Impl>,
1203 element: &E,
1204 context: &mut MatchingContext<E::Impl>,
1205 rightmost: SubjectOrPseudoElement,
1206) -> KleeneValue
1207where
1208 E: Element,
1209{
1210 if context.featureless()
1211 && compound_matches_featureless_host(
1212 &mut selector_iter.clone(),
1213 true,
1214 ) == MatchesFeaturelessHost::Never
1215 {
1216 return KleeneValue::False;
1217 }
1218 let quirks_data = if context.quirks_mode() == QuirksMode::Quirks {
1219 Some(selector_iter.clone())
1220 } else {
1221 None
1222 };
1223 let mut local_context = LocalMatchingContext {
1224 shared: context,
1225 rightmost,
1226 quirks_data,
1227 };
1228 KleeneValue::any_false(selector_iter, |simple| {
1229 matches_simple_selector(simple, element, &mut local_context)
1230 })
1231}
1232
1233fn matches_simple_selector<E>(
1235 selector: &Component<E::Impl>,
1236 element: &E,
1237 context: &mut LocalMatchingContext<E::Impl>,
1238) -> KleeneValue
1239where
1240 E: Element,
1241{
1242 debug_assert!(context.shared.is_nested() || !context.shared.in_negation());
1243 let rightmost = context.rightmost;
1244 KleeneValue::from(match *selector {
1245 Component::ID(ref id) => {
1246 element.has_id(id, context.shared.classes_and_ids_case_sensitivity())
1247 },
1248 Component::Class(ref class) => {
1249 element.has_class(class, context.shared.classes_and_ids_case_sensitivity())
1250 },
1251 Component::LocalName(ref local_name) => matches_local_name(element, local_name),
1252 Component::AttributeInNoNamespaceExists {
1253 ref local_name,
1254 ref local_name_lower,
1255 } => element.has_attr_in_no_namespace(select_name(element, local_name, local_name_lower)),
1256 Component::AttributeInNoNamespace {
1257 ref local_name,
1258 ref value,
1259 operator,
1260 case_sensitivity,
1261 } => element.attr_matches(
1262 &NamespaceConstraint::Specific(&crate::parser::namespace_empty_string::<E::Impl>()),
1263 local_name,
1264 &AttrSelectorOperation::WithValue {
1265 operator,
1266 case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
1267 value,
1268 },
1269 ),
1270 Component::AttributeOther(ref attr_sel) => {
1271 matches_rare_attribute_selector(element, attr_sel)
1272 },
1273 Component::Part(ref parts) => matches_part(element, parts, &mut context.shared),
1274 Component::Slotted(ref selector) => {
1275 return matches_slotted(element, selector, &mut context.shared, rightmost);
1276 },
1277 Component::PseudoElement(ref pseudo) => {
1278 element.match_pseudo_element(pseudo, context.shared)
1279 },
1280 Component::ExplicitUniversalType | Component::ExplicitAnyNamespace => true,
1281 Component::Namespace(_, ref url) | Component::DefaultNamespace(ref url) => {
1282 element.has_namespace(&url.borrow())
1283 },
1284 Component::ExplicitNoNamespace => {
1285 let ns = crate::parser::namespace_empty_string::<E::Impl>();
1286 element.has_namespace(&ns.borrow())
1287 },
1288 Component::NonTSPseudoClass(ref pc) => {
1289 if let Some(ref iter) = context.quirks_data {
1290 if pc.is_active_or_hover()
1291 && !element.is_link()
1292 && hover_and_active_quirk_applies(iter, context.shared, context.rightmost)
1293 {
1294 return KleeneValue::False;
1295 }
1296 }
1297 element.match_non_ts_pseudo_class(pc, &mut context.shared)
1298 },
1299 Component::Root => element.is_root(),
1300 Component::Empty => {
1301 if context.shared.needs_selector_flags() {
1302 element.apply_selector_flags(ElementSelectorFlags::HAS_EMPTY_SELECTOR);
1303 }
1304 element.is_empty()
1305 },
1306 Component::Host(ref selector) => {
1307 return matches_host(element, selector.as_ref(), &mut context.shared, rightmost);
1308 },
1309 Component::ParentSelector => match context.shared.scope_element {
1310 Some(ref scope_element) => element.opaque() == *scope_element,
1311 None => element.is_root(),
1312 },
1313 Component::Scope | Component::ImplicitScope => {
1314 let matching_for_invalidation = context.shared.matching_for_invalidation_comparison();
1315 if context.shared.matching_for_revalidation() || matching_for_invalidation.is_some() {
1316 let may_return_unknown = matching_for_invalidation.unwrap_or(false);
1317 return if may_return_unknown {
1318 KleeneValue::Unknown
1319 } else {
1320 KleeneValue::from(!context.shared.in_negation())
1321 };
1322 }
1323 match context.shared.scope_element {
1324 Some(ref scope_element) => element.opaque() == *scope_element,
1325 None => element.is_root(),
1326 }
1327 },
1328 Component::Nth(ref nth_data) => {
1329 return matches_generic_nth_child(element, context.shared, nth_data, &[], rightmost);
1330 },
1331 Component::NthOf(ref nth_of_data) => {
1332 return context.shared.nest(|context| {
1333 matches_generic_nth_child(
1334 element,
1335 context,
1336 nth_of_data.nth_data(),
1337 nth_of_data.selectors(),
1338 rightmost,
1339 )
1340 })
1341 },
1342 Component::Is(ref list) | Component::Where(ref list) => {
1343 return context.shared.nest(|context| {
1344 matches_complex_selector_list(list.slice(), element, context, rightmost)
1345 })
1346 },
1347 Component::Negation(ref list) => {
1348 return context.shared.nest_for_negation(|context| {
1349 !matches_complex_selector_list(list.slice(), element, context, rightmost)
1350 })
1351 },
1352 Component::Has(ref relative_selectors) => {
1353 return match_relative_selectors(
1354 relative_selectors,
1355 element,
1356 context.shared,
1357 rightmost,
1358 );
1359 },
1360 Component::Combinator(_) => unsafe {
1361 debug_unreachable!("Shouldn't try to selector-match combinators")
1362 },
1363 Component::RelativeSelectorAnchor => {
1364 let anchor = context.shared.relative_selector_anchor();
1365 anchor.map_or(true, |a| a == element.opaque())
1367 },
1368 Component::Invalid(..) => false,
1369 })
1370}
1371
1372#[inline(always)]
1373pub fn select_name<'a, E: Element, T: PartialEq>(
1374 element: &E,
1375 local_name: &'a T,
1376 local_name_lower: &'a T,
1377) -> &'a T {
1378 if local_name == local_name_lower || element.is_html_element_in_html_document() {
1379 local_name_lower
1380 } else {
1381 local_name
1382 }
1383}
1384
1385#[inline(always)]
1386pub fn to_unconditional_case_sensitivity<'a, E: Element>(
1387 parsed: ParsedCaseSensitivity,
1388 element: &E,
1389) -> CaseSensitivity {
1390 match parsed {
1391 ParsedCaseSensitivity::CaseSensitive | ParsedCaseSensitivity::ExplicitCaseSensitive => {
1392 CaseSensitivity::CaseSensitive
1393 },
1394 ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
1395 ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
1396 if element.is_html_element_in_html_document() {
1397 CaseSensitivity::AsciiCaseInsensitive
1398 } else {
1399 CaseSensitivity::CaseSensitive
1400 }
1401 },
1402 }
1403}
1404
1405fn matches_generic_nth_child<E>(
1406 element: &E,
1407 context: &mut MatchingContext<E::Impl>,
1408 nth_data: &NthSelectorData,
1409 selectors: &[Selector<E::Impl>],
1410 rightmost: SubjectOrPseudoElement,
1411) -> KleeneValue
1412where
1413 E: Element,
1414{
1415 if element.ignores_nth_child_selectors() {
1416 return KleeneValue::False;
1417 }
1418 let has_selectors = !selectors.is_empty();
1419 let selectors_match = !has_selectors
1420 || matches_complex_selector_list(selectors, element, context, rightmost).to_bool(true);
1421 if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
1422 return if selectors_match && may_return_unknown {
1424 KleeneValue::Unknown
1425 } else {
1426 KleeneValue::from(selectors_match && !context.in_negation())
1427 };
1428 }
1429
1430 let NthSelectorData { ty, an_plus_b, .. } = *nth_data;
1431 let is_of_type = ty.is_of_type();
1432 if ty.is_only() {
1433 debug_assert!(
1434 !has_selectors,
1435 ":only-child and :only-of-type cannot have a selector list!"
1436 );
1437 return KleeneValue::from(
1438 matches_generic_nth_child(
1439 element,
1440 context,
1441 &NthSelectorData::first(is_of_type),
1442 selectors,
1443 rightmost,
1444 )
1445 .to_bool(true)
1446 && matches_generic_nth_child(
1447 element,
1448 context,
1449 &NthSelectorData::last(is_of_type),
1450 selectors,
1451 rightmost,
1452 )
1453 .to_bool(true),
1454 );
1455 }
1456
1457 let is_from_end = ty.is_from_end();
1458
1459 let is_edge_child_selector = nth_data.is_simple_edge() && !has_selectors;
1462
1463 if context.needs_selector_flags() {
1464 let mut flags = if is_edge_child_selector {
1465 ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR
1466 } else if is_from_end {
1467 ElementSelectorFlags::HAS_SLOW_SELECTOR
1468 } else {
1469 ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS
1470 };
1471 if has_selectors {
1472 flags |= ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF;
1473 } else if !is_edge_child_selector {
1474 flags |= ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH;
1475 }
1476 element.apply_selector_flags(flags);
1477 }
1478
1479 if !selectors_match {
1480 return KleeneValue::False;
1481 }
1482
1483 if is_edge_child_selector {
1486 return if is_from_end {
1487 element.next_sibling_element()
1488 } else {
1489 element.prev_sibling_element()
1490 }
1491 .is_none()
1492 .into();
1493 }
1494
1495 let index = if let Some(i) = context
1497 .nth_index_cache(is_of_type, is_from_end, selectors)
1498 .lookup(element.opaque())
1499 {
1500 i
1501 } else {
1502 let i = nth_child_index(
1503 element,
1504 context,
1505 selectors,
1506 is_of_type,
1507 is_from_end,
1508 true,
1509 rightmost,
1510 );
1511 context
1512 .nth_index_cache(is_of_type, is_from_end, selectors)
1513 .insert(element.opaque(), i);
1514 i
1515 };
1516 debug_assert_eq!(
1517 index,
1518 nth_child_index(
1519 element,
1520 context,
1521 selectors,
1522 is_of_type,
1523 is_from_end,
1524 false,
1525 rightmost,
1526 ),
1527 "invalid cache"
1528 );
1529
1530 an_plus_b.matches_index(index).into()
1531}
1532
1533#[inline]
1534fn nth_child_index<E>(
1535 element: &E,
1536 context: &mut MatchingContext<E::Impl>,
1537 selectors: &[Selector<E::Impl>],
1538 is_of_type: bool,
1539 is_from_end: bool,
1540 check_cache: bool,
1541 rightmost: SubjectOrPseudoElement,
1542) -> i32
1543where
1544 E: Element,
1545{
1546 if check_cache
1553 && is_from_end
1554 && !context
1555 .nth_index_cache(is_of_type, is_from_end, selectors)
1556 .is_empty()
1557 {
1558 let mut index: i32 = 1;
1559 let mut curr = element.clone();
1560 while let Some(e) = curr.prev_sibling_element() {
1561 curr = e;
1562 let matches = if is_of_type {
1563 element.is_same_type(&curr)
1564 } else if !selectors.is_empty() {
1565 matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
1566 } else {
1567 true
1568 };
1569 if !matches {
1570 continue;
1571 }
1572 if let Some(i) = context
1573 .nth_index_cache(is_of_type, is_from_end, selectors)
1574 .lookup(curr.opaque())
1575 {
1576 return i - index;
1577 }
1578 index += 1;
1579 }
1580 }
1581
1582 let mut index: i32 = 1;
1583 let mut curr = element.clone();
1584 let next = |e: E| {
1585 if is_from_end {
1586 e.next_sibling_element()
1587 } else {
1588 e.prev_sibling_element()
1589 }
1590 };
1591 while let Some(e) = next(curr) {
1592 curr = e;
1593 let matches = if is_of_type {
1594 element.is_same_type(&curr)
1595 } else if !selectors.is_empty() {
1596 matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
1597 } else {
1598 true
1599 };
1600 if !matches {
1601 continue;
1602 }
1603 if !is_from_end && check_cache {
1607 if let Some(i) = context
1608 .nth_index_cache(is_of_type, is_from_end, selectors)
1609 .lookup(curr.opaque())
1610 {
1611 return i + index;
1612 }
1613 }
1614 index += 1;
1615 }
1616
1617 index
1618}