@live-codes/ocaml 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/compiler/compile.js +32 -7
package/package.json
CHANGED
package/src/compiler/compile.js
CHANGED
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
|
|
12
12
|
const lines = (text) => text.split('\n').filter((line) => line.trim() !== '');
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
14
|
+
// Two kinds of upstream noise reach the worker's stderr, and neither says anything
|
|
15
|
+
// about the program being compiled:
|
|
16
|
+
//
|
|
17
|
+
// - js_of_ocaml is a command-line program and calls `exit` after writing its
|
|
18
|
+
// output -- and in a browser-target build `exit` is not implemented, so it
|
|
19
|
+
// raises. The output has already arrived by then.
|
|
20
|
+
// - js_of_ocaml's runtime tries to `importScripts` its own chunk files, which
|
|
21
|
+
// cannot work once the worker is created from a data URL -- the trick that lets
|
|
22
|
+
// the compiler run from a CDN, since a worker script must otherwise be
|
|
23
|
+
// same-origin. It falls back to the files it was handed and the bundle is
|
|
24
|
+
// correct. A genuinely fatal load leaves no output at all, and that is reported
|
|
25
|
+
// separately by `compile`.
|
|
26
|
+
const PHANTOM =
|
|
27
|
+
/Function 'exit' not implemented|Failed to execute 'importScripts'|^Uncaught NetworkError:/;
|
|
19
28
|
const diagnosticsOf = (text) => lines(text).filter((line) => !PHANTOM.test(line));
|
|
20
29
|
|
|
21
30
|
// Byte-for-byte, and deliberately not TextDecoder: in browsers "latin1" and
|
|
@@ -38,9 +47,25 @@ function hexToBytes(hex) {
|
|
|
38
47
|
return bytes;
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
// A worker script has to be same-origin with whatever creates it: `new Worker()`
|
|
51
|
+
// refuses a cross-origin URL, and CORS does not help -- it is the script fetch the
|
|
52
|
+
// browser will not make. So the worker is created from a small data URL whose only
|
|
53
|
+
// job is to `importScripts` the harness, which *is* allowed across origins and then
|
|
54
|
+
// loads everything else itself.
|
|
55
|
+
//
|
|
56
|
+
// A data URL rather than a blob because the compiler may itself be running inside a
|
|
57
|
+
// worker, where `URL.createObjectURL` is not dependable. The URL is interpolated
|
|
58
|
+
// into JavaScript, so it is quoted with `JSON.stringify` and base64-encoded: the
|
|
59
|
+
// base64 form needs no escaping of its own.
|
|
60
|
+
const toDataUrl = (content, type = 'text/javascript') =>
|
|
61
|
+
`data:${type};charset=UTF-8;base64,` + btoa(content);
|
|
62
|
+
|
|
63
|
+
const workerDataUrlFor = (script) =>
|
|
64
|
+
toDataUrl(`importScripts(${JSON.stringify(String(script))});`);
|
|
65
|
+
|
|
66
|
+
async function runInWorker(baseUrl, script, files, env, argv, fs = []) {
|
|
67
|
+
const worker = new Worker(workerDataUrlFor(new URL('worker.js', baseUrl).href));
|
|
42
68
|
return new Promise((resolve, reject) => {
|
|
43
|
-
const worker = new Worker(new URL('worker.js', baseUrl));
|
|
44
69
|
worker.onmessage = (event) => {
|
|
45
70
|
worker.terminate();
|
|
46
71
|
resolve(event.data);
|