Skip to content

Commit b1267b0

Browse files
authored
fix: error when exporting reassigned state from module context (#10728)
fixes #10380
1 parent ae4af68 commit b1267b0

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

.changeset/small-sheep-type.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: error when exporting reassigned state from module context

packages/svelte/src/compiler/phases/2-analyze/validation.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -997,11 +997,29 @@ export const validation_runes = merge(validation, a11y_validators, {
997997
if (node.label.name !== '$' || path.at(-1)?.type !== 'Program') return;
998998
error(node, 'invalid-legacy-reactive-statement');
999999
},
1000-
ExportNamedDeclaration(node, { state }) {
1001-
if (node.declaration?.type !== 'VariableDeclaration') return;
1002-
if (node.declaration.kind !== 'let') return;
1003-
if (state.analysis.instance.scope !== state.scope) return;
1004-
error(node, 'invalid-legacy-export');
1000+
ExportNamedDeclaration(node, { state, next }) {
1001+
if (state.ast_type === 'module') {
1002+
if (node.declaration?.type !== 'VariableDeclaration') return;
1003+
1004+
// visit children, so bindings are correctly initialised
1005+
next();
1006+
1007+
for (const declarator of node.declaration.declarations) {
1008+
for (const id of extract_identifiers(declarator.id)) {
1009+
validate_export(node, state.scope, id.name);
1010+
}
1011+
}
1012+
} else {
1013+
if (node.declaration?.type !== 'VariableDeclaration') return;
1014+
if (node.declaration.kind !== 'let') return;
1015+
if (state.analysis.instance.scope !== state.scope) return;
1016+
error(node, 'invalid-legacy-export');
1017+
}
1018+
},
1019+
ExportSpecifier(node, { state }) {
1020+
if (state.ast_type === 'module') {
1021+
validate_export(node, state.scope, node.local.name);
1022+
}
10051023
},
10061024
CallExpression(node, { state, path }) {
10071025
validate_call_expression(node, state.scope, path);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
error: {
5+
code: 'invalid-state-export',
6+
message:
7+
"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",
8+
position: [76, 114]
9+
}
10+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script context="module">
2+
export const object = $state({
3+
ok: true
4+
});
5+
6+
export let primitive = $state('nope');
7+
8+
export function update_object() {
9+
object.ok = !object.ok;
10+
}
11+
12+
export function update_primitive() {
13+
primitive = 'yep';
14+
}
15+
</script>

0 commit comments

Comments
 (0)