From ae10f4d37cfa3904751ae4f58559d66c3502fe75 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Sat, 19 Oct 2024 13:38:41 +0100 Subject: [PATCH] breaking: state mutations inside the template are no longer allowed (#13660) * breaking: state mutations inside the template are no longer allowed * fix test * fix test * lint * update error message * fix test --- .changeset/wild-chairs-build.md | 5 +++++ .../98-reference/.generated/client-errors.md | 2 +- .../svelte/messages/client-errors/errors.md | 2 +- packages/svelte/src/internal/client/errors.js | 4 ++-- .../src/internal/client/reactivity/effects.js | 2 +- .../samples/side-effect-template/_config.js | 17 +++++++++++++++++ .../samples/side-effect-template/main.svelte | 6 ++++++ .../main.svelte | 5 ++++- 8 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 .changeset/wild-chairs-build.md create mode 100644 packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte diff --git a/.changeset/wild-chairs-build.md b/.changeset/wild-chairs-build.md new file mode 100644 index 0000000000..494a3d70c5 --- /dev/null +++ b/.changeset/wild-chairs-build.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +breaking: state mutations inside the template are no longer allowed diff --git a/documentation/docs/98-reference/.generated/client-errors.md b/documentation/docs/98-reference/.generated/client-errors.md index 4e7016b337..d6bd276de7 100644 --- a/documentation/docs/98-reference/.generated/client-errors.md +++ b/documentation/docs/98-reference/.generated/client-errors.md @@ -125,5 +125,5 @@ Reading state that was created inside the same derived is forbidden. Consider us ### state_unsafe_mutation ``` -Updating state inside a derived or logic block expression is forbidden. If the value should not be reactive, declare it without `$state` +Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state` ``` diff --git a/packages/svelte/messages/client-errors/errors.md b/packages/svelte/messages/client-errors/errors.md index 570a384d7c..954214cb81 100644 --- a/packages/svelte/messages/client-errors/errors.md +++ b/packages/svelte/messages/client-errors/errors.md @@ -82,4 +82,4 @@ ## state_unsafe_mutation -> Updating state inside a derived or logic block expression is forbidden. If the value should not be reactive, declare it without `$state` +> Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state` diff --git a/packages/svelte/src/internal/client/errors.js b/packages/svelte/src/internal/client/errors.js index a0f33fb784..2a8f0e8914 100644 --- a/packages/svelte/src/internal/client/errors.js +++ b/packages/svelte/src/internal/client/errors.js @@ -343,12 +343,12 @@ export function state_unsafe_local_read() { } /** - * Updating state inside a derived or logic block expression is forbidden. If the value should not be reactive, declare it without `$state` + * Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state` * @returns {never} */ export function state_unsafe_mutation() { if (DEV) { - const error = new Error(`state_unsafe_mutation\nUpdating state inside a derived or logic block expression is forbidden. If the value should not be reactive, declare it without \`$state\``); + const error = new Error(`state_unsafe_mutation\nUpdating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without \`$state\``); error.name = 'Svelte error'; throw error; diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index ba17b8d5aa..193c6df145 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -326,7 +326,7 @@ export function template_effect(fn) { value: '{expression}' }); } - return render_effect(fn); + return block(fn); } /** diff --git a/packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js b/packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js new file mode 100644 index 0000000000..b17c83849f --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js @@ -0,0 +1,17 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true + }, + + test({ assert, target }) { + const button = target.querySelector('button'); + + assert.throws(() => { + button?.click(); + flushSync(); + }, /state_unsafe_mutation/); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte b/packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte new file mode 100644 index 0000000000..0a53a08673 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte @@ -0,0 +1,6 @@ + + + +{JSON.stringify(items.sort())} diff --git a/packages/svelte/tests/runtime-runes/samples/store-unsubscribe-not-referenced-after/main.svelte b/packages/svelte/tests/runtime-runes/samples/store-unsubscribe-not-referenced-after/main.svelte index 5f8b19f4c7..e097c639f0 100644 --- a/packages/svelte/tests/runtime-runes/samples/store-unsubscribe-not-referenced-after/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/store-unsubscribe-not-referenced-after/main.svelte @@ -1,4 +1,5 @@