diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index 90901d29ce..d6398d7605 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -56,6 +56,7 @@ import { TitleElement } from './visitors/TitleElement.js'; import { TransitionDirective } from './visitors/TransitionDirective.js'; import { UpdateExpression } from './visitors/UpdateExpression.js'; import { UseDirective } from './visitors/UseDirective.js'; +import { UseTag } from './visitors/UseTag.js'; import { VariableDeclaration } from './visitors/VariableDeclaration.js'; /** @type {Visitors} */ @@ -131,6 +132,7 @@ const visitors = { TransitionDirective, UpdateExpression, UseDirective, + UseTag, VariableDeclaration }; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js index 2c2c287f12..0983aeb7e7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js @@ -82,7 +82,7 @@ export function RegularElement(node, context) { /** @type {AST.StyleDirective[]} */ const style_directives = []; - /** @type {Array} */ + /** @type {Array} */ const other_directives = []; /** @type {ExpressionStatement[]} */ @@ -152,6 +152,10 @@ export function RegularElement(node, context) { has_use = true; other_directives.push(attribute); break; + + case 'UseTag': + other_directives.push(attribute); + break; } } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseTag.js new file mode 100644 index 0000000000..76bc83279e --- /dev/null +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/UseTag.js @@ -0,0 +1,21 @@ +/** @import { Expression } from 'estree' */ +/** @import { AST } from '#compiler' */ +/** @import { ComponentContext } from '../types' */ +import * as b from '../../../../utils/builders.js'; + +/** + * @param {AST.UseTag} node + * @param {ComponentContext} context + */ +export function UseTag(node, context) { + context.state.init.push( + b.stmt( + b.call( + '$.attach', + context.state.node, + b.thunk(/** @type {Expression} */ (context.visit(node.expression))) + ) + ) + ); + context.next(); +} diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index 6b4c7d6d52..a8e32b402a 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -553,6 +553,7 @@ export namespace AST { | AST.Attribute | AST.SpreadAttribute | Directive + | AST.UseTag | AST.Comment | Block; diff --git a/packages/svelte/src/internal/client/dom/elements/attachments.js b/packages/svelte/src/internal/client/dom/elements/attachments.js new file mode 100644 index 0000000000..c7299c3716 --- /dev/null +++ b/packages/svelte/src/internal/client/dom/elements/attachments.js @@ -0,0 +1,11 @@ +import { effect } from '../../reactivity/effects.js'; + +/** + * @param {Element} node + * @param {() => (node: Element) => void} get_fn + */ +export function attach(node, get_fn) { + effect(() => { + get_fn()(node); + }); +} diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index f22c33babc..05135dc764 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -27,6 +27,7 @@ export { element } from './dom/blocks/svelte-element.js'; export { head } from './dom/blocks/svelte-head.js'; export { append_styles } from './dom/css.js'; export { action } from './dom/elements/actions.js'; +export { attach } from './dom/elements/attachments.js'; export { remove_input_defaults, set_attribute, diff --git a/packages/svelte/tests/runtime-runes/samples/attachment-basic/_config.js b/packages/svelte/tests/runtime-runes/samples/attachment-basic/_config.js new file mode 100644 index 0000000000..1be4737069 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/attachment-basic/_config.js @@ -0,0 +1,6 @@ +import { test } from '../../test'; + +export default test({ + ssrHtml: `
`, + html: `
DIV
` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/attachment-basic/main.svelte b/packages/svelte/tests/runtime-runes/samples/attachment-basic/main.svelte new file mode 100644 index 0000000000..593065e876 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/attachment-basic/main.svelte @@ -0,0 +1 @@ +
node.textContent = node.nodeName}>