diff --git a/.changeset/rich-elephants-relax.md b/.changeset/rich-elephants-relax.md new file mode 100644 index 0000000000..dbf1c88282 --- /dev/null +++ b/.changeset/rich-elephants-relax.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +feat: better destructuring assignments diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js index 6636b82a20..4365870bf7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js @@ -11,7 +11,13 @@ import { visit_assignment_expression } from '../../shared/assignments.js'; * @param {Context} context */ export function AssignmentExpression(node, context) { - return visit_assignment_expression(node, context, build_assignment); + const expression = /** @type {Expression} */ ( + visit_assignment_expression(node, context, build_assignment) ?? context.next() + ); + + return is_ignored(node, 'ownership_invalid_mutation') + ? b.call('$.skip_ownership_validation', b.thunk(expression)) + : expression; } /** @@ -109,19 +115,17 @@ function build_assignment(operator, left, right, context) { return transform.assign(object, value); } - /** @type {Expression} */ - let mutation = b.assignment( - operator, - /** @type {Pattern} */ (context.visit(left)), - /** @type {Expression} */ (context.visit(right)) - ); - // mutation if (transform?.mutate) { - mutation = transform.mutate(object, mutation); + return transform.mutate( + object, + b.assignment( + operator, + /** @type {Pattern} */ (context.visit(left)), + /** @type {Expression} */ (context.visit(right)) + ) + ); } - return is_ignored(left, 'ownership_invalid_mutation') - ? b.call('$.skip_ownership_validation', b.thunk(mutation)) - : mutation; + return null; } diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js index e92d54c3b7..2988c590fd 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js @@ -10,7 +10,7 @@ import { visit_assignment_expression } from '../../shared/assignments.js'; * @param {Context} context */ export function AssignmentExpression(node, context) { - return visit_assignment_expression(node, context, build_assignment); + return visit_assignment_expression(node, context, build_assignment) ?? context.next(); } /** diff --git a/packages/svelte/src/compiler/phases/3-transform/shared/assignments.js b/packages/svelte/src/compiler/phases/3-transform/shared/assignments.js index ce7595a06e..e8e02b8f58 100644 --- a/packages/svelte/src/compiler/phases/3-transform/shared/assignments.js +++ b/packages/svelte/src/compiler/phases/3-transform/shared/assignments.js @@ -41,7 +41,7 @@ export function visit_assignment_expression(node, context, build_assignment) { if (!changed) { // No change to output -> nothing to transform -> we can keep the original assignment - return context.next(); + return null; } const is_standalone = /** @type {Node} */ (context.path.at(-1)).type.endsWith('Statement'); @@ -70,8 +70,5 @@ export function visit_assignment_expression(node, context, build_assignment) { throw new Error(`Unexpected assignment type ${node.left.type}`); } - return ( - build_assignment(node.operator, node.left, node.right, context) ?? - /** @type {Expression} */ (context.next()) - ); + return build_assignment(node.operator, node.left, node.right, context); } diff --git a/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/client/index.svelte.js index 9400b52718..a10f4ca1a5 100644 --- a/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/client/index.svelte.js @@ -3,10 +3,14 @@ import * as $ from "svelte/internal/client"; let a = $.source(1); let b = $.source(2); +let c = 3; +let d = 4; export function update(array) { ( $.set(a, $.proxy(array[0])), $.set(b, $.proxy(array[1])) ); + + [c, d] = array; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/server/index.svelte.js index 846ed48458..2797d4312b 100644 --- a/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/server/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/server/index.svelte.js @@ -3,7 +3,10 @@ import * as $ from "svelte/internal/server"; let a = 1; let b = 2; +let c = 3; +let d = 4; export function update(array) { [a, b] = array; + [c, d] = array; } \ No newline at end of file diff --git a/packages/svelte/tests/snapshot/samples/destructured-assignments/index.svelte.js b/packages/svelte/tests/snapshot/samples/destructured-assignments/index.svelte.js index 9c0da7558a..558cc66cc2 100644 --- a/packages/svelte/tests/snapshot/samples/destructured-assignments/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/destructured-assignments/index.svelte.js @@ -1,6 +1,9 @@ let a = $state(1); let b = $state(2); +let c = 3; +let d = 4; export function update(array) { [a, b] = array; + [c, d] = array; }