diff --git a/packages/svelte/src/compiler/phases/3-transform/shared/spread_bindings.js b/packages/svelte/src/compiler/phases/3-transform/shared/spread_bindings.js index 01afe26b4b..c5727aead5 100644 --- a/packages/svelte/src/compiler/phases/3-transform/shared/spread_bindings.js +++ b/packages/svelte/src/compiler/phases/3-transform/shared/spread_bindings.js @@ -1,4 +1,4 @@ -/** @import { Expression, MemberExpression, SequenceExpression, SpreadElement, Literal, Super, UpdateExpression, ExpressionStatement } from 'estree' */ +/** @import { CallExpression, Expression, SpreadElement, Super } from 'estree' */ /** @import { ComponentClientTransformState } from '../client/types.js' */ /** @import { ComponentServerTransformState } from '../server/types.js' */ import * as b from '#compiler/builders'; @@ -17,20 +17,33 @@ export function handle_spread_binding(spread_expression, state, visit) { const visited_expression = /** @type {Expression} */ (visit(spread_expression.argument)); state.init.push(b.const(id, visited_expression)); - // Create conditional expressions that work for both arrays and objects - // Array.isArray($$bindings) ? $$bindings[0] : $$bindings.get - const get = b.conditional( - b.call('Array.isArray', id), - b.member(id, b.literal(0), true), - b.member(id, b.id('get')) - ); + const noop = b.arrow([], b.block([])); + + // Generate helper variables for clearer error messages + const get = b.id(state.scope.generate(id.name + '_get')); + const set = b.id(state.scope.generate(id.name + '_set')); - // Array.isArray($$bindings) ? $$bindings[1] : $$bindings.set - const set = b.conditional( - b.call('Array.isArray', id), - b.member(id, b.literal(1), true), - b.member(id, b.id('set')) + const getter = b.logical( + '??', + b.conditional( + b.call('Array.isArray', id), + b.member(id, b.literal(0), true), + b.member(id, b.id('get')) + ), + noop ); + const setter = b.logical( + '??', + b.conditional( + b.call('Array.isArray', id), + b.member(id, b.literal(1), true), + b.member(id, b.id('set')) + ), + noop + ); + + state.init.push(b.const(get, getter)); + state.init.push(b.const(set, setter)); return { get, set }; } diff --git a/packages/svelte/tests/runtime-runes/samples/bind-spread/_config.js b/packages/svelte/tests/runtime-runes/samples/bind-spread/_config.js index db712b6e60..2161bdea2d 100644 --- a/packages/svelte/tests/runtime-runes/samples/bind-spread/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/bind-spread/_config.js @@ -9,9 +9,8 @@ export default test({ assert.htmlEqual(target.innerHTML, ``.repeat(checkboxes.length)); - flushSync(() => { - checkboxes.forEach((checkbox) => checkbox.click()); - }); + checkboxes.forEach((checkbox) => checkbox.click()); + assert.deepEqual(logs, [ 'getArrayBindings', 'getObjectBindings', diff --git a/packages/svelte/tests/runtime-runes/samples/bind-spread/main.svelte b/packages/svelte/tests/runtime-runes/samples/bind-spread/main.svelte index bfd766c3b5..7f11eb81f6 100644 --- a/packages/svelte/tests/runtime-runes/samples/bind-spread/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/bind-spread/main.svelte @@ -1,33 +1,35 @@ + - + - + - check_bindings)()} /> + [get, set])()} />