Skip to content

Commit db0b802

Browse files
authored
fix: use safe-equals comparison for @const tags in legacy mode (#10606)
fixes #10600
1 parent c10337c commit db0b802

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

.changeset/chatty-beans-divide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: use safe-equals comparison for `@const` tags in legacy mode

packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,7 +1793,8 @@ export const template_visitors = {
17931793
b.const(
17941794
declaration.id,
17951795
b.call(
1796-
'$.derived',
1796+
// In runes mode, we want things to be fine-grained - but not in legacy mode
1797+
state.options.runes ? '$.derived' : '$.derived_safe_equal',
17971798
b.thunk(/** @type {import('estree').Expression} */ (visit(declaration.init)))
17981799
)
17991800
)
@@ -1822,7 +1823,10 @@ export const template_visitors = {
18221823
])
18231824
);
18241825

1825-
state.init.push(b.const(tmp, b.call('$.derived', fn)));
1826+
state.init.push(
1827+
// In runes mode, we want things to be fine-grained - but not in legacy mode
1828+
b.const(tmp, b.call(state.options.runes ? '$.derived' : '$.derived_safe_equal', fn))
1829+
);
18261830

18271831
for (const node of identifiers) {
18281832
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(node.name));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
// Test ensures that the `const` tag is coarse-grained in legacy mode (i.e. always fires an update when the array changes)
5+
export default test({
6+
html: `
7+
<button>Show</button>
8+
<p>0</p>
9+
<p>1</p>
10+
<p>2</p>
11+
<p>3</p>
12+
`,
13+
async test({ target, assert }) {
14+
const btn = target.querySelector('button');
15+
16+
btn?.click();
17+
await tick();
18+
assert.htmlEqual(
19+
target.innerHTML,
20+
`
21+
<button>Show</button>
22+
<p>0 show (v_item) show (item)</p>
23+
<p>1</p>
24+
<p>2 show (v_item) show (item)</p>
25+
<p>3</p>
26+
`
27+
);
28+
}
29+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script>
2+
export let items = {0:{clicked:false},length:4};
3+
</script>
4+
5+
<button on:click={()=>{
6+
items[0].clicked=true;
7+
items[2]={clicked:true};
8+
}}>Show</button>
9+
10+
{#each items as item, i}
11+
{@const v_item=item}
12+
<p>
13+
{i}
14+
{#if v_item?.clicked}
15+
show (v_item)
16+
{/if}
17+
{#if item?.clicked}
18+
show (item)
19+
{/if}
20+
</p>
21+
{/each}

0 commit comments

Comments
 (0)