diff --git a/.changeset/cool-ants-leave.md b/.changeset/cool-ants-leave.md new file mode 100644 index 0000000000..c1a1d038a9 --- /dev/null +++ b/.changeset/cool-ants-leave.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure proxied array length is updated diff --git a/packages/svelte/src/internal/client/proxy/proxy.js b/packages/svelte/src/internal/client/proxy/proxy.js index 22e0b959b6..f4a3e0c6d5 100644 --- a/packages/svelte/src/internal/client/proxy/proxy.js +++ b/packages/svelte/src/internal/client/proxy/proxy.js @@ -139,23 +139,34 @@ const handler = { target[READONLY_SYMBOL] = value; return true; } - const metadata = target[STATE_SYMBOL]; - const s = metadata.s.get(prop); if (s !== undefined) set(s, proxy(value)); + const is_array = metadata.a; + const not_has = !(prop in target); - if (metadata.a && prop === 'length') { + if (is_array && prop === 'length') { for (let i = value; i < target.length; i += 1) { const s = metadata.s.get(i + ''); if (s !== undefined) set(s, UNINITIALIZED); } } - - if (!(prop in target)) increment(metadata.v); + if (not_has) { + increment(metadata.v); + } // @ts-ignore target[prop] = value; + // If we have mutated an array directly, we might need to + // signal that length has also changed too. + if (is_array && not_has) { + const ls = metadata.s.get('length'); + const length = target.length; + if (ls !== undefined && ls.v !== length) { + set(ls, length); + } + } + return true; }, diff --git a/packages/svelte/tests/runtime-runes/samples/proxy-array-length/_config.js b/packages/svelte/tests/runtime-runes/samples/proxy-array-length/_config.js new file mode 100644 index 0000000000..ad08572129 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/proxy-array-length/_config.js @@ -0,0 +1,9 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + skip_if_ssr: 'permanent', + html: ` +