import { panicProxy } from "@/utility-functions/panic-proxy"; import { JsMessageType } from "@/wasm-communication/messages"; import { createSubscriptionRouter, SubscriptionRouter } from "@/wasm-communication/subscription-router"; export type WasmRawInstance = typeof import("@/../wasm/pkg"); export type WasmEditorInstance = InstanceType; export type Editor = Readonly>; // `wasmImport` starts uninitialized because its initialization needs to occur asynchronously, and thus needs to occur by manually calling and awaiting `initWasm()` let wasmImport: WasmRawInstance | null = null; // Should be called asynchronously before `createEditor()` export async function initWasm(): Promise { // Skip if the WASM module is already initialized if (wasmImport !== null) return; // Import the WASM module JS bindings and wrap them in the panic proxy wasmImport = await import("@/../wasm/pkg").then(panicProxy); // Provide a random starter seed which must occur after initializing the WASM module, since WASM can't generate its own random numbers const randomSeed = BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)); wasmImport?.set_random_seed(randomSeed); } // Should be called after running `initWasm()` and its promise resolving // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function createEditor() { // Functions from `api.rs` defined directly on the WASM module, not the editor instance (generated by wasm-bindgen) const raw: WasmRawInstance = getWasmInstance(); // Functions from `api.rs` that are part of the editor instance (generated by wasm-bindgen) const instance: WasmEditorInstance = new raw.JsEditorHandle(invokeJsMessageSubscription); function invokeJsMessageSubscription(messageType: JsMessageType, data: Record): void { subscriptions.handleJsMessage(messageType, data, raw, instance); } // Allows subscribing to messages in JS that are sent from the WASM backend const subscriptions: SubscriptionRouter = createSubscriptionRouter(); return { raw, instance, subscriptions, }; } export function getWasmInstance(): WasmRawInstance { if (wasmImport) return wasmImport; throw new Error("Editor WASM backend was not initialized at application startup"); }