microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
npm/src/browser.ts
72lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | // This module is the entry point for browser environments. For Node.js environment, |
| 5 | // the "./main.js" module is the entry point. |
| 6 | |
| 7 | import initWasm, * as wasm from "../lib/web/qsc_wasm.js"; |
| 8 | import { log } from "./log.js"; |
| 9 | import { Compiler, ICompiler, ICompilerWorker } from "./compiler.js"; |
| 10 | import { ResponseMsgType, createWorkerProxy } from "./worker-common.js"; |
| 11 | |
| 12 | // Create once. A module is stateless and can be efficiently passed to WebWorkers. |
| 13 | let wasmModule: WebAssembly.Module | null = null; |
| 14 | |
| 15 | // Used to track if an instance is already instantiated |
| 16 | let wasmInstance: wasm.InitOutput; |
| 17 | |
| 18 | export async function loadWasmModule(uriOrBuffer: string | ArrayBuffer) { |
| 19 | if (typeof uriOrBuffer === "string") { |
| 20 | const wasmRequst = await fetch(uriOrBuffer); |
| 21 | const wasmBuffer = await wasmRequst.arrayBuffer(); |
| 22 | wasmModule = await WebAssembly.compile(wasmBuffer); |
| 23 | } else { |
| 24 | wasmModule = await WebAssembly.compile(uriOrBuffer); |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | export async function getCompiler(): Promise<ICompiler> { |
| 29 | if (!wasmModule) throw "Wasm module must be loaded first"; |
| 30 | if (!wasmInstance) wasmInstance = await initWasm(wasmModule); |
| 31 | |
| 32 | return new Compiler(wasm); |
| 33 | } |
| 34 | |
| 35 | // Create the compiler inside a WebWorker and proxy requests. |
| 36 | // If the Worker was already created via other means and is ready to receive |
| 37 | // messages, then the worker may be passed in and it will be initialized. |
| 38 | export function getCompilerWorker(workerArg: string | Worker): ICompilerWorker { |
| 39 | if (!wasmModule) throw "Wasm module must be loaded first"; |
| 40 | |
| 41 | // Create or use the WebWorker |
| 42 | const worker = |
| 43 | typeof workerArg === "string" ? new Worker(workerArg) : workerArg; |
| 44 | |
| 45 | // Send it the Wasm module to instantiate |
| 46 | worker.postMessage({ |
| 47 | type: "init", |
| 48 | wasmModule, |
| 49 | qscLogLevel: log.getLogLevel(), |
| 50 | }); |
| 51 | |
| 52 | // If you lose the 'this' binding, some environments have issues |
| 53 | const postMessage = worker.postMessage.bind(worker); |
| 54 | const setMsgHandler = (handler: (e: ResponseMsgType) => void) => |
| 55 | (worker.onmessage = (ev) => handler(ev.data)); |
| 56 | const onTerminate = () => worker.terminate(); |
| 57 | |
| 58 | return createWorkerProxy(postMessage, setMsgHandler, onTerminate); |
| 59 | } |
| 60 | |
| 61 | export type { ICompilerWorker }; |
| 62 | export { log }; |
| 63 | export { type Dump, type ShotResult, type VSDiagnostic } from "./common.js"; |
| 64 | export { |
| 65 | getAllKatas, |
| 66 | getKata, |
| 67 | type Kata, |
| 68 | type KataItem, |
| 69 | type Example, |
| 70 | type Exercise, |
| 71 | } from "./katas.js"; |
| 72 | export { QscEventTarget } from "./events.js"; |
| 73 | |