@@ -489,14 +489,17 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
489
489
}
490
490
491
491
for ( const selector of other_selectors ) {
492
- if ( selector . type === 'Percentage' || selector . type === 'Nth' ) continue ;
492
+ if ( selector . type === 'Percentage' || selector . type === 'Nth' ) {
493
+ if ( state . inside_not ) return true ;
494
+ continue ;
495
+ }
493
496
494
497
const name = selector . name . replace ( regex_backslash_and_following_character , '$1' ) ;
495
498
496
499
switch ( selector . type ) {
497
500
case 'PseudoClassSelector' : {
498
501
if ( name === 'host' || name === 'root' ) {
499
- return false ;
502
+ return state . inside_not ;
500
503
}
501
504
502
505
if (
@@ -514,6 +517,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
514
517
515
518
if ( ( name === 'is' || name === 'where' || name === 'not' ) && selector . args ) {
516
519
let matched = false ;
520
+ let didnt_match = false ;
517
521
518
522
for ( const complex_selector of selector . args . children ) {
519
523
const relative = truncate ( complex_selector ) ;
@@ -522,10 +526,12 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
522
526
if ( is_global ) {
523
527
complex_selector . metadata . used = true ;
524
528
matched = true ;
525
- } else if ( name !== 'not' && apply_selector ( relative , rule , element , state ) ) {
529
+ didnt_match = true ;
530
+ } else if ( apply_selector ( relative , rule , element , { ...state , inside_not : true } ) ) {
526
531
complex_selector . metadata . used = true ;
527
532
matched = true ;
528
533
} else if (
534
+ false &&
529
535
name === 'not' &&
530
536
! apply_selector ( relative , rule , element , { ...state , inside_not : true } )
531
537
) {
@@ -554,9 +560,12 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
554
560
// The result may not match a real element, so the only drawback is the missing prune.
555
561
complex_selector . metadata . used = true ;
556
562
matched = true ;
563
+ didnt_match = true ;
557
564
for ( const selector of relative ) {
558
565
selector . metadata . scoped = true ;
559
566
}
567
+ } else {
568
+ didnt_match = true ;
560
569
}
561
570
}
562
571
@@ -578,21 +587,23 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
578
587
} ) ;
579
588
}
580
589
581
- return false ;
590
+ return state . inside_not && didnt_match ;
582
591
}
583
592
}
584
593
585
594
break ;
586
595
}
587
596
588
597
case 'PseudoElementSelector' : {
589
- break ;
598
+ return true ;
590
599
}
591
600
592
601
case 'AttributeSelector' : {
593
602
const whitelisted = whitelist_attribute_selector . get ( element . name . toLowerCase ( ) ) ;
603
+ if ( whitelisted ?. includes ( selector . name . toLowerCase ( ) ) ) {
604
+ return true ;
605
+ }
594
606
if (
595
- ! whitelisted ?. includes ( selector . name . toLowerCase ( ) ) &&
596
607
! attribute_matches (
597
608
element ,
598
609
selector . name ,
@@ -601,19 +612,20 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
601
612
selector . flags ?. includes ( 'i' ) ?? false
602
613
)
603
614
) {
604
- return false ;
615
+ return state . inside_not ;
605
616
}
617
+
606
618
break ;
607
619
}
608
620
609
621
case 'ClassSelector' : {
610
- if (
611
- ! attribute_matches ( element , 'class' , name , '~=' , false ) &&
612
- ! element . attributes . some (
613
- ( attribute ) => attribute . type === 'ClassDirective' && attribute . name === name
614
- )
615
- ) {
616
- return false ;
622
+ const matches_class_directive = element . attributes . some (
623
+ ( attribute ) => attribute . type === 'ClassDirective' && attribute . name === name
624
+ ) ;
625
+ if ( ! attribute_matches ( element , 'class' , name , '~=' , false ) && ! matches_class_directive ) {
626
+ return state . inside_not ;
627
+ } else if ( matches_class_directive ) {
628
+ return true ;
617
629
}
618
630
619
631
break ;
@@ -633,26 +645,34 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
633
645
name !== '*' &&
634
646
element . type !== 'SvelteElement'
635
647
) {
636
- return false ;
648
+ return state . inside_not ;
649
+ } else if ( element . type === 'SvelteElement' && state . inside_not ) {
650
+ return true ;
637
651
}
638
652
639
653
break ;
640
654
}
641
655
642
656
case 'NestingSelector' : {
643
657
let matched = false ;
658
+ let didnt_match = true ;
644
659
645
660
const parent = /** @type {Compiler.Css.Rule } */ ( rule . metadata . parent_rule ) ;
646
661
647
662
for ( const complex_selector of parent . prelude . children ) {
648
663
if ( apply_selector ( truncate ( complex_selector ) , parent , element , state ) ) {
649
664
complex_selector . metadata . used = true ;
650
665
matched = true ;
666
+ } else {
667
+ didnt_match = true ;
651
668
}
652
669
}
653
670
654
671
if ( ! matched ) {
655
- return false ;
672
+ return state . inside_not ;
673
+ }
674
+ if ( state . inside_not && didnt_match ) {
675
+ return true ;
656
676
}
657
677
658
678
break ;
@@ -661,7 +681,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
661
681
}
662
682
663
683
// possible match
664
- return true ;
684
+ return ! state . inside_not ;
665
685
}
666
686
667
687
/**
0 commit comments