Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/itchy-timers-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: prevent infinite loops when pruning CSS
11 changes: 11 additions & 0 deletions packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ const nesting_selector = {
}
};

/**
* Snippets encountered already (avoids infinite loops)
* @type {Set<Compiler.AST.SnippetBlock>}
*/
const seen = new Set();

/**
*
* @param {Compiler.Css.StyleSheet} stylesheet
Expand All @@ -60,6 +66,8 @@ export function prune(stylesheet, element) {
ComplexSelector(node) {
const selectors = get_relative_selectors(node);

seen.clear();

if (
apply_selector(selectors, /** @type {Compiler.Css.Rule} */ (node.metadata.rule), element)
) {
Expand Down Expand Up @@ -193,6 +201,9 @@ function apply_combinator(relative_selector, parent_selectors, rule, node) {
const parent = path[i];

if (parent.type === 'SnippetBlock') {
if (seen.has(parent)) return true;
seen.add(parent);

for (const site of parent.metadata.sites) {
if (apply_combinator(relative_selector, parent_selectors, rule, site)) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function visit_component(node, context) {
if (binding?.initial?.type === 'SnippetBlock') {
node.metadata.snippets.add(binding.initial);
}
} else {
} else if (expression.type !== 'Literal') {
resolved = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

div.svelte-xyz div:where(.svelte-xyz) {
color: red;
}
17 changes: 17 additions & 0 deletions packages/svelte/tests/css/samples/render-tag-loop/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{#snippet a()}
<div>
{@render b()}
</div>
{/snippet}

{#snippet b()}
<div>
{@render a()}
</div>
{/snippet}

<style>
div div {
color: red;
}
</style>