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 <5968653+dummdidumm@users.noreply.github.com>
pull/9607/head
Dominic Gannaway 2 years ago committed by GitHub
parent 7825570b07
commit ef68b66dee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: improve member expression mutation logic

@ -2170,17 +2170,15 @@ export const template_visitors = {
/**
* @param {import('estree').Pattern} expression_for_id
* @param {import('estree').Expression} expression_for_other
* @returns {import('#compiler').Binding['mutation']}
*/
const create_mutation = (expression_for_id, expression_for_other) => {
const create_mutation = (expression_for_id) => {
return (assignment, context) => {
if (assignment.left.type !== 'Identifier' && assignment.left.type !== 'MemberExpression') {
// serialize_set_binding turns other patterns into IIFEs and separates the assignments
// into separate expressions, at which point this is called again with an identifier or member expression
return serialize_set_binding(assignment, context, () => assignment);
}
const left = object(assignment.left);
const value = get_assignment_value(assignment, context);
const invalidate = b.call(
@ -2193,11 +2191,7 @@ export const template_visitors = {
return context.state.analysis.runes ? assign : b.sequence([assign, invalidate]);
} else {
const original_left = /** @type {import('estree').MemberExpression} */ (assignment.left);
const left = b.member(
expression_for_other,
context.visit(original_left).property,
original_left.computed
);
const left = context.visit(original_left);
const assign = b.assignment(assignment.operator, left, value);
return context.state.analysis.runes ? assign : b.sequence([assign, invalidate]);
}
@ -2223,8 +2217,7 @@ export const template_visitors = {
each_node_meta.array_name ? b.call(each_node_meta.array_name) : collection,
index,
true
),
binding.expression
)
);
} else {
const unwrapped = binding.expression;
@ -2252,8 +2245,7 @@ export const template_visitors = {
binding.expression = b.call(name);
binding.mutation = create_mutation(
/** @type {import('estree').Pattern} */ (path.update_expression(unwrapped)),
binding.expression
/** @type {import('estree').Pattern} */ (path.update_expression(unwrapped))
);
}
}

@ -0,0 +1,19 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<button>person.name.first = "dave"</button><h3>JSON output</h3><div>[{"name":{"first":"rob"}}]</div>`,
async test({ assert, target }) {
const button = target.querySelector('button');
flushSync(() => {
button?.click();
});
assert.htmlEqual(
target.innerHTML,
`<button>person.name.first = "dave"</button><h3>JSON output</h3><div>[{"name":{"first":"dave"}}]</div>`
);
}
});

@ -0,0 +1,15 @@
<script>
let people = $state([{name:{first:'rob'}}]);
</script>
{#each people as person}
<button on:click={()=>{
person.name.first = "dave";
people = people;
}}>person.name.first = "dave"</button>
{/each}
<h3>JSON output</h3>
{#each people as person}
<div>{JSON.stringify(people)}</div>
{/each}
Loading…
Cancel
Save