From 252f58e09c40498426155202ff78243b7271ee13 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Fri, 9 Feb 2024 12:59:14 +0100 Subject: [PATCH] fix: throw validation error when binding to each argument in runes mode closes #10437 --- .changeset/mighty-files-hammer.md | 5 +++++ packages/svelte/src/compiler/errors.js | 3 ++- .../src/compiler/phases/2-analyze/validation.js | 14 +++++++------- .../samples/runes-invalid-each-binding/_config.js | 9 +++++++++ .../samples/runes-invalid-each-binding/main.svelte | 7 +++++++ .../samples/runes-invalid-each-mutation/_config.js | 3 ++- .../runes-invalid-each-mutation/main.svelte | 2 +- 7 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 .changeset/mighty-files-hammer.md create mode 100644 packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/main.svelte diff --git a/.changeset/mighty-files-hammer.md b/.changeset/mighty-files-hammer.md new file mode 100644 index 000000000000..889e3482d3c6 --- /dev/null +++ b/.changeset/mighty-files-hammer.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: throw validation error when binding to each argument in runes mode diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 6588e71d9784..9ecd14141633 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -207,7 +207,8 @@ const runes = { /** @param {string} name */ 'invalid-runes-mode-import': (name) => `${name} cannot be used in runes mode`, '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} */ diff --git a/packages/svelte/src/compiler/phases/2-analyze/validation.js b/packages/svelte/src/compiler/phases/2-analyze/validation.js index ca6bc00efe26..8af0a2940240 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/validation.js +++ b/packages/svelte/src/compiler/phases/2-analyze/validation.js @@ -1,5 +1,5 @@ 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 fuzzymatch from '../1-parse/utils/fuzzymatch.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); const assignee = node.expression; - let left = assignee; + const left = object(assignee); - while (left.type === 'MemberExpression') { - left = /** @type {import('estree').MemberExpression} */ (left.object); - } - - if (left.type !== 'Identifier') { + if (left === null) { error(node, 'invalid-binding-expression'); } @@ -373,6 +369,10 @@ const validation = { 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 } diff --git a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/_config.js b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/_config.js new file mode 100644 index 000000000000..55eb0280ae6a --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/_config.js @@ -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')" + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/main.svelte b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/main.svelte new file mode 100644 index 000000000000..abf6d202a731 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding/main.svelte @@ -0,0 +1,7 @@ + + +{#each arr as value} + +{/each} diff --git a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/_config.js b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/_config.js index eee6ca5c8d4f..55eb0280ae6a 100644 --- a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/_config.js +++ b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/_config.js @@ -3,6 +3,7 @@ import { test } from '../../test'; export default test({ error: { 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')" } }); diff --git a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/main.svelte b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/main.svelte index f9744c08de8a..41999d53bb84 100644 --- a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/main.svelte +++ b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-mutation/main.svelte @@ -3,5 +3,5 @@ {#each arr as value} - + {/each}