Skip to content

Commit 20e6508

Browse files
authored
fix: ensure $state proxy invokes set accessor if present (#12503)
1 parent 2ce2b7d commit 20e6508

File tree

4 files changed

+48
-2
lines changed

4 files changed

+48
-2
lines changed

.changeset/shiny-starfishes-cross.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: ensure $state proxy invokes set accessor if present

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,14 @@ const state_proxy_handler = {
243243
}
244244
}
245245

246+
var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
247+
246248
// Set the new value before updating any signals so that any listeners get the new value
247-
// @ts-ignore
248-
target[prop] = value;
249+
if (descriptor?.set) {
250+
descriptor.set.call(receiver, value);
251+
} else {
252+
target[prop] = value;
253+
}
249254

250255
if (not_has) {
251256
// If we have mutated an array directly, we might need to
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { flushSync } from 'svelte';
2+
import { test, ok } from '../../test';
3+
4+
export default test({
5+
html: `<input><p>svelte</p>`,
6+
ssrHtml: `<input value="SVELTE"><p>svelte</p>`,
7+
8+
test({ assert, target }) {
9+
const input = target.querySelector('input');
10+
ok(input);
11+
12+
const event = new window.Event('input');
13+
14+
input.value = 'SVELTEy';
15+
input.dispatchEvent(event);
16+
17+
flushSync();
18+
19+
assert.htmlEqual(target.innerHTML, `<input><p>sveltey</p>`);
20+
assert.equal(input.value, 'SVELTEY');
21+
}
22+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
let text = $state({
3+
value: 'svelte',
4+
get uppercase() {
5+
return this.value.toUpperCase()
6+
},
7+
set uppercase(v) {
8+
this.value = v.toLowerCase()
9+
}
10+
})
11+
</script>
12+
13+
<input bind:value={text.uppercase} />
14+
<p>{text.value}</p>

0 commit comments

Comments
 (0)