Repository: sveltejs/svelte (JavaScript)

Issue:
Svelte 5: `.length` does not work on arrays being set with `bind:this` directive
### Describe the bug

When using `bind:this` to set a reference to an element at an index of an array, while it does correctly create the proxied state, accessing`length` directly on the array always returns 0 instead of the length of the proxied array value.

I believe this is actually consistent with how proxies ordinarily work, though it seems in other cases the proxy handler allows `length` to be read to directly.

### Reproduction

[REPL](https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE3WSQW6DMBBFrzJyKwESTdRm5ySVeoIeIMnCwNC4MjbCQxSKfPdiuyRUVVeM_595f2QzsloqtIwfRqZFg4yzt7ZlOaOh9Qd7QUU4na3pu9IrO1t2sqXXoz6SQoKLUD1a2MOjJUGYHpLamCSHpBBd_Hwlp2w7t6PCBjUtBxau7pul85y_5Jtg79b3WD0-oCjPc7KwscpBOs_ZSd32BIXUFaeztPtxzjzIk4t6GNiPkRDk9UQe157rQkS0Qn1bWaH-oDNIy-HGXEXRQYrXFksCHwlkoEDYZNPiRRfYP8suEVGaAffWcAnLRi_8bXsvPqe8VaSk8z7Zr8l_eu6wCWdpUBiek38oUwiVFqYaMhi9dKRK2laJgUOt8LqNmi-fKtlNbGk0h9KovtHBdOGtAnL6axpTyVpixTh1PbqT-wZ7yjSdcAIAAA==)

### Logs

```shell
N/A
```


### System Info

```shell
REPL Chrome
```


### Severity

annoyance


Discussion:
I've also just noticed [another weird probably related bug](https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE3WSTW6DMBCFrzJyIwESTdRm55BKPUEPkGRhYEhcGRthE4Ui373-KQlV1RXj9958M2Am0nCBmtDDRCRrkVDy3nUkJ2bs_EFfURh0Z62GvvJKoaued-btKI9GoIErEwNq2MNKG2YwPSSNUkkOScn6-PhKTtlujqPAFqVZNixcObRL5yV_zbfRdoEVl7rDyqTTDLHeKjaPjeT0hKy6zEsxHascuPWEgstuMFByWVNz4Xp_Jx34yUY9NOynSAjyxpGnjefaMCJari7K3nv3VxIoz-YCXFO4g9dRtJDizS8Pfi4YBSXCNguMMOBn4yUiSjPgEQ0faRn0wt_YR_np5q0jJZ33yX51_pN5wBxOm1FguG56FqpkIi1VPWYweeloaq47wUYKjcDbLmq-fK5579hcSQqVEkMrg2nDhQWk-6taVfOGY02o6Qe0J_sNviJf7pACAAA=). When trying to use `$inspect` on the elements array.

```
Uncaught DOMException: Failed to read the 'cookie' property from 'Document': The document is sandboxed and lacks the 'allow-same-origin' flag.
    at deep_read (playground:output:1130:20)
    at deep_read (playground:output:1130:5)
    at deep_read (playground:output:1130:5)
    at deep_read (playground:output:1130:5)
    at deep_read (playground:output:1130:5)
    at deep_read (playground:output:1130:5)
    at deep_read (playground:output:1130:5)
    at eval (playground:output:1168:4)
    at eval (playground:output:975:17)
    at execute_signal_fn (playground:output:311:40)
```




Patch:
diff --git a/.changeset/cool-ants-leave.md b/.changeset/cool-ants-leave.md
new file mode 100644
index 000000000000..c1a1d038a920
--- /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 22e0b959b6ca..f4a3e0c6d5d5 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;
 	},
 


Test patch:
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 000000000000..ad08572129f8
--- /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: `
+		<input><input><input><div>3</div>
+	`
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/proxy-array-length/main.svelte b/packages/svelte/tests/runtime-runes/samples/proxy-array-length/main.svelte
new file mode 100644
index 000000000000..ed9628320e47
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/proxy-array-length/main.svelte
@@ -0,0 +1,10 @@
+<script>
+	let values = $state(['foo', 'bar', 'baz']);
+	let elements = $state([]);
+	let nums = $state([1,2,3]);
+</script>
+
+{#each values as value, i}
+	<input bind:this={elements[i]} bind:value={values[i]} />
+{/each}
+<div>{elements.length}</div>