From 6f937f6c7f015920626cc8a3c54f281ebc6fbab7 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 18 Oct 2024 02:31:02 +0100 Subject: [PATCH 1/6] breaking: state mutations inside the template are no longer allowed --- .changeset/wild-chairs-build.md | 5 +++++ .../src/internal/client/reactivity/effects.js | 2 +- packages/svelte/src/store/shared/index.js | 8 +++++++- .../samples/side-effect-template/_config.js | 14 ++++++++++++++ .../samples/side-effect-template/main.svelte | 7 +++++++ 5 files changed, 34 insertions(+), 2 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 000000000000..494a3d70c5d8 --- /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/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 73286861d2b5..d81de41a4fd7 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -325,7 +325,7 @@ export function template_effect(fn) { value: '{expression}' }); } - return render_effect(fn); + return block(fn); } /** diff --git a/packages/svelte/src/store/shared/index.js b/packages/svelte/src/store/shared/index.js index 2b923609d16b..589231aa7dff 100644 --- a/packages/svelte/src/store/shared/index.js +++ b/packages/svelte/src/store/shared/index.js @@ -3,6 +3,8 @@ import { noop, run_all } from '../../internal/shared/utils.js'; import { safe_not_equal } from '../../internal/client/reactivity/equality.js'; import { subscribe_to_store } from '../utils.js'; +import { queue_micro_task } from '../../internal/client/dom/task.js'; +import { active_effect } from '../../internal/client/runtime.js'; /** * @type {Array | any>} @@ -168,7 +170,11 @@ export function derived(stores, fn, initial_value) { ) ); started = true; - sync(); + if (active_effect === null) { + sync(); + } else { + queue_micro_task(sync); + } return function stop() { run_all(unsubscribers); cleanup(); 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 000000000000..1616b49860b8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js @@ -0,0 +1,14 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true + }, + + test({ assert, target }) { + const button = target.querySelector('button'); + + assert.throws(() => {}, /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 000000000000..c7cf0d4690f0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte @@ -0,0 +1,7 @@ + + + +{JSON.stringify(items.sort())} + From 551b0067f512e17cfe1553dde4837efa3625be2d Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 18 Oct 2024 02:37:18 +0100 Subject: [PATCH 2/6] fix test --- .../runtime-runes/samples/side-effect-template/_config.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 index 1616b49860b8..b17c83849f2e 100644 --- a/packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/side-effect-template/_config.js @@ -9,6 +9,9 @@ export default test({ test({ assert, target }) { const button = target.querySelector('button'); - assert.throws(() => {}, /state_unsafe_mutation/); + assert.throws(() => { + button?.click(); + flushSync(); + }, /state_unsafe_mutation/); } }); From 862270fbe2235fb11ffe4036befe9177ac4ffe5b Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 18 Oct 2024 10:49:16 +0100 Subject: [PATCH 3/6] fix test --- packages/svelte/src/store/shared/index.js | 8 +------- .../samples/side-effect-template/main.svelte | 4 +++- .../store-unsubscribe-not-referenced-after/main.svelte | 5 ++++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/svelte/src/store/shared/index.js b/packages/svelte/src/store/shared/index.js index 589231aa7dff..8c8e2de92404 100644 --- a/packages/svelte/src/store/shared/index.js +++ b/packages/svelte/src/store/shared/index.js @@ -3,8 +3,6 @@ import { noop, run_all } from '../../internal/shared/utils.js'; import { safe_not_equal } from '../../internal/client/reactivity/equality.js'; import { subscribe_to_store } from '../utils.js'; -import { queue_micro_task } from '../../internal/client/dom/task.js'; -import { active_effect } from '../../internal/client/runtime.js'; /** * @type {Array | any>} @@ -170,11 +168,7 @@ export function derived(stores, fn, initial_value) { ) ); started = true; - if (active_effect === null) { - sync(); - } else { - queue_micro_task(sync); - } + sync() return function stop() { run_all(unsubscribers); cleanup(); 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 index c7cf0d4690f0..5821d6ebc179 100644 --- a/packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/side-effect-template/main.svelte @@ -3,5 +3,7 @@ -{JSON.stringify(items.sort())} +{#each items.sort() as item (item)} +

{item}

+{/each} 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 5f8b19f4c7ad..e097c639f0c8 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 @@ -{#each items.sort() as item (item)} -

{item}

-{/each} - +{JSON.stringify(items.sort())}