fix: stable attachments

pull/15961/head
Rich Harris 4 months ago
parent 7183886a73
commit ef173e3a1a

@ -104,9 +104,10 @@ export function build_set_attributes(
);
if (is_dynamic) {
context.state.init.push(b.let(attributes_id));
const update = b.stmt(b.assignment('=', attributes_id, call));
context.state.update.push(update);
context.state.init.push(
b.let(attributes_id),
b.stmt(b.call('$.set_attribute_effect', element_id, b.thunk(b.object(values))))
);
} else {
context.state.init.push(b.stmt(call));
}

@ -5,7 +5,7 @@ import { effect } from '../../reactivity/effects.js';
* @param {() => (node: Element) => void} get_fn
*/
export function attach(node, get_fn) {
effect(() => {
return effect(() => {
const fn = get_fn();
// we use `&&` rather than `?.` so that things like

@ -18,6 +18,7 @@ import { clsx } from '../../../shared/attributes.js';
import { set_class } from './class.js';
import { set_style } from './style.js';
import { ATTACHMENT_KEY, NAMESPACE_HTML } from '../../../../constants.js';
import { block, branch, destroy_effect } from '../../reactivity/effects.js';
export const CLASS = Symbol('class');
export const STYLE = Symbol('style');
@ -456,6 +457,49 @@ export function set_attributes(element, prev, next, css_hash, skip_warning = fal
return current;
}
/**
* @param {Element & ElementCSSInlineStyle} element
* @param {() => Record<string | symbol, any>} fn
* @param {string} [css_hash]
* @param {boolean} [skip_warning]
*/
export function set_attribute_effect(element, fn, css_hash, skip_warning = false) {
/** @type {Record<string | symbol, any>} */
var prev = {};
/** @type {Record<symbol, import('#client').Effect>} */
var effects = {};
block(() => {
var next = fn();
for (const key in prev) {
if (!next[key]) {
element.removeAttribute(key);
}
}
for (let symbol of Object.getOwnPropertySymbols(prev)) {
if (!next[symbol]) {
destroy_effect(effects[symbol]);
delete effects[symbol];
}
}
for (const key in next) {
set_attribute(element, key, next[key], skip_warning);
}
for (let symbol of Object.getOwnPropertySymbols(next)) {
if (symbol.description === ATTACHMENT_KEY && next[symbol] !== prev[symbol]) {
effects[symbol] = branch(() => attach(element, () => next[symbol]));
}
}
prev = next;
});
}
/**
*
* @param {Element} element

@ -28,6 +28,7 @@ export {
remove_input_defaults,
set_attribute,
set_attributes,
set_attribute_effect,
set_custom_element_data,
set_xlink_attribute,
set_value,

Loading…
Cancel
Save