Skip to content

Commit f1954d0

Browse files
authored
fix: ensure proxied array length is updated (#9782)
* fix: ensure proxied array length is updated * fix: ensure proxied array length is updated * add test * lint
1 parent 10aacfa commit f1954d0

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

.changeset/cool-ants-leave.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure proxied array length is updated

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

+16-5
Original file line numberDiff line numberDiff line change
@@ -139,23 +139,34 @@ const handler = {
139139
target[READONLY_SYMBOL] = value;
140140
return true;
141141
}
142-
143142
const metadata = target[STATE_SYMBOL];
144-
145143
const s = metadata.s.get(prop);
146144
if (s !== undefined) set(s, proxy(value));
145+
const is_array = metadata.a;
146+
const not_has = !(prop in target);
147147

148-
if (metadata.a && prop === 'length') {
148+
if (is_array && prop === 'length') {
149149
for (let i = value; i < target.length; i += 1) {
150150
const s = metadata.s.get(i + '');
151151
if (s !== undefined) set(s, UNINITIALIZED);
152152
}
153153
}
154-
155-
if (!(prop in target)) increment(metadata.v);
154+
if (not_has) {
155+
increment(metadata.v);
156+
}
156157
// @ts-ignore
157158
target[prop] = value;
158159

160+
// If we have mutated an array directly, we might need to
161+
// signal that length has also changed too.
162+
if (is_array && not_has) {
163+
const ls = metadata.s.get('length');
164+
const length = target.length;
165+
if (ls !== undefined && ls.v !== length) {
166+
set(ls, length);
167+
}
168+
}
169+
159170
return true;
160171
},
161172

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
skip_if_ssr: 'permanent',
6+
html: `
7+
<input><input><input><div>3</div>
8+
`
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
let values = $state(['foo', 'bar', 'baz']);
3+
let elements = $state([]);
4+
let nums = $state([1,2,3]);
5+
</script>
6+
7+
{#each values as value, i}
8+
<input bind:this={elements[i]} bind:value={values[i]} />
9+
{/each}
10+
<div>{elements.length}</div>

0 commit comments

Comments
 (0)