diff --git a/core/package-lock.json b/core/package-lock.json index 2a22772ff0b..d0594980479 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -368,9 +368,9 @@ } }, "node_modules/@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.2.tgz", + "integrity": "sha512-Z+R3hN6kXbgBWAuejUNPihylAL1Z5CaFqnIe0nTX8Ej+XlIy3EGtXxn6WtLMO+os2hRkQvm2yvaGMYliUzlJaw==", "dev": true, "license": "MIT" }, @@ -1208,9 +1208,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001666", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz", + "integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==", "dev": true, "funding": [ { @@ -1637,9 +1637,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.30", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.30.tgz", - "integrity": "sha512-sXI35EBN4lYxzc/pIGorlymYNzDBOqkSlVRe6MkgBsW/hW1tpC/HDJ2fjG7XnjakzfLEuvdmux0Mjs6jHq4UOA==", + "version": "1.5.31", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.31.tgz", + "integrity": "sha512-QcDoBbQeYt0+3CWcK/rEbuHvwpbT/8SV9T3OSgs6cX1FlcUAkgrkqbg9zLnDrMM/rLamzQwal4LYFCiWk861Tg==", "dev": true, "license": "ISC" }, diff --git a/core/src/core.js b/core/src/core.js index b3da8cb285f..8d472718664 100644 --- a/core/src/core.js +++ b/core/src/core.js @@ -37,6 +37,11 @@ import { import { stdlib, optional } from "./stdlib.js"; export { stdlib, optional, inputFailure }; +export const donkey = (options) => + import(/* webpackIgnore: true */ "./plugins/donkey.js").then((module) => + module.default(options), + ); + // generic helper to disambiguate between custom element and script const isScript = ({ tagName }) => tagName === "SCRIPT"; diff --git a/core/src/plugins.js b/core/src/plugins.js index d155819f1b6..121224a0714 100644 --- a/core/src/plugins.js +++ b/core/src/plugins.js @@ -5,6 +5,11 @@ export default { /* webpackIgnore: true */ "./plugins/deprecations-manager.js" ), + donkey: () => + import( + /* webpackIgnore: true */ + "./plugins/donkey.js" + ), error: () => import( /* webpackIgnore: true */ diff --git a/core/src/plugins/donkey.js b/core/src/plugins/donkey.js new file mode 100644 index 00000000000..9d6a71c3000 --- /dev/null +++ b/core/src/plugins/donkey.js @@ -0,0 +1,64 @@ +import { assign, dedent } from "polyscript/exports"; + +const invoke = (name, args) => `${name}(code, ${args.join(", ")})`; + +export default (options = {}) => { + const type = options.type || "py"; + const args = options.persistent + ? ["globals()", "__locals__"] + : ["{}", "{}"]; + const src = URL.createObjectURL( + new Blob([ + dedent(` + from pyscript import sync, config + __message__ = lambda e,v: f"\x1b[31m\x1b[1m{e.__name__}\x1b[0m: {v}" + __locals__ = {} + if config["type"] == "py": + import sys + def __error__(_): + info = sys.exc_info() + return __message__(info[0], info[1]) + else: + __error__ = lambda e: __message__(e.__class__, e.value) + def execute(code): + try: return ${invoke("exec", args)}; + except Exception as e: print(__error__(e)); + def evaluate(code): + try: return ${invoke("eval", args)}; + except Exception as e: print(__error__(e)); + sync.execute = execute + sync.evaluate = evaluate + `), + ]), + ); + + const script = assign(document.createElement("script"), { type, src }); + + script.toggleAttribute("worker", true); + script.toggleAttribute("terminal", true); + if (options.terminal) script.setAttribute("target", options.terminal); + if (options.config) + script.setAttribute("config", JSON.stringify(options.config)); + + return new Promise((resolve) => { + script.addEventListener(`${type}:done`, (event) => { + event.stopPropagation(); + URL.revokeObjectURL(src); + const { xworker, process, terminal } = script; + const { execute, evaluate } = xworker.sync; + script.remove(); + resolve({ + process, + execute: (code) => execute(dedent(code)), + evaluate: (code) => evaluate(dedent(code)), + clear: () => terminal.clear(), + reset: () => terminal.reset(), + kill: () => { + xworker.terminate(); + terminal.dispose(); + }, + }); + }); + document.body.append(script); + }); +}; diff --git a/core/tests/index.html b/core/tests/index.html index 05e1a942655..ab71d7e1c23 100644 --- a/core/tests/index.html +++ b/core/tests/index.html @@ -14,5 +14,5 @@ a:hover { opacity: 1; } -