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
pull/12282/head
Dominic Gannaway 6 months ago committed by GitHub
parent bc32b7c828
commit 15a8518b91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure each blocks properly handle $state.frozen objects in prod

@ -28,7 +28,7 @@ import {
} from '../../reactivity/effects.js'; } from '../../reactivity/effects.js';
import { source, mutable_source, set } from '../../reactivity/sources.js'; import { source, mutable_source, set } from '../../reactivity/sources.js';
import { is_array, is_frozen } from '../../utils.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 { queue_micro_task } from '../task.js';
import { current_effect } from '../../runtime.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 // 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. // are treated as reactive, so they get wrapped in a signal.
var flags = state.flags; 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; 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. // Additionally if we're in an keyed each block, we'll need ensure the items are all wrapped in signals.

@ -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);
}
});

@ -0,0 +1,16 @@
<script>
let frozen_items = $state.frozen([
{id: 0, text: 'a'},
{id: 1, text: 'b'},
{id: 2, text: 'c'}
])
</script>
{#each frozen_items as item (item.id)}
{console.log(item.text)}
{item.text}
{/each}
<button onclick={() => {
frozen_items = [...frozen_items, {id: 3, text: 'd'}]
}}></button>
Loading…
Cancel
Save