Skip to content

Commit 5225575

Browse files
authored
fix: do not prune selectors like :global(.foo):has(.scoped) (#15140)
Fixes #14910 The issue occurs only when :has() targets at a component's root element and because include_self is false. I came to the conclusion that this is the same case as :root:has(.scoped).
1 parent 8e83127 commit 5225575

File tree

5 files changed

+40
-2
lines changed

5 files changed

+40
-2
lines changed

.changeset/famous-bulldogs-tan.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: do not prune selectors like `:global(.foo):has(.scoped)`

packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,18 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element)
339339
let sibling_elements; // do them lazy because it's rarely used and expensive to calculate
340340

341341
// If this is a :has inside a global selector, we gotta include the element itself, too,
342-
// because the global selector might be for an element that's outside the component (e.g. :root).
342+
// because the global selector might be for an element that's outside the component,
343+
// e.g. :root:has(.scoped), :global(.foo):has(.scoped), or :root { &:has(.scoped) {} }
343344
const rules = get_parent_rules(rule);
344345
const include_self =
345346
rules.some((r) => r.prelude.children.some((c) => c.children.some((s) => is_global(s, r)))) ||
346347
rules[rules.length - 1].prelude.children.some((c) =>
347348
c.children.some((r) =>
348-
r.selectors.some((s) => s.type === 'PseudoClassSelector' && s.name === 'root')
349+
r.selectors.some(
350+
(s) =>
351+
s.type === 'PseudoClassSelector' &&
352+
(s.name === 'root' || (s.name === 'global' && s.args))
353+
)
349354
)
350355
);
351356
if (include_self) {

packages/svelte/tests/css/samples/has/_config.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,20 @@ export default test({
197197
column: 16,
198198
character: 1614
199199
}
200+
},
201+
{
202+
code: 'css_unused_selector',
203+
message: 'Unused CSS selector ":global(.foo):has(.unused)"',
204+
start: {
205+
line: 155,
206+
column: 1,
207+
character: 1684
208+
},
209+
end: {
210+
line: 155,
211+
column: 27,
212+
character: 1710
213+
}
200214
}
201215
]
202216
});

packages/svelte/tests/css/samples/has/expected.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,10 @@
136136
color: red;
137137
}*/
138138
}
139+
140+
.foo:has(x.svelte-xyz) {
141+
color: green;
142+
}
143+
/* (unused) :global(.foo):has(.unused) {
144+
color: red;
145+
}*/

packages/svelte/tests/css/samples/has/input.svelte

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,11 @@
148148
color: red;
149149
}
150150
}
151+
152+
:global(.foo):has(x) {
153+
color: green;
154+
}
155+
:global(.foo):has(.unused) {
156+
color: red;
157+
}
151158
</style>

0 commit comments

Comments
 (0)