From a9e7827e5e30f400668048782f702f8430e4ec6c Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 9 Jan 2025 21:09:53 +0000 Subject: [PATCH 1/3] fix: wrap each block expression in derived to encapsulte effects --- .changeset/tender-apples-scream.md | 5 +++++ .../src/internal/client/dom/blocks/each.js | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 .changeset/tender-apples-scream.md diff --git a/.changeset/tender-apples-scream.md b/.changeset/tender-apples-scream.md new file mode 100644 index 000000000000..c9325df39908 --- /dev/null +++ b/.changeset/tender-apples-scream.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: wrap each block expression in derived to encapsulte effects diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 9e6405594059..b17090948ae7 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -35,8 +35,9 @@ import { source, mutable_source, internal_set } from '../../reactivity/sources.j import { array_from, is_array } from '../../../shared/utils.js'; import { INERT } from '../../constants.js'; import { queue_micro_task } from '../task.js'; -import { active_effect, active_reaction } from '../../runtime.js'; +import { active_effect, active_reaction, get } from '../../runtime.js'; import { DEV } from 'esm-env'; +import { derived_safe_equal } from '../../reactivity/deriveds.js'; /** * The row of a keyed each block that is currently updating. We track this @@ -135,15 +136,17 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f var was_empty = false; - block(() => { + // TODO: ideally we could use derived for runes mode but because of the ability + // to use a store which can be mutated, we can't do that here as mutating a store + // will still result in the collection array being the same from the store + var each_array = derived_safe_equal(() => { var collection = get_collection(); - var array = is_array(collection) - ? collection - : collection == null - ? [] - : array_from(collection); + return is_array(collection) ? collection : collection == null ? [] : array_from(collection); + }); + block(() => { + var array = get(each_array); var length = array.length; if (was_empty && length === 0) { @@ -254,7 +257,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f // that a mutation occurred and it's made the collection MAYBE_DIRTY, so reading the // collection again can provide consistency to the reactive graph again as the deriveds // will now be `CLEAN`. - get_collection(); + get(each_array); }); if (hydrating) { From d69a3794d18ee62386da1d038888ad813082caf0 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 9 Jan 2025 21:33:32 +0000 Subject: [PATCH 2/3] add test --- .../samples/each-updates-9/_config.js | 16 +++++++ .../samples/each-updates-9/main.svelte | 46 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 packages/svelte/tests/runtime-runes/samples/each-updates-9/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/each-updates-9/main.svelte diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-9/_config.js b/packages/svelte/tests/runtime-runes/samples/each-updates-9/_config.js new file mode 100644 index 000000000000..ee35058c59bb --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-9/_config.js @@ -0,0 +1,16 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target, logs }) { + const [btn1] = target.querySelectorAll('button'); + + btn1.click(); + flushSync(); + + await Promise.resolve(); + await Promise.resolve(); + + assert.deepEqual(logs, ['cleanup']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-9/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-updates-9/main.svelte new file mode 100644 index 000000000000..f5b2c8eb1282 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-9/main.svelte @@ -0,0 +1,46 @@ + + + + +{#each myStore.data as _}{/each} From dcd124ba36675c5400c2ddef16b349e27cbe7fc4 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 9 Jan 2025 19:53:13 -0500 Subject: [PATCH 3/3] Update .changeset/tender-apples-scream.md --- .changeset/tender-apples-scream.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tender-apples-scream.md b/.changeset/tender-apples-scream.md index c9325df39908..836bdaffdf78 100644 --- a/.changeset/tender-apples-scream.md +++ b/.changeset/tender-apples-scream.md @@ -2,4 +2,4 @@ 'svelte': patch --- -fix: wrap each block expression in derived to encapsulte effects +fix: wrap each block expression in derived to encapsulate effects