microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.23.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/npm/qsharp/src/workers/browser.ts

111lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4import * as wasm from "../../lib/web/qsc_wasm.js";
5import { log } from "../log.js";
6import {
7 IServiceEventMessage,
8 IServiceProxy,
9 RequestMessage,
10 ServiceMethods,
11 ServiceProtocol,
12 createProxyInternal,
13 initService,
14} from "./common.js";
15
16/**
17 * Creates an initializes a service, setting it up to receive requests.
18 * This function to be is used in the worker.
19 *
20 * @param serviceProtocol An object that describes the service: its constructor, methods and events
21 * @returns A message handler to be assigned to the `self.onmessage` handler in a web worker
22 */
23export function createWorker<
24 TService extends ServiceMethods<TService>,
25 TServiceEventMsg extends IServiceEventMessage,
26>(
27 serviceProtocol: ServiceProtocol<TService, TServiceEventMsg>,
28): (e: MessageEvent) => void {
29 let invokeService: ((req: RequestMessage<TService>) => Promise<void>) | null =
30 null;
31
32 // This export should be assigned to 'self.onmessage' in a WebWorker
33 return function messageHandler(e: MessageEvent) {
34 const data = e.data;
35
36 if (!data.type || typeof data.type !== "string") {
37 log.error(`Unrecognized msg: ${data}`);
38 return;
39 }
40
41 switch (data.type) {
42 case "init":
43 {
44 wasm.initSync({ module: data.wasmModule });
45
46 invokeService = initService<TService, TServiceEventMsg>(
47 self.postMessage.bind(self),
48 serviceProtocol,
49 wasm,
50 data.qscLogLevel,
51 );
52 }
53 break;
54 default:
55 if (!invokeService) {
56 log.error(
57 `Received message before the service was initialized: %o`,
58 data,
59 );
60 } else {
61 invokeService(data);
62 }
63 }
64 };
65}
66
67/**
68 * Creates and initializes a service in a web worker, and returns a proxy for the service
69 * to be used from the main thread.
70 *
71 * @param workerArg The service web worker or the URL of the web worker script.
72 * @param wasmModule The wasm module to initialize the service with
73 * @param serviceProtocol An object that describes the service: its constructor, methods and events
74 * @returns A proxy object that implements the service interface.
75 * This interface can now be used as if calling into the real service,
76 * and the calls will be proxied to the web worker.
77 */
78export function createProxy<
79 TService extends ServiceMethods<TService>,
80 TServiceEventMsg extends IServiceEventMessage,
81>(
82 workerArg: string | Worker,
83 wasmModule: WebAssembly.Module,
84 serviceProtocol: ServiceProtocol<TService, TServiceEventMsg>,
85): TService & IServiceProxy {
86 // Create or use the WebWorker
87 const worker =
88 typeof workerArg === "string" ? new Worker(workerArg) : workerArg;
89
90 // Send it the Wasm module to instantiate
91 worker.postMessage({
92 type: "init",
93 wasmModule,
94 qscLogLevel: log.getLogLevel(),
95 });
96
97 // If you lose the 'this' binding, some environments have issues
98 const postMessage = worker.postMessage.bind(worker);
99 const onTerminate = () => worker.terminate();
100
101 // Create the proxy which will forward method calls to the worker
102 const proxy = createProxyInternal<TService, TServiceEventMsg>(
103 postMessage,
104 onTerminate,
105 serviceProtocol.methods,
106 );
107
108 // Let proxy handle response and event messages from the worker
109 worker.onmessage = (ev) => proxy.onMsgFromWorker(ev.data);
110 return proxy;
111}
112