restrict which symbols are recognised as attachment keys

attachments
Rich Harris 1 day ago
parent 1988ba4345
commit e1b940c45b

@ -33,6 +33,10 @@
"types": "./types/index.d.ts",
"default": "./src/animate/index.js"
},
"./attachments": {
"types": "./types/index.d.ts",
"default": "./src/attachments/index.js"
},
"./compiler": {
"types": "./types/index.d.ts",
"require": "./compiler/index.js",

@ -30,6 +30,7 @@ await createBundle({
[pkg.name]: `${dir}/src/index.d.ts`,
[`${pkg.name}/action`]: `${dir}/src/action/public.d.ts`,
[`${pkg.name}/animate`]: `${dir}/src/animate/public.d.ts`,
[`${pkg.name}/attachments`]: `${dir}/src/attachments/public.d.ts`,
[`${pkg.name}/compiler`]: `${dir}/src/compiler/public.d.ts`,
[`${pkg.name}/easing`]: `${dir}/src/easing/index.js`,
[`${pkg.name}/legacy`]: `${dir}/src/legacy/legacy-client.js`,

@ -0,0 +1,4 @@
export {
create_attachment_key as createAttachmentKey,
is_attachment_key as isAttachmentKey
} from '../internal/client/dom/elements/attachments.js';

@ -257,7 +257,7 @@ export function build_component(node, component_name, context, anchor = context.
push_prop(
b.prop(
'get',
b.call('Symbol', b.literal('@attach')),
b.call('$.create_attachment_key'),
/** @type {Expression} */ (context.visit(attribute.expression)),
true
)

@ -1,5 +1,24 @@
import { effect } from '../../reactivity/effects.js';
const key = `@attach-${Math.random().toString(36).slice(2)}`;
const name = `Symbol(${key})`;
// TODO this feels a bit belt-and-braces to me, tbh — are we sure we need it?
/**
* Creates a `Symbol` that Svelte recognises as an attachment key
*/
export function create_attachment_key() {
return Symbol(key);
}
/**
* Returns `true` if the symbol was created with `createAttachmentKey`
* @param {string | symbol} key
*/
export function is_attachment_key(key) {
return typeof key === 'symbol' && key.toString() === name;
}
/**
* @param {Element} node
* @param {() => (node: Element) => void} get_fn

@ -13,7 +13,7 @@ import {
set_active_effect,
set_active_reaction
} from '../../runtime.js';
import { attach } from './attachments.js';
import { attach, is_attachment_key } from './attachments.js';
/**
* The value/checked attribute in the template actually corresponds to the defaultValue property, so we need
@ -242,8 +242,8 @@ export function set_custom_element_data(node, prop, value) {
/**
* Spreads attributes onto a DOM element, taking into account the currently set attributes
* @param {Element & ElementCSSInlineStyle} element
* @param {Record<string, any> | undefined} prev
* @param {Record<string, any>} next New attributes - this function mutates this object
* @param {Record<string | symbol, any> | undefined} prev
* @param {Record<string | symbol, any>} next New attributes - this function mutates this object
* @param {string} [css_hash]
* @param {boolean} [preserve_attribute_case]
* @param {boolean} [is_custom_element]
@ -409,8 +409,10 @@ export function set_attributes(
}
for (let symbol of Object.getOwnPropertySymbols(next)) {
if (is_attachment_key(symbol)) {
attach(element, () => next[symbol]);
}
}
return current;
}

@ -27,7 +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 { attach, create_attachment_key, is_attachment_key } from './dom/elements/attachments.js';
export {
remove_input_defaults,
set_attribute,

@ -1,6 +1,8 @@
<script>
import { createAttachmentKey } from 'svelte/attachments';
let stuff = $state({
[Symbol()]: () => console.log('hello')
[createAttachmentKey()]: () => console.log('hello')
});
</script>

Loading…
Cancel
Save