Files
pyscript/pyscriptjs/src/plugins/importmap.ts
Andrea Giammarchi 82613d016a Fix #1429 - Use basic-devtools module (#1430)
This MR brings in `$`, `$$`, and `$x` browsers devtools' utilities to our code so we can use these whenever we find it convenient.
2023-05-02 15:12:28 +02:00

57 lines
2.1 KiB
TypeScript

import { $$ } from 'basic-devtools';
import { showWarning } from '../utils';
import { Plugin } from '../plugin';
import { getLogger } from '../logger';
import { InterpreterClient } from '../interpreter_client';
const logger = getLogger('plugins/importmap');
type ImportType = { [key: string]: unknown };
type ImportMapType = {
imports: ImportType | null;
};
export class ImportmapPlugin extends Plugin {
async afterSetup(interpreter: InterpreterClient) {
// make importmap ES modules available from python using 'import'.
//
// XXX: this code can probably be improved because errors are silently
// ignored.
//
// Moreover, it's also wrong because it's async and currently we don't
// await the module to be fully registered before executing the code
// inside py-script. It's also unclear whether we want to wait or not
// (or maybe only wait only if we do an actual 'import'?)
for (const node of $$("script[type='importmap']", document)) {
const importmap: ImportMapType = (() => {
try {
return JSON.parse(node.textContent) as ImportMapType;
} catch (e) {
const error = e as Error;
showWarning('Failed to parse import map: ' + error.message);
}
})();
if (importmap?.imports == null) continue;
for (const [name, url] of Object.entries(importmap.imports)) {
if (typeof name != 'string' || typeof url != 'string') continue;
let exports: object;
try {
// XXX: pyodide doesn't like Module(), failing with
// "can't read 'name' of undefined" at import time
exports = { ...(await import(url)) } as object;
} catch {
logger.warn(`failed to fetch '${url}' for '${name}'`);
continue;
}
logger.info('Registering JS module', name);
await interpreter._remote.registerJsModule(name, exports);
}
}
}
}