Skip to content

Commit da7ed1b

Browse files
committed
Fix #17 - Bootstrap without a type
1 parent 309a8ad commit da7ed1b

File tree

5 files changed

+64
-10
lines changed

5 files changed

+64
-10
lines changed

docs/core.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

esm/custom.js

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,38 +155,64 @@ const registry = new Map();
155155
* @prop {(environment: object, node: Element) => void} [onInterpreterReady] the callback that will be invoked once
156156
*/
157157

158+
let dontBotherCount = 0;
159+
158160
/**
159161
* Allows custom types and components on the page to receive interpreters to execute any code
160162
* @param {string} type the unique `<script type="...">` identifier
161163
* @param {CustomOptions} options the custom type configuration
162164
*/
163165
export const define = (type, options) => {
164-
if (defaultRegistry.has(type) || registry.has(type))
166+
// allow no-type to be bootstrapped out of the box
167+
let dontBother = type == null;
168+
169+
if (dontBother)
170+
type = `_ps${dontBotherCount++}`;
171+
else if (defaultRegistry.has(type) || registry.has(type))
165172
throw new Error(`<script type="${type}"> already registered`);
166173

167174
if (!defaultRegistry.has(options?.interpreter))
168175
throw new Error('Unspecified interpreter');
169176

170177
// allows reaching out the interpreter helpers on events
171-
defaultRegistry.set(type, defaultRegistry.get(options?.interpreter));
178+
defaultRegistry.set(type, defaultRegistry.get(options.interpreter));
179+
180+
// allows selector -> registry by type
181+
const selectors = [`script[type="${type}"]`];
172182

173183
// ensure a Promise can resolve once a custom type has been bootstrapped
174184
whenDefined(type);
175185

176-
// allows selector -> registry by type
177-
const selectors = [`script[type="${type}"]`, `${type}-script`];
178-
for (const selector of selectors) types.set(selector, type);
186+
if (!dontBother) {
187+
selectors.push(`${type}-script`);
188+
prefixes.push(`${type}-`);
189+
}
190+
else {
191+
// add a script then cleanup everything once that's ready
192+
const { onInterpreterReady } = options;
193+
options.onInterpreterReady = (resolved, node) => {
194+
CUSTOM_SELECTORS.splice(CUSTOM_SELECTORS.indexOf(type), 1);
195+
defaultRegistry.delete(type);
196+
registry.delete(type);
197+
waitList.delete(type);
198+
node.remove();
199+
onInterpreterReady?.(resolved);
200+
};
201+
document.head.append(
202+
assign(document.createElement('script'), { type })
203+
);
204+
}
179205

206+
for (const selector of selectors) types.set(selector, type);
180207
CUSTOM_SELECTORS.push(...selectors);
181-
prefixes.push(`${type}-`);
182208

183209
// ensure always same env for this custom type
184210
registry.set(type, {
185211
options: assign({ env: type }, options),
186212
known: new WeakSet(),
187213
});
188214

189-
addAllListeners(document);
215+
if (!dontBother) addAllListeners(document);
190216
$$(selectors.join(',')).forEach(handleCustomType);
191217
};
192218

test/integration.html

Lines changed: 1 addition & 1 deletion
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-object.html">config-object</a></li><li><a href="/test/integration/interpreter/micropython/fetch.html">fetch</a></li><li><a href="/test/integration/interpreter/micropython/worker-attribute.html">worker-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-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/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></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-object.html">config-object</a></li><li><a href="/test/integration/interpreter/micropython/fetch.html">fetch</a></li><li><a href="/test/integration/interpreter/micropython/no-type.html">no-type</a></li><li><a href="/test/integration/interpreter/micropython/worker-attribute.html">worker-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-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/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></ul></body>
99
</html>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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 { define } from '/core.js';
8+
define(null, {
9+
interpreter: 'micropython',
10+
onInterpreterReady(mpy, node) {
11+
if (node) throw new Error('unexpected node');
12+
mpy.run(`
13+
from js import document
14+
document.documentElement.classList.add('ready');
15+
document.body.textContent = 'OK'
16+
`);
17+
}
18+
});
19+
</script>
20+
</head>
21+
</html>

test/integration/micropython.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const { shared, python } = require('./_shared.js');
44

55
module.exports = (playwright, baseURL) => {
6-
const { test } = playwright;
6+
const { expect, test } = playwright;
77

88
test('MicroPython bootstrap', python.bootstrap(playwright, baseURL));
99

@@ -20,4 +20,11 @@ module.exports = (playwright, baseURL) => {
2020
test('MicroPython config as object', python.configAsObject(playwright, baseURL));
2121

2222
test('MicroPython worker attribute', python.workerAttribute(playwright, `${baseURL}/worker-attribute.html`));
23+
24+
test('MicroPython w/out type', async ({ page }) => {
25+
await page.goto(`${baseURL}/no-type.html`);
26+
await page.waitForSelector('html.ready');
27+
const result = await page.evaluate(() => document.body.innerText);
28+
await expect(result.trim()).toBe('OK');
29+
});
2330
};

0 commit comments

Comments
 (0)