@@ -489,14 +489,17 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
489489 }
490490
491491 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+ }
493496
494497 const name = selector . name . replace ( regex_backslash_and_following_character , '$1' ) ;
495498
496499 switch ( selector . type ) {
497500 case 'PseudoClassSelector' : {
498501 if ( name === 'host' || name === 'root' ) {
499- return false ;
502+ return state . inside_not ;
500503 }
501504
502505 if (
@@ -514,6 +517,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
514517
515518 if ( ( name === 'is' || name === 'where' || name === 'not' ) && selector . args ) {
516519 let matched = false ;
520+ let didnt_match = false ;
517521
518522 for ( const complex_selector of selector . args . children ) {
519523 const relative = truncate ( complex_selector ) ;
@@ -522,10 +526,12 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
522526 if ( is_global ) {
523527 complex_selector . metadata . used = true ;
524528 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 } ) ) {
526531 complex_selector . metadata . used = true ;
527532 matched = true ;
528533 } else if (
534+ false &&
529535 name === 'not' &&
530536 ! apply_selector ( relative , rule , element , { ...state , inside_not : true } )
531537 ) {
@@ -554,9 +560,12 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
554560 // The result may not match a real element, so the only drawback is the missing prune.
555561 complex_selector . metadata . used = true ;
556562 matched = true ;
563+ didnt_match = true ;
557564 for ( const selector of relative ) {
558565 selector . metadata . scoped = true ;
559566 }
567+ } else {
568+ didnt_match = true ;
560569 }
561570 }
562571
@@ -578,21 +587,23 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
578587 } ) ;
579588 }
580589
581- return false ;
590+ return state . inside_not && didnt_match ;
582591 }
583592 }
584593
585594 break ;
586595 }
587596
588597 case 'PseudoElementSelector' : {
589- break ;
598+ return true ;
590599 }
591600
592601 case 'AttributeSelector' : {
593602 const whitelisted = whitelist_attribute_selector . get ( element . name . toLowerCase ( ) ) ;
603+ if ( whitelisted ?. includes ( selector . name . toLowerCase ( ) ) ) {
604+ return true ;
605+ }
594606 if (
595- ! whitelisted ?. includes ( selector . name . toLowerCase ( ) ) &&
596607 ! attribute_matches (
597608 element ,
598609 selector . name ,
@@ -601,19 +612,20 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
601612 selector . flags ?. includes ( 'i' ) ?? false
602613 )
603614 ) {
604- return false ;
615+ return state . inside_not ;
605616 }
617+
606618 break ;
607619 }
608620
609621 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 ;
617629 }
618630
619631 break ;
@@ -633,26 +645,34 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
633645 name !== '*' &&
634646 element . type !== 'SvelteElement'
635647 ) {
636- return false ;
648+ return state . inside_not ;
649+ } else if ( element . type === 'SvelteElement' && state . inside_not ) {
650+ return true ;
637651 }
638652
639653 break ;
640654 }
641655
642656 case 'NestingSelector' : {
643657 let matched = false ;
658+ let didnt_match = true ;
644659
645660 const parent = /** @type {Compiler.Css.Rule } */ ( rule . metadata . parent_rule ) ;
646661
647662 for ( const complex_selector of parent . prelude . children ) {
648663 if ( apply_selector ( truncate ( complex_selector ) , parent , element , state ) ) {
649664 complex_selector . metadata . used = true ;
650665 matched = true ;
666+ } else {
667+ didnt_match = true ;
651668 }
652669 }
653670
654671 if ( ! matched ) {
655- return false ;
672+ return state . inside_not ;
673+ }
674+ if ( state . inside_not && didnt_match ) {
675+ return true ;
656676 }
657677
658678 break ;
@@ -661,7 +681,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
661681 }
662682
663683 // possible match
664- return true ;
684+ return ! state . inside_not ;
665685}
666686
667687/**
0 commit comments