From 15a8518b91b80a8e578fd3378c59f808677c9a53 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 4 Jul 2024 15:20:21 +0100 Subject: [PATCH] fix: ensure each blocks properly handle $state.frozen objects in prod (#12305) * fix: ensure each blocks properly handle $state.frozen objects in prod * fix: ensure each blocks properly handle $state.frozen objects in prod --- .changeset/long-carrots-sneeze.md | 5 +++++ .../src/internal/client/dom/blocks/each.js | 9 +++++++-- .../samples/each-updates-frozen/_config.js | 19 +++++++++++++++++++ .../samples/each-updates-frozen/main.svelte | 16 ++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 .changeset/long-carrots-sneeze.md create mode 100644 packages/svelte/tests/runtime-runes/samples/each-updates-frozen/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/each-updates-frozen/main.svelte diff --git a/.changeset/long-carrots-sneeze.md b/.changeset/long-carrots-sneeze.md new file mode 100644 index 0000000000..90a66121e4 --- /dev/null +++ b/.changeset/long-carrots-sneeze.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure each blocks properly handle $state.frozen objects in prod diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index e6146b2f23..2e274d1b03 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -28,7 +28,7 @@ import { } from '../../reactivity/effects.js'; import { source, mutable_source, set } from '../../reactivity/sources.js'; import { is_array, is_frozen } from '../../utils.js'; -import { INERT, STATE_SYMBOL } from '../../constants.js'; +import { INERT, STATE_FROZEN_SYMBOL, STATE_SYMBOL } from '../../constants.js'; import { queue_micro_task } from '../task.js'; import { current_effect } from '../../runtime.js'; @@ -137,7 +137,12 @@ export function each(anchor, flags, get_collection, get_key, render_fn, fallback // If we are working with an array that isn't proxied or frozen, then remove strict equality and ensure the items // are treated as reactive, so they get wrapped in a signal. var flags = state.flags; - if ((flags & EACH_IS_STRICT_EQUALS) !== 0 && !is_frozen(array) && !(STATE_SYMBOL in array)) { + if ( + (flags & EACH_IS_STRICT_EQUALS) !== 0 && + !is_frozen(array) && + !(STATE_FROZEN_SYMBOL in array) && + !(STATE_SYMBOL in array) + ) { flags ^= EACH_IS_STRICT_EQUALS; // Additionally if we're in an keyed each block, we'll need ensure the items are all wrapped in signals. diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-frozen/_config.js b/packages/svelte/tests/runtime-runes/samples/each-updates-frozen/_config.js new file mode 100644 index 0000000000..42e0796d91 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-frozen/_config.js @@ -0,0 +1,19 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + // TODO: need to force DEV to be false for runtime somehow + async test({ assert, target, logs }) { + const [btn1] = target.querySelectorAll('button'); + + assert.equal(logs.length, 3); + + logs.length = 0; + + flushSync(() => { + btn1.click(); + }); + + assert.equal(logs.length, 1); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-frozen/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-updates-frozen/main.svelte new file mode 100644 index 0000000000..8aabde46cf --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-frozen/main.svelte @@ -0,0 +1,16 @@ + + +{#each frozen_items as item (item.id)} + {console.log(item.text)} + {item.text} +{/each} + +