aboutsummaryrefslogtreecommitdiff
path: root/static/worker.js
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2024-01-19 11:43:01 +0000
committerLouis Pilfold <louis@lpil.uk>2024-01-19 11:43:01 +0000
commitde91b7cd1b3266ae9a1b4d6fe1999d3b8a7c70e5 (patch)
treeeb7683b83d53b537c82b105c30c52c6a6de41a3d /static/worker.js
parent3edd3a3de2500e04fc4e57c709d4667ce4689994 (diff)
downloadtour-de91b7cd1b3266ae9a1b4d6fe1999d3b8a7c70e5.tar.gz
tour-de91b7cd1b3266ae9a1b4d6fe1999d3b8a7c70e5.zip
Run compiler and code in web worker
Diffstat (limited to 'static/worker.js')
-rw-r--r--static/worker.js67
1 files changed, 67 insertions, 0 deletions
diff --git a/static/worker.js b/static/worker.js
new file mode 100644
index 0000000..9b975db
--- /dev/null
+++ b/static/worker.js
@@ -0,0 +1,67 @@
+import initGleamCompiler from "./compiler.js";
+import stdlib from "./stdlib.js";
+
+const compiler = await initGleamCompiler();
+const project = compiler.newProject();
+
+for (const [name, code] of Object.entries(stdlib)) {
+ project.writeModule(name, code);
+}
+
+// Monkey patch console.log to keep a copy of the output
+let logged = "";
+const log = console.log;
+console.log = (...args) => {
+ log(...args);
+ logged += args.map((e) => `${e}`).join(" ") + "\n";
+};
+
+function resetLogCapture() {
+ logged = "";
+}
+
+async function loadProgram(js) {
+ const url = new URL(import.meta.url);
+ url.pathname = "";
+ url.hash = "";
+ url.search = "";
+ const href = url.toString();
+ const js1 = js.replaceAll(
+ /from\s+"\.\/(.+)"/g,
+ `from "${href}precompiled/$1"`,
+ );
+ const js2 = btoa(unescape(encodeURIComponent(js1)));
+ const module = await import("data:text/javascript;base64," + js2);
+ return module.main;
+}
+
+async function compileEval(code) {
+ const result = {
+ log: null,
+ error: null,
+ warnings: [],
+ };
+
+ try {
+ project.writeModule("main", code);
+ project.compilePackage("javascript");
+ const js = project.readCompiledJavaScript("main");
+ const main = await loadProgram(js);
+ resetLogCapture();
+ if (main) main();
+ } catch (error) {
+ console.error(error);
+ result.error = error.toString();
+ }
+ for (const warning of project.takeWarnings()) {
+ result.warnings.push(warning);
+ }
+ result.log = logged;
+
+ return result;
+}
+
+self.onmessage = async (event) => {
+ const result = compileEval(event.data);
+ postMessage(await result);
+};