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, FeaturelessHostMatches, LocalName, 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 log::debug;
21use smallvec::SmallVec;
22use std::borrow::Borrow;
23use bitflags::bitflags;
24use debug_unreachable::debug_unreachable;
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}
89
90impl ElementSelectorFlags {
91 pub fn for_self(self) -> ElementSelectorFlags {
93 self & (ElementSelectorFlags::HAS_EMPTY_SELECTOR |
94 ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR |
95 ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT |
96 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING |
97 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR)
98 }
99
100 pub fn for_parent(self) -> ElementSelectorFlags {
102 self & (ElementSelectorFlags::HAS_SLOW_SELECTOR |
103 ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS |
104 ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH |
105 ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF |
106 ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR)
107 }
108}
109
110struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
112 shared: &'a mut MatchingContext<'b, Impl>,
113 rightmost: SubjectOrPseudoElement,
114 quirks_data: Option<SelectorIter<'a, Impl>>,
115}
116
117#[inline(always)]
118pub fn matches_selector_list<E>(
119 selector_list: &SelectorList<E::Impl>,
120 element: &E,
121 context: &mut MatchingContext<E::Impl>,
122) -> bool
123where
124 E: Element,
125{
126 for selector in selector_list.slice() {
129 let matches = matches_selector(selector, 0, None, element, context);
130 if matches {
131 return true;
132 }
133 }
134
135 false
136}
137
138#[inline(always)]
141pub fn selector_may_match(hashes: &AncestorHashes, bf: &BloomFilter) -> bool {
142 for i in 0..3 {
150 let packed = hashes.packed_hashes[i];
151 if packed == 0 {
152 return true;
154 }
155
156 if !bf.might_contain_hash(packed & BLOOM_HASH_MASK) {
157 return false;
159 }
160 }
161
162 let fourth = hashes.fourth_hash();
165 fourth == 0 || bf.might_contain_hash(fourth)
166}
167
168#[derive(Clone, Copy, Eq, PartialEq)]
225enum SelectorMatchingResult {
226 Matched,
227 NotMatchedAndRestartFromClosestLaterSibling,
228 NotMatchedAndRestartFromClosestDescendant,
229 NotMatchedGlobally,
230 Unknown,
231}
232
233impl From<SelectorMatchingResult> for KleeneValue {
234 fn from(value: SelectorMatchingResult) -> Self {
235 match value {
236 SelectorMatchingResult::Matched => KleeneValue::True,
237 SelectorMatchingResult::Unknown => KleeneValue::Unknown,
238 SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling |
239 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant |
240 SelectorMatchingResult::NotMatchedGlobally => KleeneValue::False,
241 }
242 }
243}
244
245#[inline(always)]
254pub fn matches_selector<E>(
255 selector: &Selector<E::Impl>,
256 offset: usize,
257 hashes: Option<&AncestorHashes>,
258 element: &E,
259 context: &mut MatchingContext<E::Impl>,
260) -> bool
261where
262 E: Element,
263{
264 let result = matches_selector_kleene(selector, offset, hashes, element, context);
265 if cfg!(debug_assertions) && result == KleeneValue::Unknown {
266 debug_assert!(
267 context.matching_for_invalidation_comparison().unwrap_or(false),
268 "How did we return unknown?"
269 );
270 }
271 result.to_bool(true)
272}
273
274#[inline(always)]
276pub fn matches_selector_kleene<E>(
277 selector: &Selector<E::Impl>,
278 offset: usize,
279 hashes: Option<&AncestorHashes>,
280 element: &E,
281 context: &mut MatchingContext<E::Impl>,
282) -> KleeneValue
283where
284 E: Element,
285{
286 if let Some(hashes) = hashes {
288 if let Some(filter) = context.bloom_filter {
289 if !selector_may_match(hashes, filter) {
290 return KleeneValue::False;
291 }
292 }
293 }
294 matches_complex_selector(
295 selector.iter_from(offset),
296 element,
297 context,
298 if selector.is_rightmost(offset) {
299 SubjectOrPseudoElement::Yes
300 } else {
301 SubjectOrPseudoElement::No
302 },
303 )
304}
305
306pub enum CompoundSelectorMatchingResult {
309 FullyMatched,
311 Matched { next_combinator_offset: usize },
314 NotMatched,
316}
317
318pub fn matches_compound_selector_from<E>(
326 selector: &Selector<E::Impl>,
327 mut from_offset: usize,
328 context: &mut MatchingContext<E::Impl>,
329 element: &E,
330) -> CompoundSelectorMatchingResult
331where
332 E: Element,
333{
334 debug_assert!(
335 !context
336 .matching_for_invalidation_comparison()
337 .unwrap_or(false),
338 "CompoundSelectorMatchingResult doesn't support unknown"
339 );
340 if cfg!(debug_assertions) && from_offset != 0 {
341 selector.combinator_at_parse_order(from_offset - 1); }
343
344 let mut local_context = LocalMatchingContext {
345 shared: context,
346 rightmost: SubjectOrPseudoElement::No,
350 quirks_data: None,
351 };
352
353 let start_offset = from_offset;
357 for component in selector.iter_raw_parse_order_from(from_offset) {
358 if matches!(*component, Component::Combinator(..)) {
359 debug_assert_ne!(from_offset, 0, "Selector started with a combinator?");
360 break;
361 }
362
363 from_offset += 1;
364 }
365
366 debug_assert!(from_offset >= 1);
367 debug_assert!(from_offset <= selector.len());
368
369 let iter = selector.iter_from(selector.len() - from_offset);
370 debug_assert!(
371 iter.clone().next().is_some() || from_offset != selector.len(),
372 "Got the math wrong: {:?} | {:?} | {} {}",
373 selector,
374 selector.iter_raw_match_order().as_slice(),
375 from_offset,
376 start_offset
377 );
378
379 for component in iter {
380 let result = matches_simple_selector(component, element, &mut local_context);
381 debug_assert!(result != KleeneValue::Unknown, "Returned unknown in non invalidation context?");
382 if !result.to_bool(true) {
383 return CompoundSelectorMatchingResult::NotMatched;
384 }
385 }
386
387 if from_offset != selector.len() {
388 return CompoundSelectorMatchingResult::Matched {
389 next_combinator_offset: from_offset,
390 };
391 }
392
393 CompoundSelectorMatchingResult::FullyMatched
394}
395
396#[inline(always)]
398fn matches_complex_selector<E>(
399 mut iter: SelectorIter<E::Impl>,
400 element: &E,
401 context: &mut MatchingContext<E::Impl>,
402 rightmost: SubjectOrPseudoElement,
403) -> KleeneValue
404where
405 E: Element,
406{
407 if context.matching_mode() == MatchingMode::ForStatelessPseudoElement && !context.is_nested() {
410 match *iter.next().unwrap() {
412 Component::PseudoElement(ref pseudo) => {
413 if let Some(ref f) = context.pseudo_element_matching_fn {
414 if !f(pseudo) {
415 return KleeneValue::False;
416 }
417 }
418 },
419 ref other => {
420 debug_assert!(
421 false,
422 "Used MatchingMode::ForStatelessPseudoElement \
423 in a non-pseudo selector {:?}",
424 other
425 );
426 return KleeneValue::False;
427 },
428 }
429
430 if !iter.matches_for_stateless_pseudo_element() {
431 return KleeneValue::False;
432 }
433
434 let next_sequence = iter.next_sequence().unwrap();
436 debug_assert_eq!(next_sequence, Combinator::PseudoElement);
437 }
438
439 matches_complex_selector_internal(
440 iter,
441 element,
442 context,
443 rightmost,
444 SubjectOrPseudoElement::Yes,
445 )
446 .into()
447}
448
449fn matches_complex_selector_list<E: Element>(
451 list: &[Selector<E::Impl>],
452 element: &E,
453 context: &mut MatchingContext<E::Impl>,
454 rightmost: SubjectOrPseudoElement,
455) -> KleeneValue {
456 KleeneValue::any(
457 list.iter(),
458 |selector| matches_complex_selector(
459 selector.iter(),
460 element,
461 context,
462 rightmost
463 )
464 )
465}
466
467fn matches_relative_selector<E: Element>(
468 relative_selector: &RelativeSelector<E::Impl>,
469 element: &E,
470 context: &mut MatchingContext<E::Impl>,
471 rightmost: SubjectOrPseudoElement,
472) -> bool {
473 if relative_selector.match_hint.is_descendant_direction() {
476 if context.needs_selector_flags() {
477 element.apply_selector_flags(
478 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
479 );
480 }
481 let mut next_element = element.first_element_child();
482 while let Some(el) = next_element {
483 if context.needs_selector_flags() {
484 el.apply_selector_flags(
485 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
486 );
487 }
488 let mut matched = matches_complex_selector(
489 relative_selector.selector.iter(),
490 &el,
491 context,
492 rightmost,
493 )
494 .to_bool(true);
495 if !matched && relative_selector.match_hint.is_subtree() {
496 matched = matches_relative_selector_subtree(
497 &relative_selector.selector,
498 &el,
499 context,
500 rightmost,
501 );
502 }
503 if matched {
504 return true;
505 }
506 next_element = el.next_sibling_element();
507 }
508 } else {
509 debug_assert!(
510 matches!(
511 relative_selector.match_hint,
512 RelativeSelectorMatchHint::InNextSibling |
513 RelativeSelectorMatchHint::InNextSiblingSubtree |
514 RelativeSelectorMatchHint::InSibling |
515 RelativeSelectorMatchHint::InSiblingSubtree
516 ),
517 "Not descendant direction, but also not sibling direction?"
518 );
519 if context.needs_selector_flags() {
520 element.apply_selector_flags(
521 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
522 );
523 }
524 let sibling_flag = if relative_selector.match_hint.is_subtree() {
525 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING
526 } else {
527 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
528 };
529 let mut next_element = element.next_sibling_element();
530 while let Some(el) = next_element {
531 if context.needs_selector_flags() {
532 el.apply_selector_flags(sibling_flag);
533 }
534 let matched = if relative_selector.match_hint.is_subtree() {
535 matches_relative_selector_subtree(
536 &relative_selector.selector,
537 &el,
538 context,
539 rightmost,
540 )
541 } else {
542 matches_complex_selector(relative_selector.selector.iter(), &el, context, rightmost)
543 .to_bool(true)
544 };
545 if matched {
546 return true;
547 }
548 if relative_selector.match_hint.is_next_sibling() {
549 break;
550 }
551 next_element = el.next_sibling_element();
552 }
553 }
554 return false;
555}
556
557fn relative_selector_match_early<E: Element>(
558 selector: &RelativeSelector<E::Impl>,
559 element: &E,
560 context: &mut MatchingContext<E::Impl>,
561) -> Option<bool> {
562 if let Some(cached) = context
564 .selector_caches
565 .relative_selector
566 .lookup(element.opaque(), selector)
567 {
568 return Some(cached.matched());
569 }
570 if context
572 .selector_caches
573 .relative_selector_filter_map
574 .fast_reject(element, selector, context.quirks_mode())
575 {
576 context.selector_caches.relative_selector.add(
578 element.opaque(),
579 selector,
580 RelativeSelectorCachedMatch::NotMatched,
581 );
582 return Some(false);
583 }
584 None
585}
586
587fn match_relative_selectors<E: Element>(
588 selectors: &[RelativeSelector<E::Impl>],
589 element: &E,
590 context: &mut MatchingContext<E::Impl>,
591 rightmost: SubjectOrPseudoElement,
592) -> KleeneValue {
593 if context.relative_selector_anchor().is_some() {
594 return KleeneValue::False;
600 }
601 if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
602 return if may_return_unknown {
606 KleeneValue::Unknown
607 } else {
608 KleeneValue::from(!context.in_negation())
609 };
610 }
611 context.nest_for_relative_selector(element.opaque(), |context| {
612 do_match_relative_selectors(selectors, element, context, rightmost)
613 }).into()
614}
615
616fn do_match_relative_selectors<E: Element>(
618 selectors: &[RelativeSelector<E::Impl>],
619 element: &E,
620 context: &mut MatchingContext<E::Impl>,
621 rightmost: SubjectOrPseudoElement,
622) -> bool {
623 if rightmost == SubjectOrPseudoElement::Yes {
627 if context.needs_selector_flags() {
628 element.apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR);
629 }
630 } else {
631 if context.needs_selector_flags() {
632 element
633 .apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT);
634 }
635 }
636
637 for relative_selector in selectors.iter() {
638 if let Some(result) = relative_selector_match_early(relative_selector, element, context) {
639 if result {
640 return true;
641 }
642 continue;
644 }
645
646 let matched = matches_relative_selector(relative_selector, element, context, rightmost);
647 context.selector_caches.relative_selector.add(
648 element.opaque(),
649 relative_selector,
650 if matched {
651 RelativeSelectorCachedMatch::Matched
652 } else {
653 RelativeSelectorCachedMatch::NotMatched
654 },
655 );
656 if matched {
657 return true;
658 }
659 }
660
661 false
662}
663
664fn matches_relative_selector_subtree<E: Element>(
665 selector: &Selector<E::Impl>,
666 element: &E,
667 context: &mut MatchingContext<E::Impl>,
668 rightmost: SubjectOrPseudoElement,
669) -> bool {
670 let mut current = element.first_element_child();
671
672 while let Some(el) = current {
673 if context.needs_selector_flags() {
674 el.apply_selector_flags(
675 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
676 );
677 }
678 if matches_complex_selector(selector.iter(), &el, context, rightmost).to_bool(true) {
679 return true;
680 }
681
682 if matches_relative_selector_subtree(selector, &el, context, rightmost) {
683 return true;
684 }
685
686 current = el.next_sibling_element();
687 }
688
689 false
690}
691
692fn hover_and_active_quirk_applies<Impl: SelectorImpl>(
696 selector_iter: &SelectorIter<Impl>,
697 context: &MatchingContext<Impl>,
698 rightmost: SubjectOrPseudoElement,
699) -> bool {
700 if context.quirks_mode() != QuirksMode::Quirks {
701 return false;
702 }
703
704 if context.is_nested() {
705 return false;
706 }
707
708 if rightmost == SubjectOrPseudoElement::Yes &&
711 context.matching_mode() == MatchingMode::ForStatelessPseudoElement
712 {
713 return false;
714 }
715
716 selector_iter.clone().all(|simple| match *simple {
717 Component::NonTSPseudoClass(ref pseudo_class) => pseudo_class.is_active_or_hover(),
718 _ => false,
719 })
720}
721
722#[derive(Clone, Copy, PartialEq)]
723enum SubjectOrPseudoElement {
724 Yes,
725 No,
726}
727
728fn host_for_part<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
729where
730 E: Element,
731{
732 let scope = context.current_host;
733 let mut curr = element.containing_shadow_host()?;
734 if scope == Some(curr.opaque()) {
735 return Some(curr);
736 }
737 loop {
738 let parent = curr.containing_shadow_host();
739 if parent.as_ref().map(|h| h.opaque()) == scope {
740 return Some(curr);
741 }
742 curr = parent?;
743 }
744}
745
746fn assigned_slot<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
747where
748 E: Element,
749{
750 debug_assert!(element
751 .assigned_slot()
752 .map_or(true, |s| s.is_html_slot_element()));
753 let scope = context.current_host?;
754 let mut current_slot = element.assigned_slot()?;
755 while current_slot.containing_shadow_host().unwrap().opaque() != scope {
756 current_slot = current_slot.assigned_slot()?;
757 }
758 Some(current_slot)
759}
760
761#[inline(always)]
762fn next_element_for_combinator<E>(
763 element: &E,
764 combinator: Combinator,
765 selector: &SelectorIter<E::Impl>,
766 context: &MatchingContext<E::Impl>,
767) -> Option<E>
768where
769 E: Element,
770{
771 match combinator {
772 Combinator::NextSibling | Combinator::LaterSibling => element.prev_sibling_element(),
773 Combinator::Child | Combinator::Descendant => {
774 match element.parent_element() {
775 Some(e) => return Some(e),
776 None => {},
777 }
778
779 if !element.parent_node_is_shadow_root() {
780 return None;
781 }
782
783 let matches_featureless_host = selector.clone().is_featureless_host_selector();
800 if matches_featureless_host.intersects(FeaturelessHostMatches::FOR_HOST) {
801 return element.containing_shadow_host()
803 } else if matches_featureless_host.intersects(FeaturelessHostMatches::FOR_SCOPE) {
804 let host = element.containing_shadow_host();
805 if context.scope_element.is_some() &&
809 context.scope_element.clone() == host.clone().map(|e| e.opaque())
810 {
811 return host;
812 }
813 return None;
814 } else {
815 return None;
816 }
817 },
818 Combinator::Part => host_for_part(element, context),
819 Combinator::SlotAssignment => assigned_slot(element, context),
820 Combinator::PseudoElement => element.pseudo_element_originating_element(),
821 }
822}
823
824fn matches_complex_selector_internal<E>(
825 mut selector_iter: SelectorIter<E::Impl>,
826 element: &E,
827 context: &mut MatchingContext<E::Impl>,
828 rightmost: SubjectOrPseudoElement,
829 first_subject_compound: SubjectOrPseudoElement,
830) -> SelectorMatchingResult
831where
832 E: Element,
833{
834 debug!(
835 "Matching complex selector {:?} for {:?}",
836 selector_iter, element
837 );
838
839 let matches_compound_selector = {
840 let result = matches_compound_selector(&mut selector_iter, element, context, rightmost);
841 if result == KleeneValue::Unknown && first_subject_compound == SubjectOrPseudoElement::No {
845 debug_assert!(
846 context
847 .matching_for_invalidation_comparison()
848 .unwrap_or(false),
849 "How did we return unknown?"
850 );
851 KleeneValue::True
853 } else {
854 result
855 }
856 };
857
858 let combinator = selector_iter.next_sequence();
859 if combinator.map_or(false, |c| c.is_sibling()) {
860 if context.needs_selector_flags() {
861 element.apply_selector_flags(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS);
862 }
863 }
864
865 if matches_compound_selector == KleeneValue::False {
868 return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
869 }
870
871 let combinator = match combinator {
872 None => {
873 return match matches_compound_selector {
874 KleeneValue::True => SelectorMatchingResult::Matched,
875 KleeneValue::Unknown => SelectorMatchingResult::Unknown,
876 KleeneValue::False => unreachable!(),
877 }
878 },
879 Some(c) => c,
880 };
881
882 let (candidate_not_found, rightmost, first_subject_compound) = match combinator {
883 Combinator::NextSibling | Combinator::LaterSibling => (
884 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant,
885 SubjectOrPseudoElement::No,
886 SubjectOrPseudoElement::No,
887 ),
888 Combinator::Child |
889 Combinator::Descendant |
890 Combinator::SlotAssignment |
891 Combinator::Part => (
892 SelectorMatchingResult::NotMatchedGlobally,
893 SubjectOrPseudoElement::No,
894 SubjectOrPseudoElement::No,
895 ),
896 Combinator::PseudoElement => (
897 SelectorMatchingResult::NotMatchedGlobally,
898 rightmost,
899 first_subject_compound,
900 ),
901 };
902
903 let mut visited_handling = if combinator.is_sibling() {
906 VisitedHandlingMode::AllLinksUnvisited
907 } else {
908 context.visited_handling()
909 };
910
911 let mut element = element.clone();
912 loop {
913 if element.is_link() {
914 visited_handling = VisitedHandlingMode::AllLinksUnvisited;
915 }
916
917 element = match next_element_for_combinator(&element, combinator, &selector_iter, &context)
918 {
919 None => return candidate_not_found,
920 Some(next_element) => next_element,
921 };
922
923 let result = context.with_visited_handling_mode(visited_handling, |context| {
924 matches_complex_selector_internal(
925 selector_iter.clone(),
926 &element,
927 context,
928 rightmost,
929 first_subject_compound,
930 )
931 });
932
933 match (result, combinator) {
934 (SelectorMatchingResult::Matched | SelectorMatchingResult::Unknown, _) => {
936 debug_assert!(
937 matches_compound_selector.to_bool(true),
938 "Compound didn't match?"
939 );
940 if result == SelectorMatchingResult::Matched &&
941 matches_compound_selector.to_bool(false)
942 {
943 return result;
945 }
946 return SelectorMatchingResult::Unknown;
948 },
949 (SelectorMatchingResult::NotMatchedGlobally, _) | (_, Combinator::NextSibling) => {
950 return result;
951 },
952
953 (_, Combinator::PseudoElement) | (_, Combinator::Child) => {
956 return SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant;
957 },
958
959 (
964 SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant,
965 Combinator::LaterSibling,
966 ) => {
967 return result;
968 },
969
970 _ => {},
977 }
978 }
979}
980
981#[inline]
982fn matches_local_name<E>(element: &E, local_name: &LocalName<E::Impl>) -> bool
983where
984 E: Element,
985{
986 let name = select_name(element, &local_name.name, &local_name.lower_name).borrow();
987 element.has_local_name(name)
988}
989
990fn matches_part<E>(
991 element: &E,
992 parts: &[<E::Impl as SelectorImpl>::Identifier],
993 context: &mut MatchingContext<E::Impl>,
994) -> bool
995where
996 E: Element,
997{
998 let mut hosts = SmallVec::<[E; 4]>::new();
999
1000 let mut host = match element.containing_shadow_host() {
1001 Some(h) => h,
1002 None => return false,
1003 };
1004
1005 let current_host = context.current_host;
1006 if current_host != Some(host.opaque()) {
1007 loop {
1008 let outer_host = host.containing_shadow_host();
1009 if outer_host.as_ref().map(|h| h.opaque()) == current_host {
1010 break;
1011 }
1012 let outer_host = match outer_host {
1013 Some(h) => h,
1014 None => return false,
1015 };
1016 hosts.push(host);
1019 host = outer_host;
1020 }
1021 }
1022
1023 parts.iter().all(|part| {
1025 let mut part = part.clone();
1026 for host in hosts.iter().rev() {
1027 part = match host.imported_part(&part) {
1028 Some(p) => p,
1029 None => return false,
1030 };
1031 }
1032 element.is_part(&part)
1033 })
1034}
1035
1036fn matches_host<E>(
1037 element: &E,
1038 selector: Option<&Selector<E::Impl>>,
1039 context: &mut MatchingContext<E::Impl>,
1040 rightmost: SubjectOrPseudoElement,
1041) -> KleeneValue
1042where
1043 E: Element,
1044{
1045 let host = match context.shadow_host() {
1046 Some(h) => h,
1047 None => return KleeneValue::False,
1048 };
1049 if host != element.opaque() {
1050 return KleeneValue::False;
1051 }
1052 selector.map_or(KleeneValue::True, |selector| {
1053 context
1054 .nest(|context| matches_complex_selector(selector.iter(), element, context, rightmost))
1055 })
1056}
1057
1058fn matches_slotted<E>(
1059 element: &E,
1060 selector: &Selector<E::Impl>,
1061 context: &mut MatchingContext<E::Impl>,
1062 rightmost: SubjectOrPseudoElement,
1063) -> KleeneValue
1064where
1065 E: Element,
1066{
1067 if element.is_html_slot_element() {
1069 return KleeneValue::False;
1070 }
1071 context.nest(|context| matches_complex_selector(selector.iter(), element, context, rightmost))
1072}
1073
1074fn matches_rare_attribute_selector<E>(
1075 element: &E,
1076 attr_sel: &AttrSelectorWithOptionalNamespace<E::Impl>,
1077) -> bool
1078where
1079 E: Element,
1080{
1081 let empty_string;
1082 let namespace = match attr_sel.namespace() {
1083 Some(ns) => ns,
1084 None => {
1085 empty_string = crate::parser::namespace_empty_string::<E::Impl>();
1086 NamespaceConstraint::Specific(&empty_string)
1087 },
1088 };
1089 element.attr_matches(
1090 &namespace,
1091 select_name(element, &attr_sel.local_name, &attr_sel.local_name_lower),
1092 &match attr_sel.operation {
1093 ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
1094 ParsedAttrSelectorOperation::WithValue {
1095 operator,
1096 case_sensitivity,
1097 ref value,
1098 } => AttrSelectorOperation::WithValue {
1099 operator,
1100 case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
1101 value,
1102 },
1103 },
1104 )
1105}
1106
1107#[inline]
1109fn matches_compound_selector<E>(
1110 selector_iter: &mut SelectorIter<E::Impl>,
1111 element: &E,
1112 context: &mut MatchingContext<E::Impl>,
1113 rightmost: SubjectOrPseudoElement,
1114) -> KleeneValue
1115where
1116 E: Element,
1117{
1118 let quirks_data = if context.quirks_mode() == QuirksMode::Quirks {
1119 Some(selector_iter.clone())
1120 } else {
1121 None
1122 };
1123 let mut local_context = LocalMatchingContext {
1124 shared: context,
1125 rightmost,
1126 quirks_data,
1127 };
1128 KleeneValue::any_false(
1129 selector_iter,
1130 |simple| matches_simple_selector(
1131 simple,
1132 element,
1133 &mut local_context
1134 )
1135 )
1136}
1137
1138fn matches_simple_selector<E>(
1140 selector: &Component<E::Impl>,
1141 element: &E,
1142 context: &mut LocalMatchingContext<E::Impl>,
1143) -> KleeneValue
1144where
1145 E: Element,
1146{
1147 debug_assert!(context.shared.is_nested() || !context.shared.in_negation());
1148 let rightmost = context.rightmost;
1149 KleeneValue::from(match *selector {
1150 Component::ID(ref id) => {
1151 element.has_id(id, context.shared.classes_and_ids_case_sensitivity())
1152 },
1153 Component::Class(ref class) => {
1154 element.has_class(class, context.shared.classes_and_ids_case_sensitivity())
1155 },
1156 Component::LocalName(ref local_name) => matches_local_name(element, local_name),
1157 Component::AttributeInNoNamespaceExists {
1158 ref local_name,
1159 ref local_name_lower,
1160 } => element.has_attr_in_no_namespace(select_name(element, local_name, local_name_lower)),
1161 Component::AttributeInNoNamespace {
1162 ref local_name,
1163 ref value,
1164 operator,
1165 case_sensitivity,
1166 } => element.attr_matches(
1167 &NamespaceConstraint::Specific(&crate::parser::namespace_empty_string::<E::Impl>()),
1168 local_name,
1169 &AttrSelectorOperation::WithValue {
1170 operator,
1171 case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
1172 value,
1173 },
1174 ),
1175 Component::AttributeOther(ref attr_sel) => {
1176 matches_rare_attribute_selector(element, attr_sel)
1177 },
1178 Component::Part(ref parts) => matches_part(element, parts, &mut context.shared),
1179 Component::Slotted(ref selector) => {
1180 return matches_slotted(element, selector, &mut context.shared, rightmost);
1181 },
1182 Component::PseudoElement(ref pseudo) => {
1183 element.match_pseudo_element(pseudo, context.shared)
1184 },
1185 Component::ExplicitUniversalType | Component::ExplicitAnyNamespace => true,
1186 Component::Namespace(_, ref url) | Component::DefaultNamespace(ref url) => {
1187 element.has_namespace(&url.borrow())
1188 },
1189 Component::ExplicitNoNamespace => {
1190 let ns = crate::parser::namespace_empty_string::<E::Impl>();
1191 element.has_namespace(&ns.borrow())
1192 },
1193 Component::NonTSPseudoClass(ref pc) => {
1194 if let Some(ref iter) = context.quirks_data {
1195 if pc.is_active_or_hover() &&
1196 !element.is_link() &&
1197 hover_and_active_quirk_applies(iter, context.shared, context.rightmost)
1198 {
1199 return KleeneValue::False;
1200 }
1201 }
1202 element.match_non_ts_pseudo_class(pc, &mut context.shared)
1203 },
1204 Component::Root => element.is_root(),
1205 Component::Empty => {
1206 if context.shared.needs_selector_flags() {
1207 element.apply_selector_flags(ElementSelectorFlags::HAS_EMPTY_SELECTOR);
1208 }
1209 element.is_empty()
1210 },
1211 Component::Host(ref selector) => {
1212 return matches_host(element, selector.as_ref(), &mut context.shared, rightmost);
1213 },
1214 Component::ParentSelector | Component::Scope | Component::ImplicitScope => match context.shared.scope_element {
1215 Some(ref scope_element) => element.opaque() == *scope_element,
1216 None => element.is_root(),
1217 },
1218 Component::Nth(ref nth_data) => {
1219 return matches_generic_nth_child(element, context.shared, nth_data, &[], rightmost);
1220 },
1221 Component::NthOf(ref nth_of_data) => {
1222 return context.shared.nest(|context| {
1223 matches_generic_nth_child(
1224 element,
1225 context,
1226 nth_of_data.nth_data(),
1227 nth_of_data.selectors(),
1228 rightmost,
1229 )
1230 })
1231 },
1232 Component::Is(ref list) | Component::Where(ref list) => {
1233 return context.shared.nest(|context| {
1234 matches_complex_selector_list(list.slice(), element, context, rightmost)
1235 })
1236 },
1237 Component::Negation(ref list) => {
1238 return context.shared.nest_for_negation(|context| {
1239 !matches_complex_selector_list(list.slice(), element, context, rightmost)
1240 })
1241 },
1242 Component::Has(ref relative_selectors) => {
1243 return match_relative_selectors(
1244 relative_selectors,
1245 element,
1246 context.shared,
1247 rightmost,
1248 );
1249 },
1250 Component::Combinator(_) => unsafe {
1251 debug_unreachable!("Shouldn't try to selector-match combinators")
1252 },
1253 Component::RelativeSelectorAnchor => {
1254 let anchor = context.shared.relative_selector_anchor();
1255 anchor.map_or(true, |a| a == element.opaque())
1257 },
1258 Component::Invalid(..) => false,
1259 })
1260}
1261
1262#[inline(always)]
1263pub fn select_name<'a, E: Element, T: PartialEq>(
1264 element: &E,
1265 local_name: &'a T,
1266 local_name_lower: &'a T,
1267) -> &'a T {
1268 if local_name == local_name_lower || element.is_html_element_in_html_document() {
1269 local_name_lower
1270 } else {
1271 local_name
1272 }
1273}
1274
1275#[inline(always)]
1276pub fn to_unconditional_case_sensitivity<'a, E: Element>(
1277 parsed: ParsedCaseSensitivity,
1278 element: &E,
1279) -> CaseSensitivity {
1280 match parsed {
1281 ParsedCaseSensitivity::CaseSensitive | ParsedCaseSensitivity::ExplicitCaseSensitive => {
1282 CaseSensitivity::CaseSensitive
1283 },
1284 ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
1285 ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
1286 if element.is_html_element_in_html_document() {
1287 CaseSensitivity::AsciiCaseInsensitive
1288 } else {
1289 CaseSensitivity::CaseSensitive
1290 }
1291 },
1292 }
1293}
1294
1295fn matches_generic_nth_child<E>(
1296 element: &E,
1297 context: &mut MatchingContext<E::Impl>,
1298 nth_data: &NthSelectorData,
1299 selectors: &[Selector<E::Impl>],
1300 rightmost: SubjectOrPseudoElement,
1301) -> KleeneValue
1302where
1303 E: Element,
1304{
1305 if element.ignores_nth_child_selectors() {
1306 return KleeneValue::False;
1307 }
1308 let has_selectors = !selectors.is_empty();
1309 let selectors_match = !has_selectors ||
1310 matches_complex_selector_list(selectors, element, context, rightmost).to_bool(true);
1311 if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
1312 return if selectors_match && may_return_unknown {
1314 KleeneValue::Unknown
1315 } else {
1316 KleeneValue::from(selectors_match && !context.in_negation())
1317 };
1318 }
1319
1320 let NthSelectorData { ty, a, b, .. } = *nth_data;
1321 let is_of_type = ty.is_of_type();
1322 if ty.is_only() {
1323 debug_assert!(
1324 !has_selectors,
1325 ":only-child and :only-of-type cannot have a selector list!"
1326 );
1327 return KleeneValue::from(
1328 matches_generic_nth_child(
1329 element,
1330 context,
1331 &NthSelectorData::first(is_of_type),
1332 selectors,
1333 rightmost,
1334 )
1335 .to_bool(true) &&
1336 matches_generic_nth_child(
1337 element,
1338 context,
1339 &NthSelectorData::last(is_of_type),
1340 selectors,
1341 rightmost,
1342 )
1343 .to_bool(true),
1344 );
1345 }
1346
1347 let is_from_end = ty.is_from_end();
1348
1349 let is_edge_child_selector = nth_data.is_simple_edge() && !has_selectors;
1352
1353 if context.needs_selector_flags() {
1354 let mut flags = if is_edge_child_selector {
1355 ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR
1356 } else if is_from_end {
1357 ElementSelectorFlags::HAS_SLOW_SELECTOR
1358 } else {
1359 ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS
1360 };
1361 flags |= if has_selectors {
1362 ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF
1363 } else {
1364 ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH
1365 };
1366 element.apply_selector_flags(flags);
1367 }
1368
1369 if !selectors_match {
1370 return KleeneValue::False;
1371 }
1372
1373 if is_edge_child_selector {
1376 return if is_from_end {
1377 element.next_sibling_element()
1378 } else {
1379 element.prev_sibling_element()
1380 }
1381 .is_none()
1382 .into();
1383 }
1384
1385 let index = if let Some(i) = context
1387 .nth_index_cache(is_of_type, is_from_end, selectors)
1388 .lookup(element.opaque())
1389 {
1390 i
1391 } else {
1392 let i = nth_child_index(
1393 element,
1394 context,
1395 selectors,
1396 is_of_type,
1397 is_from_end,
1398 true,
1399 rightmost,
1400 );
1401 context
1402 .nth_index_cache(is_of_type, is_from_end, selectors)
1403 .insert(element.opaque(), i);
1404 i
1405 };
1406 debug_assert_eq!(
1407 index,
1408 nth_child_index(
1409 element,
1410 context,
1411 selectors,
1412 is_of_type,
1413 is_from_end,
1414 false,
1415 rightmost,
1416 ),
1417 "invalid cache"
1418 );
1419
1420 match index.checked_sub(b) {
1422 None => false,
1423 Some(an) => match an.checked_div(a) {
1424 Some(n) => n >= 0 && a * n == an,
1425 None => an == 0,
1426 },
1427 }
1428 .into()
1429}
1430
1431#[inline]
1432fn nth_child_index<E>(
1433 element: &E,
1434 context: &mut MatchingContext<E::Impl>,
1435 selectors: &[Selector<E::Impl>],
1436 is_of_type: bool,
1437 is_from_end: bool,
1438 check_cache: bool,
1439 rightmost: SubjectOrPseudoElement,
1440) -> i32
1441where
1442 E: Element,
1443{
1444 if check_cache &&
1451 is_from_end &&
1452 !context
1453 .nth_index_cache(is_of_type, is_from_end, selectors)
1454 .is_empty()
1455 {
1456 let mut index: i32 = 1;
1457 let mut curr = element.clone();
1458 while let Some(e) = curr.prev_sibling_element() {
1459 curr = e;
1460 let matches = if is_of_type {
1461 element.is_same_type(&curr)
1462 } else if !selectors.is_empty() {
1463 matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
1464 } else {
1465 true
1466 };
1467 if !matches {
1468 continue;
1469 }
1470 if let Some(i) = context
1471 .nth_index_cache(is_of_type, is_from_end, selectors)
1472 .lookup(curr.opaque())
1473 {
1474 return i - index;
1475 }
1476 index += 1;
1477 }
1478 }
1479
1480 let mut index: i32 = 1;
1481 let mut curr = element.clone();
1482 let next = |e: E| {
1483 if is_from_end {
1484 e.next_sibling_element()
1485 } else {
1486 e.prev_sibling_element()
1487 }
1488 };
1489 while let Some(e) = next(curr) {
1490 curr = e;
1491 let matches = if is_of_type {
1492 element.is_same_type(&curr)
1493 } else if !selectors.is_empty() {
1494 matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
1495 } else {
1496 true
1497 };
1498 if !matches {
1499 continue;
1500 }
1501 if !is_from_end && check_cache {
1505 if let Some(i) = context
1506 .nth_index_cache(is_of_type, is_from_end, selectors)
1507 .lookup(curr.opaque())
1508 {
1509 return i + index;
1510 }
1511 }
1512 index += 1;
1513 }
1514
1515 index
1516}