diff --git a/.changeset/witty-readers-provide.md b/.changeset/witty-readers-provide.md new file mode 100644 index 000000000000..60a6bdf009c5 --- /dev/null +++ b/.changeset/witty-readers-provide.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: handle component binding mutation diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index b3559ae99fed..72123fb521d1 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -175,10 +175,13 @@ export function prop(props, key, flags, initial) { // intermediate mode — prop is written to, but the parent component had // `bind:foo` which means we can just call `$$props.foo = value` directly if (setter) { - return function (/** @type {V} */ value) { + return function (/** @type {V} */ value, mutation = false) { if (arguments.length === 1) { /** @type {Function} */ (setter)(value); return value; + } else if (mutation) { + /** @type {Function} */ (setter)(getter()); + return value; } else { return getter(); } diff --git a/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/Widget.svelte b/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/Widget.svelte new file mode 100644 index 000000000000..c28dfbda901e --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/Widget.svelte @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/_config.js new file mode 100644 index 000000000000..0479b7c5299d --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/_config.js @@ -0,0 +1,32 @@ +import { ok, test } from '../../test'; + +export default test({ + html: ` + +

foo

+ `, + + ssrHtml: ` + +

foo

+ `, + + async test({ assert, component, target, window }) { + const event = new window.MouseEvent('input'); + const input = target.querySelector('input'); + ok(input); + + input.value = 'blah'; + await input.dispatchEvent(event); + await Promise.resolve(); + + assert.deepEqual(component.deep, { name: 'blah' }); + assert.htmlEqual( + target.innerHTML, + ` + +

blah

+ ` + ); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/main.svelte b/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/main.svelte new file mode 100644 index 000000000000..db8cd83b91b3 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/component-binding-deep2/main.svelte @@ -0,0 +1,11 @@ + + + + +

{deep.name}

\ No newline at end of file