@thi.ng/wasm-api
Version:
Generic, modular, extensible API bridge and infrastructure for hybrid JS & WebAssembly projects
202 lines • 8.53 kB
TypeScript
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