mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
committed by
GitHub
parent
d6b1c393f6
commit
0a7e1ce0d7
@@ -27,6 +27,7 @@ repos:
|
|||||||
rev: v0.0.257
|
rev: v0.0.257
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
|
exclude: pyscript\.core/test
|
||||||
args: [--fix]
|
args: [--fix]
|
||||||
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ export const handleCustomType = (node) => {
|
|||||||
afterRunAsync: codeAfterRunWorkerAsync,
|
afterRunAsync: codeAfterRunWorkerAsync,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.setGlobal(interpreter, "XWorker", XWorker);
|
||||||
|
|
||||||
const resolved = {
|
const resolved = {
|
||||||
type,
|
type,
|
||||||
interpreter,
|
interpreter,
|
||||||
|
|||||||
@@ -7,22 +7,6 @@ export const run = (interpreter, code) => interpreter.runPython(clean(code));
|
|||||||
export const runAsync = (interpreter, code) =>
|
export const runAsync = (interpreter, code) =>
|
||||||
interpreter.runPythonAsync(clean(code));
|
interpreter.runPythonAsync(clean(code));
|
||||||
|
|
||||||
export function runEvent(interpreter, code, key) {
|
|
||||||
code = `import js;event=js.__events.get(${key});${code}`;
|
|
||||||
return this.run(interpreter, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
const worker = (method) =>
|
|
||||||
function (interpreter, code, xworker) {
|
|
||||||
code = `from js import xworker;${code}`;
|
|
||||||
globalThis.xworker = xworker;
|
|
||||||
return this[method](interpreter, code);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const runWorker = worker("run");
|
|
||||||
|
|
||||||
export const runWorkerAsync = worker("runAsync");
|
|
||||||
|
|
||||||
export const writeFile = ({ FS }, path, buffer) =>
|
export const writeFile = ({ FS }, path, buffer) =>
|
||||||
writeFileUtil(FS, path, buffer);
|
writeFileUtil(FS, path, buffer);
|
||||||
/* c8 ignore stop */
|
/* c8 ignore stop */
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import { fetchPaths, stdio } from "./_utils.js";
|
import { fetchPaths, stdio } from "./_utils.js";
|
||||||
import {
|
import { run, runAsync, writeFile } from "./_python.js";
|
||||||
run,
|
|
||||||
runAsync,
|
|
||||||
runEvent,
|
|
||||||
runWorker,
|
|
||||||
runWorkerAsync,
|
|
||||||
writeFile,
|
|
||||||
} from "./_python.js";
|
|
||||||
|
|
||||||
const type = "micropython";
|
const type = "micropython";
|
||||||
|
|
||||||
@@ -23,11 +16,18 @@ export default {
|
|||||||
if (config.fetch) await fetchPaths(this, runtime, config.fetch);
|
if (config.fetch) await fetchPaths(this, runtime, config.fetch);
|
||||||
return runtime;
|
return runtime;
|
||||||
},
|
},
|
||||||
|
setGlobal(interpreter, name, value) {
|
||||||
|
const id = `__pyscript_${this.type}_${name}`;
|
||||||
|
globalThis[id] = value;
|
||||||
|
this.run(interpreter, `from js import ${id};${name}=${id};`);
|
||||||
|
},
|
||||||
|
deleteGlobal(interpreter, name) {
|
||||||
|
const id = `__pyscript_${this.type}_${name}`;
|
||||||
|
this.run(interpreter, `del ${id};del ${name}`);
|
||||||
|
delete globalThis[id];
|
||||||
|
},
|
||||||
run,
|
run,
|
||||||
runAsync,
|
runAsync,
|
||||||
runEvent,
|
|
||||||
runWorker,
|
|
||||||
runWorkerAsync,
|
|
||||||
writeFile,
|
writeFile,
|
||||||
};
|
};
|
||||||
/* c8 ignore stop */
|
/* c8 ignore stop */
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import { fetchPaths, stdio } from "./_utils.js";
|
import { fetchPaths, stdio } from "./_utils.js";
|
||||||
import {
|
import { run, runAsync, writeFile } from "./_python.js";
|
||||||
run,
|
|
||||||
runAsync,
|
|
||||||
runEvent,
|
|
||||||
runWorker,
|
|
||||||
runWorkerAsync,
|
|
||||||
writeFile,
|
|
||||||
} from "./_python.js";
|
|
||||||
|
|
||||||
const type = "pyodide";
|
const type = "pyodide";
|
||||||
|
|
||||||
@@ -31,11 +24,14 @@ export default {
|
|||||||
}
|
}
|
||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
|
setGlobal(interpreter, name, value) {
|
||||||
|
interpreter.globals.set(name, value);
|
||||||
|
},
|
||||||
|
deleteGlobal(interpreter, name) {
|
||||||
|
interpreter.globals.delete(name);
|
||||||
|
},
|
||||||
run,
|
run,
|
||||||
runAsync,
|
runAsync,
|
||||||
runEvent,
|
|
||||||
runWorker,
|
|
||||||
runWorkerAsync,
|
|
||||||
writeFile,
|
writeFile,
|
||||||
};
|
};
|
||||||
/* c8 ignore stop */
|
/* c8 ignore stop */
|
||||||
|
|||||||
@@ -9,15 +9,6 @@ const type = "ruby-wasm-wasi";
|
|||||||
|
|
||||||
// REQUIRES INTEGRATION TEST
|
// REQUIRES INTEGRATION TEST
|
||||||
/* c8 ignore start */
|
/* c8 ignore start */
|
||||||
const worker = (method) =>
|
|
||||||
function (interpreter, code, xworker) {
|
|
||||||
globalThis.xworker = xworker;
|
|
||||||
return this[method](
|
|
||||||
interpreter,
|
|
||||||
`require "js";xworker=JS::eval("return xworker");${code}`,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
type,
|
type,
|
||||||
experimental: true,
|
experimental: true,
|
||||||
@@ -32,16 +23,18 @@ export default {
|
|||||||
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
|
setGlobal(interpreter, name, value) {
|
||||||
|
const id = `__pyscript_ruby_wasm_wasi_${name}`;
|
||||||
|
globalThis[id] = value;
|
||||||
|
this.run(interpreter, `require "js";$${name}=JS::eval("return ${id}")`);
|
||||||
|
},
|
||||||
|
deleteGlobal(interpreter, name) {
|
||||||
|
const id = `__pyscript_ruby_wasm_wasi_${name}`;
|
||||||
|
this.run(interpreter, `$${name}=nil`);
|
||||||
|
delete globalThis[id];
|
||||||
|
},
|
||||||
run: (interpreter, code) => interpreter.eval(clean(code)),
|
run: (interpreter, code) => interpreter.eval(clean(code)),
|
||||||
runAsync: (interpreter, code) => interpreter.evalAsync(clean(code)),
|
runAsync: (interpreter, code) => interpreter.evalAsync(clean(code)),
|
||||||
runEvent(interpreter, code, key) {
|
|
||||||
return this.run(
|
|
||||||
interpreter,
|
|
||||||
`require "js";event=JS::eval("return __events.get(${key})");${code}`,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
runWorker: worker("run"),
|
|
||||||
runWorkerAsync: worker("runAsync"),
|
|
||||||
writeFile: () => {
|
writeFile: () => {
|
||||||
throw new Error(`writeFile is not supported in ${type}`);
|
throw new Error(`writeFile is not supported in ${type}`);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,12 +4,6 @@ const type = "wasmoon";
|
|||||||
|
|
||||||
// REQUIRES INTEGRATION TEST
|
// REQUIRES INTEGRATION TEST
|
||||||
/* c8 ignore start */
|
/* c8 ignore start */
|
||||||
const worker = (method) =>
|
|
||||||
function (interpreter, code, xworker) {
|
|
||||||
interpreter.global.set("xworker", xworker);
|
|
||||||
return this[method](interpreter, code);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
type,
|
type,
|
||||||
module: (version = "1.15.0") =>
|
module: (version = "1.15.0") =>
|
||||||
@@ -24,14 +18,14 @@ export default {
|
|||||||
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
|
setGlobal(interpreter, name, value) {
|
||||||
|
interpreter.global.set(name, value);
|
||||||
|
},
|
||||||
|
deleteGlobal(interpreter, name) {
|
||||||
|
interpreter.global.set(name, void 0);
|
||||||
|
},
|
||||||
run: (interpreter, code) => interpreter.doStringSync(clean(code)),
|
run: (interpreter, code) => interpreter.doStringSync(clean(code)),
|
||||||
runAsync: (interpreter, code) => interpreter.doString(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: (
|
writeFile: (
|
||||||
{
|
{
|
||||||
cmodule: {
|
cmodule: {
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ defineProperty(globalThis, "pyscript", {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
globalThis.__events = new Map();
|
|
||||||
|
|
||||||
/* c8 ignore start */ // attributes are tested via integration / e2e
|
/* c8 ignore start */ // attributes are tested via integration / e2e
|
||||||
// ensure both interpreter and its queue are awaited then returns the interpreter
|
// ensure both interpreter and its queue are awaited then returns the interpreter
|
||||||
const awaitInterpreter = async (key) => {
|
const awaitInterpreter = async (key) => {
|
||||||
@@ -43,12 +40,12 @@ export const listener = async (event) => {
|
|||||||
const interpreter = await awaitInterpreter(
|
const interpreter = await awaitInterpreter(
|
||||||
el.getAttribute(`${name}-env`) || name,
|
el.getAttribute(`${name}-env`) || name,
|
||||||
);
|
);
|
||||||
const i = index++;
|
const handler = registry.get(name);
|
||||||
try {
|
try {
|
||||||
globalThis.__events.set(i, event);
|
handler.setGlobal(interpreter, "event", event);
|
||||||
registry.get(name).runEvent(interpreter, value, i);
|
handler.run(interpreter, value);
|
||||||
} finally {
|
} finally {
|
||||||
globalThis.__events.delete(i);
|
handler.deleteGlobal(interpreter, "event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,18 +54,15 @@ const execute = async (script, source, XWorker, isAsync) => {
|
|||||||
try {
|
try {
|
||||||
// temporarily override inherited document.currentScript in a non writable way
|
// 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)
|
// but it deletes it right after to preserve native behavior (as it's sync: no trouble)
|
||||||
defineProperty(globalThis, "XWorker", {
|
|
||||||
configurable: true,
|
|
||||||
get: () => XWorker,
|
|
||||||
});
|
|
||||||
defineProperty(document, "currentScript", {
|
defineProperty(document, "currentScript", {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get: () => script,
|
get: () => script,
|
||||||
});
|
});
|
||||||
|
module.setGlobal(interpreter, "XWorker", XWorker);
|
||||||
return module[isAsync ? "runAsync" : "run"](interpreter, content);
|
return module[isAsync ? "runAsync" : "run"](interpreter, content);
|
||||||
} finally {
|
} finally {
|
||||||
delete globalThis.XWorker;
|
|
||||||
delete document.currentScript;
|
delete document.currentScript;
|
||||||
|
module.deleteGlobal(interpreter, "XWorker");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,15 +23,15 @@ try {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let engine, run, interpreterEvent;
|
let interpreter, run, interpreterEvent;
|
||||||
const add = (type, fn) => {
|
const add = (type, fn) => {
|
||||||
addEventListener(
|
addEventListener(
|
||||||
type,
|
type,
|
||||||
fn ||
|
fn ||
|
||||||
(async (event) => {
|
(async (event) => {
|
||||||
const interpreter = await engine;
|
await interpreter;
|
||||||
interpreterEvent = event;
|
interpreterEvent = event;
|
||||||
run(interpreter, `xworker.on${type}(xworker.event);`, xworker);
|
run(`xworker.on${type}(xworker.event);`, xworker);
|
||||||
}),
|
}),
|
||||||
!!fn && { once: true },
|
!!fn && { once: true },
|
||||||
);
|
);
|
||||||
@@ -48,6 +48,8 @@ const xworker = {
|
|||||||
// this getter exists so that arbitrarily access to xworker.event
|
// this getter exists so that arbitrarily access to xworker.event
|
||||||
// would always fail once an event has been dispatched, as that's not
|
// 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.
|
// meant to be accessed in the wild, respecting the one-off event nature of JS.
|
||||||
|
// because xworker is a unique well defined globally shared reference,
|
||||||
|
// there's also no need to bother setGlobal and deleteGlobal every single time.
|
||||||
get event() {
|
get event() {
|
||||||
const event = interpreterEvent;
|
const event = interpreterEvent;
|
||||||
if (!event) throw new Error("Unauthorized event access");
|
if (!event) throw new Error("Unauthorized event access");
|
||||||
@@ -57,11 +59,14 @@ const xworker = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
add("message", ({ data: { options, code, hooks } }) => {
|
add("message", ({ data: { options, code, hooks } }) => {
|
||||||
engine = (async () => {
|
interpreter = (async () => {
|
||||||
const { type, version, config, async: isAsync } = options;
|
const { type, version, config, async: isAsync } = options;
|
||||||
const engine = await getRuntime(getRuntimeID(type, version), config);
|
const interpreter = await getRuntime(
|
||||||
|
getRuntimeID(type, version),
|
||||||
|
config,
|
||||||
|
);
|
||||||
const details = create(registry.get(type));
|
const details = create(registry.get(type));
|
||||||
const name = `runWorker${isAsync ? "Async" : ""}`;
|
const name = `run${isAsync ? "Async" : ""}`;
|
||||||
|
|
||||||
if (hooks) {
|
if (hooks) {
|
||||||
// patch code if needed
|
// patch code if needed
|
||||||
@@ -73,33 +78,25 @@ add("message", ({ data: { options, code, hooks } }) => {
|
|||||||
|
|
||||||
// append code that should be executed *after* first
|
// append code that should be executed *after* first
|
||||||
if (after) {
|
if (after) {
|
||||||
const method = details[name];
|
const method = details[name].bind(details);
|
||||||
details[name] = function (interpreter, code, xworker) {
|
details[name] = (interpreter, code) =>
|
||||||
return method.call(
|
method(interpreter, `${code}\n${after}`);
|
||||||
this,
|
|
||||||
interpreter,
|
|
||||||
`${code}\n${after}`,
|
|
||||||
xworker,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepend code that should be executed *before* (so that after is post-patched)
|
// prepend code that should be executed *before* (so that after is post-patched)
|
||||||
if (before) {
|
if (before) {
|
||||||
const method = details[name];
|
const method = details[name].bind(details);
|
||||||
details[name] = function (interpreter, code, xworker) {
|
details[name] = (interpreter, code) =>
|
||||||
return method.call(
|
method(interpreter, `${before}\n${code}`);
|
||||||
this,
|
|
||||||
interpreter,
|
|
||||||
`${before}\n${code}`,
|
|
||||||
xworker,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run = details[name].bind(details);
|
// set the `xworker` global reference once
|
||||||
run(engine, code, xworker);
|
details.setGlobal(interpreter, "xworker", xworker);
|
||||||
return engine;
|
// simplify run calls after possible patches
|
||||||
|
run = details[name].bind(details, interpreter);
|
||||||
|
// execute the content of the worker file
|
||||||
|
run(code);
|
||||||
|
return interpreter;
|
||||||
})();
|
})();
|
||||||
add("error");
|
add("error");
|
||||||
add("message");
|
add("message");
|
||||||
|
|||||||
@@ -50,6 +50,6 @@
|
|||||||
"coincident": "^0.4.1"
|
"coincident": "^0.4.1"
|
||||||
},
|
},
|
||||||
"worker": {
|
"worker": {
|
||||||
"blob": "sha256-XQCxBN0Tsy6N0TFG5kG5/CaigwJWLnA63q5ZnUchya4="
|
"blob": "sha256-obDch1OaxOZKhaCpSW9vEAHJk01N+9kYvSiGkNmeJRU="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ globalThis.XPathEvaluator =
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { registerPlugin } = require("../cjs");
|
require("../cjs");
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
// shared 3rd party mocks
|
// shared 3rd party mocks
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="micropython">
|
<script type="micropython">
|
||||||
from js import XWorker
|
|
||||||
|
|
||||||
def show_image(event):
|
def show_image(event):
|
||||||
from js import document
|
from js import document
|
||||||
img = document.createElement("img")
|
img = document.createElement("img")
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
export const python = { content: "", target: null };
|
export const python = { content: "", target: null };
|
||||||
export const loadMicroPython = () => ({
|
export const loadMicroPython = () => ({
|
||||||
runPython(content) {
|
runPython(content) {
|
||||||
python.content = content;
|
if (document.currentScript?.target) {
|
||||||
python.target = document.currentScript.target;
|
python.content = content;
|
||||||
|
python.target = document.currentScript.target;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ export const loadPyodide = () => ({
|
|||||||
}
|
}
|
||||||
python.target = document.currentScript.target;
|
python.target = document.currentScript.target;
|
||||||
},
|
},
|
||||||
|
globals: {
|
||||||
|
set(name, value) {
|
||||||
|
globalThis[name] = value;
|
||||||
|
},
|
||||||
|
delete(name) {
|
||||||
|
delete globalThis[name];
|
||||||
|
},
|
||||||
|
},
|
||||||
FS: {
|
FS: {
|
||||||
mkdirTree() {},
|
mkdirTree() {},
|
||||||
writeFile() {},
|
writeFile() {},
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
print "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
|
print "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
|
||||||
end
|
end
|
||||||
</script>
|
</script>
|
||||||
<button ruby-wasm-wasi-click="print_version(event)">
|
<button ruby-wasm-wasi-click="print_version($event)">
|
||||||
ruby-wasm-wasi version
|
ruby-wasm-wasi version
|
||||||
</button>
|
</button>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
<!-- XWorker - MicroPython to MicroPython -->
|
<!-- XWorker - MicroPython to MicroPython -->
|
||||||
<script type="micropython">
|
<script type="micropython">
|
||||||
from js import XWorker
|
|
||||||
|
|
||||||
def handle_message(event):
|
def handle_message(event):
|
||||||
print(event.data)
|
print(event.data)
|
||||||
|
|
||||||
@@ -42,8 +40,6 @@
|
|||||||
|
|
||||||
<!-- XWorker - MicroPython to Pyodide -->
|
<!-- XWorker - MicroPython to Pyodide -->
|
||||||
<script type="micropython">
|
<script type="micropython">
|
||||||
from js import XWorker
|
|
||||||
|
|
||||||
def handle_message(event):
|
def handle_message(event):
|
||||||
print(event.data)
|
print(event.data)
|
||||||
|
|
||||||
@@ -54,8 +50,6 @@
|
|||||||
|
|
||||||
<!-- XWorker - MicroPython to Lua -->
|
<!-- XWorker - MicroPython to Lua -->
|
||||||
<script type="micropython">
|
<script type="micropython">
|
||||||
from js import XWorker
|
|
||||||
|
|
||||||
def handle_message(event):
|
def handle_message(event):
|
||||||
print(event.data)
|
print(event.data)
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="micropython">
|
<script type="micropython">
|
||||||
from js import XWorker, Promise, document
|
from js import Promise, document
|
||||||
|
|
||||||
deferred = Promise.withResolvers()
|
deferred = Promise.withResolvers()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
from js import xworker
|
|
||||||
|
|
||||||
print("What is 2 + 3?")
|
print("What is 2 + 3?")
|
||||||
print("Answer: " + xworker.sync.input("What is 2 + 3?"))
|
print("Answer: " + xworker.sync.input("What is 2 + 3?"))
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from js import xworker
|
|
||||||
|
|
||||||
|
|
||||||
def on_message(event):
|
def on_message(event):
|
||||||
print(event.data)
|
print(event.data)
|
||||||
|
|||||||
Reference in New Issue
Block a user