UNPKG

@thi.ng/wasm-api

Version:

Generic, modular, extensible API bridge and infrastructure for hybrid JS & WebAssembly projects

202 lines 8.53 kB
import type { Event, INotify, IObjectOf, Listener, NumericArray } from "@thi.ng/api"; import type { ILogger } from "@thi.ng/logger"; import { type BigIntArray, type BridgeEventType, type CoreAPI, type IWasmAPI, type IWasmMemoryAccess, type MemorySlice, type WasmExports, type WasmModuleSpec } from "./api.js"; export declare const Panic: { new (msg?: string | undefined): { origMessage: string; name: string; message: string; stack?: string; cause?: unknown; }; captureStackTrace(targetObject: object, constructorOpt?: Function): void; prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any; stackTraceLimit: number; }; export declare const OutOfMemoryError: { new (msg?: string | undefined): { origMessage: string; name: string; message: string; stack?: string; cause?: unknown; }; captureStackTrace(targetObject: object, constructorOpt?: Function): void; prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any; stackTraceLimit: number; }; /** * The main interop API bridge between the JS host environment and a WebAssembly * module. This class provides a small core API with various typed accessors and * utils to exchange data (scalars, arrays, strings etc.) via the WASM module's * memory. * * @remarks * All typed memory accessors are assuming the given lookup addresses are * properly aligned to the corresponding primitive types (e.g. f32 values are * aligned to 4 byte boundaries, f64 to 8 bytes etc.) Unaligned access is * explicitly **not supported**! If you need such, please refer to other * mechanisms like JS `DataView`... * * 64bit integers are handled via JS `BigInt` and hence require the host env to * support it. No polyfills are provided. */ export declare class WasmBridge<T extends WasmExports = WasmExports> implements IWasmMemoryAccess, INotify<BridgeEventType> { logger: ILogger; readonly id = "wasmapi"; i8: Int8Array; u8: Uint8Array; i16: Int16Array; u16: Uint16Array; i32: Int32Array; u32: Uint32Array; i64: BigInt64Array; u64: BigUint64Array; f32: Float32Array; f64: Float64Array; utf8Decoder: TextDecoder; utf8Encoder: TextEncoder; imports: WebAssembly.Imports; exports: T; api: CoreAPI; modules: IObjectOf<IWasmAPI<T>>; order: string[]; constructor(modules?: WasmModuleSpec<T>[], logger?: ILogger); /** * Takes array of root module specs, extracts all transitive dependencies, * pre-computes their topological order, then calls * {@link WasmModuleSpec.factory} for each module and stores all modules for * future reference. * * @remarks * Note: The pre-instantiated modules will only be fully initialized later * via {@link WasmBridge.instantiate} or {@link WasmBridge.init}. * * @param specs */ protected _buildModuleGraph(specs: WasmModuleSpec<T>[]): void; /** * Instantiates WASM module from given `src` (and optional provided extra * imports), then automatically calls {@link WasmBridge.init} with the * modules exports. * * @remarks * If the given `src` is a `Response` or `Promise<Response>`, the module * will be instantiated via `WebAssembly.instantiateStreaming()`, otherwise * the non-streaming version will be used. * * @param src * @param imports */ instantiate(src: Response | BufferSource | PromiseLike<Response | BufferSource>, imports?: WebAssembly.Imports): Promise<boolean>; /** * Receives the WASM module's combined exports, stores them for future * reference and then initializes all declared bridge child API modules in * their stated dependency order. Returns false if any of the module * initializations failed. * * @remarks * Emits the {@link EVENT_MEMORY_CHANGED} event just before returning (and * AFTER all child API modules have been initialized). * * @param exports */ init(exports: T): Promise<boolean>; /** * Called automatically during initialization and from other memory * accessors. Initializes and/or updates the various typed WASM memory views * (e.g. after growing the WASM memory and the previous buffer becoming * detached). Unless `notify` is false, the {@link EVENT_MEMORY_CHANGED} * event will be emitted if the memory views had to be updated. * * @param notify */ ensureMemory(notify?: boolean): void; /** * Required use for WASM module instantiation to provide JS imports to the * module. Returns an object of all WASM imports declared by the bridge core * API and any provided bridge API modules. * * @remarks * Each API module's imports will be in their own WASM import object/table, * named using the same key which is defined by the JS side of the module * via {@link WasmModuleSpec.id}. The bridge's core API is named `wasmapi` * and is reserved. * * @example * The following creates a bridge with a fictional `custom` API module: * * ```ts * import { WasmBridge } from "@thi.ng/wasm-api"; * * const bridge = new WasmBridge([new CustomAPI()]); * * // get combined imports object * bridge.getImports(); * { * // imports defined by the core API of the bridge itself * wasmapi: { ... }, * // imports defined by the CustomAPI module * custom: { ... } * } * ``` * * Any related API bindings on the WASM (Zig) side then also need to refer * to these custom import sections (also see `/zig/core.zig`): * * ```zig * pub export "custom" fn foo(x: u32) void; * ``` */ getImports(): WebAssembly.Imports; growMemory(numPages: number): void; allocate(numBytes: number, clear?: boolean): MemorySlice; free([addr, numBytes]: MemorySlice): void; getI8(addr: number): number; getU8(addr: number): number; getI16(addr: number): number; getU16(addr: number): number; getI32(addr: number): number; getU32(addr: number): number; getI64(addr: number): bigint; getU64(addr: number): bigint; getF32(addr: number): number; getF64(addr: number): number; setI8(addr: number, x: number): this; setU8(addr: number, x: number): this; setI16(addr: number, x: number): this; setU16(addr: number, x: number): this; setI32(addr: number, x: number): this; setU32(addr: number, x: number): this; setI64(addr: number, x: bigint): this; setU64(addr: number, x: bigint): this; setF32(addr: number, x: number): this; setF64(addr: number, x: number): this; getI8Array(addr: number, len: number): Int8Array<ArrayBufferLike>; getU8Array(addr: number, len: number): Uint8Array<ArrayBufferLike>; getI16Array(addr: number, len: number): Int16Array<ArrayBufferLike>; getU16Array(addr: number, len: number): Uint16Array<ArrayBufferLike>; getI32Array(addr: number, len: number): Int32Array<ArrayBufferLike>; getU32Array(addr: number, len: number): Uint32Array<ArrayBufferLike>; getI64Array(addr: number, len: number): BigInt64Array<ArrayBufferLike>; getU64Array(addr: number, len: number): BigUint64Array<ArrayBufferLike>; getF32Array(addr: number, len: number): Float32Array<ArrayBufferLike>; getF64Array(addr: number, len: number): Float64Array<ArrayBufferLike>; setI8Array(addr: number, buf: NumericArray): this; setU8Array(addr: number, buf: NumericArray): this; setI16Array(addr: number, buf: NumericArray): this; setU16Array(addr: number, buf: NumericArray): this; setI32Array(addr: number, buf: NumericArray): this; setU32Array(addr: number, buf: NumericArray): this; setI64Array(addr: number, buf: BigIntArray): this; setU64Array(addr: number, buf: BigIntArray): this; setF32Array(addr: number, buf: NumericArray): this; setF64Array(addr: number, buf: NumericArray): this; getString(addr: number, len?: number): string; setString(str: string, addr: number, maxBytes: number, terminate?: boolean): number; getElementById(addr: number, len?: number): HTMLElement; addListener(id: BridgeEventType, fn: Listener<BridgeEventType>, scope?: any): boolean; removeListener(id: BridgeEventType, fn: Listener<BridgeEventType>, scope?: any): boolean; notify(event: Event<BridgeEventType>): boolean; } //# sourceMappingURL=bridge.d.ts.map