@@ -143,10 +143,10 @@ function truncate(node) {
143143 * @param {Compiler.Css.Rule } rule
144144 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement } element
145145 * @param {Compiler.Css.StyleSheet } stylesheet
146- * @param {boolean } separate_has Whether or not to separate the `:has(...)` selectors
146+ * @param {boolean } check_has Whether or not to check the `:has(...)` selectors
147147 * @returns {boolean }
148148 */
149- function apply_selector ( relative_selectors , rule , element , stylesheet , separate_has ) {
149+ function apply_selector ( relative_selectors , rule , element , stylesheet , check_has ) {
150150 const parent_selectors = relative_selectors . slice ( ) ;
151151 const relative_selector = parent_selectors . pop ( ) ;
152152
@@ -157,7 +157,7 @@ function apply_selector(relative_selectors, rule, element, stylesheet, separate_
157157 rule ,
158158 element ,
159159 stylesheet ,
160- separate_has
160+ check_has
161161 ) ;
162162
163163 if ( ! possible_match ) {
@@ -172,7 +172,7 @@ function apply_selector(relative_selectors, rule, element, stylesheet, separate_
172172 rule ,
173173 element ,
174174 stylesheet ,
175- separate_has
175+ check_has
176176 ) ;
177177 }
178178
@@ -193,7 +193,7 @@ function apply_selector(relative_selectors, rule, element, stylesheet, separate_
193193 * @param {Compiler.Css.Rule } rule
194194 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement } element
195195 * @param {Compiler.Css.StyleSheet } stylesheet
196- * @param {boolean } separate_has
196+ * @param {boolean } check_has Whether or not to check the `:has(...)` selectors
197197 * @returns {boolean }
198198 */
199199function apply_combinator (
@@ -203,7 +203,7 @@ function apply_combinator(
203203 rule ,
204204 element ,
205205 stylesheet ,
206- separate_has
206+ check_has
207207) {
208208 const name = combinator . name ;
209209
@@ -221,7 +221,7 @@ function apply_combinator(
221221 }
222222
223223 if ( parent . type === 'RegularElement' || parent . type === 'SvelteElement' ) {
224- if ( apply_selector ( parent_selectors , rule , parent , stylesheet , separate_has ) ) {
224+ if ( apply_selector ( parent_selectors , rule , parent , stylesheet , check_has ) ) {
225225 // TODO the `name === ' '` causes false positives, but removing it causes false negatives...
226226 if ( name === ' ' || crossed_component_boundary ) {
227227 mark ( parent_selectors [ parent_selectors . length - 1 ] , parent ) ;
@@ -253,7 +253,7 @@ function apply_combinator(
253253 sibling_matched = true ;
254254 }
255255 } else if (
256- apply_selector ( parent_selectors , rule , possible_sibling , stylesheet , separate_has )
256+ apply_selector ( parent_selectors , rule , possible_sibling , stylesheet , check_has )
257257 ) {
258258 mark ( relative_selector , element ) ;
259259 sibling_matched = true ;
@@ -336,37 +336,31 @@ const regex_backslash_and_following_character = /\\(.)/g;
336336 * @param {Compiler.Css.Rule } rule
337337 * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement } element
338338 * @param {Compiler.Css.StyleSheet } stylesheet
339- * @param {boolean } separate_has Whether or not to separate the `:has(...)` selectors
339+ * @param {boolean } check_has Whether or not to check the `:has(...)` selectors
340340 * @returns {boolean }
341341 */
342342function relative_selector_might_apply_to_node (
343343 relative_selector ,
344344 rule ,
345345 element ,
346346 stylesheet ,
347- separate_has
347+ check_has
348348) {
349- // Sort :has(...) selectors in one bucket and everything else into another,
350- // unless we're called recursively from a :has(...) selector, in which case
351- // we're on the way of checking if the upper selectors match. In that
352- // case ignore them to avoid an infinite loop.
349+ // Sort :has(...) selectors in one bucket and everything else into another
353350 const has_selectors = [ ] ;
354351 const other_selectors = [ ] ;
355352
356353 for ( const selector of relative_selector . selectors ) {
357- if (
358- separate_has &&
359- selector . type === 'PseudoClassSelector' &&
360- selector . name === 'has' &&
361- selector . args
362- ) {
354+ if ( selector . type === 'PseudoClassSelector' && selector . name === 'has' && selector . args ) {
363355 has_selectors . push ( selector ) ;
364356 } else {
365357 other_selectors . push ( selector ) ;
366358 }
367359 }
368360
369- if ( has_selectors . length > 0 ) {
361+ // If we're called recursively from a :has(...) selector, we're on the way of checking if the other selectors match.
362+ // In that case ignore this check (because we just came from this) to avoid an infinite loop.
363+ if ( check_has && has_selectors . length > 0 ) {
370364 // :has(...) is special in that it means "look downwards in the CSS tree". Since our matching algorithm goes
371365 // upwards and back-to-front, we need to first check the selectors inside :has(...), then check the rest of the
372366 // selector in a way that is similar to ancestor matching. In a sense, we're treating `.x:has(.y)` as `.x .y`.
@@ -379,7 +373,7 @@ function relative_selector_might_apply_to_node(
379373 const selectors = truncate ( complex_selector ) ;
380374 if (
381375 selectors . length === 0 /* is :global(...) */ ||
382- apply_selector ( selectors , rule , element , stylesheet , separate_has )
376+ apply_selector ( selectors , rule , element , stylesheet , check_has )
383377 ) {
384378 // Treat e.g. `.x:has(.y)` as `.x .y` with the .y part already being matched,
385379 // and now looking upwards for the .x part.
@@ -440,7 +434,7 @@ function relative_selector_might_apply_to_node(
440434 ) {
441435 const args = selector . args ;
442436 const complex_selector = args . children [ 0 ] ;
443- return apply_selector ( complex_selector . children , rule , element , stylesheet , separate_has ) ;
437+ return apply_selector ( complex_selector . children , rule , element , stylesheet , check_has ) ;
444438 }
445439
446440 // We came across a :global, everything beyond it is global and therefore a potential match
@@ -450,9 +444,7 @@ function relative_selector_might_apply_to_node(
450444 let matched = false ;
451445
452446 for ( const complex_selector of selector . args . children ) {
453- if (
454- apply_selector ( truncate ( complex_selector ) , rule , element , stylesheet , separate_has )
455- ) {
447+ if ( apply_selector ( truncate ( complex_selector ) , rule , element , stylesheet , check_has ) ) {
456448 complex_selector . metadata . used = true ;
457449 matched = true ;
458450 }
@@ -526,9 +518,7 @@ function relative_selector_might_apply_to_node(
526518 const parent = /** @type {Compiler.Css.Rule } */ ( rule . metadata . parent_rule ) ;
527519
528520 for ( const complex_selector of parent . prelude . children ) {
529- if (
530- apply_selector ( truncate ( complex_selector ) , parent , element , stylesheet , separate_has )
531- ) {
521+ if ( apply_selector ( truncate ( complex_selector ) , parent , element , stylesheet , check_has ) ) {
532522 complex_selector . metadata . used = true ;
533523 matched = true ;
534524 }
0 commit comments