From 083359dc131fb41024d75abdba673261207faa79 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:03:23 +0800 Subject: [PATCH 01/14] add attachments symbol --- packages/svelte/src/attachments/index.js | 1 + packages/svelte/src/attachments/public.d.ts | 4 +++ .../svelte/src/internal/client/constants.js | 1 + .../client/dom/elements/attributes.js | 9 ++++--- packages/svelte/types/index.d.ts | 27 ++++++++++++------- 5 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 packages/svelte/src/attachments/index.js create mode 100644 packages/svelte/src/attachments/public.d.ts diff --git a/packages/svelte/src/attachments/index.js b/packages/svelte/src/attachments/index.js new file mode 100644 index 000000000000..453cf9d90dbe --- /dev/null +++ b/packages/svelte/src/attachments/index.js @@ -0,0 +1 @@ +export { ATTACHMENTS_SYMBOL as AttachmentsKey } from '../internal/client/constants.js'; diff --git a/packages/svelte/src/attachments/public.d.ts b/packages/svelte/src/attachments/public.d.ts new file mode 100644 index 000000000000..7685151ab4b1 --- /dev/null +++ b/packages/svelte/src/attachments/public.d.ts @@ -0,0 +1,4 @@ +/** + * A unique symbol used for defining the attachments to be applied to an element or component. + */ +export const AttachmentsKey: unique symbol; diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index a4840ce4ebd0..42d7db4f174f 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -25,3 +25,4 @@ export const STATE_SYMBOL = Symbol('$state'); export const STATE_SYMBOL_METADATA = Symbol('$state metadata'); export const LEGACY_PROPS = Symbol('legacy props'); export const LOADING_ATTR_SYMBOL = Symbol(''); +export const ATTACHMENTS_SYMBOL = Symbol.for('svelte.attachments'); diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 17362cedea1d..4d4539ba5778 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -4,7 +4,7 @@ import { get_descriptors, get_prototype_of } from '../../../shared/utils.js'; import { create_event, delegate } from './events.js'; import { add_form_reset_listener, autofocus } from './misc.js'; import * as w from '../../warnings.js'; -import { LOADING_ATTR_SYMBOL } from '../../constants.js'; +import { ATTACHMENTS_SYMBOL, LOADING_ATTR_SYMBOL } from '../../constants.js'; import { queue_idle_task } from '../task.js'; import { is_capture_event, is_delegated, normalize_attribute } from '../../../../utils.js'; import { @@ -416,8 +416,11 @@ export function set_attributes( } } - for (let symbol of Object.getOwnPropertySymbols(next)) { - attach(element, () => next[symbol]); + const attachments = next[ATTACHMENTS_SYMBOL]; + if (attachments) { + for (let attachment of attachments) { + attach(element, () => attachment); + } } return current; diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index ad328b11acf4..7cf170d980e0 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -593,6 +593,13 @@ declare module 'svelte/action' { export {}; } +declare module 'svelte/attachments' { + /** + * A unique symbol used for defining the attachments to be applied to an element or component. + */ + export const AttachmentsKey: unique symbol; +} + declare module 'svelte/animate' { // todo: same as Transition, should it be shared? export interface AnimationConfig { @@ -1881,10 +1888,10 @@ declare module 'svelte/motion' { * const tween = Tween.of(() => number); * * ``` - * + * */ static of(fn: () => U, options?: TweenedOptions | undefined): Tween; - + constructor(value: T, options?: TweenedOptions); /** * Sets `tween.target` to `value` and returns a `Promise` that resolves if and when `tween.current` catches up to it. @@ -1903,21 +1910,21 @@ declare module 'svelte/motion' { declare module 'svelte/reactivity' { export class SvelteDate extends Date { - + constructor(...params: any[]); #private; } export class SvelteSet extends Set { - + constructor(value?: Iterable | null | undefined); - + add(value: T): this; #private; } export class SvelteMap extends Map { - + constructor(value?: Iterable | null | undefined); - + set(key: K, value: V): this; #private; } @@ -1927,7 +1934,7 @@ declare module 'svelte/reactivity' { } const REPLACE: unique symbol; export class SvelteURLSearchParams extends URLSearchParams { - + [REPLACE](params: URLSearchParams): void; #private; } @@ -1999,7 +2006,7 @@ declare module 'svelte/reactivity' { */ export function createSubscriber(start: (update: () => void) => (() => void) | void): () => void; class ReactiveValue { - + constructor(fn: () => T, onsubscribe: (update: () => void) => void); get current(): T; #private; @@ -2064,7 +2071,7 @@ declare module 'svelte/reactivity/window' { get current(): number | undefined; }; class ReactiveValue { - + constructor(fn: () => T, onsubscribe: (update: () => void) => void); get current(): T; #private; From c04054c1391de215025c1535d5c9e4e78d5bace2 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:12:08 +0800 Subject: [PATCH 02/14] add attachments path --- packages/svelte/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte/tsconfig.json b/packages/svelte/tsconfig.json index c9f0fb3b2bba..7829c3c2e7a5 100644 --- a/packages/svelte/tsconfig.json +++ b/packages/svelte/tsconfig.json @@ -18,6 +18,7 @@ "acorn-typescript": ["./src/compiler/phases/1-parse/ambient.d.ts"], "svelte": ["./src/index.d.ts"], "svelte/action": ["./src/action/public.d.ts"], + "svelte/attachments": ["./src/attachments/public.d.ts"], "svelte/compiler": ["./src/compiler/public.d.ts"], "svelte/events": ["./src/events/public.d.ts"], "svelte/internal/client": ["./src/internal/client/index.js"], From 92fa0999c5ce943f4cab8fa86420ed937a7c308e Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:18:29 +0800 Subject: [PATCH 03/14] empty export --- packages/svelte/types/index.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 7cf170d980e0..65aca4563f80 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -598,6 +598,8 @@ declare module 'svelte/attachments' { * A unique symbol used for defining the attachments to be applied to an element or component. */ export const AttachmentsKey: unique symbol; + + export {}; } declare module 'svelte/animate' { From b088f27970c675251aced6ca19c0947b13dd8cb6 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:21:51 +0800 Subject: [PATCH 04/14] update svelte package.json --- packages/svelte/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/svelte/package.json b/packages/svelte/package.json index f426b97be4aa..bda1d7b3bfe6 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -29,6 +29,9 @@ "./action": { "types": "./types/index.d.ts" }, + "./attachments": { + "types": "./types/index.d.ts" + }, "./animate": { "types": "./types/index.d.ts", "default": "./src/animate/index.js" From b8924a73695d8a44633b9d87f7ff850b045cb14a Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:23:31 +0800 Subject: [PATCH 05/14] update generate-types --- packages/svelte/scripts/generate-types.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte/scripts/generate-types.js b/packages/svelte/scripts/generate-types.js index d44afe8205a8..37d67be4ef1e 100644 --- a/packages/svelte/scripts/generate-types.js +++ b/packages/svelte/scripts/generate-types.js @@ -29,6 +29,7 @@ await createBundle({ modules: { [pkg.name]: `${dir}/src/index.d.ts`, [`${pkg.name}/action`]: `${dir}/src/action/public.d.ts`, + [`${pkg.name}/attachments`]: `${dir}/src/attachments/public.d.ts`, [`${pkg.name}/animate`]: `${dir}/src/animate/public.d.ts`, [`${pkg.name}/compiler`]: `${dir}/src/compiler/public.d.ts`, [`${pkg.name}/easing`]: `${dir}/src/easing/index.js`, From fdad771035c6ddb9e9cd3b9f114d7edee33dc63a Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:29:53 +0800 Subject: [PATCH 06/14] update git ignore --- packages/svelte/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte/.gitignore b/packages/svelte/.gitignore index d0c4ba8d6144..622014804bd4 100644 --- a/packages/svelte/.gitignore +++ b/packages/svelte/.gitignore @@ -3,6 +3,7 @@ /compiler/index.js /action.d.ts +/attachments.d.ts /animate.d.ts /compiler.d.ts /easing.d.ts From 29705764f91fd12133621ebd724b0ca346af2634 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:39:06 +0800 Subject: [PATCH 07/14] temp use Symbol.for() duplicate variable --- packages/svelte/src/attachments/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/attachments/index.js b/packages/svelte/src/attachments/index.js index 453cf9d90dbe..c73c5a8aa6c1 100644 --- a/packages/svelte/src/attachments/index.js +++ b/packages/svelte/src/attachments/index.js @@ -1 +1 @@ -export { ATTACHMENTS_SYMBOL as AttachmentsKey } from '../internal/client/constants.js'; +export const AttachmentsKey = Symbol.for('svelte.attachments'); From 4b9892c4794139ed360f6fdc7aea7e9952d0fcc3 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:43:21 +0800 Subject: [PATCH 08/14] add missing attachments module to generate-types --- packages/svelte/scripts/generate-types.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/svelte/scripts/generate-types.js b/packages/svelte/scripts/generate-types.js index 37d67be4ef1e..4bd2763a307d 100644 --- a/packages/svelte/scripts/generate-types.js +++ b/packages/svelte/scripts/generate-types.js @@ -8,7 +8,16 @@ const pkg = JSON.parse(fs.readFileSync(`${dir}/package.json`, 'utf-8')); // For people not using moduleResolution: 'bundler', we need to generate these files. Think about removing this in Svelte 6 or 7 // It may look weird, but the imports MUST be ending with index.js to be properly resolved in all TS modes -for (const name of ['action', 'animate', 'easing', 'motion', 'store', 'transition', 'legacy']) { +for (const name of [ + 'action', + 'attachments', + 'animate', + 'easing', + 'motion', + 'store', + 'transition', + 'legacy' +]) { fs.writeFileSync(`${dir}/${name}.d.ts`, "import './types/index.js';\n"); } From 51c540c66fe4c5c769185230fae6af7cc32f38d6 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 01:47:51 +0800 Subject: [PATCH 09/14] add missing default --- packages/svelte/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/svelte/package.json b/packages/svelte/package.json index bda1d7b3bfe6..ece8b73df2b8 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -30,7 +30,8 @@ "types": "./types/index.d.ts" }, "./attachments": { - "types": "./types/index.d.ts" + "types": "./types/index.d.ts", + "default": "./src/attachments/index.js" }, "./animate": { "types": "./types/index.d.ts", From 561ed8f3d955460853d72cf070cdaf23691217a0 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 13:11:21 +0800 Subject: [PATCH 10/14] update type --- packages/svelte/elements.d.ts | 4 +++- packages/svelte/src/attachments/public.d.ts | 7 ++++++- .../phases/3-transform/client/visitors/shared/component.js | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index 7b67e2a07ebd..cb1df6ddebab 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -31,6 +31,8 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 +import { AttachmentsKey } from 'svelte/attachments'; + // Note: We also allow `null` as a valid value because Svelte treats this the same as `undefined` type Booleanish = boolean | 'true' | 'false'; @@ -861,7 +863,7 @@ export interface HTMLAttributes extends AriaAttributes, D [key: `data-${string}`]: any; // allow any attachment - [key: symbol]: (node: T) => void | (() => void); + [AttachmentsKey]: Array<(node: T) => void | (() => void)>; } export type HTMLAttributeAnchorTarget = '_self' | '_blank' | '_parent' | '_top' | (string & {}); diff --git a/packages/svelte/src/attachments/public.d.ts b/packages/svelte/src/attachments/public.d.ts index 7685151ab4b1..fe3811816b1c 100644 --- a/packages/svelte/src/attachments/public.d.ts +++ b/packages/svelte/src/attachments/public.d.ts @@ -1,4 +1,9 @@ +declare const brand: unique symbol; +type Brand = { [brand]: B }; +type Branded = T & Brand; +type AttachmentsKeySymbol = Branded; + /** * A unique symbol used for defining the attachments to be applied to an element or component. */ -export const AttachmentsKey: unique symbol; +export const AttachmentsKey: AttachmentsKeySymbol; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js index 47b7b4436878..9621f29f7585 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js @@ -267,7 +267,7 @@ export function build_component(node, component_name, context, anchor = context. push_prop( b.prop( 'get', - b.call('Symbol'), + b.call("Symbol.for('svelte.attachments')"), /** @type {Expression} */ ( context.visit(attachment.type === 'SpreadElement' ? attachment.argument : attachment) ), From 01cad3e05674afcc21ad991d57be2594ce4e033c Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 13:14:07 +0800 Subject: [PATCH 11/14] revert branded type change --- packages/svelte/src/attachments/public.d.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/svelte/src/attachments/public.d.ts b/packages/svelte/src/attachments/public.d.ts index fe3811816b1c..7685151ab4b1 100644 --- a/packages/svelte/src/attachments/public.d.ts +++ b/packages/svelte/src/attachments/public.d.ts @@ -1,9 +1,4 @@ -declare const brand: unique symbol; -type Brand = { [brand]: B }; -type Branded = T & Brand; -type AttachmentsKeySymbol = Branded; - /** * A unique symbol used for defining the attachments to be applied to an element or component. */ -export const AttachmentsKey: AttachmentsKeySymbol; +export const AttachmentsKey: unique symbol; From 301552872c877c454aa4a7d0ebdaf90d9df8fc83 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 13:15:01 +0800 Subject: [PATCH 12/14] rename AttachmentsKey to Attachments --- packages/svelte/elements.d.ts | 4 ++-- packages/svelte/src/attachments/index.js | 2 +- packages/svelte/src/attachments/public.d.ts | 2 +- packages/svelte/types/index.d.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index cb1df6ddebab..eda33c434c64 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -31,7 +31,7 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 -import { AttachmentsKey } from 'svelte/attachments'; +import { Attachments } from 'svelte/attachments'; // Note: We also allow `null` as a valid value because Svelte treats this the same as `undefined` @@ -863,7 +863,7 @@ export interface HTMLAttributes extends AriaAttributes, D [key: `data-${string}`]: any; // allow any attachment - [AttachmentsKey]: Array<(node: T) => void | (() => void)>; + [Attachments]: Array<(node: T) => void | (() => void)>; } export type HTMLAttributeAnchorTarget = '_self' | '_blank' | '_parent' | '_top' | (string & {}); diff --git a/packages/svelte/src/attachments/index.js b/packages/svelte/src/attachments/index.js index c73c5a8aa6c1..87d0fa3ac002 100644 --- a/packages/svelte/src/attachments/index.js +++ b/packages/svelte/src/attachments/index.js @@ -1 +1 @@ -export const AttachmentsKey = Symbol.for('svelte.attachments'); +export const Attachments = Symbol.for('svelte.attachments'); diff --git a/packages/svelte/src/attachments/public.d.ts b/packages/svelte/src/attachments/public.d.ts index 7685151ab4b1..b1e6c5f2c1db 100644 --- a/packages/svelte/src/attachments/public.d.ts +++ b/packages/svelte/src/attachments/public.d.ts @@ -1,4 +1,4 @@ /** * A unique symbol used for defining the attachments to be applied to an element or component. */ -export const AttachmentsKey: unique symbol; +export const Attachments: unique symbol; diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 65aca4563f80..055d08cf4ebd 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -597,7 +597,7 @@ declare module 'svelte/attachments' { /** * A unique symbol used for defining the attachments to be applied to an element or component. */ - export const AttachmentsKey: unique symbol; + export const Attachments: unique symbol; export {}; } From 3ad1e0afc93d86d44ec1cbcbda339eb1032912ba Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 22:17:17 +0800 Subject: [PATCH 13/14] wip support adding attachments to attachments prop array --- .../client/visitors/shared/component.js | 72 +++++++++++++++---- .../svelte/src/compiler/utils/builders.js | 38 +++++++--- 2 files changed, 88 insertions(+), 22 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js index 9621f29f7585..0b803d3207b8 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js @@ -1,4 +1,4 @@ -/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement } from 'estree' */ +/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement, SpreadElement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../../types.js' */ import { dev, is_ignored } from '../../../../../state.js'; @@ -10,6 +10,39 @@ import { build_attribute_value } from '../shared/element.js'; import { build_event_handler } from './events.js'; import { determine_slot } from '../../../../../utils/slot.js'; +/** + * @param {Property} prop + * @param {ComponentContext} context + * @returns {boolean} + */ +function is_attachments_prop(prop, context) { + if (prop.key.type !== 'Identifier') { + return false; + } + + const binding = context.state.scope?.get?.(prop.key.name) ?? undefined; + const expression = prop.computed && prop.key.type === 'Identifier' ? prop.key : binding?.initial; + + if (!expression || expression.type !== 'CallExpression') { + return false; + } + + if ( + expression.callee.type !== 'MemberExpression' || + expression.callee.object.type !== 'Identifier' || + expression.callee.object.name !== 'Symbol' || + expression.callee.property.type !== 'Identifier' || + expression.callee.property.name !== 'for' || + expression.arguments.length !== 1 || + expression.arguments[0].type !== 'Literal' || + expression.arguments[0].value !== 'svelte.attachments' + ) { + return false; + } + + return true; +} + /** * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node * @param {string} component_name @@ -50,6 +83,9 @@ export function build_component(node, component_name, context, anchor = context. /** @type {ExpressionStatement[]} */ const binding_initializers = []; + /** @type {Array} */ + const all_attachments = []; + /** * If this component has a slot property, it is a named slot within another component. In this case * the slot scope applies to the component itself, too, and not just its children. @@ -262,24 +298,36 @@ export function build_component(node, component_name, context, anchor = context. } } } else if (attribute.type === 'Attachment') { - // TODO do we need to create a derived here? for (const attachment of attribute.attachments) { - push_prop( - b.prop( - 'get', - b.call("Symbol.for('svelte.attachments')"), - /** @type {Expression} */ ( - context.visit(attachment.type === 'SpreadElement' ? attachment.argument : attachment) - ), - true - ) - ); + if (attachment.type === 'SpreadElement') { + const visited = /** @type {ExpressionStatement} */ (context.visit(attachment.argument)); + all_attachments.push(b.spread(visited.expression)); + } else { + const visited = /** @type {ExpressionStatement} */ (context.visit(attachment)); + all_attachments.push(visited.expression); + } } } } delayed_props.forEach((fn) => fn()); + if (all_attachments.length > 0) { + const attachment_symbol = b.member( + b.id('Symbol'), + b.call('for', b.literal('svelte.attachments')) + ); + + push_prop( + b.prop( + 'init', + attachment_symbol, + b.array(all_attachments), + true // Mark as computed property + ) + ); + } + if (slot_scope_applies_to_itself) { context.state.init.push(...lets); } diff --git a/packages/svelte/src/compiler/utils/builders.js b/packages/svelte/src/compiler/utils/builders.js index ecb595d74dbd..90ee5ea09d33 100644 --- a/packages/svelte/src/compiler/utils/builders.js +++ b/packages/svelte/src/compiler/utils/builders.js @@ -229,12 +229,21 @@ export function function_declaration(id, params, body) { } /** - * @param {string} name + * @param {string | ESTree.Expression} name_or_expr * @param {ESTree.Statement[]} body - * @returns {ESTree.Property & { value: ESTree.FunctionExpression}}} - */ -export function get(name, body) { - return prop('get', key(name), function_builder(null, [], block(body))); + * @returns {ESTree.Property & { value: ESTree.FunctionExpression }} + */ +export function get(name_or_expr, body) { + let key_expr; + let computed = false; + if (typeof name_or_expr === 'string') { + key_expr = key(name_or_expr); + computed = key_expr.type !== 'Identifier'; + } else { + key_expr = name_or_expr; + computed = true; + } + return prop('get', key_expr, function_builder(null, [], block(body)), computed); } /** @@ -380,12 +389,21 @@ export function sequence(expressions) { } /** - * @param {string} name + * @param {string | ESTree.Expression} name_or_expr * @param {ESTree.Statement[]} body - * @returns {ESTree.Property & { value: ESTree.FunctionExpression}} - */ -export function set(name, body) { - return prop('set', key(name), function_builder(null, [id('$$value')], block(body))); + * @returns {ESTree.Property & { value: ESTree.FunctionExpression }} + */ +export function set(name_or_expr, body) { + let key_expr; + let computed = false; + if (typeof name_or_expr === 'string') { + key_expr = key(name_or_expr); + computed = key_expr.type !== 'Identifier'; + } else { + key_expr = name_or_expr; + computed = true; + } + return prop('set', key_expr, function_builder(null, [id('$$value')], block(body)), computed); } /** From 8a6810dfa808f067b384414bf2d47dae75274121 Mon Sep 17 00:00:00 2001 From: Jayden Carey Date: Thu, 23 Jan 2025 22:38:04 +0800 Subject: [PATCH 14/14] attempt getting attachments from spreadelement --- .../3-transform/client/visitors/shared/component.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js index 0b803d3207b8..99b931abbd40 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js @@ -165,6 +165,14 @@ export function build_component(node, component_name, context, anchor = context. } else { props_and_spreads.push(expression); } + + // Handle attachments from spread attributes + const symbol = b.call('Symbol.for', b.literal('svelte.attachments')); + const member = b.member(expression, symbol, true); // computed property + const default_empty = b.array([]); + const attachments_expr = b.logical('??', member, default_empty); + + all_attachments.push(b.spread(attachments_expr)); } else if (attribute.type === 'Attribute') { if (attribute.name.startsWith('--')) { custom_css_props.push(