withImportmap = function withImportMap(importmap, hook) {
let resolve, reject;
const ready = new Promise(function set(resolve_, reject_) {
resolve = resolve_;
reject = reject_;
});
const source = [
`<script type=importmap onerror="frameElement.reject">`,
JSON.stringify(importmap).replace(
/<(?:!--|\/?script)/g,
(match) => "\\x3C" + match.substring(1)
),
`</script>`,
"<script type=module>(",
async function importer() {
const { hook, importmap, resolve, reject } = window.frameElement;
try {
hook?.(window, (name) => import(name));
const toEntry = async (name) => [name, await import(name)];
const entries = await Promise.all(
Object.keys(importmap.imports || {}).map(toEntry)
);
const imports = Object.fromEntries(entries);
resolve({ imports, window });
} catch (e) {
reject(e);
}
}.toString(),
")()</script>"
].join("");
const iframe = document.createElement("iframe");
iframe.setAttribute("srcdoc", source);
Object.assign(iframe, {
hook,
ready,
resolve,
reject,
importmap,
appendTo: (invalidation, parent = document.body) => {
invalidation.then(() => {
iframe.remove();
});
parent.append(iframe);
return iframe.ready;
}
});
return iframe;
}