Skip to content

Commit b14b17f

Browse files
committed
fix: prevent infinite loops when pruning CSS
1 parent ca3690f commit b14b17f

File tree

5 files changed

+38
-1
lines changed

5 files changed

+38
-1
lines changed

.changeset/itchy-timers-relax.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: prevent infinite loops when pruning CSS

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ const nesting_selector = {
4343
}
4444
};
4545

46+
/**
47+
* Snippets encountered already (avoids infinite loops)
48+
* @type {Set<Compiler.AST.SnippetBlock>}
49+
*/
50+
const seen = new Set();
51+
4652
/**
4753
*
4854
* @param {Compiler.Css.StyleSheet} stylesheet
@@ -60,6 +66,8 @@ export function prune(stylesheet, element) {
6066
ComplexSelector(node) {
6167
const selectors = get_relative_selectors(node);
6268

69+
seen.clear();
70+
6371
if (
6472
apply_selector(selectors, /** @type {Compiler.Css.Rule} */ (node.metadata.rule), element)
6573
) {
@@ -193,6 +201,9 @@ function apply_combinator(relative_selector, parent_selectors, rule, node) {
193201
const parent = path[i];
194202

195203
if (parent.type === 'SnippetBlock') {
204+
if (seen.has(parent)) return true;
205+
seen.add(parent);
206+
196207
for (const site of parent.metadata.sites) {
197208
if (apply_combinator(relative_selector, parent_selectors, rule, site)) {
198209
return true;

packages/svelte/src/compiler/phases/2-analyze/visitors/shared/component.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function visit_component(node, context) {
5151
if (binding?.initial?.type === 'SnippetBlock') {
5252
node.metadata.snippets.add(binding.initial);
5353
}
54-
} else {
54+
} else if (expression.type !== 'Literal') {
5555
resolved = false;
5656
}
5757
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
div.svelte-xyz div:where(.svelte-xyz) {
3+
color: red;
4+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{#snippet a()}
2+
<div>
3+
{@render b()}
4+
</div>
5+
{/snippet}
6+
7+
{#snippet b()}
8+
<div>
9+
{@render a()}
10+
</div>
11+
{/snippet}
12+
13+
<style>
14+
div div {
15+
color: red;
16+
}
17+
</style>

0 commit comments

Comments
 (0)