diff --git a/packages/svelte/src/attachments/index.js b/packages/svelte/src/attachments/index.js index 9d40fe95f0..0bb16cc514 100644 --- a/packages/svelte/src/attachments/index.js +++ b/packages/svelte/src/attachments/index.js @@ -1,9 +1,8 @@ -/** - * @import { FromAction } from "./public.js"; - * @import { ActionReturn } from "svelte/action"; - */ -import { render_effect } from 'svelte/internal/client'; +/** @import { FromAction } from './public.js' */ +import { noop, render_effect } from 'svelte/internal/client'; import { ATTACHMENT_KEY } from '../constants.js'; +import { untrack } from 'svelte'; +import { teardown } from '../internal/client/reactivity/effects.js'; /** * Creates an object key that will be recognised as an attachment when the object is spread onto an element, @@ -36,36 +35,21 @@ export function createAttachmentKey() { * attachments on Components but you have library provided actions. * @type {FromAction} */ -export function fromAction(action, args) { +export function fromAction(action, /** @type {() => any} */ get_arg = noop) { return (element) => { - /** - * @typedef {typeof args} Args; - */ + const { update, destroy } = untrack(() => action(element, get_arg()) ?? {}); - /** - * @type {ReturnType> | undefined} - */ - let actual_args; - /** - * @type {ActionReturn['update']} - */ - let update; - /** - * @type {ActionReturn['destroy']} - */ - let destroy; - render_effect(() => { - actual_args = args?.(); - update?.(/** @type {any} */ (actual_args)); - }); + if (update) { + var ran = false; + render_effect(() => { + const arg = get_arg(); + if (ran) update(arg); + }); + ran = true; + } - render_effect(() => { - return () => { - destroy?.(); - }; - }); - ({ update, destroy } = /** @type {ActionReturn} */ ( - action(element, /** @type {any} */ (actual_args)) - )); + if (destroy) { + teardown(destroy); + } }; }