fix: ensure implicit children snippet renders correctly (#9706)

place anchors around render tags, not snippet tags
fixes #9678
pull/9715/head
Simon H 1 year ago committed by GitHub
parent bde42d5676
commit 2416587215
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure implicit children snippet renders correctly

@ -1125,11 +1125,17 @@ const template_visitors = {
);
},
RenderTag(node, context) {
const snippet_function = context.state.options.dev
const state = context.state;
const [anchor, anchor_id] = serialize_anchor(state);
state.init.push(anchor);
state.template.push(t_expression(anchor_id));
const snippet_function = state.options.dev
? b.call('$.validate_snippet', node.expression)
: node.expression;
if (node.argument) {
context.state.template.push(
state.template.push(
t_statement(
b.stmt(
b.call(
@ -1141,8 +1147,10 @@ const template_visitors = {
)
);
} else {
context.state.template.push(t_statement(b.stmt(b.call(snippet_function, b.id('$$payload')))));
state.template.push(t_statement(b.stmt(b.call(snippet_function, b.id('$$payload')))));
}
state.template.push(t_expression(anchor_id));
},
ClassDirective(node) {
error(node, 'INTERNAL', 'Node should have been handled elsewhere');
@ -1435,8 +1443,6 @@ const template_visitors = {
state.template.push(t_expression(id));
},
SnippetBlock(node, context) {
const [dec, id] = serialize_anchor(context.state);
// TODO hoist where possible
/** @type {import('estree').Pattern[]} */
const args = [b.id('$$payload')];
@ -1444,18 +1450,11 @@ const template_visitors = {
args.push(node.context);
}
const out = b.member_id('$$payload.out');
context.state.init.push(
b.function_declaration(
node.expression,
args,
b.block([
dec,
b.stmt(b.assignment('+=', out, id)),
.../** @type {import('estree').BlockStatement} */ (context.visit(node.body)).body,
b.stmt(b.assignment('+=', out, id))
])
/** @type {import('estree').BlockStatement} */ (context.visit(node.body))
)
);
if (context.state.options.dev) {

@ -0,0 +1,7 @@
<script>
const { children, change } = $props();
</script>
<button onclick={change}>
{@render children()}
</button>

@ -0,0 +1,16 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<button><span>hidden</span></button>`,
async test({ assert, target }) {
const [b1] = target.querySelectorAll('button');
flushSync(() => {
b1?.click();
});
assert.htmlEqual(target.innerHTML, `<button><span>showing</span></button>`);
}
});

@ -0,0 +1,13 @@
<script>
import Button from "./Button.svelte";
let show = $state(false);
</script>
<Button change={() => show = true}>
{#if show}
<span>showing</span>
{:else}
<span>hidden</span>
{/if}
</Button>
Loading…
Cancel
Save