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';