From e42bb61296d57619404e19a53c887ce777c42fff Mon Sep 17 00:00:00 2001 From: Paolo Ricciuti Date: Thu, 4 Jul 2024 20:45:57 +0200 Subject: [PATCH] fix: ensure components always return an object (#12290) Closes #12287 --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> Co-authored-by: Simon Holthausen --- .changeset/warm-waves-reply.md | 5 ++++ .../3-transform/client/transform-client.js | 3 +++ .../bind-this-frozen/ComponentA.svelte | 5 ++++ .../bind-this-frozen/ComponentB.svelte | 1 + .../samples/bind-this-frozen/_config.js | 26 +++++++++++++++++++ .../samples/bind-this-frozen/main.svelte | 24 +++++++++++++++++ .../_expected/client/index.svelte.js | 1 + .../_expected/client/index.svelte.js | 1 + .../_expected/client/main.svelte.js | 1 + .../_expected/client/index.svelte.js | 1 + .../_expected/client/index.svelte.js | 2 ++ .../_expected/client/index.svelte.js | 1 + .../hmr/_expected/client/index.svelte.js | 1 + .../_expected/client/index.svelte.js | 1 + .../_expected/client/index.svelte.js | 1 + 15 files changed, 74 insertions(+) create mode 100644 .changeset/warm-waves-reply.md create mode 100644 packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentA.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentB.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/bind-this-frozen/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/bind-this-frozen/main.svelte diff --git a/.changeset/warm-waves-reply.md b/.changeset/warm-waves-reply.md new file mode 100644 index 000000000000..7f7f901aa3a9 --- /dev/null +++ b/.changeset/warm-waves-reply.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure component always returns an object diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index d0dd2315a564..222610e1e36c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -339,6 +339,9 @@ export function client_component(source, analysis, options) { ? b.return(b.call('$.pop', b.object(component_returned_object))) : b.stmt(b.call('$.pop')) ); + } else { + // Always return an object, so that `bind:this` on this component will not be falsy + component_block.body.push(b.return(b.object(component_returned_object))); } if (analysis.uses_rest_props) { diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentA.svelte b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentA.svelte new file mode 100644 index 000000000000..c94874725062 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentA.svelte @@ -0,0 +1,5 @@ + + +
a
diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentB.svelte b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentB.svelte new file mode 100644 index 000000000000..6e0b2d36d071 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/ComponentB.svelte @@ -0,0 +1 @@ +
b
diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/_config.js b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/_config.js new file mode 100644 index 000000000000..395899daff87 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/_config.js @@ -0,0 +1,26 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `
a
`, + compileOptions: { + dev: false + }, + + async test({ assert, target, logs, ok }) { + const [btn1, btn2] = target.querySelectorAll('button'); + + flushSync(() => { + btn2.click(); + }); + + assert.htmlEqual(target.innerHTML, `
b
`); + + flushSync(() => { + btn1.click(); + }); + + assert.htmlEqual(target.innerHTML, `
a
`); + assert.deepEqual(logs, [{ a: {} }, {}, { a: {} }]); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/main.svelte b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/main.svelte new file mode 100644 index 000000000000..4b314a33fa7c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/bind-this-frozen/main.svelte @@ -0,0 +1,24 @@ + + + + + +Content diff --git a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js index ba4352d57b80..2ffcbeffabb2 100644 --- a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js @@ -30,4 +30,5 @@ export default function Bind_component_snippet($$anchor) { $.template_effect(() => $.set_text(text, ` value: ${$.get(value) ?? ""}`)); $.append($$anchor, fragment_1); + return {}; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js index bd24eca96227..a2fc02644b3c 100644 --- a/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js @@ -3,4 +3,5 @@ import * as $ from "svelte/internal/client"; export default function Bind_this($$anchor) { $.bind_this(Foo($$anchor, { $$legacy: true }), ($$value) => foo = $$value, () => foo); + return {}; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/dynamic-attributes-casing/_expected/client/main.svelte.js b/packages/svelte/tests/snapshot/samples/dynamic-attributes-casing/_expected/client/main.svelte.js index aa4d22d99a6d..eafec512f626 100644 --- a/packages/svelte/tests/snapshot/samples/dynamic-attributes-casing/_expected/client/main.svelte.js +++ b/packages/svelte/tests/snapshot/samples/dynamic-attributes-casing/_expected/client/main.svelte.js @@ -30,4 +30,5 @@ export default function Main($$anchor) { }); $.append($$anchor, fragment); + return {}; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/each-string-template/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/each-string-template/_expected/client/index.svelte.js index 5d5e47faf2d6..872fa30d8daa 100644 --- a/packages/svelte/tests/snapshot/samples/each-string-template/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/each-string-template/_expected/client/index.svelte.js @@ -13,4 +13,5 @@ export default function Each_string_template($$anchor) { }); $.append($$anchor, fragment); + return {}; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js index 8fb6d075cd7c..512c2d9d8d9f 100644 --- a/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js @@ -22,4 +22,6 @@ export default function Function_prop_no_getter($$anchor) { }, $$slots: { default: true } }); + + return {}; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/hello-world/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/hello-world/_expected/client/index.svelte.js index 92354d8f1483..da64ce05c5dd 100644 --- a/packages/svelte/tests/snapshot/samples/hello-world/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/hello-world/_expected/client/index.svelte.js @@ -7,4 +7,5 @@ export default function Hello_world($$anchor) { var h1 = root(); $.append($$anchor, h1); + return {}; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js index 6cb6845c1cce..7358eefd3081 100644 --- a/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/hmr/_expected/client/index.svelte.js @@ -7,6 +7,7 @@ function Hmr($$anchor) { var h1 = root(); $.append($$anchor, h1); + return {}; } if (import.meta.hot) { diff --git a/packages/svelte/tests/snapshot/samples/state-proxy-literal/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/state-proxy-literal/_expected/client/index.svelte.js index 0f2d6f420094..45427aa6ff1a 100644 --- a/packages/svelte/tests/snapshot/samples/state-proxy-literal/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/state-proxy-literal/_expected/client/index.svelte.js @@ -28,6 +28,7 @@ export default function State_proxy_literal($$anchor) { $.bind_value(input, () => $.get(str), ($$value) => $.set(str, $$value)); $.bind_value(input_1, () => $.get(tpl), ($$value) => $.set(tpl, $$value)); $.append($$anchor, fragment); + return {}; } $.delegate(["click"]); \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/svelte-element/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/svelte-element/_expected/client/index.svelte.js index a4bbea582bf3..484d937327f4 100644 --- a/packages/svelte/tests/snapshot/samples/svelte-element/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/svelte-element/_expected/client/index.svelte.js @@ -8,4 +8,5 @@ export default function Svelte_element($$anchor, $$props) { $.element(node, tag, false); $.append($$anchor, fragment); + return {}; } \ No newline at end of file