Skip to content

Commit ddd7926

Browse files
authored
fix: improve key block reactivity detection (#10092)
1 parent 86eae7e commit ddd7926

File tree

5 files changed

+99
-5
lines changed

5 files changed

+99
-5
lines changed

.changeset/old-oranges-compete.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: improve key block reactivity detection

packages/svelte/src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export const EACH_ITEM_REACTIVE = 1;
22
export const EACH_INDEX_REACTIVE = 1 << 1;
33
export const EACH_KEYED = 1 << 2;
4+
export const EACH_PROXIED = 1 << 3;
45
export const EACH_IS_CONTROLLED = 1 << 3;
56
export const EACH_IS_ANIMATED = 1 << 4;
67
export const EACH_IS_IMMUTABLE = 1 << 6;

packages/svelte/src/internal/client/each.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,13 +351,8 @@ function reconcile_tracked_array(
351351
) {
352352
var a_blocks = each_block.v;
353353
const is_computed_key = keys !== null;
354-
var is_proxied_array = STATE_SYMBOL in array && /** @type {any} */ (array[STATE_SYMBOL]).i;
355354
var active_transitions = each_block.s;
356355

357-
if (is_proxied_array) {
358-
flags &= ~EACH_ITEM_REACTIVE;
359-
}
360-
361356
/** @type {number | void} */
362357
var a = a_blocks.length;
363358

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
html: `<p>test costs $1</p><p>test 2 costs $2</p><p>test costs $1</p><p>test 2 costs $2</p><button>add</button><button>change</button><button>reload</button>`,
6+
skip_if_ssr: 'permanent',
7+
skip_if_hydrate: 'permanent',
8+
9+
async test({ assert, target }) {
10+
const [btn1, btn2, btn3] = target.querySelectorAll('button');
11+
12+
flushSync(() => {
13+
btn2.click();
14+
});
15+
16+
assert.htmlEqual(
17+
target.innerHTML,
18+
`<p>test costs $1</p><p>test 2 costs $2000</p><p>test costs $1</p><p>test 2 costs $2000</p><button>add</button><button>change</button><button>reload</button>`
19+
);
20+
21+
flushSync(() => {
22+
btn1.click();
23+
});
24+
25+
assert.htmlEqual(
26+
target.innerHTML,
27+
`<p>test costs $1</p><p>test 2 costs $2000</p><p>test 3 costs $3</p><p>test costs $1</p><p>test 2 costs $2000</p><p>test 3 costs $3</p><button>add</button><button>change</button><button>reload</button>`
28+
);
29+
30+
flushSync(() => {
31+
btn3.click();
32+
});
33+
34+
assert.htmlEqual(
35+
target.innerHTML,
36+
`<p>test costs $1</p><p>test 2 costs $2000</p><p>test costs $1</p><p>test 2 costs $2000</p><button>add</button><button>change</button><button>reload</button>`
37+
);
38+
}
39+
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<script>
2+
let data = $state({ items: [] });
3+
4+
function fetchData() {
5+
data = {
6+
items: [{
7+
id: 1,
8+
price: 1,
9+
name: 'test'
10+
}, {
11+
id: 2,
12+
price: 2,
13+
name: 'test 2'
14+
}]
15+
};
16+
}
17+
18+
fetchData();
19+
20+
function copyItems(original) {
21+
return [...original.map((item) => ({ ...item }))];
22+
}
23+
24+
let items = $state();
25+
26+
$effect(() => {
27+
items = copyItems(data.items);
28+
});
29+
</script>
30+
31+
{#each items as item}
32+
<p>{item.name} costs ${item.price}</p>
33+
{/each}
34+
35+
{#each items as item (item.id)}
36+
<p>{item.name} costs ${item.price}</p>
37+
{/each}
38+
39+
40+
<button onclick={() => {
41+
items.push({
42+
id: 3,
43+
price: 3,
44+
name: 'test 3'
45+
})
46+
}}>add</button>
47+
48+
<button onclick={() => {
49+
data.items[1].price = 2000
50+
}}>change</button>
51+
52+
<button onclick={() => {
53+
fetchData();
54+
}}>reload</button>

0 commit comments

Comments
 (0)