diff --git a/.changeset/forty-dogs-divide.md b/.changeset/forty-dogs-divide.md new file mode 100644 index 000000000000..e0351241c6da --- /dev/null +++ b/.changeset/forty-dogs-divide.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: improve each block item equality for immutable mode diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index af73c0f1379c..7b672502b938 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -28,7 +28,7 @@ import { DOMBooleanAttributes, EACH_INDEX_REACTIVE, EACH_IS_CONTROLLED, - EACH_IS_IMMUTABLE, + EACH_IS_STRICT_EQUALS, EACH_ITEM_REACTIVE, EACH_KEYED } from '../../../../../constants.js'; @@ -2259,8 +2259,8 @@ export const template_visitors = { each_type |= EACH_IS_CONTROLLED; } - if (context.state.analysis.immutable) { - each_type |= EACH_IS_IMMUTABLE; + if (context.state.analysis.runes) { + each_type |= EACH_IS_STRICT_EQUALS; } // Find the parent each blocks which contain the arrays to invalidate diff --git a/packages/svelte/src/constants.js b/packages/svelte/src/constants.js index 45b4d25835ef..faacabcb9715 100644 --- a/packages/svelte/src/constants.js +++ b/packages/svelte/src/constants.js @@ -5,7 +5,7 @@ export const EACH_KEYED = 1 << 2; /** See EachBlock interface metadata.is_controlled for an explanation what this is */ export const EACH_IS_CONTROLLED = 1 << 3; export const EACH_IS_ANIMATED = 1 << 4; -export const EACH_IS_IMMUTABLE = 1 << 6; +export const EACH_IS_STRICT_EQUALS = 1 << 6; export const PROPS_IS_IMMUTABLE = 1; export const PROPS_IS_RUNES = 1 << 1; diff --git a/packages/svelte/src/internal/client/each.js b/packages/svelte/src/internal/client/each.js index 2d81a0b070b1..2a791423df51 100644 --- a/packages/svelte/src/internal/client/each.js +++ b/packages/svelte/src/internal/client/each.js @@ -2,7 +2,7 @@ import { EACH_INDEX_REACTIVE, EACH_IS_ANIMATED, EACH_IS_CONTROLLED, - EACH_IS_IMMUTABLE, + EACH_IS_STRICT_EQUALS, EACH_ITEM_REACTIVE, EACH_KEYED } from '../../constants.js'; @@ -852,9 +852,9 @@ function each_item_block(item, key, index, render_fn, flags) { const item_value = each_item_not_reactive ? item - : (flags & EACH_IS_IMMUTABLE) === 0 - ? mutable_source(item) - : source(item); + : (flags & EACH_IS_STRICT_EQUALS) !== 0 + ? source(item) + : mutable_source(item); const index_value = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index); const block = create_each_item_block(item_value, index_value, key); diff --git a/packages/svelte/tests/runtime-legacy/samples/immutable-each-equals/_config.js b/packages/svelte/tests/runtime-legacy/samples/immutable-each-equals/_config.js new file mode 100644 index 000000000000..90fcbfe2c0c7 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/immutable-each-equals/_config.js @@ -0,0 +1,16 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + immutable: true, + + test({ assert, target }) { + const btn = target.querySelector('button'); + + flushSync(() => { + btn?.click(); + }); + + assert.htmlEqual(target.innerHTML, `