diff --git a/packages/svelte/src/compiler/compile/Component.js b/packages/svelte/src/compiler/compile/Component.js index 7598e6096741..6a90888ba254 100644 --- a/packages/svelte/src/compiler/compile/Component.js +++ b/packages/svelte/src/compiler/compile/Component.js @@ -18,7 +18,7 @@ import fuzzymatch from '../utils/fuzzymatch.js'; import get_object from './utils/get_object.js'; import add_to_set from './utils/add_to_set.js'; import check_graph_for_cycles from './utils/check_graph_for_cycles.js'; -import { print, b } from 'code-red'; +import { print, b, x } from 'code-red'; import { is_reserved_keyword } from './utils/reserved_keywords.js'; import { apply_preprocessor_sourcemap } from '../utils/mapped_code.js'; import { clone } from '../utils/clone.js'; @@ -1124,7 +1124,9 @@ export default class Component { if (node.type === 'VariableDeclaration') { // NOTE: `var` does not follow block scoping if (node.kind === 'var' || scope === instance_scope) { + /** @type {import('estree').Node[][]} */ const inserts = []; + /** @type {import('estree').AssignmentProperty[]} */ const props = []; /** @@ -1155,8 +1157,7 @@ export default class Component { // ``` // into // ``` - // let { x: x$, y: y$ = 123 } = OBJ; - // let { x = x$, y = y$, z = 456 } = $$props; + // let { x: x$, y: y$ = 123 } = OBJ, { x = x$, y = y$, z = 456 } = $$props; // ``` for (let index = 0; index < node.declarations.length; index++) { const declarator = node.declarations[index]; @@ -1251,15 +1252,28 @@ export default class Component { } } } - this.replace( - /** @type {any} */ ( - b` - ${node.declarations.length ? node : null} - ${props.length > 0 && b`let { ${props} } = $$props;`} - ${inserts} - ` - ) - ); + + if (props.length > 0) { + node.declarations.push({ + type: 'VariableDeclarator', + id: { + type: 'ObjectPattern', + properties: props + }, + init: x`$$props` + }); + } + + if (inserts.length > 0) { + node.declarations.push({ + type: 'VariableDeclarator', + id: component.get_unique_name('$$subscriptions'), + init: x`(() => { + ${inserts} + })()` + }); + } + return this.skip(); } } diff --git a/packages/svelte/test/js/samples/capture-inject-state/expected.js b/packages/svelte/test/js/samples/capture-inject-state/expected.js index 0c081eaae968..1baea1cf2c2d 100644 --- a/packages/svelte/test/js/samples/capture-inject-state/expected.js +++ b/packages/svelte/test/js/samples/capture-inject-state/expected.js @@ -109,9 +109,13 @@ function instance($$self, $$props, $$invalidate) { $$self.$$.on_destroy.push(() => $$unsubscribe_prop()); let { $$slots: slots = {}, $$scope } = $$props; validate_slots('Component', slots, []); - let { prop } = $$props; - validate_store(prop, 'prop'); - $$subscribe_prop(); + + let { prop } = $$props, + $$subscriptions = (() => { + validate_store(prop, 'prop'); + $$subscribe_prop(); + })(); + let { alias: realName } = $$props; let local; let shadowedByModule; diff --git a/packages/svelte/test/js/samples/component-store-access-invalidate/expected.js b/packages/svelte/test/js/samples/component-store-access-invalidate/expected.js index 4b12c4060061..eb4f35373966 100644 --- a/packages/svelte/test/js/samples/component-store-access-invalidate/expected.js +++ b/packages/svelte/test/js/samples/component-store-access-invalidate/expected.js @@ -43,8 +43,12 @@ function create_fragment(ctx) { function instance($$self, $$props, $$invalidate) { let $foo; - const foo = writable(0); - component_subscribe($$self, foo, value => $$invalidate(0, $foo = value)); + + const foo = writable(0), + $$subscriptions = (() => { + component_subscribe($$self, foo, value => $$invalidate(0, $foo = value)); + })(); + return [$foo, foo]; } diff --git a/packages/svelte/test/js/samples/component-store-reassign-invalidate/expected.js b/packages/svelte/test/js/samples/component-store-reassign-invalidate/expected.js index edff2112ec43..5291e545deef 100644 --- a/packages/svelte/test/js/samples/component-store-reassign-invalidate/expected.js +++ b/packages/svelte/test/js/samples/component-store-reassign-invalidate/expected.js @@ -68,8 +68,12 @@ function instance($$self, $$props, $$invalidate) { $$subscribe_foo = () => ($$unsubscribe_foo(), $$unsubscribe_foo = subscribe(foo, $$value => $$invalidate(1, $foo = $$value)), foo); $$self.$$.on_destroy.push(() => $$unsubscribe_foo()); - let foo = writable(0); - $$subscribe_foo(); + + let foo = writable(0), + $$subscriptions = (() => { + $$subscribe_foo(); + })(); + const click_handler = () => $$subscribe_foo($$invalidate(0, foo = writable(0))); return [foo, $foo, click_handler]; } diff --git a/packages/svelte/test/js/samples/var-in-block/expected.js b/packages/svelte/test/js/samples/var-in-block/expected.js new file mode 100644 index 000000000000..afacd7ba3890 --- /dev/null +++ b/packages/svelte/test/js/samples/var-in-block/expected.js @@ -0,0 +1,48 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + detach, + init, + insert, + noop, + safe_not_equal, + text +} from "svelte/internal"; + +function create_fragment(ctx) { + let t; + + return { + c() { + t = text(/*one*/ ctx[0]); + }, + m(target, anchor) { + insert(target, t, anchor); + }, + p: noop, + i: noop, + o: noop, + d(detaching) { + if (detaching) { + detach(t); + } + } + }; +} + +function instance($$self) { + { + var one = 1; + } + + return [one]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; diff --git a/packages/svelte/test/js/samples/var-in-block/input.svelte b/packages/svelte/test/js/samples/var-in-block/input.svelte new file mode 100644 index 000000000000..5aa45f0aa4ec --- /dev/null +++ b/packages/svelte/test/js/samples/var-in-block/input.svelte @@ -0,0 +1,7 @@ + + +{one} diff --git a/packages/svelte/test/js/samples/variable-declaration-in-switch-case/expected.js b/packages/svelte/test/js/samples/variable-declaration-in-switch-case/expected.js new file mode 100644 index 000000000000..71fbab6a3468 --- /dev/null +++ b/packages/svelte/test/js/samples/variable-declaration-in-switch-case/expected.js @@ -0,0 +1,20 @@ +/* generated by Svelte vX.Y.Z */ +import { SvelteComponent, init, safe_not_equal } from "svelte/internal"; + +function instance($$self) { + switch (1) { + case 1: + const value = Math.random(); + } + + return []; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, null, safe_not_equal, {}); + } +} + +export default Component; diff --git a/packages/svelte/test/js/samples/variable-declaration-in-switch-case/input.svelte b/packages/svelte/test/js/samples/variable-declaration-in-switch-case/input.svelte new file mode 100644 index 000000000000..9f9e326668e5 --- /dev/null +++ b/packages/svelte/test/js/samples/variable-declaration-in-switch-case/input.svelte @@ -0,0 +1,6 @@ + diff --git a/packages/svelte/test/runtime/samples/var-in-block/_config.js b/packages/svelte/test/runtime/samples/var-in-block/_config.js new file mode 100644 index 000000000000..941fdb9c29b3 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-block/_config.js @@ -0,0 +1,3 @@ +export default { + html: '

12345

67890

' +}; diff --git a/packages/svelte/test/runtime/samples/var-in-block/main.svelte b/packages/svelte/test/runtime/samples/var-in-block/main.svelte new file mode 100644 index 000000000000..a115a831724e --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-block/main.svelte @@ -0,0 +1,9 @@ + + +

{foo}

+

{bar}

diff --git a/packages/svelte/test/runtime/samples/var-in-do-while-block/_config.js b/packages/svelte/test/runtime/samples/var-in-do-while-block/_config.js new file mode 100644 index 000000000000..2c49ff177031 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-do-while-block/_config.js @@ -0,0 +1,7 @@ +export default { + props: { + a: 13 + }, + + html: '

169

' +}; diff --git a/packages/svelte/test/runtime/samples/var-in-do-while-block/main.svelte b/packages/svelte/test/runtime/samples/var-in-do-while-block/main.svelte new file mode 100644 index 000000000000..feafc7ce9311 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-do-while-block/main.svelte @@ -0,0 +1,9 @@ + + +

{b}

diff --git a/packages/svelte/test/runtime/samples/var-in-for-in-loop/_config.js b/packages/svelte/test/runtime/samples/var-in-for-in-loop/_config.js new file mode 100644 index 000000000000..9b1998c4ac60 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-for-in-loop/_config.js @@ -0,0 +1,3 @@ +export default { + html: '

0

2

4

6

8

' +}; diff --git a/packages/svelte/test/runtime/samples/var-in-for-in-loop/main.svelte b/packages/svelte/test/runtime/samples/var-in-for-in-loop/main.svelte new file mode 100644 index 000000000000..5a318153a054 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-for-in-loop/main.svelte @@ -0,0 +1,10 @@ + + +{#each array as a} +

{a}

+{/each} diff --git a/packages/svelte/test/runtime/samples/var-in-for-loop/_config.js b/packages/svelte/test/runtime/samples/var-in-for-loop/_config.js new file mode 100644 index 000000000000..90d76669a185 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-for-loop/_config.js @@ -0,0 +1,3 @@ +export default { + html: '

0

1

2

3

4

' +}; diff --git a/packages/svelte/test/runtime/samples/var-in-for-loop/main.svelte b/packages/svelte/test/runtime/samples/var-in-for-loop/main.svelte new file mode 100644 index 000000000000..413271c16396 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-for-loop/main.svelte @@ -0,0 +1,10 @@ + + +{#each array as a} +

{a}

+{/each} diff --git a/packages/svelte/test/runtime/samples/var-in-function/_config.js b/packages/svelte/test/runtime/samples/var-in-function/_config.js new file mode 100644 index 000000000000..32e9b89383cd --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-function/_config.js @@ -0,0 +1,11 @@ +export default { + html: '

0

', + + async test({ assert, target, window }) { + const button = target.querySelector('button'); + const clickEvent = new window.MouseEvent('click'); + + await button.dispatchEvent(clickEvent); + assert.htmlEqual(target.innerHTML, '

4

'); + } +}; diff --git a/packages/svelte/test/runtime/samples/var-in-function/main.svelte b/packages/svelte/test/runtime/samples/var-in-function/main.svelte new file mode 100644 index 000000000000..d81a2ee781b1 --- /dev/null +++ b/packages/svelte/test/runtime/samples/var-in-function/main.svelte @@ -0,0 +1,10 @@ + + +