diff --git a/.changeset/small-sheep-type.md b/.changeset/small-sheep-type.md new file mode 100644 index 0000000000..8985dbe826 --- /dev/null +++ b/.changeset/small-sheep-type.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: error when exporting reassigned state from module context diff --git a/packages/svelte/src/compiler/phases/2-analyze/validation.js b/packages/svelte/src/compiler/phases/2-analyze/validation.js index 9a09a1ea53..6bfe56f25e 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/validation.js +++ b/packages/svelte/src/compiler/phases/2-analyze/validation.js @@ -997,11 +997,29 @@ export const validation_runes = merge(validation, a11y_validators, { if (node.label.name !== '$' || path.at(-1)?.type !== 'Program') return; error(node, 'invalid-legacy-reactive-statement'); }, - ExportNamedDeclaration(node, { state }) { - if (node.declaration?.type !== 'VariableDeclaration') return; - if (node.declaration.kind !== 'let') return; - if (state.analysis.instance.scope !== state.scope) return; - error(node, 'invalid-legacy-export'); + ExportNamedDeclaration(node, { state, next }) { + if (state.ast_type === 'module') { + if (node.declaration?.type !== 'VariableDeclaration') return; + + // visit children, so bindings are correctly initialised + next(); + + for (const declarator of node.declaration.declarations) { + for (const id of extract_identifiers(declarator.id)) { + validate_export(node, state.scope, id.name); + } + } + } else { + if (node.declaration?.type !== 'VariableDeclaration') return; + if (node.declaration.kind !== 'let') return; + if (state.analysis.instance.scope !== state.scope) return; + error(node, 'invalid-legacy-export'); + } + }, + ExportSpecifier(node, { state }) { + if (state.ast_type === 'module') { + validate_export(node, state.scope, node.local.name); + } }, CallExpression(node, { state, path }) { validate_call_expression(node, state.scope, path); diff --git a/packages/svelte/tests/compiler-errors/samples/export-state-module/_config.js b/packages/svelte/tests/compiler-errors/samples/export-state-module/_config.js new file mode 100644 index 0000000000..f1bad80670 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/export-state-module/_config.js @@ -0,0 +1,10 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'invalid-state-export', + message: + "Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties", + position: [76, 114] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/export-state-module/main.svelte b/packages/svelte/tests/compiler-errors/samples/export-state-module/main.svelte new file mode 100644 index 0000000000..00a05eae8a --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/export-state-module/main.svelte @@ -0,0 +1,15 @@ +