From 20e6508c477972295874d698c73fbd4f071a6155 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 19 Jul 2024 12:25:03 +0100 Subject: [PATCH] fix: ensure $state proxy invokes set accessor if present (#12503) --- .changeset/shiny-starfishes-cross.md | 5 +++++ packages/svelte/src/internal/client/proxy.js | 9 ++++++-- .../samples/proxy-set-accessor/_config.js | 22 +++++++++++++++++++ .../samples/proxy-set-accessor/main.svelte | 14 ++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 .changeset/shiny-starfishes-cross.md create mode 100644 packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/main.svelte diff --git a/.changeset/shiny-starfishes-cross.md b/.changeset/shiny-starfishes-cross.md new file mode 100644 index 0000000000..2eead25214 --- /dev/null +++ b/.changeset/shiny-starfishes-cross.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure $state proxy invokes set accessor if present diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index 206c97fbc7..a0c5ca23e0 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -243,9 +243,14 @@ const state_proxy_handler = { } } + var descriptor = Reflect.getOwnPropertyDescriptor(target, prop); + // Set the new value before updating any signals so that any listeners get the new value - // @ts-ignore - target[prop] = value; + if (descriptor?.set) { + descriptor.set.call(receiver, value); + } else { + target[prop] = value; + } if (not_has) { // If we have mutated an array directly, we might need to diff --git a/packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/_config.js b/packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/_config.js new file mode 100644 index 0000000000..1ea2ee622a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/_config.js @@ -0,0 +1,22 @@ +import { flushSync } from 'svelte'; +import { test, ok } from '../../test'; + +export default test({ + html: `

svelte

`, + ssrHtml: `

svelte

`, + + test({ assert, target }) { + const input = target.querySelector('input'); + ok(input); + + const event = new window.Event('input'); + + input.value = 'SVELTEy'; + input.dispatchEvent(event); + + flushSync(); + + assert.htmlEqual(target.innerHTML, `

sveltey

`); + assert.equal(input.value, 'SVELTEY'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/main.svelte b/packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/main.svelte new file mode 100644 index 0000000000..13a4acfea8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/proxy-set-accessor/main.svelte @@ -0,0 +1,14 @@ + + + +

{text.value}