import { EvtRt } from '../EvtRt.js';
import { MountConfig, MountContext } from '../types/mount-observer/types.js';
import { MountObserver } from '../MountObserver.js';
/**
* Handler for `
*
*
*
*
*
*
*
*
*
*
*
* ```
*/
export class CedeScriptHandler extends EvtRt {
static matching = 'script[type="cede"][data-extends]';
static whereInstanceOf = HTMLScriptElement;
async mount(mountedElement: Element, mountConfig: MountConfig, context: MountContext): Promise {
this.abort();
const scriptEl = mountedElement as HTMLScriptElement;
const extendsName = scriptEl.dataset.extends;
if (!extendsName) return;
const parentEl = scriptEl.parentElement;
if (!parentEl) {
throw new Error('CedeScript: script element must have a parentElement');
}
const tagName = parentEl.localName;
const registry = (scriptEl as any).customElementRegistry || customElements;
// Already defined? Do nothing (first one prevails).
if (registry.get(tagName)) return;
// Parse config: from export, src, or inline JSON
let config: Record = (scriptEl as any).export;
if (!config) {
const srcAttr = scriptEl.getAttribute('src');
if (srcAttr) {
try {
const module = await import(srcAttr, { with: { type: 'json' } } as any);
config = module.default;
} catch (error) {
throw new Error(`Failed to import JSON from '${srcAttr}': ${error instanceof Error ? error.message : String(error)}`);
}
} else {
const jsonText = scriptEl.textContent?.trim();
if (jsonText) {
try {
config = JSON.parse(jsonText);
} catch (error) {
throw new Error(`Failed to parse JSON content: ${error instanceof Error ? error.message : String(error)}`);
}
} else {
config = {};
}
}
// Store parsed config and dispatch resolved event
(scriptEl as any).export = config;
const { ResolvedEvent } = await import('../Events.js');
scriptEl.dispatchEvent(new ResolvedEvent(config));
}
// Delegate to defineWithFeatures
const { defineWithFeatures } = await import('assign-gingerly/defineWithFeatures.js');
// Race condition guard: check again after async operations
if (registry.get(tagName)) return;
await defineWithFeatures(tagName, extendsName, config as any, registry, {
onSubclassCreated(NewCtr) {
(NewCtr as any).seedRef = new WeakRef(scriptEl);
}
});
}
}
MountObserver.define('builtIns.cedeScript', CedeScriptHandler);
export const cedeScript = 'builtIns.cedeScript';