/*! (c) PyScript Development Team */ import "@ungap/with-resolvers"; // These imports can hook more than usual and help debugging possible polyscript issues import { INVALID_CONTENT, define, XWorker, } from "../node_modules/polyscript/esm/index.js"; import { queryTarget } from "../node_modules/polyscript/esm/script-handler.js"; import { dedent, dispatch, unescape, } from "../node_modules/polyscript/esm/utils.js"; import { Hook } from "../node_modules/polyscript/esm/worker/hooks.js"; import "./all-done.js"; import TYPES from "./types.js"; import configs from "./config.js"; import hooks from "./hooks.js"; import sync from "./sync.js"; import stdlib from "./stdlib.js"; import { ErrorCode } from "./exceptions.js"; import { robustFetch as fetch, getText } from "./fetch.js"; const { assign, defineProperty } = Object; // allows lazy element features on code evaluation let currentElement; // generic helper to disambiguate between custom element and script const isScript = ({ tagName }) => tagName === "SCRIPT"; // helper for all script[type="py"] out there const before = (script) => { defineProperty(document, "currentScript", { configurable: true, get: () => script, }); }; const after = () => { delete document.currentScript; }; // common life-cycle handlers for any node const bootstrapNodeAndPlugins = (wrap, element, callback, hook) => { // make it possible to reach the current target node via Python callback(element); for (const fn of hooks[hook]) fn(wrap, element); }; let shouldRegister = true; const registerModule = ({ XWorker: $XWorker, interpreter, io }) => { // automatically use the pyscript stderr (when/if defined) // this defaults to console.error function PyWorker(...args) { const worker = $XWorker(...args); worker.onerror = ({ error }) => io.stderr(error); return worker; } // enrich the Python env with some JS utility for main interpreter.registerJsModule("_pyscript", { PyWorker, get target() { return isScript(currentElement) ? currentElement.target.id : currentElement.id; }, }); interpreter.runPython(stdlib, { globals: interpreter.runPython("{}") }); }; // this is a super-ugly workaround for a polyscript issue: in theory I should // define a codeBeforeRunWorker hook inside py-terminal.js, but since it's a // lazy plugin, it is too late: https://github.com/pyscript/polyscript/issues/52 const py_terminal_codeBeforeRunner = ` from pyscript import pyterminal pyterminal.init() `; const workerHooks = { codeBeforeRunWorker: () => [stdlib, py_terminal_codeBeforeRunner, ...hooks.codeBeforeRunWorker] .map(dedent) .join("\n"), codeBeforeRunWorkerAsync: () => [stdlib, ...hooks.codeBeforeRunWorkerAsync].map(dedent).join("\n"), codeAfterRunWorker: () => [...hooks.codeAfterRunWorker].map(dedent).join("\n"), codeAfterRunWorkerAsync: () => [...hooks.codeAfterRunWorkerAsync].map(dedent).join("\n"), }; const exportedConfig = {}; export { exportedConfig as config, hooks }; for (const [TYPE, interpreter] of TYPES) { const dispatchDone = (element, isAsync, result) => { if (isAsync) result.then(() => dispatch(element, TYPE, "done")); else dispatch(element, TYPE, "done"); }; const { config, plugins, error } = configs.get(TYPE); // create a unique identifier when/if needed let id = 0; const getID = (prefix = TYPE) => `${prefix}-${id++}`; /** * Given a generic DOM Element, tries to fetch the 'src' attribute, if present. * It either throws an error if the 'src' can't be fetched or it returns a fallback * content as source. */ const fetchSource = async (tag, io, asText) => { if (tag.hasAttribute("src")) { try { return await fetch(tag.getAttribute("src")).then(getText); } catch (error) { io.stderr(error); } } if (asText) return dedent(tag.textContent); const code = dedent(unescape(tag.innerHTML)); console.warn( `Deprecated: use