Skip to content

Commit 339782f

Browse files
fix: handle component binding mutation (#10786)
* fix: handle component binding mutation #10359 (comment) * alternative approach to mutating props (#10788) Co-authored-by: Rich Harris <[email protected]> --------- Co-authored-by: Rich Harris <[email protected]> Co-authored-by: Rich Harris <[email protected]>
1 parent 2cb78ac commit 339782f

File tree

6 files changed

+64
-9
lines changed

6 files changed

+64
-9
lines changed

.changeset/witty-readers-provide.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: handle component binding mutation

packages/svelte/src/compiler/phases/3-transform/client/utils.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -470,12 +470,14 @@ export function serialize_set_binding(node, context, fallback, options) {
470470
if (binding.kind === 'prop') {
471471
return b.call(
472472
left,
473-
b.assignment(
474-
node.operator,
475-
/** @type {import('estree').Pattern} */ (visit(node.left)),
476-
value
477-
),
478-
b.literal(true)
473+
b.sequence([
474+
b.assignment(
475+
node.operator,
476+
/** @type {import('estree').Pattern} */ (visit(node.left)),
477+
value
478+
),
479+
b.call(left)
480+
])
479481
);
480482
} else {
481483
return b.call(

packages/svelte/src/internal/client/reactivity/props.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ export function prop(props, key, flags, initial) {
210210

211211
if (!immutable) current_value.equals = safe_equals;
212212

213-
return function (/** @type {V} */ value, mutation = false) {
213+
return function (/** @type {V} */ value) {
214214
var current = get(current_value);
215215

216216
// legacy nonsense — need to ensure the source is invalidated when necessary
@@ -226,9 +226,9 @@ export function prop(props, key, flags, initial) {
226226
}
227227

228228
if (arguments.length > 0) {
229-
if (mutation || (immutable ? value !== current : safe_not_equal(value, current))) {
229+
if (!current_value.equals(value)) {
230230
from_child = true;
231-
set(inner_current_value, mutation ? current : value);
231+
set(inner_current_value, value);
232232
get(current_value); // force a synchronisation immediately
233233
}
234234

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
export let value;
3+
</script>
4+
5+
<input bind:value={value.name}>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { ok, test } from '../../test';
2+
3+
export default test({
4+
html: `
5+
<input>
6+
<p>foo</p>
7+
`,
8+
9+
ssrHtml: `
10+
<input value=foo>
11+
<p>foo</p>
12+
`,
13+
14+
async test({ assert, component, target, window }) {
15+
const event = new window.MouseEvent('input');
16+
const input = target.querySelector('input');
17+
ok(input);
18+
19+
input.value = 'blah';
20+
await input.dispatchEvent(event);
21+
await Promise.resolve();
22+
23+
assert.deepEqual(component.deep, { name: 'blah' });
24+
assert.htmlEqual(
25+
target.innerHTML,
26+
`
27+
<input>
28+
<p>blah</p>
29+
`
30+
);
31+
}
32+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
import Widget from './Widget.svelte';
3+
4+
export let deep = {
5+
name: 'foo'
6+
};
7+
</script>
8+
9+
<Widget bind:value={deep}/>
10+
11+
<p>{deep.name}</p>

0 commit comments

Comments
 (0)