diff --git a/.changeset/eleven-avocados-walk.md b/.changeset/eleven-avocados-walk.md new file mode 100644 index 0000000000..af50fb60b2 --- /dev/null +++ b/.changeset/eleven-avocados-walk.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: correctly serialize object assignment expressions diff --git a/packages/svelte/src/compiler/phases/3-transform/client/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/utils.js index c716bb83b6..595c8db13c 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js @@ -120,7 +120,7 @@ export function serialize_get_binding(node, state) { * @param {import('estree').AssignmentExpression} node * @param {import('zimmerframe').Context} context * @param {() => any} fallback - * @param {boolean} prefix + * @param {boolean | null} [prefix] - If the assignment is a transformed update expression, set this. Else `null` * @param {{skip_proxy_and_freeze?: boolean}} [options] * @returns {import('estree').Expression} */ @@ -419,6 +419,7 @@ export function serialize_set_binding(node, context, fallback, prefix, options) } } else if ( node.right.type === 'Literal' && + prefix != null && (node.operator === '+=' || node.operator === '-=') ) { return b.update( diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js index 2834e9ff06..37dd02855f 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/global.js @@ -32,7 +32,7 @@ export const global_visitors = { next(); }, AssignmentExpression(node, context) { - return serialize_set_binding(node, context, context.next, false); + return serialize_set_binding(node, context, context.next); }, UpdateExpression(node, context) { const { state, next, visit } = context; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index 3134409b85..6a426db0d4 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -791,9 +791,7 @@ function serialize_inline_component(node, component_name, context) { const assignment = b.assignment('=', attribute.expression, b.id('$$value')); push_prop( b.set(attribute.name, [ - b.stmt( - serialize_set_binding(assignment, context, () => context.visit(assignment), false) - ) + b.stmt(serialize_set_binding(assignment, context, () => context.visit(assignment))) ]) ); } @@ -1025,7 +1023,7 @@ function serialize_bind_this(bind_this, context, node) { const bind_this_id = /** @type {import('estree').Expression} */ (context.visit(bind_this)); const ids = Array.from(each_ids.values()).map((id) => b.id('$$value_' + id[0])); const assignment = b.assignment('=', bind_this, b.id('$$value')); - const update = serialize_set_binding(assignment, context, () => context.visit(assignment), false); + const update = serialize_set_binding(assignment, context, () => context.visit(assignment)); for (const [binding, [, , expression]] of each_ids) { // reset expressions to what they were before @@ -2399,7 +2397,7 @@ export const template_visitors = { 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, false); + return serialize_set_binding(assignment, context, () => assignment); } const left = object(assignment.left); const value = get_assignment_value(assignment, context); @@ -2780,7 +2778,7 @@ export const template_visitors = { assignment, context, () => /** @type {import('estree').Expression} */ (visit(assignment)), - false, + null, { skip_proxy_and_freeze: true } diff --git a/packages/svelte/tests/runtime-runes/samples/state-update/_config.js b/packages/svelte/tests/runtime-runes/samples/state-update/_config.js index 9d183557f9..4adf2095b8 100644 --- a/packages/svelte/tests/runtime-runes/samples/state-update/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/state-update/_config.js @@ -2,6 +2,6 @@ import { test } from '../../test'; export default test({ test({ assert, logs }) { - assert.deepEqual(logs, [1, 1, 1, 1]); + assert.deepEqual(logs, [1, 1, 1, 1, 4, 4]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/state-update/main.svelte b/packages/svelte/tests/runtime-runes/samples/state-update/main.svelte index 011a3f6931..c0012c74ec 100644 --- a/packages/svelte/tests/runtime-runes/samples/state-update/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/state-update/main.svelte @@ -6,4 +6,6 @@ console.log(x++); console.log(++o.x); console.log(o.x++); + console.log((o.x += 2)); + console.log((x += 2));