From e3e348df35b22f9c80689dfa03eb421971dfb9cd Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Fri, 10 Jan 2025 17:06:36 +0100 Subject: [PATCH 1/2] fix: don't hoist types referencing stores or destructured variables #2659 --- .../svelte2tsx/nodes/HoistableInterfaces.ts | 28 +++++++++++++++++-- .../expectedv2.ts | 11 ++++++++ .../input.svelte | 4 +++ .../expectedv2.ts | 14 ++++++++++ .../input.svelte | 7 +++++ 5 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/input.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/input.svelte diff --git a/packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts b/packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts index bca4a25ce..8fd726ff6 100644 --- a/packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts +++ b/packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts @@ -179,6 +179,19 @@ export class HoistableInterfaces { node.declarationList.declarations.forEach((declaration) => { if (ts.isIdentifier(declaration.name)) { this.disallowed_values.add(declaration.name.text); + } else { + const walk = (node: ts.Node) => { + if ( + ts.isIdentifier(node) && + ts.isBindingElement(node.parent) && + node.parent.name === node + ) { + this.disallowed_values.add(node.text); + } + ts.forEachChild(node, walk); + }; + + walk(declaration.name); } }); } @@ -256,7 +269,7 @@ export class HoistableInterfaces { } for (const dep of deps.value_deps) { - if (this.disallowed_values.has(dep)) { + if (!this.isAllowedReference(dep)) { this.disallowed_types.add(interface_name); can_hoist = false; break; @@ -275,7 +288,7 @@ export class HoistableInterfaces { ...this.props_interface.type_deps, ...this.props_interface.value_deps ].every((dep) => { - return !this.disallowed_types.has(dep) && !this.disallowed_values.has(dep); + return !this.disallowed_types.has(dep) && this.isAllowedReference(dep); }); if (can_hoist) { @@ -333,7 +346,16 @@ export class HoistableInterfaces { } isAllowedReference(reference: string) { - return !this.disallowed_values.has(reference); + return !( + this.disallowed_values.has(reference) || + reference === '$$props' || + reference === '$$restProps' || + reference === '$$slots' || + // could be a $store reference + (reference[0] === '$' && + reference[1] !== '$' && + this.disallowed_values.has(reference.slice(1))) + ); } /** diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/expectedv2.ts new file mode 100644 index 000000000..23dd09fb8 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/expectedv2.ts @@ -0,0 +1,11 @@ +/// +;function render() { + + let store = null/*Ωignore_startΩ*/;let $store = __sveltets_2_store_get(store);/*Ωignore_endΩ*/;;type $$ComponentProps = { someProp: typeof $store }; + let { someProp }:/*Ωignore_startΩ*/$$ComponentProps/*Ωignore_endΩ*/ = $props(); +; +async () => {}; +return { props: {} as any as $$ComponentProps, exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }} +const Input__SvelteComponent_ = __sveltets_2_fn_component(render()); +type Input__SvelteComponent_ = ReturnType; +export default Input__SvelteComponent_; \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/input.svelte new file mode 100644 index 000000000..452f0d22c --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-6.v5/input.svelte @@ -0,0 +1,4 @@ + diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/expectedv2.ts new file mode 100644 index 000000000..c5bbee061 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/expectedv2.ts @@ -0,0 +1,14 @@ +/// +;function render() { + + let { destructured } = {}; + type Props = { + prop: typeof destructured; + }; + let { prop }: Props = $props(); +; +async () => {}; +return { props: {} as any as Props, exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }} +const Input__SvelteComponent_ = __sveltets_2_fn_component(render()); +type Input__SvelteComponent_ = ReturnType; +export default Input__SvelteComponent_; \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/input.svelte new file mode 100644 index 000000000..1e219d3e8 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-false-7.v5/input.svelte @@ -0,0 +1,7 @@ + \ No newline at end of file From 0c4119ebe56523c1c4f9c5fe4ac0330ea69e4d5e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Fri, 10 Jan 2025 17:23:54 +0100 Subject: [PATCH 2/2] fix --- packages/svelte-vscode/prettier-options-schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte-vscode/prettier-options-schema.json b/packages/svelte-vscode/prettier-options-schema.json index 5d3877d07..382633ee4 100644 --- a/packages/svelte-vscode/prettier-options-schema.json +++ b/packages/svelte-vscode/prettier-options-schema.json @@ -33,7 +33,7 @@ "styles-options-scripts-markup", "styles-scripts-markup-options", "styles-scripts-options-markup", - "none", + "none" ] }, "svelteStrictMode": {