fix: throw validation error when binding to each argument in runes mode (#10441)

closes #10437
pull/10446/head
Simon H 9 months ago committed by GitHub
parent 49bfb6b1d6
commit 456cf843d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: throw validation error when binding to each argument in runes mode

@ -207,7 +207,8 @@ const runes = {
/** @param {string} name */ /** @param {string} name */
'invalid-runes-mode-import': (name) => `${name} cannot be used in runes mode`, 'invalid-runes-mode-import': (name) => `${name} cannot be used in runes mode`,
'duplicate-props-rune': () => `Cannot use $props() more than once`, 'duplicate-props-rune': () => `Cannot use $props() more than once`,
'invalid-each-assignment': () => `Cannot reassign each block argument in runes mode` 'invalid-each-assignment': () =>
`Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. 'array[i] = value' instead of 'entry = value')`
}; };
/** @satisfies {Errors} */ /** @satisfies {Errors} */

@ -1,5 +1,5 @@
import { error } from '../../errors.js'; import { error } from '../../errors.js';
import { extract_identifiers, get_parent, is_text_attribute } from '../../utils/ast.js'; import { extract_identifiers, get_parent, is_text_attribute, object } from '../../utils/ast.js';
import { warn } from '../../warnings.js'; import { warn } from '../../warnings.js';
import fuzzymatch from '../1-parse/utils/fuzzymatch.js'; import fuzzymatch from '../1-parse/utils/fuzzymatch.js';
import { disallowed_parapgraph_contents, interactive_elements } from '../1-parse/utils/html.js'; import { disallowed_parapgraph_contents, interactive_elements } from '../1-parse/utils/html.js';
@ -341,13 +341,9 @@ const validation = {
validate_no_const_assignment(node, node.expression, context.state.scope, true); validate_no_const_assignment(node, node.expression, context.state.scope, true);
const assignee = node.expression; const assignee = node.expression;
let left = assignee; const left = object(assignee);
while (left.type === 'MemberExpression') { if (left === null) {
left = /** @type {import('estree').MemberExpression} */ (left.object);
}
if (left.type !== 'Identifier') {
error(node, 'invalid-binding-expression'); error(node, 'invalid-binding-expression');
} }
@ -373,6 +369,10 @@ const validation = {
error(node.expression, 'invalid-derived-binding'); error(node.expression, 'invalid-derived-binding');
} }
if (context.state.analysis.runes && binding.kind === 'each') {
error(node, 'invalid-each-assignment');
}
// TODO handle mutations of non-state/props in runes mode // TODO handle mutations of non-state/props in runes mode
} }

@ -0,0 +1,9 @@
import { test } from '../../test';
export default test({
error: {
code: 'invalid-each-assignment',
message:
"Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. 'array[i] = value' instead of 'entry = value')"
}
});

@ -0,0 +1,7 @@
<script>
let arr = $state([1,2,3]);
</script>
{#each arr as value}
<input bind:value>
{/each}

@ -3,6 +3,7 @@ import { test } from '../../test';
export default test({ export default test({
error: { error: {
code: 'invalid-each-assignment', code: 'invalid-each-assignment',
message: 'Cannot reassign each block argument in runes mode' message:
"Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. 'array[i] = value' instead of 'entry = value')"
} }
}); });

@ -3,5 +3,5 @@
</script> </script>
{#each arr as value} {#each arr as value}
<button onclick={() => value += 1}>click</button> <button onclick={() => value += 1}>click</button>
{/each} {/each}

Loading…
Cancel
Save