fix: correctly serialize object assignment expressions (#12175)

fixes #12174
#12109 didn't take into account actual object assignments and couldn't differentiate them from our "fake" assignments, this fixes that
pull/12180/head
Simon H 1 year ago committed by GitHub
parent 8910fe1d57
commit ff946812b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: correctly serialize object assignment expressions

@ -120,7 +120,7 @@ export function serialize_get_binding(node, state) {
* @param {import('estree').AssignmentExpression} node * @param {import('estree').AssignmentExpression} node
* @param {import('zimmerframe').Context<import('#compiler').SvelteNode, State>} context * @param {import('zimmerframe').Context<import('#compiler').SvelteNode, State>} context
* @param {() => any} fallback * @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] * @param {{skip_proxy_and_freeze?: boolean}} [options]
* @returns {import('estree').Expression} * @returns {import('estree').Expression}
*/ */
@ -419,6 +419,7 @@ export function serialize_set_binding(node, context, fallback, prefix, options)
} }
} else if ( } else if (
node.right.type === 'Literal' && node.right.type === 'Literal' &&
prefix != null &&
(node.operator === '+=' || node.operator === '-=') (node.operator === '+=' || node.operator === '-=')
) { ) {
return b.update( return b.update(

@ -32,7 +32,7 @@ export const global_visitors = {
next(); next();
}, },
AssignmentExpression(node, context) { AssignmentExpression(node, context) {
return serialize_set_binding(node, context, context.next, false); return serialize_set_binding(node, context, context.next);
}, },
UpdateExpression(node, context) { UpdateExpression(node, context) {
const { state, next, visit } = context; const { state, next, visit } = context;

@ -791,9 +791,7 @@ function serialize_inline_component(node, component_name, context) {
const assignment = b.assignment('=', attribute.expression, b.id('$$value')); const assignment = b.assignment('=', attribute.expression, b.id('$$value'));
push_prop( push_prop(
b.set(attribute.name, [ b.set(attribute.name, [
b.stmt( b.stmt(serialize_set_binding(assignment, context, () => context.visit(assignment)))
serialize_set_binding(assignment, context, () => context.visit(assignment), false)
)
]) ])
); );
} }
@ -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 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 ids = Array.from(each_ids.values()).map((id) => b.id('$$value_' + id[0]));
const assignment = b.assignment('=', bind_this, b.id('$$value')); 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) { for (const [binding, [, , expression]] of each_ids) {
// reset expressions to what they were before // reset expressions to what they were before
@ -2399,7 +2397,7 @@ export const template_visitors = {
if (assignment.left.type !== 'Identifier' && assignment.left.type !== 'MemberExpression') { if (assignment.left.type !== 'Identifier' && assignment.left.type !== 'MemberExpression') {
// serialize_set_binding turns other patterns into IIFEs and separates the assignments // 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 // 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 left = object(assignment.left);
const value = get_assignment_value(assignment, context); const value = get_assignment_value(assignment, context);
@ -2780,7 +2778,7 @@ export const template_visitors = {
assignment, assignment,
context, context,
() => /** @type {import('estree').Expression} */ (visit(assignment)), () => /** @type {import('estree').Expression} */ (visit(assignment)),
false, null,
{ {
skip_proxy_and_freeze: true skip_proxy_and_freeze: true
} }

@ -2,6 +2,6 @@ import { test } from '../../test';
export default test({ export default test({
test({ assert, logs }) { test({ assert, logs }) {
assert.deepEqual(logs, [1, 1, 1, 1]); assert.deepEqual(logs, [1, 1, 1, 1, 4, 4]);
} }
}); });

@ -6,4 +6,6 @@
console.log(x++); console.log(x++);
console.log(++o.x); console.log(++o.x);
console.log(o.x++); console.log(o.x++);
console.log((o.x += 2));
console.log((x += 2));
</script> </script>

Loading…
Cancel
Save