fix: deconflict multiple snippets of the same name

pull/12221/head
Dominic Gannaway 4 months ago
parent c42bb04276
commit 426792492a

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: deconflict multiple snippets of the same name

@ -1096,13 +1096,12 @@ function serialize_update(statement) {
}
/**
*
* @param {import('../types.js').ComponentClientTransformState} state
* @param {import('estree').Statement[]} update
*/
function serialize_render_stmt(state) {
return state.update.length === 1
? serialize_update(state.update[0])
: b.stmt(b.call('$.template_effect', b.thunk(b.block(state.update))));
function serialize_render_stmt(update) {
return update.length === 1
? serialize_update(update[0])
: b.stmt(b.call('$.template_effect', b.thunk(b.block(update))));
}
/**
@ -1709,7 +1708,7 @@ export const template_visitors = {
}
if (state.update.length > 0) {
body.push(serialize_render_stmt(state));
body.push(serialize_render_stmt(state.update));
}
body.push(...state.after_update);
@ -2157,8 +2156,21 @@ export const template_visitors = {
state.options.preserveComments
);
/**
* @type {import("estree").Statement[]}
*/
const init = [];
/**
* @type {never[]}
*/
const update = [];
/**
* @type {never[]}
*/
const after_update = [];
for (const node of hoisted) {
context.visit(node, state);
context.visit(node, { ...state, init, update, after_update });
}
process_children(
@ -2171,9 +2183,13 @@ export const template_visitors = {
: context.state.node
),
true,
{ ...context, state }
{ ...context, state: { ...state, init, update, after_update } }
);
if (init.length !== 0 || update.length !== 0 || after_update.length !== 0) {
context.state.init.push(b.block([...init, serialize_render_stmt(update), ...after_update]));
}
if (has_direction_attribute) {
// This fixes an issue with Chromium where updates to text content within an element
// does not update the direction when set to auto. If we just re-assign the dir, this fixes it.
@ -2270,7 +2286,7 @@ export const template_visitors = {
/** @type {import('estree').Statement[]} */
const inner = inner_context.state.init;
if (inner_context.state.update.length > 0) {
inner.push(serialize_render_stmt(inner_context.state));
inner.push(serialize_render_stmt(inner_context.state.update));
}
inner.push(...inner_context.state.after_update);
inner.push(
@ -2735,7 +2751,7 @@ export const template_visitors = {
snippet = b.call('$.wrap_snippet', snippet, b.id(context.state.analysis.name));
}
const declaration = b.var(node.expression, snippet);
const declaration = b.const(node.expression, snippet);
// Top-level snippets are hoisted so they can be referenced in the `<script>`
if (context.path.length === 1 && context.path[0].type === 'Fragment') {

@ -3,4 +3,4 @@
<svelte:element this={"div"} />
<!-- we don't try to fix this bug, we just leave it as-is -->
<svelte:element this="h{n}" />
<svelte:element this="h{n}" />

@ -27,8 +27,8 @@
"parameters": [
{
"type": "Identifier",
"name": "msg",
"start": 43,
"end": 46,
"loc": {
"start": {
"line": 3,
@ -39,7 +39,7 @@
"column": 25
}
},
"end": 46,
"name": "msg",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start": 46,

@ -0,0 +1,24 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
mode: ['client'],
test({ assert, target }) {
const btn = target.querySelector('button');
btn?.click();
btn?.click();
btn?.click();
flushSync();
assert.htmlEqual(
target.innerHTML,
`
<button>push</button><div style="display: grid; grid-template-columns: 1fr 1fr"><div><p style="color: red">1</p><p style="color: red">2</p><p style="color: red">3</p>
<p style="color: red">4</p><p style="color: red">5</p><p style="color: red">6</p></div><div><p style="color: blue">1</p><p style="color: blue">2</p><p style="color: blue">3</p>
<p style="color: blue">4</p><p style="color: blue">5</p><p style="color: blue">6</p></div></div>
`
);
}
});

@ -0,0 +1,29 @@
<script>
let numbers = $state([1, 2, 3]);
</script>
<button onclick={() => numbers.push(numbers.length + 1)}>
push
</button>
<div style="display: grid; grid-template-columns: 1fr 1fr">
<div>
{#snippet x(n)}
<p style="color: red">{n}</p>
{/snippet}
{#each numbers as n}
{@render x(n)}
{/each}
</div>
<div>
{#snippet x(n)}
<p style="color: blue">{n}</p>
{/snippet}
{#each numbers as n}
{@render x(n)}
{/each}
</div>
</div>

@ -6,7 +6,7 @@ var root_1 = $.template(`Something`, 1);
var root = $.template(`<!> `, 1);
export default function Bind_component_snippet($$anchor) {
var snippet = ($$anchor) => {
const snippet = ($$anchor) => {
var fragment = root_1();
$.append($$anchor, fragment);

@ -30,4 +30,4 @@ export default function State_proxy_literal($$anchor) {
$.append($$anchor, fragment);
}
$.delegate(["click"]);
$.delegate(["click"]);
Loading…
Cancel
Save