Skip to content

Commit ef68b66

Browse files
trueadmdummdidumm
andauthored
fix: improve member expression mutation logic (#9625)
* fix: improve member expression mutation logic * cleanup * Update .changeset/moody-frogs-exist.md --------- Co-authored-by: Simon H <[email protected]>
1 parent 7825570 commit ef68b66

File tree

4 files changed

+43
-12
lines changed

4 files changed

+43
-12
lines changed

.changeset/moody-frogs-exist.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: improve member expression mutation logic

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

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,17 +2170,15 @@ export const template_visitors = {
21702170

21712171
/**
21722172
* @param {import('estree').Pattern} expression_for_id
2173-
* @param {import('estree').Expression} expression_for_other
21742173
* @returns {import('#compiler').Binding['mutation']}
21752174
*/
2176-
const create_mutation = (expression_for_id, expression_for_other) => {
2175+
const create_mutation = (expression_for_id) => {
21772176
return (assignment, context) => {
21782177
if (assignment.left.type !== 'Identifier' && assignment.left.type !== 'MemberExpression') {
21792178
// serialize_set_binding turns other patterns into IIFEs and separates the assignments
21802179
// into separate expressions, at which point this is called again with an identifier or member expression
21812180
return serialize_set_binding(assignment, context, () => assignment);
21822181
}
2183-
21842182
const left = object(assignment.left);
21852183
const value = get_assignment_value(assignment, context);
21862184
const invalidate = b.call(
@@ -2193,11 +2191,7 @@ export const template_visitors = {
21932191
return context.state.analysis.runes ? assign : b.sequence([assign, invalidate]);
21942192
} else {
21952193
const original_left = /** @type {import('estree').MemberExpression} */ (assignment.left);
2196-
const left = b.member(
2197-
expression_for_other,
2198-
context.visit(original_left).property,
2199-
original_left.computed
2200-
);
2194+
const left = context.visit(original_left);
22012195
const assign = b.assignment(assignment.operator, left, value);
22022196
return context.state.analysis.runes ? assign : b.sequence([assign, invalidate]);
22032197
}
@@ -2223,8 +2217,7 @@ export const template_visitors = {
22232217
each_node_meta.array_name ? b.call(each_node_meta.array_name) : collection,
22242218
index,
22252219
true
2226-
),
2227-
binding.expression
2220+
)
22282221
);
22292222
} else {
22302223
const unwrapped = binding.expression;
@@ -2252,8 +2245,7 @@ export const template_visitors = {
22522245

22532246
binding.expression = b.call(name);
22542247
binding.mutation = create_mutation(
2255-
/** @type {import('estree').Pattern} */ (path.update_expression(unwrapped)),
2256-
binding.expression
2248+
/** @type {import('estree').Pattern} */ (path.update_expression(unwrapped))
22572249
);
22582250
}
22592251
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
html: `<button>person.name.first = "dave"</button><h3>JSON output</h3><div>[{"name":{"first":"rob"}}]</div>`,
6+
7+
async test({ assert, target }) {
8+
const button = target.querySelector('button');
9+
10+
flushSync(() => {
11+
button?.click();
12+
});
13+
14+
assert.htmlEqual(
15+
target.innerHTML,
16+
`<button>person.name.first = "dave"</button><h3>JSON output</h3><div>[{"name":{"first":"dave"}}]</div>`
17+
);
18+
}
19+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
let people = $state([{name:{first:'rob'}}]);
3+
</script>
4+
5+
{#each people as person}
6+
<button on:click={()=>{
7+
person.name.first = "dave";
8+
people = people;
9+
}}>person.name.first = "dave"</button>
10+
{/each}
11+
12+
<h3>JSON output</h3>
13+
{#each people as person}
14+
<div>{JSON.stringify(people)}</div>
15+
{/each}

0 commit comments

Comments
 (0)