Skip to content

Commit 76d7137

Browse files
committed
Polyscript workers by name
1 parent 90c18e7 commit 76d7137

File tree

10 files changed

+93
-7
lines changed

10 files changed

+93
-7
lines changed

docs/index.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

esm/custom.js

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { registry as defaultRegistry, prefixes, configs } from './interpreters.j
77
import { getRuntimeID } from './loader.js';
88
import { addAllListeners } from './listeners.js';
99
import { Hook, XWorker as XW } from './xworker.js';
10+
import { workers, workersHandler } from './workers.js';
1011
import { polluteJS, js as jsHooks, code as codeHooks } from './hooks.js';
1112
import workerURL from './worker/url.js';
1213

@@ -72,6 +73,8 @@ export const handleCustomType = async (node) => {
7273
});
7374
defineProperty(node, 'xworker', { value: xworker });
7475
resolve({ type, xworker });
76+
const workerName = node.getAttribute('name');
77+
if (workerName) workers[workerName].resolve(xworker.ready);
7578
return;
7679
}
7780
}
@@ -118,6 +121,7 @@ export const handleCustomType = async (node) => {
118121
config: resolved.config,
119122
currentScript: type.startsWith('_') ? null : node,
120123
js_modules: JSModules,
124+
workers: workersHandler,
121125
});
122126

123127
// patch methods accordingly to hooks (and only if needed)

esm/script-handler.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fetch from '@webreflection/fetch';
22
import { $ } from 'basic-devtools';
33

4+
import { workers, workersHandler } from './workers.js';
45
import $xworker from './worker/class.js';
56
import workerURL from './worker/url.js';
67
import { getRuntime, getRuntimeID } from './loader.js';
@@ -65,6 +66,7 @@ const execute = async (currentScript, source, XWorker, isAsync) => {
6566
XWorker,
6667
currentScript,
6768
js_modules: JSModules,
69+
workers: workersHandler,
6870
});
6971
dispatch(currentScript, type, 'ready');
7072
const result = module[isAsync ? 'runAsync' : 'run'](interpreter, content);
@@ -122,7 +124,7 @@ export const handle = async (script) => {
122124
// allow a shared config among scripts, beside interpreter,
123125
// and/or source code with different config or interpreter
124126
const {
125-
attributes: { async: isAsync, config, env, target, version },
127+
attributes: { async: isAsync, config, env, name: wn, target, version },
126128
src,
127129
type,
128130
} = script;
@@ -140,12 +142,14 @@ export const handle = async (script) => {
140142
const xworker = new XWorker(url, {
141143
...nodeInfo(script, type),
142144
async: !!isAsync,
143-
config: configValue
145+
config: configValue,
144146
});
145147
handled.set(
146148
defineProperty(script, 'xworker', { value: xworker }),
147149
{ xworker }
148150
);
151+
const workerName = wn?.value;
152+
if (workerName) workers[workerName].resolve(xworker.ready);
149153
return;
150154
}
151155
/* c8 ignore stop */

esm/worker/_template.js

+22
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,28 @@ add('message', ({ data: { options, config: baseURL, configURL, code, hooks } })
204204
// run either sync or async code in the worker
205205
await details[name](interpreter, code);
206206

207+
if (['micropython', 'pyodide'].includes(details.type)) {
208+
// this dance is required due Pyodide issues with runtime sync exports
209+
// or MicroPython issue with `runPython` not returning values
210+
const polyscript = 'polyscript';
211+
const workers = `__${polyscript}_workers__`;
212+
const exports = '__export__';
213+
interpreter.runPython([
214+
`import js as ${workers}`,
215+
`${workers}.${workers} = "${exports}" in locals() and ${exports} or []`,
216+
`del ${workers}`,
217+
].join('\n'));
218+
const list = [...globalThis[workers]];
219+
delete globalThis[workers];
220+
if (list.length) {
221+
interpreter.runPython([
222+
`from ${polyscript} import xworker as ${workers}`,
223+
...list.map(util => `${workers}.sync.${util} = ${util}`),
224+
`del ${workers}`,
225+
].join('\n'));
226+
}
227+
}
228+
207229
// notify worker done executing
208230
if (currentScript) notify('done');
209231
postMessage('polyscript:done');

esm/workers.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// REQUIRES INTEGRATION TEST
2+
/* c8 ignore start */
3+
export const workers = new Proxy(new Map, {
4+
get(map, name) {
5+
if (!map.has(name))
6+
map.set(name, Promise.withResolvers());
7+
return map.get(name);
8+
},
9+
});
10+
11+
export const workersHandler = new Proxy(workers, {
12+
get: (_, name) => workers[name].promise.then(w => w.sync),
13+
});
14+
/* c8 ignore stop */

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,6 @@
9191
"to-json-callback": "^0.1.1"
9292
},
9393
"worker": {
94-
"blob": "sha256-b+rQo4UjotSb69yF8u3W6zCnHV8eW55yotbdVICsICY="
94+
"blob": "sha256-zrvckOW/DJa6Ds33kWWyNZtvV7aajCLCG+5LnBkpLiA="
9595
}
9696
}

test/integration.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>polyscript integration tests</title>
77
</head>
8-
<body><ul><li><strong>micropython</strong><ul><li><a href="/test/integration/interpreter/micropython/bootstrap.html">bootstrap</a></li><li><a href="/test/integration/interpreter/micropython/config-json.html">config-json</a></li><li><a href="/test/integration/interpreter/micropython/config-object.html">config-object</a></li><li><a href="/test/integration/interpreter/micropython/current-script.html">current-script</a></li><li><a href="/test/integration/interpreter/micropython/custom-hooks.html">custom-hooks</a></li><li><a href="/test/integration/interpreter/micropython/fetch.html">fetch</a></li><li><a href="/test/integration/interpreter/micropython/interpreter-local.html">interpreter-local</a></li><li><a href="/test/integration/interpreter/micropython/mip.html">mip</a></li><li><a href="/test/integration/interpreter/micropython/no-type.html">no-type</a></li><li><a href="/test/integration/interpreter/micropython/ready-done.html">ready-done</a></li><li><a href="/test/integration/interpreter/micropython/storage.html">storage</a></li><li><a href="/test/integration/interpreter/micropython/worker-attribute.html">worker-attribute</a></li><li><a href="/test/integration/interpreter/micropython/worker-bad.html">worker-bad</a></li><li><a href="/test/integration/interpreter/micropython/worker-empty-attribute.html">worker-empty-attribute</a></li><li><a href="/test/integration/interpreter/micropython/worker-error.html">worker-error</a></li><li><a href="/test/integration/interpreter/micropython/worker-lua.html">worker-lua</a></li><li><a href="/test/integration/interpreter/micropython/worker-tag.html">worker-tag</a></li><li><a href="/test/integration/interpreter/micropython/worker-window.html">worker-window</a></li><li><a href="/test/integration/interpreter/micropython/worker.html">worker</a></li></ul><li><strong>pyodide</strong><ul><li><a href="/test/integration/interpreter/pyodide/bootstrap.html">bootstrap</a></li><li><a href="/test/integration/interpreter/pyodide/button.html">button</a></li><li><a href="/test/integration/interpreter/pyodide/config-json.html">config-json</a></li><li><a href="/test/integration/interpreter/pyodide/fetch.html">fetch</a></li><li><a href="/test/integration/interpreter/pyodide/sync.html">sync</a></li><li><a href="/test/integration/interpreter/pyodide/worker-error.html">worker-error</a></li><li><a href="/test/integration/interpreter/pyodide/worker-transform.html">worker-transform</a></li><li><a href="/test/integration/interpreter/pyodide/worker.html">worker</a></li></ul><li><strong>ruby-wasm-wasi</strong><ul><li><a href="/test/integration/interpreter/ruby-wasm-wasi/bootstrap.html">bootstrap</a></li></ul><li><strong>wasmoon</strong><ul><li><a href="/test/integration/interpreter/wasmoon/bootstrap.html">bootstrap</a></li><li><a href="/test/integration/interpreter/wasmoon/worker.html">worker</a></li></ul><li><strong>webr</strong><ul><li><a href="/test/integration/interpreter/webr/just-click.html">just-click</a></li></ul></ul></body>
8+
<body><ul><li><strong>micropython</strong><ul><li><a href="/test/integration/interpreter/micropython/bootstrap.html">bootstrap</a></li><li><a href="/test/integration/interpreter/micropython/config-json.html">config-json</a></li><li><a href="/test/integration/interpreter/micropython/config-object.html">config-object</a></li><li><a href="/test/integration/interpreter/micropython/current-script.html">current-script</a></li><li><a href="/test/integration/interpreter/micropython/custom-hooks.html">custom-hooks</a></li><li><a href="/test/integration/interpreter/micropython/fetch.html">fetch</a></li><li><a href="/test/integration/interpreter/micropython/interpreter-local.html">interpreter-local</a></li><li><a href="/test/integration/interpreter/micropython/mip.html">mip</a></li><li><a href="/test/integration/interpreter/micropython/no-type.html">no-type</a></li><li><a href="/test/integration/interpreter/micropython/ready-done.html">ready-done</a></li><li><a href="/test/integration/interpreter/micropython/storage.html">storage</a></li><li><a href="/test/integration/interpreter/micropython/worker-attribute.html">worker-attribute</a></li><li><a href="/test/integration/interpreter/micropython/worker-bad.html">worker-bad</a></li><li><a href="/test/integration/interpreter/micropython/worker-empty-attribute.html">worker-empty-attribute</a></li><li><a href="/test/integration/interpreter/micropython/worker-error.html">worker-error</a></li><li><a href="/test/integration/interpreter/micropython/worker-lua.html">worker-lua</a></li><li><a href="/test/integration/interpreter/micropython/worker-tag.html">worker-tag</a></li><li><a href="/test/integration/interpreter/micropython/worker-window.html">worker-window</a></li><li><a href="/test/integration/interpreter/micropython/worker.html">worker</a></li><li><a href="/test/integration/interpreter/micropython/workers.html">workers</a></li></ul><li><strong>pyodide</strong><ul><li><a href="/test/integration/interpreter/pyodide/bootstrap.html">bootstrap</a></li><li><a href="/test/integration/interpreter/pyodide/button.html">button</a></li><li><a href="/test/integration/interpreter/pyodide/config-json.html">config-json</a></li><li><a href="/test/integration/interpreter/pyodide/fetch.html">fetch</a></li><li><a href="/test/integration/interpreter/pyodide/sync.html">sync</a></li><li><a href="/test/integration/interpreter/pyodide/worker-error.html">worker-error</a></li><li><a href="/test/integration/interpreter/pyodide/worker-transform.html">worker-transform</a></li><li><a href="/test/integration/interpreter/pyodide/worker.html">worker</a></li></ul><li><strong>ruby-wasm-wasi</strong><ul><li><a href="/test/integration/interpreter/ruby-wasm-wasi/bootstrap.html">bootstrap</a></li></ul><li><strong>wasmoon</strong><ul><li><a href="/test/integration/interpreter/wasmoon/bootstrap.html">bootstrap</a></li><li><a href="/test/integration/interpreter/wasmoon/worker.html">worker</a></li></ul><li><strong>webr</strong><ul><li><a href="/test/integration/interpreter/webr/just-click.html">just-click</a></li></ul></ul></body>
99
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<script type="module">
7+
import { init } from '../utils.js';
8+
init('micropython');
9+
</script>
10+
</head>
11+
<body>
12+
<script type="micropython" async>
13+
import js
14+
from polyscript import workers
15+
16+
js.document.body.append("waiting Pyodide version ... ")
17+
18+
print("waiting for test worker ...")
19+
test = await workers["test"]
20+
print("test worker ready ...")
21+
22+
print("waiting for test.pyodide_version() ...")
23+
version = await test.pyodide_version()
24+
print("done")
25+
26+
js.document.body.append(version)
27+
js.document.documentElement.classList.add("ok")
28+
</script>
29+
<script type="pyodide" name="test" worker>
30+
def pyodide_version():
31+
import sys
32+
return sys.version
33+
34+
__export__ = ['pyodide_version']
35+
</script>
36+
</body>
37+
</html>

test/integration/micropython.js

+5
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,9 @@ module.exports = (playwright, baseURL) => {
5757
await page.goto(`${baseURL}/storage.html`);
5858
await page.waitForSelector(`html.ready.main.worker`);
5959
});
60+
61+
test('MicroPython using workers', async ({ page }) => {
62+
await page.goto(`${baseURL}/workers.html`);
63+
await page.waitForSelector(`html.ok`);
64+
});
6065
};

0 commit comments

Comments
 (0)