From 33a39bf85ebe436d618eeb60ada666d34d0f840f Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Sun, 24 Dec 2023 01:50:10 -0500 Subject: [PATCH] feat: current tests pass; I'm sure I'm missing stuff for new things --- .../src/compiler/phases/1-parse/state/tag.js | 3 ++- .../3-transform/client/visitors/template.js | 14 +++++++++++--- .../3-transform/server/transform-server.js | 17 ++++++----------- packages/svelte/src/internal/client/utils.js | 15 +++++++++++++++ 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index cf80f0e1bd..a71ddd5fa3 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -298,7 +298,8 @@ function open(parser) { throw new Error(); } - parser.eat(raw_snippet_declaration); + // slice the `{#` off the beginning since it's already been eaten + parser.eat(raw_snippet_declaration.slice(2), true); const block = parser.append( /** @type {Omit} */ 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 f3a2cbb2af..06f7beb35c 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 @@ -1755,9 +1755,17 @@ export const template_visitors = { /** @type {import('estree').Expression[]} */ const args = [context.state.node]; - node.arguments.forEach((arg) => - args.push(b.thunk(/** @type {import('estree').Expression} */ (context.visit(arg)))) - ); + node.arguments.forEach((arg) => { + if (arg.type === 'SpreadElement') { + // this is a spread operation, meaning we need to thunkify all of its members + args.push( + /** @type {import('estree').Expression} */ ( + context.visit(b.spread(b.call('$.shallow_thunk', arg.argument))) + ) + ); + } + args.push(b.thunk(/** @type {import('estree').Expression} */ (context.visit(arg)))); + }); let snippet_function = /** @type {import('estree').Expression} */ ( context.visit(node.expression) diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index 584e6e379f..9250647d37 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -1127,18 +1127,13 @@ const template_visitors = { const snippet_function = state.options.dev ? b.call('$.validate_snippet', node.expression) : node.expression; + + const snippet_args = node.arguments.map((arg) => { + return /** @type {import('estree').Expression} */ (context.visit(arg)); + }); + state.template.push( - t_statement( - b.stmt( - b.call( - snippet_function, - b.id('$$payload'), - ...node.arguments.map( - (arg) => /** @type {import('estree').Expression} */ (context.visit(arg)) - ) - ) - ) - ) + t_statement(b.stmt(b.call(snippet_function, b.id('$$payload'), ...snippet_args))) ); state.template.push(t_expression(anchor_id)); diff --git a/packages/svelte/src/internal/client/utils.js b/packages/svelte/src/internal/client/utils.js index 627d2b34fb..79e5b3d79d 100644 --- a/packages/svelte/src/internal/client/utils.js +++ b/packages/svelte/src/internal/client/utils.js @@ -16,3 +16,18 @@ export var get_descriptors = Object.getOwnPropertyDescriptors; export function is_function(thing) { return typeof thing === 'function'; } + +/** + * TODO: Do the types matter on this? If so, can we improve them so that + * `shallow_thunk(['one', 2])` returns a tuple type instead of a union? + * @template {unknown} T + * @param {Iterable} iterable + * @returns {(() => T)[]} + */ +function shallow_thunk(iterable) { + const thunks = []; + for (const item of iterable) { + thunks.push(() => item); + } + return thunks; +}