diff options
author | Louis Pilfold <louis@lpil.uk> | 2024-01-19 11:43:01 +0000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2024-01-19 11:43:01 +0000 |
commit | de91b7cd1b3266ae9a1b4d6fe1999d3b8a7c70e5 (patch) | |
tree | eb7683b83d53b537c82b105c30c52c6a6de41a3d /static/worker.js | |
parent | 3edd3a3de2500e04fc4e57c709d4667ce4689994 (diff) | |
download | tour-de91b7cd1b3266ae9a1b4d6fe1999d3b8a7c70e5.tar.gz tour-de91b7cd1b3266ae9a1b4d6fe1999d3b8a7c70e5.zip |
Run compiler and code in web worker
Diffstat (limited to 'static/worker.js')
-rw-r--r-- | static/worker.js | 67 |
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); +}; |