From db0b802fc2a8d0cd75f3dc209f19e06712be5a92 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 22 Feb 2024 17:48:13 +0100 Subject: [PATCH] fix: use safe-equals comparison for `@const` tags in legacy mode (#10606) fixes #10600 --- .changeset/chatty-beans-divide.md | 5 ++++ .../3-transform/client/visitors/template.js | 8 +++-- .../samples/const-tag-each-update/_config.js | 29 +++++++++++++++++++ .../samples/const-tag-each-update/main.svelte | 21 ++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 .changeset/chatty-beans-divide.md create mode 100644 packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/_config.js create mode 100644 packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/main.svelte diff --git a/.changeset/chatty-beans-divide.md b/.changeset/chatty-beans-divide.md new file mode 100644 index 0000000000..bcf47bfbbf --- /dev/null +++ b/.changeset/chatty-beans-divide.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: use safe-equals comparison for `@const` tags in legacy 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 46906b3e98..0bd8d9235d 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 @@ -1793,7 +1793,8 @@ export const template_visitors = { b.const( declaration.id, b.call( - '$.derived', + // In runes mode, we want things to be fine-grained - but not in legacy mode + state.options.runes ? '$.derived' : '$.derived_safe_equal', b.thunk(/** @type {import('estree').Expression} */ (visit(declaration.init))) ) ) @@ -1822,7 +1823,10 @@ export const template_visitors = { ]) ); - state.init.push(b.const(tmp, b.call('$.derived', fn))); + state.init.push( + // In runes mode, we want things to be fine-grained - but not in legacy mode + b.const(tmp, b.call(state.options.runes ? '$.derived' : '$.derived_safe_equal', fn)) + ); for (const node of identifiers) { const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(node.name)); diff --git a/packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/_config.js b/packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/_config.js new file mode 100644 index 0000000000..90363bd88e --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/_config.js @@ -0,0 +1,29 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +// Test ensures that the `const` tag is coarse-grained in legacy mode (i.e. always fires an update when the array changes) +export default test({ + html: ` + +

0

+

1

+

2

+

3

+ `, + async test({ target, assert }) { + const btn = target.querySelector('button'); + + btn?.click(); + await tick(); + assert.htmlEqual( + target.innerHTML, + ` + +

0 show (v_item) show (item)

+

1

+

2 show (v_item) show (item)

+

3

+ ` + ); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/main.svelte b/packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/main.svelte new file mode 100644 index 0000000000..66d0d4d0a2 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/const-tag-each-update/main.svelte @@ -0,0 +1,21 @@ + + + + +{#each items as item, i} + {@const v_item=item} +

+ {i} + {#if v_item?.clicked} + show (v_item) + {/if} + {#if item?.clicked} + show (item) + {/if} +

+{/each}