let outputIndex = 0; export const jsConsole = console; // Overwrite globalThis.console with domConsole to redirect output to the DOM console. // To always output to the JavaScript console regardless, use jsConsole. export const domConsole = { log(...message) { postMessage({ kind: "output", output: { kind: "console.log", message: [...message], }, outputIndex, }); }, }; let kernel = { init() { return {}; }, async evalModule(_state, source, language, _params) { if (language == "javascript") { let blobUrl = URL.createObjectURL(new Blob([source], { type: "text/javascript" })); let module = await import(blobUrl); for (let exportedKey in module) { globalThis[exportedKey] = module[exportedKey]; } return true; } else { return false; } }, }; export function getKernel() { return kernel; } let evaluationComplete = null; export async function evaluate(commands, { error, newOutput }) { if (evaluationComplete != null) { await evaluationComplete; } let signalEvaluationComplete; evaluationComplete = new Promise((resolve, _reject) => { signalEvaluationComplete = resolve; }); let kernelState = kernel.init(); outputIndex = 0; try { for (let command of commands) { if (command.kind == "module") { await kernel.evalModule( kernelState, command.source, command.language, command.kernelParameters, ); } else if (command.kind == "output") { if (newOutput != null) { newOutput(outputIndex); } ++outputIndex; } } postMessage({ kind: "evalComplete", }); } catch (err) { postMessage({ kind: "output", output: { kind: "error", message: [err.toString()], }, outputIndex, }); if (error != null) { error(); } } signalEvaluationComplete(); }