From 1ad7aef5df9e270835d303d96e0538cf11445fcd Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Wed, 8 Jan 2025 16:42:06 +0100 Subject: [PATCH 1/2] docs: tweak "invalid assignment" compiler error message fixes #14702 --- .changeset/sharp-dryers-try.md | 5 +++ .../98-reference/.generated/compile-errors.md | 32 ++++++++++++++++++- .../svelte/messages/compile-errors/script.md | 32 ++++++++++++++++++- packages/svelte/src/compiler/errors.js | 4 +-- 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 .changeset/sharp-dryers-try.md diff --git a/.changeset/sharp-dryers-try.md b/.changeset/sharp-dryers-try.md new file mode 100644 index 000000000000..dcdbd99d0293 --- /dev/null +++ b/.changeset/sharp-dryers-try.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: tweak "invalid assignment" compiler error message diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index c4989200075d..acbefa47f114 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -331,7 +331,37 @@ The $ prefix is reserved, and cannot be used for variables and imports ### each_item_invalid_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`) +Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments `array[i] = value` instead of `entry = value`, for bindings `bind:prop={array[i]}` instead of `bind:prop={value}` +``` + +In legacy mode, it was possible to reassign or bind to the each block argument itself: + +```svelte + + +{#each array as entry} + + + + +{/each} +``` + +This is no longer possible in runes mode, because the array could also be a computed value such as `{#each array.filter((i) => i % 2)}`, at which point things get unstable. Svelte therefore requires you to be explicit about what to bind to, requiring a stable reference. Therefore, use the array and index variables instead: + +```svelte + + +{#each array as entry, idx} + + + + +{/each} ``` ### effect_invalid_placement diff --git a/packages/svelte/messages/compile-errors/script.md b/packages/svelte/messages/compile-errors/script.md index fa851cec89ea..2841516c6d8f 100644 --- a/packages/svelte/messages/compile-errors/script.md +++ b/packages/svelte/messages/compile-errors/script.md @@ -32,7 +32,37 @@ ## each_item_invalid_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`) +> Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments `array[i] = value` instead of `entry = value`, for bindings `bind:prop={array[i]}` instead of `bind:prop={value}` + +In legacy mode, it was possible to reassign or bind to the each block argument itself: + +```svelte + + +{#each array as entry} + + + + +{/each} +``` + +This is no longer possible in runes mode, because the array could also be a computed value such as `{#each array.filter((i) => i % 2)}`, at which point things get unstable. Svelte therefore requires you to be explicit about what to bind to, requiring a stable reference. Therefore, use the array and index variables instead: + +```svelte + + +{#each array as entry, idx} + + + + +{/each} +``` ## effect_invalid_placement diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 870cd9ac093d..8d8a2c6d2ac9 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -151,12 +151,12 @@ export function dollar_prefix_invalid(node) { } /** - * 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`) + * Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments `array[i] = value` instead of `entry = value`, for bindings `bind:prop={array[i]}` instead of `bind:prop={value}` * @param {null | number | NodeLike} node * @returns {never} */ export function each_item_invalid_assignment(node) { - e(node, "each_item_invalid_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\`)\nhttps://svelte.dev/e/each_item_invalid_assignment`); + e(node, "each_item_invalid_assignment", `Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments \`array[i] = value\` instead of \`entry = value\`, for bindings \`bind:prop={array[i]}\` instead of \`bind:prop={value}\`\nhttps://svelte.dev/e/each_item_invalid_assignment`); } /** From cc960d37e9f814fdb86ac0071f506a6381de9ea4 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 8 Jan 2025 13:17:20 -0500 Subject: [PATCH 2/2] tweak wording --- .../docs/98-reference/.generated/compile-errors.md | 12 +++++++----- packages/svelte/messages/compile-errors/script.md | 12 +++++++----- packages/svelte/src/compiler/errors.js | 4 ++-- .../runes-invalid-each-binding-this/_config.js | 2 +- .../samples/runes-invalid-each-binding/_config.js | 2 +- .../samples/runes-invalid-each-mutation/_config.js | 2 +- 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/documentation/docs/98-reference/.generated/compile-errors.md b/documentation/docs/98-reference/.generated/compile-errors.md index acbefa47f114..a867cfe88cb9 100644 --- a/documentation/docs/98-reference/.generated/compile-errors.md +++ b/documentation/docs/98-reference/.generated/compile-errors.md @@ -331,7 +331,7 @@ The $ prefix is reserved, and cannot be used for variables and imports ### each_item_invalid_assignment ``` -Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments `array[i] = value` instead of `entry = value`, for bindings `bind:prop={array[i]}` instead of `bind:prop={value}` +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`, or `bind:value={array[i]}` instead of `bind:value={entry}`) ``` In legacy mode, it was possible to reassign or bind to the each block argument itself: @@ -344,23 +344,25 @@ In legacy mode, it was possible to reassign or bind to the each block argument i {#each array as entry} + {/each} ``` -This is no longer possible in runes mode, because the array could also be a computed value such as `{#each array.filter((i) => i % 2)}`, at which point things get unstable. Svelte therefore requires you to be explicit about what to bind to, requiring a stable reference. Therefore, use the array and index variables instead: +This turned out to be buggy and unpredictable, particularly when working with derived values (such as `array.map(...)`), and as such is forbidden in runes mode. You can achieve the same outcome by using the index instead: ```svelte -{#each array as entry, idx} +{#each array as entry, i} - + + - + {/each} ``` diff --git a/packages/svelte/messages/compile-errors/script.md b/packages/svelte/messages/compile-errors/script.md index 2841516c6d8f..0aa6fbed90d8 100644 --- a/packages/svelte/messages/compile-errors/script.md +++ b/packages/svelte/messages/compile-errors/script.md @@ -32,7 +32,7 @@ ## each_item_invalid_assignment -> Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments `array[i] = value` instead of `entry = value`, for bindings `bind:prop={array[i]}` instead of `bind:prop={value}` +> 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`, or `bind:value={array[i]}` instead of `bind:value={entry}`) In legacy mode, it was possible to reassign or bind to the each block argument itself: @@ -44,23 +44,25 @@ In legacy mode, it was possible to reassign or bind to the each block argument i {#each array as entry} + {/each} ``` -This is no longer possible in runes mode, because the array could also be a computed value such as `{#each array.filter((i) => i % 2)}`, at which point things get unstable. Svelte therefore requires you to be explicit about what to bind to, requiring a stable reference. Therefore, use the array and index variables instead: +This turned out to be buggy and unpredictable, particularly when working with derived values (such as `array.map(...)`), and as such is forbidden in runes mode. You can achieve the same outcome by using the index instead: ```svelte -{#each array as entry, idx} +{#each array as entry, i} - + + - + {/each} ``` diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 8d8a2c6d2ac9..a997eeef8d7c 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -151,12 +151,12 @@ export function dollar_prefix_invalid(node) { } /** - * Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments `array[i] = value` instead of `entry = value`, for bindings `bind:prop={array[i]}` instead of `bind:prop={value}` + * 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`, or `bind:value={array[i]}` instead of `bind:value={entry}`) * @param {null | number | NodeLike} node * @returns {never} */ export function each_item_invalid_assignment(node) { - e(node, "each_item_invalid_assignment", `Cannot reassign or bind to the each block argument itself in runes mode. Use the array and index variables instead: For reassignments \`array[i] = value\` instead of \`entry = value\`, for bindings \`bind:prop={array[i]}\` instead of \`bind:prop={value}\`\nhttps://svelte.dev/e/each_item_invalid_assignment`); + e(node, "each_item_invalid_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\`, or \`bind:value={array[i]}\` instead of \`bind:value={entry}\`)\nhttps://svelte.dev/e/each_item_invalid_assignment`); } /** diff --git a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding-this/_config.js b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding-this/_config.js index 524c2f161c27..ed02e0960d39 100644 --- a/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding-this/_config.js +++ b/packages/svelte/tests/compiler-errors/samples/runes-invalid-each-binding-this/_config.js @@ -4,6 +4,6 @@ export default test({ error: { code: 'each_item_invalid_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`)' + '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`, or `bind:value={array[i]}` instead of `bind:value={entry}`)' } }); 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 index 524c2f161c27..ed02e0960d39 100644 --- 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 @@ -4,6 +4,6 @@ export default test({ error: { code: 'each_item_invalid_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`)' + '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`, or `bind:value={array[i]}` instead of `bind:value={entry}`)' } }); 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 524c2f161c27..ed02e0960d39 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 @@ -4,6 +4,6 @@ export default test({ error: { code: 'each_item_invalid_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`)' + '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`, or `bind:value={array[i]}` instead of `bind:value={entry}`)' } });