const pageScriptInfoBySrc = new Map(); function registerPageScriptElement(src) { if (!src) { throw new Error('Must provide a non-empty value for the "src" attribute.'); } let pageScriptInfo = pageScriptInfoBySrc.get(src); if (pageScriptInfo) { pageScriptInfo.referenceCount++; } else { pageScriptInfo = { referenceCount: 1, module: null }; pageScriptInfoBySrc.set(src, pageScriptInfo); initializePageScriptModule(src, pageScriptInfo); } } function unregisterPageScriptElement(src) { if (!src) { return; } const pageScriptInfo = pageScriptInfoBySrc.get(src); if (!pageScriptInfo) { return; } pageScriptInfo.referenceCount--; } async function initializePageScriptModule(src, pageScriptInfo) { // If the path is relative, normalize it by by making it an absolute URL // with document's the base HREF. if (src.startsWith("./")) { src = new URL(src.substr(2), document.baseURI).toString(); } const module = await import(src); if (pageScriptInfo.referenceCount <= 0) { // All page-script elements with the same 'src' were // unregistered while we were loading the module. return; } pageScriptInfo.module = module; module.onLoad?.(); module.onUpdate?.(); } function onEnhancedLoad() { // Start by invoking 'onDispose' on any modules that are no longer referenced. for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) { if (referenceCount <= 0) { module?.onDispose?.(); pageScriptInfoBySrc.delete(src); } } // Then invoke 'onUpdate' on the remaining modules. for (const { module } of pageScriptInfoBySrc.values()) { module?.onUpdate?.(); } } export function afterWebStarted(blazor) { customElements.define('page-script', class extends HTMLElement { static observedAttributes = ['src']; // We use attributeChangedCallback instead of connectedCallback // because a page-script element might get reused between enhanced // navigations. attributeChangedCallback(name, oldValue, newValue) { if (name !== 'src') { return; } this.src = newValue; unregisterPageScriptElement(oldValue); registerPageScriptElement(newValue); } disconnectedCallback() { unregisterPageScriptElement(this.src); } }); blazor.addEventListener('enhancedload', onEnhancedLoad); }