mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-18 13:00:39 -05:00
[next] Rename all runtime(s) references to interpreter(s) (#1536)
This commit is contained in:
committed by
GitHub
parent
db27d52352
commit
6284c02032
@@ -1,9 +1,9 @@
|
||||
import { $x, $$ } from "basic-devtools";
|
||||
|
||||
import xworker from "./worker/class.js";
|
||||
import { handle, runtimes } from "./script-handler.js";
|
||||
import { handle, interpreters } from "./script-handler.js";
|
||||
import { all, assign, create, defineProperty } from "./utils.js";
|
||||
import { registry, selectors, prefixes } from "./runtimes.js";
|
||||
import { registry, selectors, prefixes } from "./interpreters.js";
|
||||
import { PLUGINS_SELECTORS, handlePlugin } from "./plugins.js";
|
||||
|
||||
export { registerPlugin } from "./plugins.js";
|
||||
@@ -11,20 +11,20 @@ export const XWorker = xworker();
|
||||
|
||||
const RUNTIME_SELECTOR = selectors.join(",");
|
||||
|
||||
// ensure both runtime and its queue are awaited then returns the runtime
|
||||
// ensure both interpreter and its queue are awaited then returns the interpreter
|
||||
const awaitRuntime = async (key) => {
|
||||
if (runtimes.has(key)) {
|
||||
const { runtime, queue } = runtimes.get(key);
|
||||
return (await all([runtime, queue]))[0];
|
||||
if (interpreters.has(key)) {
|
||||
const { interpreter, queue } = interpreters.get(key);
|
||||
return (await all([interpreter, queue]))[0];
|
||||
}
|
||||
|
||||
const available = runtimes.size
|
||||
? `Available runtimes are: ${[...runtimes.keys()]
|
||||
const available = interpreters.size
|
||||
? `Available interpreters are: ${[...interpreters.keys()]
|
||||
.map((r) => `"${r}"`)
|
||||
.join(", ")}.`
|
||||
: `There are no runtimes in this page.`;
|
||||
: `There are no interpreters in this page.`;
|
||||
|
||||
throw new Error(`The runtime "${key}" was not found. ${available}`);
|
||||
throw new Error(`The interpreter "${key}" was not found. ${available}`);
|
||||
};
|
||||
|
||||
defineProperty(globalThis, "pyscript", {
|
||||
@@ -45,13 +45,13 @@ const listener = async (event) => {
|
||||
currentTarget,
|
||||
)) {
|
||||
name = name.slice(0, -(type.length + 1));
|
||||
const runtime = await awaitRuntime(
|
||||
const interpreter = await awaitRuntime(
|
||||
el.getAttribute(`${name}-env`) || name,
|
||||
);
|
||||
const i = index++;
|
||||
try {
|
||||
globalThis.__events.set(i, event);
|
||||
registry.get(name).runEvent(runtime, value, i);
|
||||
registry.get(name).runEvent(interpreter, value, i);
|
||||
} finally {
|
||||
globalThis.__events.delete(i);
|
||||
}
|
||||
|
||||
@@ -2,20 +2,21 @@ import { clean, writeFile as writeFileUtil } from "./_utils.js";
|
||||
|
||||
// REQUIRES INTEGRATION TEST
|
||||
/* c8 ignore start */
|
||||
export const run = (runtime, code) => runtime.runPython(clean(code));
|
||||
export const run = (interpreter, code) => interpreter.runPython(clean(code));
|
||||
|
||||
export const runAsync = (runtime, code) => runtime.runPythonAsync(clean(code));
|
||||
export const runAsync = (interpreter, code) =>
|
||||
interpreter.runPythonAsync(clean(code));
|
||||
|
||||
export function runEvent(runtime, code, key) {
|
||||
export function runEvent(interpreter, code, key) {
|
||||
code = `import js;event=js.__events.get(${key});${code}`;
|
||||
return this.run(runtime, code);
|
||||
return this.run(interpreter, code);
|
||||
}
|
||||
|
||||
const worker = (method) =>
|
||||
function (runtime, code, xworker) {
|
||||
function (interpreter, code, xworker) {
|
||||
code = `from js import xworker;${code}`;
|
||||
globalThis.xworker = xworker;
|
||||
return this[method](runtime, code);
|
||||
return this[method](interpreter, code);
|
||||
};
|
||||
|
||||
export const runWorker = worker("run");
|
||||
@@ -24,9 +24,9 @@ export const stdio = (init) => {
|
||||
stderr: (...args) => localIO.stderr(...args),
|
||||
stdout: (...args) => localIO.stdout(...args),
|
||||
async get(engine) {
|
||||
const runtime = await engine;
|
||||
io.set(runtime, localIO);
|
||||
return runtime;
|
||||
const interpreter = await engine;
|
||||
io.set(interpreter, localIO);
|
||||
return interpreter;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -123,11 +123,11 @@ const fetchResolved = (config_fetch, url) =>
|
||||
|
||||
export const base = new WeakMap();
|
||||
|
||||
export const fetchPaths = (module, runtime, config_fetch) =>
|
||||
export const fetchPaths = (module, interpreter, config_fetch) =>
|
||||
all(
|
||||
calculateFetchPaths(config_fetch).map(({ url, path }) =>
|
||||
fetchResolved(config_fetch, url)
|
||||
.then(getBuffer)
|
||||
.then((buffer) => module.writeFile(runtime, path, buffer)),
|
||||
.then((buffer) => module.writeFile(interpreter, path, buffer)),
|
||||
),
|
||||
);
|
||||
@@ -19,15 +19,17 @@ export default {
|
||||
async engine({ loadPyodide }, config, url) {
|
||||
const { stderr, stdout, get } = stdio();
|
||||
const indexURL = url.slice(0, url.lastIndexOf("/"));
|
||||
const runtime = await get(loadPyodide({ stderr, stdout, indexURL }));
|
||||
if (config.fetch) await fetchPaths(this, runtime, config.fetch);
|
||||
const interpreter = await get(
|
||||
loadPyodide({ stderr, stdout, indexURL }),
|
||||
);
|
||||
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
||||
if (config.packages) {
|
||||
await runtime.loadPackage("micropip");
|
||||
const micropip = await runtime.pyimport("micropip");
|
||||
await interpreter.loadPackage("micropip");
|
||||
const micropip = await interpreter.pyimport("micropip");
|
||||
await micropip.install(config.packages);
|
||||
micropip.destroy();
|
||||
}
|
||||
return runtime;
|
||||
return interpreter;
|
||||
},
|
||||
run,
|
||||
runAsync,
|
||||
@@ -10,10 +10,10 @@ const type = "ruby";
|
||||
// REQUIRES INTEGRATION TEST
|
||||
/* c8 ignore start */
|
||||
const worker = (method) =>
|
||||
function (runtime, code, xworker) {
|
||||
function (interpreter, code, xworker) {
|
||||
globalThis.xworker = xworker;
|
||||
return this[method](
|
||||
runtime,
|
||||
interpreter,
|
||||
`require "js";xworker=JS::eval("return xworker");${code}`,
|
||||
);
|
||||
};
|
||||
@@ -28,15 +28,15 @@ export default {
|
||||
`${url.slice(0, url.lastIndexOf("/"))}/ruby.wasm`,
|
||||
);
|
||||
const module = await WebAssembly.compile(await response.arrayBuffer());
|
||||
const { vm: runtime } = await DefaultRubyVM(module);
|
||||
if (config.fetch) await fetchPaths(this, runtime, config.fetch);
|
||||
return runtime;
|
||||
const { vm: interpreter } = await DefaultRubyVM(module);
|
||||
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
||||
return interpreter;
|
||||
},
|
||||
run: (runtime, code) => runtime.eval(clean(code)),
|
||||
runAsync: (runtime, code) => runtime.evalAsync(clean(code)),
|
||||
runEvent(runtime, code, key) {
|
||||
run: (interpreter, code) => interpreter.eval(clean(code)),
|
||||
runAsync: (interpreter, code) => interpreter.evalAsync(clean(code)),
|
||||
runEvent(interpreter, code, key) {
|
||||
return this.run(
|
||||
runtime,
|
||||
interpreter,
|
||||
`require "js";event=JS::eval("return __events.get(${key})");${code}`,
|
||||
);
|
||||
},
|
||||
45
pyscript.core/esm/interpreter/wasmoon.js
Normal file
45
pyscript.core/esm/interpreter/wasmoon.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { clean, fetchPaths, stdio, writeFileShim } from "./_utils.js";
|
||||
|
||||
const type = "wasmoon";
|
||||
|
||||
// REQUIRES INTEGRATION TEST
|
||||
/* c8 ignore start */
|
||||
const worker = (method) =>
|
||||
function (interpreter, code, xworker) {
|
||||
interpreter.global.set("xworker", xworker);
|
||||
return this[method](interpreter, code);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: [type, "lua"],
|
||||
module: (version = "1.15.0") =>
|
||||
`https://cdn.jsdelivr.net/npm/wasmoon@${version}/+esm`,
|
||||
async engine({ LuaFactory, LuaLibraries }, config) {
|
||||
const { stderr, stdout, get } = stdio();
|
||||
const interpreter = await get(new LuaFactory().createEngine());
|
||||
interpreter.global.getTable(LuaLibraries.Base, (index) => {
|
||||
interpreter.global.setField(index, "print", stdout);
|
||||
interpreter.global.setField(index, "printErr", stderr);
|
||||
});
|
||||
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
||||
return interpreter;
|
||||
},
|
||||
run: (interpreter, code) => interpreter.doStringSync(clean(code)),
|
||||
runAsync: (interpreter, code) => interpreter.doString(clean(code)),
|
||||
runEvent(interpreter, code, key) {
|
||||
interpreter.global.set("event", globalThis.__events.get(key));
|
||||
return this.run(interpreter, code);
|
||||
},
|
||||
runWorker: worker("run"),
|
||||
runWorkerAsync: worker("runAsync"),
|
||||
writeFile: (
|
||||
{
|
||||
cmodule: {
|
||||
module: { FS },
|
||||
},
|
||||
},
|
||||
path,
|
||||
buffer,
|
||||
) => writeFileShim(FS, path, buffer),
|
||||
};
|
||||
/* c8 ignore stop */
|
||||
@@ -1,8 +1,8 @@
|
||||
// ⚠️ Part of this file is automatically generated
|
||||
// The :RUNTIMES comment is a delimiter and no code should be written/changed after
|
||||
// See rollup/build_runtimes.cjs to know more
|
||||
// See rollup/build_interpreters.cjs to know more
|
||||
|
||||
import { base } from "./runtime/_utils.js";
|
||||
import { base } from "./interpreter/_utils.js";
|
||||
|
||||
/** @type {Map<string, object>} */
|
||||
export const registry = new Map();
|
||||
@@ -16,18 +16,18 @@ export const selectors = [];
|
||||
/** @type {string[]} */
|
||||
export const prefixes = [];
|
||||
|
||||
export const runtime = new Proxy(new Map(), {
|
||||
export const interpreter = new Proxy(new Map(), {
|
||||
get(map, id) {
|
||||
if (!map.has(id)) {
|
||||
const [type, ...rest] = id.split("@");
|
||||
const runtime = registry.get(type);
|
||||
const interpreter = registry.get(type);
|
||||
const url = /^https?:\/\//i.test(rest)
|
||||
? rest[0]
|
||||
: runtime.module(...rest);
|
||||
: interpreter.module(...rest);
|
||||
map.set(id, {
|
||||
url,
|
||||
module: import(url),
|
||||
engine: runtime.engine.bind(runtime),
|
||||
engine: interpreter.engine.bind(interpreter),
|
||||
});
|
||||
}
|
||||
const { url, module, engine } = map.get(id);
|
||||
@@ -41,17 +41,18 @@ export const runtime = new Proxy(new Map(), {
|
||||
},
|
||||
});
|
||||
|
||||
const register = (runtime) => {
|
||||
for (const type of [].concat(runtime.type)) {
|
||||
registry.set(type, runtime);
|
||||
const register = (interpreter) => {
|
||||
for (const type of [].concat(interpreter.type)) {
|
||||
registry.set(type, interpreter);
|
||||
selectors.push(`script[type="${type}"]`);
|
||||
prefixes.push(`${type}-`);
|
||||
}
|
||||
};
|
||||
|
||||
//:RUNTIMES
|
||||
import micropython from "./runtime/micropython.js";
|
||||
import pyodide from "./runtime/pyodide.js";
|
||||
import ruby from "./runtime/ruby.js";
|
||||
import wasmoon from "./runtime/wasmoon.js";
|
||||
for (const runtime of [micropython, pyodide, ruby, wasmoon]) register(runtime);
|
||||
import micropython from "./interpreter/micropython.js";
|
||||
import pyodide from "./interpreter/pyodide.js";
|
||||
import ruby from "./interpreter/ruby.js";
|
||||
import wasmoon from "./interpreter/wasmoon.js";
|
||||
for (const interpreter of [micropython, pyodide, ruby, wasmoon])
|
||||
register(interpreter);
|
||||
@@ -1,10 +1,10 @@
|
||||
import { runtime } from "./runtimes.js";
|
||||
import { interpreter } from "./interpreters.js";
|
||||
import { absoluteURL, resolve } from "./utils.js";
|
||||
import { parse } from "./toml.js";
|
||||
import { getJSON, getText } from "./fetch-utils.js";
|
||||
|
||||
/**
|
||||
* @param {string} id the runtime name @ version identifier
|
||||
* @param {string} id the interpreter name @ version identifier
|
||||
* @param {string} [config] optional config file to parse
|
||||
* @returns
|
||||
*/
|
||||
@@ -28,12 +28,12 @@ export const getRuntime = (id, config) => {
|
||||
}
|
||||
/* c8 ignore stop */
|
||||
}
|
||||
return resolve(options).then((options) => runtime[id](options, config));
|
||||
return resolve(options).then((options) => interpreter[id](options, config));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} type the runtime type
|
||||
* @param {string} [version] the optional runtime version
|
||||
* @param {string} type the interpreter type
|
||||
* @param {string} [version] the optional interpreter version
|
||||
* @returns
|
||||
*/
|
||||
export const getRuntimeID = (type, version = "") =>
|
||||
|
||||
@@ -2,9 +2,9 @@ import { $$ } from "basic-devtools";
|
||||
|
||||
import { create } from "./utils.js";
|
||||
import { getDetails } from "./script-handler.js";
|
||||
import { registry, configs } from "./runtimes.js";
|
||||
import { registry, configs } from "./interpreters.js";
|
||||
import { getRuntimeID } from "./loader.js";
|
||||
import { io } from "./runtime/_utils.js";
|
||||
import { io } from "./interpreter/_utils.js";
|
||||
|
||||
import workerHooks from "./worker/hooks.js";
|
||||
|
||||
@@ -12,12 +12,12 @@ export const PLUGINS_SELECTORS = [];
|
||||
|
||||
/**
|
||||
* @typedef {Object} Runtime plugin configuration
|
||||
* @prop {string} type the runtime type
|
||||
* @prop {object} runtime the bootstrapped runtime
|
||||
* @prop {(url:string, options?: object) => Worker} XWorker an XWorker constructor that defaults to same runtime on the Worker.
|
||||
* @prop {object} config a cloned config used to bootstrap the runtime
|
||||
* @prop {(code:string) => any} run an utility to run code within the runtime
|
||||
* @prop {(code:string) => Promise<any>} runAsync an utility to run code asynchronously within the runtime
|
||||
* @prop {string} type the interpreter type
|
||||
* @prop {object} interpreter the bootstrapped interpreter
|
||||
* @prop {(url:string, options?: object) => Worker} XWorker an XWorker constructor that defaults to same interpreter on the Worker.
|
||||
* @prop {object} config a cloned config used to bootstrap the interpreter
|
||||
* @prop {(code:string) => any} run an utility to run code within the interpreter
|
||||
* @prop {(code:string) => Promise<any>} runAsync an utility to run code asynchronously within the interpreter
|
||||
* @prop {(path:string, data:ArrayBuffer) => void} writeFile an utility to write a file in the virtual FS, if available
|
||||
*/
|
||||
|
||||
@@ -37,14 +37,14 @@ export const handlePlugin = (node) => {
|
||||
const { type, version, config, env, onRuntimeReady } = options;
|
||||
const name = getRuntimeID(type, version);
|
||||
const id = env || `${name}${config ? `|${config}` : ""}`;
|
||||
const { runtime: engine, XWorker } = getDetails(
|
||||
const { interpreter: engine, XWorker } = getDetails(
|
||||
type,
|
||||
id,
|
||||
name,
|
||||
version,
|
||||
config,
|
||||
);
|
||||
engine.then((runtime) => {
|
||||
engine.then((interpreter) => {
|
||||
if (!patched.has(id)) {
|
||||
const module = create(registry.get(type));
|
||||
const {
|
||||
@@ -67,9 +67,13 @@ export const handlePlugin = (node) => {
|
||||
["run", [onBeforeRun, onAfterRun]],
|
||||
]) {
|
||||
const method = module[name];
|
||||
module[name] = function (runtime, code) {
|
||||
module[name] = function (interpreter, code) {
|
||||
if (before) before.call(this, resolved, node);
|
||||
const result = method.call(this, runtime, code);
|
||||
const result = method.call(
|
||||
this,
|
||||
interpreter,
|
||||
code,
|
||||
);
|
||||
if (after) after.call(this, resolved, node);
|
||||
return result;
|
||||
};
|
||||
@@ -80,12 +84,12 @@ export const handlePlugin = (node) => {
|
||||
["runAsync", [onBeforeRunAsync, onAfterRunAsync]],
|
||||
]) {
|
||||
const method = module[name];
|
||||
module[name] = async function (runtime, code) {
|
||||
module[name] = async function (interpreter, code) {
|
||||
if (before)
|
||||
await before.call(this, resolved, node);
|
||||
const result = await method.call(
|
||||
this,
|
||||
runtime,
|
||||
interpreter,
|
||||
code,
|
||||
);
|
||||
if (after)
|
||||
@@ -107,12 +111,12 @@ export const handlePlugin = (node) => {
|
||||
|
||||
const resolved = {
|
||||
type,
|
||||
runtime,
|
||||
interpreter,
|
||||
XWorker,
|
||||
io: io.get(runtime),
|
||||
io: io.get(interpreter),
|
||||
config: structuredClone(configs.get(name)),
|
||||
run: module.run.bind(module, runtime),
|
||||
runAsync: module.runAsync.bind(module, runtime),
|
||||
run: module.run.bind(module, interpreter),
|
||||
runAsync: module.runAsync.bind(module, interpreter),
|
||||
};
|
||||
|
||||
patched.set(id, resolved);
|
||||
@@ -132,15 +136,15 @@ const plugins = new Map();
|
||||
|
||||
/**
|
||||
* @typedef {Object} PluginOptions plugin configuration
|
||||
* @prop {string} type the runtime/interpreter type to receive
|
||||
* @prop {string} [version] the optional runtime version to use
|
||||
* @prop {string} [config] the optional config to use within such runtime
|
||||
* @prop {string} type the interpreter/interpreter type to receive
|
||||
* @prop {string} [version] the optional interpreter version to use
|
||||
* @prop {string} [config] the optional config to use within such interpreter
|
||||
* @prop {string} [env] the optional environment to use
|
||||
* @prop {(node: Element, runtime: Runtime) => void} onRuntimeReady the callback that will be invoked once
|
||||
* @prop {(node: Element, interpreter: Runtime) => void} onRuntimeReady the callback that will be invoked once
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows plugins and components on the page to receive runtimes to execute any code.
|
||||
* Allows plugins and components on the page to receive interpreters to execute any code.
|
||||
* @param {string} name the unique plugin name
|
||||
* @param {PluginOptions} options the plugin configuration
|
||||
*/
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { clean, fetchPaths, stdio, writeFileShim } from "./_utils.js";
|
||||
|
||||
const type = "wasmoon";
|
||||
|
||||
// REQUIRES INTEGRATION TEST
|
||||
/* c8 ignore start */
|
||||
const worker = (method) =>
|
||||
function (runtime, code, xworker) {
|
||||
runtime.global.set("xworker", xworker);
|
||||
return this[method](runtime, code);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: [type, "lua"],
|
||||
module: (version = "1.15.0") =>
|
||||
`https://cdn.jsdelivr.net/npm/wasmoon@${version}/+esm`,
|
||||
async engine({ LuaFactory, LuaLibraries }, config) {
|
||||
const { stderr, stdout, get } = stdio();
|
||||
const runtime = await get(new LuaFactory().createEngine());
|
||||
runtime.global.getTable(LuaLibraries.Base, (index) => {
|
||||
runtime.global.setField(index, "print", stdout);
|
||||
runtime.global.setField(index, "printErr", stderr);
|
||||
});
|
||||
if (config.fetch) await fetchPaths(this, runtime, config.fetch);
|
||||
return runtime;
|
||||
},
|
||||
run: (runtime, code) => runtime.doStringSync(clean(code)),
|
||||
runAsync: (runtime, code) => runtime.doString(clean(code)),
|
||||
runEvent(runtime, code, key) {
|
||||
runtime.global.set("event", globalThis.__events.get(key));
|
||||
return this.run(runtime, code);
|
||||
},
|
||||
runWorker: worker("run"),
|
||||
runWorkerAsync: worker("runAsync"),
|
||||
writeFile: (
|
||||
{
|
||||
cmodule: {
|
||||
module: { FS },
|
||||
},
|
||||
},
|
||||
path,
|
||||
buffer,
|
||||
) => writeFileShim(FS, path, buffer),
|
||||
};
|
||||
/* c8 ignore stop */
|
||||
@@ -2,7 +2,7 @@ import { $ } from "basic-devtools";
|
||||
|
||||
import xworker from "./worker/class.js";
|
||||
import { getRuntime, getRuntimeID } from "./loader.js";
|
||||
import { registry } from "./runtimes.js";
|
||||
import { registry } from "./interpreters.js";
|
||||
import { all, resolve, defineProperty, absoluteURL } from "./utils.js";
|
||||
import { getText } from "./fetch-utils.js";
|
||||
|
||||
@@ -40,14 +40,17 @@ const targetDescriptor = {
|
||||
|
||||
const handled = new WeakMap();
|
||||
|
||||
export const runtimes = new Map();
|
||||
export const interpreters = new Map();
|
||||
|
||||
const execute = async (script, source, XWorker, isAsync) => {
|
||||
const module = registry.get(script.type);
|
||||
/* c8 ignore next */
|
||||
if (module.experimental)
|
||||
console.warn(`The ${script.type} runtime is experimental`);
|
||||
const [runtime, content] = await all([handled.get(script).runtime, source]);
|
||||
console.warn(`The ${script.type} interpreter is experimental`);
|
||||
const [interpreter, content] = await all([
|
||||
handled.get(script).interpreter,
|
||||
source,
|
||||
]);
|
||||
try {
|
||||
// temporarily override inherited document.currentScript in a non writable way
|
||||
// but it deletes it right after to preserve native behavior (as it's sync: no trouble)
|
||||
@@ -59,7 +62,7 @@ const execute = async (script, source, XWorker, isAsync) => {
|
||||
configurable: true,
|
||||
get: () => script,
|
||||
});
|
||||
return module[isAsync ? "runAsync" : "run"](runtime, content);
|
||||
return module[isAsync ? "runAsync" : "run"](interpreter, content);
|
||||
} finally {
|
||||
delete globalThis.XWorker;
|
||||
delete document.currentScript;
|
||||
@@ -72,18 +75,18 @@ const getValue = (ref, prefix) => {
|
||||
};
|
||||
|
||||
export const getDetails = (type, id, name, version, config) => {
|
||||
if (!runtimes.has(id)) {
|
||||
if (!interpreters.has(id)) {
|
||||
const details = {
|
||||
runtime: getRuntime(name, config),
|
||||
interpreter: getRuntime(name, config),
|
||||
queue: resolve(),
|
||||
XWorker: xworker(type, version),
|
||||
};
|
||||
runtimes.set(id, details);
|
||||
// enable sane defaults when single runtime *of kind* is used in the page
|
||||
// this allows `xxx-*` attributes to refer to such runtime without `env` around
|
||||
if (!runtimes.has(type)) runtimes.set(type, details);
|
||||
interpreters.set(id, details);
|
||||
// enable sane defaults when single interpreter *of kind* is used in the page
|
||||
// this allows `xxx-*` attributes to refer to such interpreter without `env` around
|
||||
if (!interpreters.has(type)) interpreters.set(type, details);
|
||||
}
|
||||
return runtimes.get(id);
|
||||
return interpreters.get(id);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -104,8 +107,8 @@ export const handle = async (script) => {
|
||||
// new script to handle ... allow newly created scripts to work
|
||||
// just exactly like any other script would
|
||||
else {
|
||||
// allow a shared config among scripts, beside runtime,
|
||||
// and/or source code with different config or runtime
|
||||
// allow a shared config among scripts, beside interpreter,
|
||||
// and/or source code with different config or interpreter
|
||||
const {
|
||||
attributes: { async: isAsync, config, env, target, version },
|
||||
src,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import coincident from "coincident/structured";
|
||||
|
||||
import { create } from "../utils.js";
|
||||
import { registry } from "../runtimes.js";
|
||||
import { registry } from "../interpreters.js";
|
||||
import { getRuntime, getRuntimeID } from "../loader.js";
|
||||
|
||||
// bails out out of the box with a native/meaningful error
|
||||
@@ -23,15 +23,15 @@ try {
|
||||
);
|
||||
}
|
||||
|
||||
let engine, run, runtimeEvent;
|
||||
let engine, run, interpreterEvent;
|
||||
const add = (type, fn) => {
|
||||
addEventListener(
|
||||
type,
|
||||
fn ||
|
||||
(async (event) => {
|
||||
const runtime = await engine;
|
||||
runtimeEvent = event;
|
||||
run(runtime, `xworker.on${type}(xworker.event);`, xworker);
|
||||
const interpreter = await engine;
|
||||
interpreterEvent = event;
|
||||
run(interpreter, `xworker.on${type}(xworker.event);`, xworker);
|
||||
}),
|
||||
!!fn && { once: true },
|
||||
);
|
||||
@@ -49,9 +49,9 @@ const xworker = {
|
||||
// would always fail once an event has been dispatched, as that's not
|
||||
// meant to be accessed in the wild, respecting the one-off event nature of JS.
|
||||
get event() {
|
||||
const event = runtimeEvent;
|
||||
const event = interpreterEvent;
|
||||
if (!event) throw new Error("Unauthorized event access");
|
||||
runtimeEvent = void 0;
|
||||
interpreterEvent = void 0;
|
||||
return event;
|
||||
},
|
||||
};
|
||||
@@ -74,10 +74,10 @@ add("message", ({ data: { options, code, hooks } }) => {
|
||||
// append code that should be executed *after* first
|
||||
if (after) {
|
||||
const method = details[name];
|
||||
details[name] = function (runtime, code, xworker) {
|
||||
details[name] = function (interpreter, code, xworker) {
|
||||
return method.call(
|
||||
this,
|
||||
runtime,
|
||||
interpreter,
|
||||
`${code}\n${after}`,
|
||||
xworker,
|
||||
);
|
||||
@@ -87,10 +87,10 @@ add("message", ({ data: { options, code, hooks } }) => {
|
||||
// prepend code that should be executed *before* (so that after is post-patched)
|
||||
if (before) {
|
||||
const method = details[name];
|
||||
details[name] = function (runtime, code, xworker) {
|
||||
details[name] = function (interpreter, code, xworker) {
|
||||
return method.call(
|
||||
this,
|
||||
runtime,
|
||||
interpreter,
|
||||
`${before}\n${code}`,
|
||||
xworker,
|
||||
);
|
||||
|
||||
@@ -6,16 +6,16 @@ import workerHooks from "./hooks.js";
|
||||
|
||||
/**
|
||||
* @typedef {Object} WorkerOptions plugin configuration
|
||||
* @prop {string} type the runtime/interpreter type to use
|
||||
* @prop {string} [version] the optional runtime version to use
|
||||
* @prop {string} [config] the optional config to use within such runtime
|
||||
* @prop {string} type the interpreter type to use
|
||||
* @prop {string} [version] the optional interpreter version to use
|
||||
* @prop {string} [config] the optional config to use within such interpreter
|
||||
*/
|
||||
|
||||
export default (...args) =>
|
||||
/**
|
||||
* A XWorker is a Worker facade able to bootstrap a channel with any desired runtime.
|
||||
* A XWorker is a Worker facade able to bootstrap a channel with any desired interpreter.
|
||||
* @param {string} url the remote file to evaluate on bootstrap
|
||||
* @param {WorkerOptions} [options] optional arguments to define the runtime to use
|
||||
* @param {WorkerOptions} [options] optional arguments to define the interpreter to use
|
||||
* @returns {Worker}
|
||||
*/
|
||||
function XWorker(url, options) {
|
||||
|
||||
14
pyscript.core/package-lock.json
generated
14
pyscript.core/package-lock.json
generated
@@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"coincident": "^0.4.0"
|
||||
"coincident": "^0.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@node-loader/import-maps": "^1.1.0",
|
||||
@@ -534,9 +534,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/coincident": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/coincident/-/coincident-0.4.0.tgz",
|
||||
"integrity": "sha512-s4uoaRx9Tbaigy3iuD9+ap92hIp16ZejiF/S4ngI4AEtcXWs5Ad5GoKoUWfjUkYXwXtGQ6hlghwUTyW8j32vXw==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/coincident/-/coincident-0.4.1.tgz",
|
||||
"integrity": "sha512-CiHZVx/eUano0G+sSc0S0pXTBH51q0W7pMw1ScRa57BgfBw8l19pMW2Z6sVDHjOih5c9NYrP0budO8SslJv2sA==",
|
||||
"dependencies": {
|
||||
"@ungap/structured-clone": "^1.2.0"
|
||||
}
|
||||
@@ -2447,9 +2447,9 @@
|
||||
}
|
||||
},
|
||||
"coincident": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/coincident/-/coincident-0.4.0.tgz",
|
||||
"integrity": "sha512-s4uoaRx9Tbaigy3iuD9+ap92hIp16ZejiF/S4ngI4AEtcXWs5Ad5GoKoUWfjUkYXwXtGQ6hlghwUTyW8j32vXw==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/coincident/-/coincident-0.4.1.tgz",
|
||||
"integrity": "sha512-CiHZVx/eUano0G+sSc0S0pXTBH51q0W7pMw1ScRa57BgfBw8l19pMW2Z6sVDHjOih5c9NYrP0budO8SslJv2sA==",
|
||||
"requires": {
|
||||
"@ungap/structured-clone": "^1.2.0"
|
||||
}
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"coincident": "^0.4.0"
|
||||
"coincident": "^0.4.1"
|
||||
},
|
||||
"worker": {
|
||||
"blob": "sha256-cyZ90yuiHhmQ0syjP+lzJYZoUaioBPzIDmKPEpGSXaU="
|
||||
"blob": "sha256-TbwtN60VpzVf6WDe6PfdTcHNVyKO4Z2zUN1gi/0rJeE="
|
||||
}
|
||||
}
|
||||
|
||||
37
pyscript.core/rollup/build_interpreters.cjs
Normal file
37
pyscript.core/rollup/build_interpreters.cjs
Normal file
@@ -0,0 +1,37 @@
|
||||
// ⚠️ This files modifies at build time esm/interpreters.js so that
|
||||
// it's impossible to forget to export a interpreter from esm/interpreter folder.
|
||||
|
||||
const { join, resolve } = require("node:path");
|
||||
const { readdirSync, readFileSync, writeFileSync } = require("node:fs");
|
||||
|
||||
const RUNTIMES_DIR = resolve(join(__dirname, "..", "esm", "interpreter"));
|
||||
const RUNTIMES_JS = resolve(join(__dirname, "..", "esm", "interpreters.js"));
|
||||
|
||||
const createRuntimes = () => {
|
||||
const interpreters = [];
|
||||
for (const file of readdirSync(RUNTIMES_DIR)) {
|
||||
// ignore files starting with underscore
|
||||
if (/^[a-z].+?\.js/.test(file)) interpreters.push(file.slice(0, -3));
|
||||
}
|
||||
// generate the output to append at the end of the file
|
||||
const output = [];
|
||||
for (const interpreter of interpreters)
|
||||
output.push(
|
||||
`import ${interpreter} from "./interpreter/${interpreter}.js";`,
|
||||
);
|
||||
output.push(
|
||||
`
|
||||
for (const interpreter of [${interpreters.join(", ")}])
|
||||
register(interpreter);
|
||||
`.trim(),
|
||||
);
|
||||
return output.join("\n");
|
||||
};
|
||||
|
||||
writeFileSync(
|
||||
RUNTIMES_JS,
|
||||
// find //:RUNTIMES comment and replace anything after that
|
||||
readFileSync(RUNTIMES_JS)
|
||||
.toString()
|
||||
.replace(/(\/\/:RUNTIMES)([\S\s]*)$/, `$1\n${createRuntimes()}\n`),
|
||||
);
|
||||
@@ -1,32 +0,0 @@
|
||||
// ⚠️ This files modifies at build time esm/runtimes.js so that
|
||||
// it's impossible to forget to export a runtime from esm/runtime folder.
|
||||
|
||||
const { join, resolve } = require("node:path");
|
||||
const { readdirSync, readFileSync, writeFileSync } = require("node:fs");
|
||||
|
||||
const RUNTIMES_DIR = resolve(join(__dirname, "..", "esm", "runtime"));
|
||||
const RUNTIMES_JS = resolve(join(__dirname, "..", "esm", "runtimes.js"));
|
||||
|
||||
const createRuntimes = () => {
|
||||
const runtimes = [];
|
||||
for (const file of readdirSync(RUNTIMES_DIR)) {
|
||||
// ignore files starting with underscore
|
||||
if (/^[a-z].+?\.js/.test(file)) runtimes.push(file.slice(0, -3));
|
||||
}
|
||||
// generate the output to append at the end of the file
|
||||
const output = [];
|
||||
for (const runtime of runtimes)
|
||||
output.push(`import ${runtime} from "./runtime/${runtime}.js";`);
|
||||
output.push(
|
||||
`for (const runtime of [${runtimes.join(", ")}]) register(runtime);`,
|
||||
);
|
||||
return output.join("\n");
|
||||
};
|
||||
|
||||
writeFileSync(
|
||||
RUNTIMES_JS,
|
||||
// find //:RUNTIMES comment and replace anything after that
|
||||
readFileSync(RUNTIMES_JS)
|
||||
.toString()
|
||||
.replace(/(\/\/:RUNTIMES)([\S\s]*)$/, `$1\n${createRuntimes()}\n`),
|
||||
);
|
||||
@@ -8,7 +8,7 @@ import { createRequire } from "node:module";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
|
||||
createRequire(import.meta.url)("./build_runtimes.cjs");
|
||||
createRequire(import.meta.url)("./build_interpreters.cjs");
|
||||
|
||||
const WORKERS_DIR = resolve(
|
||||
join(dirname(fileURLToPath(import.meta.url)), "..", "esm", "worker"),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { writeFileShim } = require("../cjs/runtime/_utils.js");
|
||||
const { writeFileShim } = require("../cjs/interpreter/_utils.js");
|
||||
|
||||
const assert = require("./assert.js");
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ const sharedPyodide = new Promise((resolve) => {
|
||||
codeBeforeRunWorker: `print('codeBeforeRunWorker')`,
|
||||
codeAfterRunWorker: `print('codeAfterRunWorker')`,
|
||||
onBeforeRun(pyodide, node) {
|
||||
pyodide.runtime.globals.set("XWorker", XWorker);
|
||||
pyodide.interpreter.globals.set("XWorker", XWorker);
|
||||
console.log("onBeforeRun", sharedRuntime === pyodide, node);
|
||||
},
|
||||
onAfterRun(pyodide, node) {
|
||||
|
||||
Reference in New Issue
Block a user