Product API
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021-present Toyobayashi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
See [https://github.com/toyobayashi/emnapi](https://github.com/toyobayashi/emnapi)
|
||||||
Generated
Vendored
+7619
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+419
@@ -0,0 +1,419 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Context } from '@emnapi/runtime';
|
||||||
|
import type { ReferenceOwnership } from '@emnapi/runtime';
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type BaseCreateOptions = {
|
||||||
|
filename?: string
|
||||||
|
nodeBinding?: NodeBinding
|
||||||
|
reuseWorker?: ThreadManagerOptionsMain['reuseWorker']
|
||||||
|
asyncWorkPoolSize?: number
|
||||||
|
waitThreadStart?: MainThreadBaseOptions['waitThreadStart']
|
||||||
|
onCreateWorker?: (info: CreateWorkerInfo) => any
|
||||||
|
print?: (str: string) => void
|
||||||
|
printErr?: (str: string) => void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createNapiModule (
|
||||||
|
options: CreateOptions
|
||||||
|
): NapiModule
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CreateOptions = BaseCreateOptions & ({
|
||||||
|
context: Context
|
||||||
|
childThread?: boolean
|
||||||
|
} | {
|
||||||
|
context?: Context
|
||||||
|
childThread: true
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CreateWorkerInfo {
|
||||||
|
type: 'thread' | 'async-work'
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InitOptions {
|
||||||
|
instance: WebAssembly.Instance
|
||||||
|
module: WebAssembly.Module
|
||||||
|
memory?: WebAssembly.Memory
|
||||||
|
table?: WebAssembly.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type InputType = string | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InstantiatedSource extends LoadedSource {
|
||||||
|
napiModule: NapiModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModule(
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options: InstantiateOptions): Promise<InstantiatedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModuleSync(wasmInput: BufferSource | WebAssembly.Module, options: InstantiateOptions): InstantiatedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type InstantiateOptions = CreateOptions & LoadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedSource extends WebAssembly.WebAssemblyInstantiatedSource {
|
||||||
|
usedInstance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModule(napiModule: NapiModule,
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options?: LoadOptions): Promise<LoadedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModuleSync(napiModule: NapiModule, wasmInput: BufferSource | WebAssembly.Module, options?: LoadOptions): LoadedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadOptions {
|
||||||
|
wasi?: WASIInstance;
|
||||||
|
overwriteImports?: (importObject: WebAssembly.Imports) => WebAssembly.Imports;
|
||||||
|
beforeInit?: (source: WebAssembly.WebAssemblyInstantiatedSource) => void;
|
||||||
|
getMemory?: (exports: WebAssembly.Exports) => WebAssembly.Memory;
|
||||||
|
getTable?: (exports: WebAssembly.Exports) => WebAssembly.Table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class MessageHandler extends ThreadMessageHandler {
|
||||||
|
napiModule: NapiModule | undefined;
|
||||||
|
constructor(options: MessageHandlerOptions);
|
||||||
|
instantiate(data: LoadPayload): InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
handle(e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageHandlerOptions extends ThreadMessageHandlerOptions {
|
||||||
|
onLoad: (data: LoadPayload) => InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NapiModule {
|
||||||
|
imports: {
|
||||||
|
env: any
|
||||||
|
napi: any
|
||||||
|
emnapi: any
|
||||||
|
}
|
||||||
|
exports: any
|
||||||
|
loaded: boolean
|
||||||
|
filename: string
|
||||||
|
childThread: boolean
|
||||||
|
emnapi: {
|
||||||
|
syncMemory<T extends ArrayBuffer | ArrayBufferView> (
|
||||||
|
js_to_wasm: boolean,
|
||||||
|
arrayBufferOrView: T,
|
||||||
|
offset?: number,
|
||||||
|
len?: number
|
||||||
|
): T
|
||||||
|
getMemoryAddress (arrayBufferOrView: ArrayBuffer | ArrayBufferView): PointerInfo
|
||||||
|
addSendListener (worker: any): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
init (options: InitOptions): any
|
||||||
|
initWorker (arg: number, func: [number, number]): void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
|
||||||
|
waitThreadStart: boolean | number
|
||||||
|
/* Excluded from this release type: PThread */}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NodeBinding {
|
||||||
|
node: {
|
||||||
|
emitAsyncInit: Function
|
||||||
|
emitAsyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
napi: {
|
||||||
|
asyncInit: Function
|
||||||
|
asyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface PointerInfo {
|
||||||
|
address: number
|
||||||
|
ownership: ReferenceOwnership
|
||||||
|
runtimeAllocated: 0 | 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+419
@@ -0,0 +1,419 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Context } from '@emnapi/runtime';
|
||||||
|
import type { ReferenceOwnership } from '@emnapi/runtime';
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type BaseCreateOptions = {
|
||||||
|
filename?: string
|
||||||
|
nodeBinding?: NodeBinding
|
||||||
|
reuseWorker?: ThreadManagerOptionsMain['reuseWorker']
|
||||||
|
asyncWorkPoolSize?: number
|
||||||
|
waitThreadStart?: MainThreadBaseOptions['waitThreadStart']
|
||||||
|
onCreateWorker?: (info: CreateWorkerInfo) => any
|
||||||
|
print?: (str: string) => void
|
||||||
|
printErr?: (str: string) => void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createNapiModule (
|
||||||
|
options: CreateOptions
|
||||||
|
): NapiModule
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CreateOptions = BaseCreateOptions & ({
|
||||||
|
context: Context
|
||||||
|
childThread?: boolean
|
||||||
|
} | {
|
||||||
|
context?: Context
|
||||||
|
childThread: true
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CreateWorkerInfo {
|
||||||
|
type: 'thread' | 'async-work'
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InitOptions {
|
||||||
|
instance: WebAssembly.Instance
|
||||||
|
module: WebAssembly.Module
|
||||||
|
memory?: WebAssembly.Memory
|
||||||
|
table?: WebAssembly.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type InputType = string | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InstantiatedSource extends LoadedSource {
|
||||||
|
napiModule: NapiModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModule(
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options: InstantiateOptions): Promise<InstantiatedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModuleSync(wasmInput: BufferSource | WebAssembly.Module, options: InstantiateOptions): InstantiatedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type InstantiateOptions = CreateOptions & LoadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedSource extends WebAssembly.WebAssemblyInstantiatedSource {
|
||||||
|
usedInstance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModule(napiModule: NapiModule,
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options?: LoadOptions): Promise<LoadedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModuleSync(napiModule: NapiModule, wasmInput: BufferSource | WebAssembly.Module, options?: LoadOptions): LoadedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadOptions {
|
||||||
|
wasi?: WASIInstance;
|
||||||
|
overwriteImports?: (importObject: WebAssembly.Imports) => WebAssembly.Imports;
|
||||||
|
beforeInit?: (source: WebAssembly.WebAssemblyInstantiatedSource) => void;
|
||||||
|
getMemory?: (exports: WebAssembly.Exports) => WebAssembly.Memory;
|
||||||
|
getTable?: (exports: WebAssembly.Exports) => WebAssembly.Table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class MessageHandler extends ThreadMessageHandler {
|
||||||
|
napiModule: NapiModule | undefined;
|
||||||
|
constructor(options: MessageHandlerOptions);
|
||||||
|
instantiate(data: LoadPayload): InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
handle(e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageHandlerOptions extends ThreadMessageHandlerOptions {
|
||||||
|
onLoad: (data: LoadPayload) => InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NapiModule {
|
||||||
|
imports: {
|
||||||
|
env: any
|
||||||
|
napi: any
|
||||||
|
emnapi: any
|
||||||
|
}
|
||||||
|
exports: any
|
||||||
|
loaded: boolean
|
||||||
|
filename: string
|
||||||
|
childThread: boolean
|
||||||
|
emnapi: {
|
||||||
|
syncMemory<T extends ArrayBuffer | ArrayBufferView> (
|
||||||
|
js_to_wasm: boolean,
|
||||||
|
arrayBufferOrView: T,
|
||||||
|
offset?: number,
|
||||||
|
len?: number
|
||||||
|
): T
|
||||||
|
getMemoryAddress (arrayBufferOrView: ArrayBuffer | ArrayBufferView): PointerInfo
|
||||||
|
addSendListener (worker: any): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
init (options: InitOptions): any
|
||||||
|
initWorker (arg: number, func: [number, number]): void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
|
||||||
|
waitThreadStart: boolean | number
|
||||||
|
/* Excluded from this release type: PThread */}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NodeBinding {
|
||||||
|
node: {
|
||||||
|
emitAsyncInit: Function
|
||||||
|
emitAsyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
napi: {
|
||||||
|
asyncInit: Function
|
||||||
|
asyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface PointerInfo {
|
||||||
|
address: number
|
||||||
|
ownership: ReferenceOwnership
|
||||||
|
runtimeAllocated: 0 | 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
+421
@@ -0,0 +1,421 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Context } from '@emnapi/runtime';
|
||||||
|
import type { ReferenceOwnership } from '@emnapi/runtime';
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type BaseCreateOptions = {
|
||||||
|
filename?: string
|
||||||
|
nodeBinding?: NodeBinding
|
||||||
|
reuseWorker?: ThreadManagerOptionsMain['reuseWorker']
|
||||||
|
asyncWorkPoolSize?: number
|
||||||
|
waitThreadStart?: MainThreadBaseOptions['waitThreadStart']
|
||||||
|
onCreateWorker?: (info: CreateWorkerInfo) => any
|
||||||
|
print?: (str: string) => void
|
||||||
|
printErr?: (str: string) => void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createNapiModule (
|
||||||
|
options: CreateOptions
|
||||||
|
): NapiModule
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CreateOptions = BaseCreateOptions & ({
|
||||||
|
context: Context
|
||||||
|
childThread?: boolean
|
||||||
|
} | {
|
||||||
|
context?: Context
|
||||||
|
childThread: true
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CreateWorkerInfo {
|
||||||
|
type: 'thread' | 'async-work'
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InitOptions {
|
||||||
|
instance: WebAssembly.Instance
|
||||||
|
module: WebAssembly.Module
|
||||||
|
memory?: WebAssembly.Memory
|
||||||
|
table?: WebAssembly.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type InputType = string | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InstantiatedSource extends LoadedSource {
|
||||||
|
napiModule: NapiModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModule(
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options: InstantiateOptions): Promise<InstantiatedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModuleSync(wasmInput: BufferSource | WebAssembly.Module, options: InstantiateOptions): InstantiatedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type InstantiateOptions = CreateOptions & LoadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedSource extends WebAssembly.WebAssemblyInstantiatedSource {
|
||||||
|
usedInstance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModule(napiModule: NapiModule,
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options?: LoadOptions): Promise<LoadedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModuleSync(napiModule: NapiModule, wasmInput: BufferSource | WebAssembly.Module, options?: LoadOptions): LoadedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadOptions {
|
||||||
|
wasi?: WASIInstance;
|
||||||
|
overwriteImports?: (importObject: WebAssembly.Imports) => WebAssembly.Imports;
|
||||||
|
beforeInit?: (source: WebAssembly.WebAssemblyInstantiatedSource) => void;
|
||||||
|
getMemory?: (exports: WebAssembly.Exports) => WebAssembly.Memory;
|
||||||
|
getTable?: (exports: WebAssembly.Exports) => WebAssembly.Table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class MessageHandler extends ThreadMessageHandler {
|
||||||
|
napiModule: NapiModule | undefined;
|
||||||
|
constructor(options: MessageHandlerOptions);
|
||||||
|
instantiate(data: LoadPayload): InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
handle(e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageHandlerOptions extends ThreadMessageHandlerOptions {
|
||||||
|
onLoad: (data: LoadPayload) => InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NapiModule {
|
||||||
|
imports: {
|
||||||
|
env: any
|
||||||
|
napi: any
|
||||||
|
emnapi: any
|
||||||
|
}
|
||||||
|
exports: any
|
||||||
|
loaded: boolean
|
||||||
|
filename: string
|
||||||
|
childThread: boolean
|
||||||
|
emnapi: {
|
||||||
|
syncMemory<T extends ArrayBuffer | ArrayBufferView> (
|
||||||
|
js_to_wasm: boolean,
|
||||||
|
arrayBufferOrView: T,
|
||||||
|
offset?: number,
|
||||||
|
len?: number
|
||||||
|
): T
|
||||||
|
getMemoryAddress (arrayBufferOrView: ArrayBuffer | ArrayBufferView): PointerInfo
|
||||||
|
addSendListener (worker: any): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
init (options: InitOptions): any
|
||||||
|
initWorker (arg: number, func: [number, number]): void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
|
||||||
|
waitThreadStart: boolean | number
|
||||||
|
/* Excluded from this release type: PThread */}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NodeBinding {
|
||||||
|
node: {
|
||||||
|
emitAsyncInit: Function
|
||||||
|
emitAsyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
napi: {
|
||||||
|
asyncInit: Function
|
||||||
|
asyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface PointerInfo {
|
||||||
|
address: number
|
||||||
|
ownership: ReferenceOwnership
|
||||||
|
runtimeAllocated: 0 | 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
|
|
||||||
|
export as namespace emnapiCore;
|
||||||
Generated
Vendored
+8516
File diff suppressed because it is too large
Load Diff
+9510
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+419
@@ -0,0 +1,419 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Context } from '@emnapi/runtime';
|
||||||
|
import type { ReferenceOwnership } from '@emnapi/runtime';
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type BaseCreateOptions = {
|
||||||
|
filename?: string
|
||||||
|
nodeBinding?: NodeBinding
|
||||||
|
reuseWorker?: ThreadManagerOptionsMain['reuseWorker']
|
||||||
|
asyncWorkPoolSize?: number
|
||||||
|
waitThreadStart?: MainThreadBaseOptions['waitThreadStart']
|
||||||
|
onCreateWorker?: (info: CreateWorkerInfo) => any
|
||||||
|
print?: (str: string) => void
|
||||||
|
printErr?: (str: string) => void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createNapiModule (
|
||||||
|
options: CreateOptions
|
||||||
|
): NapiModule
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CreateOptions = BaseCreateOptions & ({
|
||||||
|
context: Context
|
||||||
|
childThread?: boolean
|
||||||
|
} | {
|
||||||
|
context?: Context
|
||||||
|
childThread: true
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CreateWorkerInfo {
|
||||||
|
type: 'thread' | 'async-work'
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InitOptions {
|
||||||
|
instance: WebAssembly.Instance
|
||||||
|
module: WebAssembly.Module
|
||||||
|
memory?: WebAssembly.Memory
|
||||||
|
table?: WebAssembly.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type InputType = string | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface InstantiatedSource extends LoadedSource {
|
||||||
|
napiModule: NapiModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModule(
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options: InstantiateOptions): Promise<InstantiatedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function instantiateNapiModuleSync(wasmInput: BufferSource | WebAssembly.Module, options: InstantiateOptions): InstantiatedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type InstantiateOptions = CreateOptions & LoadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedSource extends WebAssembly.WebAssemblyInstantiatedSource {
|
||||||
|
usedInstance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModule(napiModule: NapiModule,
|
||||||
|
/** Only support `BufferSource` or `WebAssembly.Module` on Node.js */
|
||||||
|
wasmInput: InputType | Promise<InputType>, options?: LoadOptions): Promise<LoadedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadNapiModuleSync(napiModule: NapiModule, wasmInput: BufferSource | WebAssembly.Module, options?: LoadOptions): LoadedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadOptions {
|
||||||
|
wasi?: WASIInstance;
|
||||||
|
overwriteImports?: (importObject: WebAssembly.Imports) => WebAssembly.Imports;
|
||||||
|
beforeInit?: (source: WebAssembly.WebAssemblyInstantiatedSource) => void;
|
||||||
|
getMemory?: (exports: WebAssembly.Exports) => WebAssembly.Memory;
|
||||||
|
getTable?: (exports: WebAssembly.Exports) => WebAssembly.Table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class MessageHandler extends ThreadMessageHandler {
|
||||||
|
napiModule: NapiModule | undefined;
|
||||||
|
constructor(options: MessageHandlerOptions);
|
||||||
|
instantiate(data: LoadPayload): InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
handle(e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageHandlerOptions extends ThreadMessageHandlerOptions {
|
||||||
|
onLoad: (data: LoadPayload) => InstantiatedSource | PromiseLike<InstantiatedSource>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NapiModule {
|
||||||
|
imports: {
|
||||||
|
env: any
|
||||||
|
napi: any
|
||||||
|
emnapi: any
|
||||||
|
}
|
||||||
|
exports: any
|
||||||
|
loaded: boolean
|
||||||
|
filename: string
|
||||||
|
childThread: boolean
|
||||||
|
emnapi: {
|
||||||
|
syncMemory<T extends ArrayBuffer | ArrayBufferView> (
|
||||||
|
js_to_wasm: boolean,
|
||||||
|
arrayBufferOrView: T,
|
||||||
|
offset?: number,
|
||||||
|
len?: number
|
||||||
|
): T
|
||||||
|
getMemoryAddress (arrayBufferOrView: ArrayBuffer | ArrayBufferView): PointerInfo
|
||||||
|
addSendListener (worker: any): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
init (options: InitOptions): any
|
||||||
|
initWorker (arg: number, func: [number, number]): void
|
||||||
|
postMessage?: (msg: any) => any
|
||||||
|
|
||||||
|
waitThreadStart: boolean | number
|
||||||
|
/* Excluded from this release type: PThread */}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface NodeBinding {
|
||||||
|
node: {
|
||||||
|
emitAsyncInit: Function
|
||||||
|
emitAsyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
napi: {
|
||||||
|
asyncInit: Function
|
||||||
|
asyncDestroy: Function
|
||||||
|
makeCallback: Function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface PointerInfo {
|
||||||
|
address: number
|
||||||
|
ownership: ReferenceOwnership
|
||||||
|
runtimeAllocated: 0 | 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+7608
File diff suppressed because it is too large
Load Diff
+5
@@ -0,0 +1,5 @@
|
|||||||
|
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
|
||||||
|
module.exports = require('./dist/emnapi-core.cjs.min.js')
|
||||||
|
} else {
|
||||||
|
module.exports = require('./dist/emnapi-core.cjs.js')
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "@emnapi/core",
|
||||||
|
"version": "1.11.1",
|
||||||
|
"description": "emnapi core",
|
||||||
|
"main": "index.js",
|
||||||
|
"module": "./dist/emnapi-core.esm-bundler.js",
|
||||||
|
"types": "./dist/emnapi-core.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": {
|
||||||
|
"module": "./dist/emnapi-core.d.ts",
|
||||||
|
"import": "./dist/emnapi-core.d.mts",
|
||||||
|
"default": "./dist/emnapi-core.d.ts"
|
||||||
|
},
|
||||||
|
"module": "./dist/emnapi-core.esm-bundler.js",
|
||||||
|
"import": "./dist/emnapi-core.mjs",
|
||||||
|
"default": "./index.js"
|
||||||
|
},
|
||||||
|
"./dist/emnapi-core.cjs.min": {
|
||||||
|
"types": "./dist/emnapi-core.d.ts",
|
||||||
|
"default": "./dist/emnapi-core.cjs.min.js"
|
||||||
|
},
|
||||||
|
"./dist/emnapi-core.min.mjs": {
|
||||||
|
"types": "./dist/emnapi-core.d.mts",
|
||||||
|
"default": "./dist/emnapi-core.min.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.2.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "node ./script/build.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/toyobayashi/emnapi.git"
|
||||||
|
},
|
||||||
|
"author": "toyobayashi",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/toyobayashi/emnapi/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/toyobayashi/emnapi#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021-present Toyobayashi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
See [https://github.com/toyobayashi/emnapi](https://github.com/toyobayashi/emnapi)
|
||||||
+1381
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+671
@@ -0,0 +1,671 @@
|
|||||||
|
export declare type Ptr = number | bigint
|
||||||
|
|
||||||
|
export declare interface IBuffer extends Uint8Array {}
|
||||||
|
export declare interface BufferCtor {
|
||||||
|
readonly prototype: IBuffer
|
||||||
|
/** @deprecated */
|
||||||
|
new (...args: any[]): IBuffer
|
||||||
|
from: {
|
||||||
|
(buffer: ArrayBufferLike): IBuffer
|
||||||
|
(buffer: ArrayBufferLike, byteOffset: number, length: number): IBuffer
|
||||||
|
}
|
||||||
|
alloc: (size: number) => IBuffer
|
||||||
|
isBuffer: (obj: unknown) => obj is IBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum GlobalHandle {
|
||||||
|
UNDEFINED = 1,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
GLOBAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum Version {
|
||||||
|
NODE_API_SUPPORTED_VERSION_MIN = 1,
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION = 8,
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX = 10,
|
||||||
|
NAPI_VERSION_EXPERIMENTAL = 2147483647 // INT_MAX
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type Pointer<T> = number
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type PointerPointer<T> = number
|
||||||
|
export declare type FunctionPointer<T extends (...args: any[]) => any> = Pointer<T>
|
||||||
|
export declare type Const<T> = T
|
||||||
|
|
||||||
|
export declare type void_p = Pointer<void>
|
||||||
|
export declare type void_pp = Pointer<void_p>
|
||||||
|
export declare type bool = number
|
||||||
|
export declare type char = number
|
||||||
|
export declare type char_p = Pointer<char>
|
||||||
|
export declare type unsigned_char = number
|
||||||
|
export declare type const_char = Const<char>
|
||||||
|
export declare type const_char_p = Pointer<const_char>
|
||||||
|
export declare type char16_t_p = number
|
||||||
|
export declare type const_char16_t_p = number
|
||||||
|
|
||||||
|
export declare type short = number
|
||||||
|
export declare type unsigned_short = number
|
||||||
|
export declare type int = number
|
||||||
|
export declare type unsigned_int = number
|
||||||
|
export declare type long = number
|
||||||
|
export declare type unsigned_long = number
|
||||||
|
export declare type long_long = bigint
|
||||||
|
export declare type unsigned_long_long = bigint
|
||||||
|
export declare type float = number
|
||||||
|
export declare type double = number
|
||||||
|
export declare type long_double = number
|
||||||
|
export declare type size_t = number
|
||||||
|
|
||||||
|
export declare type int8_t = number
|
||||||
|
export declare type uint8_t = number
|
||||||
|
export declare type int16_t = number
|
||||||
|
export declare type uint16_t = number
|
||||||
|
export declare type int32_t = number
|
||||||
|
export declare type uint32_t = number
|
||||||
|
export declare type int64_t = bigint
|
||||||
|
export declare type uint64_t = bigint
|
||||||
|
export declare type napi_env = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_value = Pointer<unknown>
|
||||||
|
export declare type napi_ref = Pointer<unknown>
|
||||||
|
export declare type napi_deferred = Pointer<unknown>
|
||||||
|
export declare type napi_handle_scope = Pointer<unknown>
|
||||||
|
export declare type napi_escapable_handle_scope = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_addon_register_func = FunctionPointer<(env: napi_env, exports: napi_value) => napi_value>
|
||||||
|
|
||||||
|
export declare type napi_callback_info = Pointer<unknown>
|
||||||
|
export declare type napi_callback = FunctionPointer<(env: napi_env, info: napi_callback_info) => napi_value>
|
||||||
|
|
||||||
|
export declare interface napi_extended_error_info {
|
||||||
|
error_message: const_char_p
|
||||||
|
engine_reserved: void_p
|
||||||
|
engine_error_code: uint32_t
|
||||||
|
error_code: napi_status
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_property_descriptor {
|
||||||
|
// One of utf8name or name should be NULL.
|
||||||
|
utf8name: const_char_p
|
||||||
|
name: napi_value
|
||||||
|
|
||||||
|
method: napi_callback
|
||||||
|
getter: napi_callback
|
||||||
|
setter: napi_callback
|
||||||
|
value: napi_value
|
||||||
|
/* napi_property_attributes */
|
||||||
|
attributes: number
|
||||||
|
data: void_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type napi_finalize = FunctionPointer<(
|
||||||
|
env: napi_env,
|
||||||
|
finalize_data: void_p,
|
||||||
|
finalize_hint: void_p
|
||||||
|
) => void>
|
||||||
|
|
||||||
|
export declare interface node_module {
|
||||||
|
nm_version: int32_t
|
||||||
|
nm_flags: uint32_t
|
||||||
|
nm_filename: Pointer<const_char>
|
||||||
|
nm_register_func: napi_addon_register_func
|
||||||
|
nm_modname: Pointer<const_char>
|
||||||
|
nm_priv: Pointer<void>
|
||||||
|
reserved: PointerPointer<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_node_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
release: const_char_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface emnapi_emscripten_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_status {
|
||||||
|
napi_ok,
|
||||||
|
napi_invalid_arg,
|
||||||
|
napi_object_expected,
|
||||||
|
napi_string_expected,
|
||||||
|
napi_name_expected,
|
||||||
|
napi_function_expected,
|
||||||
|
napi_number_expected,
|
||||||
|
napi_boolean_expected,
|
||||||
|
napi_array_expected,
|
||||||
|
napi_generic_failure,
|
||||||
|
napi_pending_exception,
|
||||||
|
napi_cancelled,
|
||||||
|
napi_escape_called_twice,
|
||||||
|
napi_handle_scope_mismatch,
|
||||||
|
napi_callback_scope_mismatch,
|
||||||
|
napi_queue_full,
|
||||||
|
napi_closing,
|
||||||
|
napi_bigint_expected,
|
||||||
|
napi_date_expected,
|
||||||
|
napi_arraybuffer_expected,
|
||||||
|
napi_detachable_arraybuffer_expected,
|
||||||
|
napi_would_deadlock, // unused
|
||||||
|
napi_no_external_buffers_allowed,
|
||||||
|
napi_cannot_run_js
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_property_attributes {
|
||||||
|
napi_default = 0,
|
||||||
|
napi_writable = 1 << 0,
|
||||||
|
napi_enumerable = 1 << 1,
|
||||||
|
napi_configurable = 1 << 2,
|
||||||
|
|
||||||
|
// Used with napi_define_class to distinguish static properties
|
||||||
|
// from instance properties. Ignored by napi_define_properties.
|
||||||
|
napi_static = 1 << 10,
|
||||||
|
|
||||||
|
/// #ifdef NAPI_EXPERIMENTAL
|
||||||
|
// Default for class methods.
|
||||||
|
napi_default_method = napi_writable | napi_configurable,
|
||||||
|
|
||||||
|
// Default for object properties, like in JS obj[prop].
|
||||||
|
napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable
|
||||||
|
/// #endif // NAPI_EXPERIMENTAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_valuetype {
|
||||||
|
napi_undefined,
|
||||||
|
napi_null,
|
||||||
|
napi_boolean,
|
||||||
|
napi_number,
|
||||||
|
napi_string,
|
||||||
|
napi_symbol,
|
||||||
|
napi_object,
|
||||||
|
napi_function,
|
||||||
|
napi_external,
|
||||||
|
napi_bigint
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_typedarray_type {
|
||||||
|
napi_int8_array,
|
||||||
|
napi_uint8_array,
|
||||||
|
napi_uint8_clamped_array,
|
||||||
|
napi_int16_array,
|
||||||
|
napi_uint16_array,
|
||||||
|
napi_int32_array,
|
||||||
|
napi_uint32_array,
|
||||||
|
napi_float32_array,
|
||||||
|
napi_float64_array,
|
||||||
|
napi_bigint64_array,
|
||||||
|
napi_biguint64_array,
|
||||||
|
napi_float16_array,
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_collection_mode {
|
||||||
|
napi_key_include_prototypes,
|
||||||
|
napi_key_own_only
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_filter {
|
||||||
|
napi_key_all_properties = 0,
|
||||||
|
napi_key_writable = 1,
|
||||||
|
napi_key_enumerable = 1 << 1,
|
||||||
|
napi_key_configurable = 1 << 2,
|
||||||
|
napi_key_skip_strings = 1 << 3,
|
||||||
|
napi_key_skip_symbols = 1 << 4
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_conversion {
|
||||||
|
napi_key_keep_numbers,
|
||||||
|
napi_key_numbers_to_strings
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum emnapi_memory_view_type {
|
||||||
|
emnapi_int8_array,
|
||||||
|
emnapi_uint8_array,
|
||||||
|
emnapi_uint8_clamped_array,
|
||||||
|
emnapi_int16_array,
|
||||||
|
emnapi_uint16_array,
|
||||||
|
emnapi_int32_array,
|
||||||
|
emnapi_uint32_array,
|
||||||
|
emnapi_float32_array,
|
||||||
|
emnapi_float64_array,
|
||||||
|
emnapi_bigint64_array,
|
||||||
|
emnapi_biguint64_array,
|
||||||
|
emnapi_float16_array,
|
||||||
|
emnapi_data_view = -1,
|
||||||
|
emnapi_buffer = -2
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_call_mode {
|
||||||
|
napi_tsfn_nonblocking,
|
||||||
|
napi_tsfn_blocking
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_release_mode {
|
||||||
|
napi_tsfn_release,
|
||||||
|
napi_tsfn_abort
|
||||||
|
}
|
||||||
|
export declare type CleanupHookCallbackFunction = number | ((arg: number) => void);
|
||||||
|
|
||||||
|
export declare class ConstHandle<S extends undefined | null | boolean | typeof globalThis> extends Handle<S> {
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Context {
|
||||||
|
private _isStopping;
|
||||||
|
private _canCallIntoJs;
|
||||||
|
private _suppressDestroy;
|
||||||
|
envStore: Store<Env>;
|
||||||
|
scopeStore: ScopeStore;
|
||||||
|
refStore: Store<Reference>;
|
||||||
|
deferredStore: Store<Deferred<any>>;
|
||||||
|
handleStore: HandleStore;
|
||||||
|
private readonly refCounter?;
|
||||||
|
private readonly cleanupQueue;
|
||||||
|
private readonly _externalMemory;
|
||||||
|
feature: {
|
||||||
|
supportReflect: boolean;
|
||||||
|
supportFinalizer: boolean;
|
||||||
|
supportWeakSymbol: boolean;
|
||||||
|
supportBigInt: boolean;
|
||||||
|
supportNewFunction: boolean;
|
||||||
|
canSetFunctionName: boolean;
|
||||||
|
setImmediate: (callback: () => void) => void;
|
||||||
|
Buffer: BufferCtor | undefined;
|
||||||
|
MessageChannel: {
|
||||||
|
new (): MessageChannel;
|
||||||
|
prototype: MessageChannel;
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
constructor(options?: ContextOptions);
|
||||||
|
/**
|
||||||
|
* Suppress the destroy on `beforeExit` event in Node.js.
|
||||||
|
* Call this method if you want to keep the context and
|
||||||
|
* all associated {@link Env | Env} alive,
|
||||||
|
* this also means that cleanup hooks will not be called.
|
||||||
|
* After call this method, you should call
|
||||||
|
* {@link Context.destroy | `Context.prototype.destroy`} method manually.
|
||||||
|
*/
|
||||||
|
suppressDestroy(): void;
|
||||||
|
getRuntimeVersions(): {
|
||||||
|
version: string;
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX: Version;
|
||||||
|
NAPI_VERSION_EXPERIMENTAL: Version;
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION: Version;
|
||||||
|
};
|
||||||
|
createNotSupportWeakRefError(api: string, message: string): NotSupportWeakRefError;
|
||||||
|
createNotSupportBufferError(api: string, message: string): NotSupportBufferError;
|
||||||
|
createReference(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership): Reference;
|
||||||
|
createReferenceWithData(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): Reference;
|
||||||
|
createReferenceWithFinalizer(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback?: napi_finalize, finalize_data?: void_p, finalize_hint?: void_p): Reference;
|
||||||
|
createDeferred<T = any>(value: IDeferrdValue<T>): Deferred<T>;
|
||||||
|
adjustAmountOfExternalAllocatedMemory(changeInBytes: number | bigint): bigint;
|
||||||
|
createEnv(filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any): Env;
|
||||||
|
createTrackedFinalizer(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
getCurrentScope(): HandleScope | null;
|
||||||
|
addToCurrentScope<V>(value: V): Handle<V>;
|
||||||
|
openScope(envObject?: Env): HandleScope;
|
||||||
|
closeScope(envObject?: Env, _scope?: HandleScope): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
addCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
removeCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
runCleanup(): void;
|
||||||
|
increaseWaitingRequestCounter(): void;
|
||||||
|
decreaseWaitingRequestCounter(): void;
|
||||||
|
setCanCallIntoJs(value: boolean): void;
|
||||||
|
setStopping(value: boolean): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
/**
|
||||||
|
* Destroy the context and call cleanup hooks.
|
||||||
|
* Associated {@link Env | Env} will be destroyed.
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ContextOptions {
|
||||||
|
onExternalMemoryChange?: (current: bigint, old: bigint, delta: bigint) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function createContext(options?: ContextOptions): Context;
|
||||||
|
|
||||||
|
export declare class Deferred<T = any> implements IStoreValue {
|
||||||
|
static create<T = any>(ctx: Context, value: IDeferrdValue<T>): Deferred;
|
||||||
|
id: number;
|
||||||
|
ctx: Context;
|
||||||
|
value: IDeferrdValue<T>;
|
||||||
|
constructor(ctx: Context, value: IDeferrdValue<T>);
|
||||||
|
resolve(value: T): void;
|
||||||
|
reject(reason?: any): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class EmnapiError extends Error {
|
||||||
|
constructor(message?: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare abstract class Env implements IStoreValue {
|
||||||
|
readonly ctx: Context;
|
||||||
|
moduleApiVersion: number;
|
||||||
|
makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void;
|
||||||
|
makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void;
|
||||||
|
abort: (msg?: string) => never;
|
||||||
|
id: number;
|
||||||
|
openHandleScopes: number;
|
||||||
|
instanceData: TrackedFinalizer | null;
|
||||||
|
tryCatch: TryCatch;
|
||||||
|
refs: number;
|
||||||
|
reflist: RefTracker;
|
||||||
|
finalizing_reflist: RefTracker;
|
||||||
|
pendingFinalizers: RefTracker[];
|
||||||
|
lastError: {
|
||||||
|
errorCode: napi_status;
|
||||||
|
engineErrorCode: number;
|
||||||
|
engineReserved: Ptr;
|
||||||
|
};
|
||||||
|
inGcFinalizer: boolean;
|
||||||
|
constructor(ctx: Context, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never);
|
||||||
|
/** @virtual */
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
terminatedOrTerminating(): boolean;
|
||||||
|
ref(): void;
|
||||||
|
unref(): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
ensureHandleId(value: any): napi_value;
|
||||||
|
clearLastError(): napi_status;
|
||||||
|
setLastError(error_code: napi_status, engine_error_code?: uint32_t, engine_reserved?: void_p): napi_status;
|
||||||
|
getReturnStatus(): napi_status;
|
||||||
|
callIntoModule<T>(fn: (env: Env) => T, handleException?: (envObject: Env, value: any) => void): T;
|
||||||
|
/** @virtual */
|
||||||
|
abstract callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
invokeFinalizerFromGC(finalizer: RefTracker): void;
|
||||||
|
checkGCAccess(): void;
|
||||||
|
/** @virtual */
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
dequeueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
deleteMe(): void;
|
||||||
|
dispose(): void;
|
||||||
|
private readonly _bindingMap;
|
||||||
|
initObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
getObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
setInstanceData(data: number, finalize_cb: number, finalize_hint: number): void;
|
||||||
|
getInstanceData(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare interface External_2 extends Record<any, any> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare const External_2: {
|
||||||
|
new (value: number | bigint): External_2;
|
||||||
|
prototype: null;
|
||||||
|
};
|
||||||
|
export { External_2 as External }
|
||||||
|
|
||||||
|
export declare class Finalizer {
|
||||||
|
envObject: Env;
|
||||||
|
private _finalizeCallback;
|
||||||
|
private _finalizeData;
|
||||||
|
private _finalizeHint;
|
||||||
|
private _makeDynCall_vppp;
|
||||||
|
constructor(envObject: Env, _finalizeCallback?: napi_finalize, _finalizeData?: void_p, _finalizeHint?: void_p);
|
||||||
|
callback(): napi_finalize;
|
||||||
|
data(): void_p;
|
||||||
|
hint(): void_p;
|
||||||
|
resetEnv(): void;
|
||||||
|
resetFinalizer(): void;
|
||||||
|
callFinalizer(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function getDefaultContext(): Context;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function getExternalValue(external: External_2): number | bigint;
|
||||||
|
|
||||||
|
export declare class Handle<S> {
|
||||||
|
id: number;
|
||||||
|
value: S;
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
data(): void_p;
|
||||||
|
isNumber(): boolean;
|
||||||
|
isBigInt(): boolean;
|
||||||
|
isString(): boolean;
|
||||||
|
isFunction(): boolean;
|
||||||
|
isExternal(): boolean;
|
||||||
|
isObject(): boolean;
|
||||||
|
isArray(): boolean;
|
||||||
|
isArrayBuffer(): boolean;
|
||||||
|
isTypedArray(): boolean;
|
||||||
|
isBuffer(BufferConstructor?: BufferCtor): boolean;
|
||||||
|
isDataView(): boolean;
|
||||||
|
isDate(): boolean;
|
||||||
|
isPromise(): boolean;
|
||||||
|
isBoolean(): boolean;
|
||||||
|
isUndefined(): boolean;
|
||||||
|
isSymbol(): boolean;
|
||||||
|
isNull(): boolean;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleScope {
|
||||||
|
handleStore: HandleStore;
|
||||||
|
id: number;
|
||||||
|
parent: HandleScope | null;
|
||||||
|
child: HandleScope | null;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
private _escapeCalled;
|
||||||
|
callbackInfo: ICallbackInfo;
|
||||||
|
constructor(handleStore: HandleStore, id: number, parentScope: HandleScope | null, start: number, end?: number);
|
||||||
|
add<V>(value: V): Handle<V>;
|
||||||
|
addExternal(data: void_p): Handle<object>;
|
||||||
|
dispose(): void;
|
||||||
|
escape(handle: number): Handle<any> | null;
|
||||||
|
escapeCalled(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleStore {
|
||||||
|
static UNDEFINED: ConstHandle<undefined>;
|
||||||
|
static NULL: ConstHandle<null>;
|
||||||
|
static FALSE: ConstHandle<false>;
|
||||||
|
static TRUE: ConstHandle<true>;
|
||||||
|
static GLOBAL: ConstHandle<typeof globalThis>;
|
||||||
|
static MIN_ID: 6;
|
||||||
|
private readonly _values;
|
||||||
|
private _next;
|
||||||
|
push<S>(value: S): Handle<S>;
|
||||||
|
erase(start: number, end: number): void;
|
||||||
|
get(id: Ptr): Handle<any> | undefined;
|
||||||
|
swap(a: number, b: number): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ICallbackInfo {
|
||||||
|
thiz: any;
|
||||||
|
data: void_p;
|
||||||
|
args: ArrayLike<any>;
|
||||||
|
fn: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IDeferrdValue<T = any> {
|
||||||
|
resolve: (value: T) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IReferenceBinding {
|
||||||
|
wrapped: number;
|
||||||
|
tag: Uint32Array | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isExternal(object: unknown): object is External_2;
|
||||||
|
|
||||||
|
export declare function isReferenceType(v: any): v is object;
|
||||||
|
|
||||||
|
export declare interface IStoreValue {
|
||||||
|
id: number;
|
||||||
|
dispose(): void;
|
||||||
|
[x: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const NAPI_VERSION_EXPERIMENTAL = Version.NAPI_VERSION_EXPERIMENTAL;
|
||||||
|
|
||||||
|
export declare const NODE_API_DEFAULT_MODULE_API_VERSION = Version.NODE_API_DEFAULT_MODULE_API_VERSION;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MAX = Version.NODE_API_SUPPORTED_VERSION_MAX;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MIN = Version.NODE_API_SUPPORTED_VERSION_MIN;
|
||||||
|
|
||||||
|
export declare class NodeEnv extends Env {
|
||||||
|
filename: string;
|
||||||
|
private readonly nodeBinding?;
|
||||||
|
destructing: boolean;
|
||||||
|
finalizationScheduled: boolean;
|
||||||
|
constructor(ctx: Context, filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any);
|
||||||
|
deleteMe(): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
triggerFatalException(err: any): void;
|
||||||
|
callbackIntoModule<T>(enforceUncaughtExceptionPolicy: boolean, fn: (env: Env) => T): T;
|
||||||
|
callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
callFinalizerInternal(forceUncaught: int, cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
drainFinalizerQueue(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportBufferError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportWeakRefError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Persistent<T> {
|
||||||
|
private _ref;
|
||||||
|
private _param;
|
||||||
|
private _callback;
|
||||||
|
private static readonly _registry;
|
||||||
|
constructor(value: T);
|
||||||
|
setWeak<P>(param: P, callback: (param: P) => void): void;
|
||||||
|
clearWeak(): void;
|
||||||
|
reset(): void;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
deref(): T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Reference extends RefTracker implements IStoreValue {
|
||||||
|
private static weakCallback;
|
||||||
|
id: number;
|
||||||
|
envObject: Env;
|
||||||
|
private readonly canBeWeak;
|
||||||
|
private _refcount;
|
||||||
|
private readonly _ownership;
|
||||||
|
persistent: Persistent<object>;
|
||||||
|
static create(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, _unused1?: void_p, _unused2?: void_p, _unused3?: void_p): Reference;
|
||||||
|
protected constructor(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership);
|
||||||
|
ref(): number;
|
||||||
|
unref(): number;
|
||||||
|
get(envObject?: Env): napi_value;
|
||||||
|
/** @virtual */
|
||||||
|
resetFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
data(): void_p;
|
||||||
|
refcount(): number;
|
||||||
|
ownership(): ReferenceOwnership;
|
||||||
|
/** @virtual */
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
private _setWeak;
|
||||||
|
finalize(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare enum ReferenceOwnership {
|
||||||
|
kRuntime = 0,
|
||||||
|
kUserland = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithData extends Reference {
|
||||||
|
private readonly _data;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): ReferenceWithData;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithFinalizer extends Reference {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): ReferenceWithFinalizer;
|
||||||
|
private constructor();
|
||||||
|
resetFinalizer(): void;
|
||||||
|
data(): void_p;
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class RefTracker {
|
||||||
|
/** @virtual */
|
||||||
|
dispose(): void;
|
||||||
|
/** @virtual */
|
||||||
|
finalize(): void;
|
||||||
|
private _next;
|
||||||
|
private _prev;
|
||||||
|
link(list: RefTracker): void;
|
||||||
|
unlink(): void;
|
||||||
|
static finalizeAll(list: RefTracker): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ScopeStore {
|
||||||
|
private readonly _rootScope;
|
||||||
|
currentScope: HandleScope;
|
||||||
|
private readonly _values;
|
||||||
|
constructor();
|
||||||
|
get(id: number): HandleScope | undefined;
|
||||||
|
openScope(handleStore: HandleStore): HandleScope;
|
||||||
|
closeScope(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Store<V extends IStoreValue> {
|
||||||
|
protected _values: Array<V | undefined>;
|
||||||
|
private _freeList;
|
||||||
|
private _size;
|
||||||
|
constructor();
|
||||||
|
add(value: V): void;
|
||||||
|
get(id: Ptr): V | undefined;
|
||||||
|
has(id: Ptr): boolean;
|
||||||
|
remove(id: Ptr): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TrackedFinalizer extends RefTracker {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
dispose(): void;
|
||||||
|
finalize(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TryCatch {
|
||||||
|
private _exception;
|
||||||
|
private _caught;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
hasCaught(): boolean;
|
||||||
|
exception(): any;
|
||||||
|
setError(err: any): void;
|
||||||
|
reset(): void;
|
||||||
|
extractException(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+671
@@ -0,0 +1,671 @@
|
|||||||
|
export declare type Ptr = number | bigint
|
||||||
|
|
||||||
|
export declare interface IBuffer extends Uint8Array {}
|
||||||
|
export declare interface BufferCtor {
|
||||||
|
readonly prototype: IBuffer
|
||||||
|
/** @deprecated */
|
||||||
|
new (...args: any[]): IBuffer
|
||||||
|
from: {
|
||||||
|
(buffer: ArrayBufferLike): IBuffer
|
||||||
|
(buffer: ArrayBufferLike, byteOffset: number, length: number): IBuffer
|
||||||
|
}
|
||||||
|
alloc: (size: number) => IBuffer
|
||||||
|
isBuffer: (obj: unknown) => obj is IBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum GlobalHandle {
|
||||||
|
UNDEFINED = 1,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
GLOBAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum Version {
|
||||||
|
NODE_API_SUPPORTED_VERSION_MIN = 1,
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION = 8,
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX = 10,
|
||||||
|
NAPI_VERSION_EXPERIMENTAL = 2147483647 // INT_MAX
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type Pointer<T> = number
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type PointerPointer<T> = number
|
||||||
|
export declare type FunctionPointer<T extends (...args: any[]) => any> = Pointer<T>
|
||||||
|
export declare type Const<T> = T
|
||||||
|
|
||||||
|
export declare type void_p = Pointer<void>
|
||||||
|
export declare type void_pp = Pointer<void_p>
|
||||||
|
export declare type bool = number
|
||||||
|
export declare type char = number
|
||||||
|
export declare type char_p = Pointer<char>
|
||||||
|
export declare type unsigned_char = number
|
||||||
|
export declare type const_char = Const<char>
|
||||||
|
export declare type const_char_p = Pointer<const_char>
|
||||||
|
export declare type char16_t_p = number
|
||||||
|
export declare type const_char16_t_p = number
|
||||||
|
|
||||||
|
export declare type short = number
|
||||||
|
export declare type unsigned_short = number
|
||||||
|
export declare type int = number
|
||||||
|
export declare type unsigned_int = number
|
||||||
|
export declare type long = number
|
||||||
|
export declare type unsigned_long = number
|
||||||
|
export declare type long_long = bigint
|
||||||
|
export declare type unsigned_long_long = bigint
|
||||||
|
export declare type float = number
|
||||||
|
export declare type double = number
|
||||||
|
export declare type long_double = number
|
||||||
|
export declare type size_t = number
|
||||||
|
|
||||||
|
export declare type int8_t = number
|
||||||
|
export declare type uint8_t = number
|
||||||
|
export declare type int16_t = number
|
||||||
|
export declare type uint16_t = number
|
||||||
|
export declare type int32_t = number
|
||||||
|
export declare type uint32_t = number
|
||||||
|
export declare type int64_t = bigint
|
||||||
|
export declare type uint64_t = bigint
|
||||||
|
export declare type napi_env = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_value = Pointer<unknown>
|
||||||
|
export declare type napi_ref = Pointer<unknown>
|
||||||
|
export declare type napi_deferred = Pointer<unknown>
|
||||||
|
export declare type napi_handle_scope = Pointer<unknown>
|
||||||
|
export declare type napi_escapable_handle_scope = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_addon_register_func = FunctionPointer<(env: napi_env, exports: napi_value) => napi_value>
|
||||||
|
|
||||||
|
export declare type napi_callback_info = Pointer<unknown>
|
||||||
|
export declare type napi_callback = FunctionPointer<(env: napi_env, info: napi_callback_info) => napi_value>
|
||||||
|
|
||||||
|
export declare interface napi_extended_error_info {
|
||||||
|
error_message: const_char_p
|
||||||
|
engine_reserved: void_p
|
||||||
|
engine_error_code: uint32_t
|
||||||
|
error_code: napi_status
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_property_descriptor {
|
||||||
|
// One of utf8name or name should be NULL.
|
||||||
|
utf8name: const_char_p
|
||||||
|
name: napi_value
|
||||||
|
|
||||||
|
method: napi_callback
|
||||||
|
getter: napi_callback
|
||||||
|
setter: napi_callback
|
||||||
|
value: napi_value
|
||||||
|
/* napi_property_attributes */
|
||||||
|
attributes: number
|
||||||
|
data: void_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type napi_finalize = FunctionPointer<(
|
||||||
|
env: napi_env,
|
||||||
|
finalize_data: void_p,
|
||||||
|
finalize_hint: void_p
|
||||||
|
) => void>
|
||||||
|
|
||||||
|
export declare interface node_module {
|
||||||
|
nm_version: int32_t
|
||||||
|
nm_flags: uint32_t
|
||||||
|
nm_filename: Pointer<const_char>
|
||||||
|
nm_register_func: napi_addon_register_func
|
||||||
|
nm_modname: Pointer<const_char>
|
||||||
|
nm_priv: Pointer<void>
|
||||||
|
reserved: PointerPointer<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_node_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
release: const_char_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface emnapi_emscripten_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_status {
|
||||||
|
napi_ok,
|
||||||
|
napi_invalid_arg,
|
||||||
|
napi_object_expected,
|
||||||
|
napi_string_expected,
|
||||||
|
napi_name_expected,
|
||||||
|
napi_function_expected,
|
||||||
|
napi_number_expected,
|
||||||
|
napi_boolean_expected,
|
||||||
|
napi_array_expected,
|
||||||
|
napi_generic_failure,
|
||||||
|
napi_pending_exception,
|
||||||
|
napi_cancelled,
|
||||||
|
napi_escape_called_twice,
|
||||||
|
napi_handle_scope_mismatch,
|
||||||
|
napi_callback_scope_mismatch,
|
||||||
|
napi_queue_full,
|
||||||
|
napi_closing,
|
||||||
|
napi_bigint_expected,
|
||||||
|
napi_date_expected,
|
||||||
|
napi_arraybuffer_expected,
|
||||||
|
napi_detachable_arraybuffer_expected,
|
||||||
|
napi_would_deadlock, // unused
|
||||||
|
napi_no_external_buffers_allowed,
|
||||||
|
napi_cannot_run_js
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_property_attributes {
|
||||||
|
napi_default = 0,
|
||||||
|
napi_writable = 1 << 0,
|
||||||
|
napi_enumerable = 1 << 1,
|
||||||
|
napi_configurable = 1 << 2,
|
||||||
|
|
||||||
|
// Used with napi_define_class to distinguish static properties
|
||||||
|
// from instance properties. Ignored by napi_define_properties.
|
||||||
|
napi_static = 1 << 10,
|
||||||
|
|
||||||
|
/// #ifdef NAPI_EXPERIMENTAL
|
||||||
|
// Default for class methods.
|
||||||
|
napi_default_method = napi_writable | napi_configurable,
|
||||||
|
|
||||||
|
// Default for object properties, like in JS obj[prop].
|
||||||
|
napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable
|
||||||
|
/// #endif // NAPI_EXPERIMENTAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_valuetype {
|
||||||
|
napi_undefined,
|
||||||
|
napi_null,
|
||||||
|
napi_boolean,
|
||||||
|
napi_number,
|
||||||
|
napi_string,
|
||||||
|
napi_symbol,
|
||||||
|
napi_object,
|
||||||
|
napi_function,
|
||||||
|
napi_external,
|
||||||
|
napi_bigint
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_typedarray_type {
|
||||||
|
napi_int8_array,
|
||||||
|
napi_uint8_array,
|
||||||
|
napi_uint8_clamped_array,
|
||||||
|
napi_int16_array,
|
||||||
|
napi_uint16_array,
|
||||||
|
napi_int32_array,
|
||||||
|
napi_uint32_array,
|
||||||
|
napi_float32_array,
|
||||||
|
napi_float64_array,
|
||||||
|
napi_bigint64_array,
|
||||||
|
napi_biguint64_array,
|
||||||
|
napi_float16_array,
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_collection_mode {
|
||||||
|
napi_key_include_prototypes,
|
||||||
|
napi_key_own_only
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_filter {
|
||||||
|
napi_key_all_properties = 0,
|
||||||
|
napi_key_writable = 1,
|
||||||
|
napi_key_enumerable = 1 << 1,
|
||||||
|
napi_key_configurable = 1 << 2,
|
||||||
|
napi_key_skip_strings = 1 << 3,
|
||||||
|
napi_key_skip_symbols = 1 << 4
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_conversion {
|
||||||
|
napi_key_keep_numbers,
|
||||||
|
napi_key_numbers_to_strings
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum emnapi_memory_view_type {
|
||||||
|
emnapi_int8_array,
|
||||||
|
emnapi_uint8_array,
|
||||||
|
emnapi_uint8_clamped_array,
|
||||||
|
emnapi_int16_array,
|
||||||
|
emnapi_uint16_array,
|
||||||
|
emnapi_int32_array,
|
||||||
|
emnapi_uint32_array,
|
||||||
|
emnapi_float32_array,
|
||||||
|
emnapi_float64_array,
|
||||||
|
emnapi_bigint64_array,
|
||||||
|
emnapi_biguint64_array,
|
||||||
|
emnapi_float16_array,
|
||||||
|
emnapi_data_view = -1,
|
||||||
|
emnapi_buffer = -2
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_call_mode {
|
||||||
|
napi_tsfn_nonblocking,
|
||||||
|
napi_tsfn_blocking
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_release_mode {
|
||||||
|
napi_tsfn_release,
|
||||||
|
napi_tsfn_abort
|
||||||
|
}
|
||||||
|
export declare type CleanupHookCallbackFunction = number | ((arg: number) => void);
|
||||||
|
|
||||||
|
export declare class ConstHandle<S extends undefined | null | boolean | typeof globalThis> extends Handle<S> {
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Context {
|
||||||
|
private _isStopping;
|
||||||
|
private _canCallIntoJs;
|
||||||
|
private _suppressDestroy;
|
||||||
|
envStore: Store<Env>;
|
||||||
|
scopeStore: ScopeStore;
|
||||||
|
refStore: Store<Reference>;
|
||||||
|
deferredStore: Store<Deferred<any>>;
|
||||||
|
handleStore: HandleStore;
|
||||||
|
private readonly refCounter?;
|
||||||
|
private readonly cleanupQueue;
|
||||||
|
private readonly _externalMemory;
|
||||||
|
feature: {
|
||||||
|
supportReflect: boolean;
|
||||||
|
supportFinalizer: boolean;
|
||||||
|
supportWeakSymbol: boolean;
|
||||||
|
supportBigInt: boolean;
|
||||||
|
supportNewFunction: boolean;
|
||||||
|
canSetFunctionName: boolean;
|
||||||
|
setImmediate: (callback: () => void) => void;
|
||||||
|
Buffer: BufferCtor | undefined;
|
||||||
|
MessageChannel: {
|
||||||
|
new (): MessageChannel;
|
||||||
|
prototype: MessageChannel;
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
constructor(options?: ContextOptions);
|
||||||
|
/**
|
||||||
|
* Suppress the destroy on `beforeExit` event in Node.js.
|
||||||
|
* Call this method if you want to keep the context and
|
||||||
|
* all associated {@link Env | Env} alive,
|
||||||
|
* this also means that cleanup hooks will not be called.
|
||||||
|
* After call this method, you should call
|
||||||
|
* {@link Context.destroy | `Context.prototype.destroy`} method manually.
|
||||||
|
*/
|
||||||
|
suppressDestroy(): void;
|
||||||
|
getRuntimeVersions(): {
|
||||||
|
version: string;
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX: Version;
|
||||||
|
NAPI_VERSION_EXPERIMENTAL: Version;
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION: Version;
|
||||||
|
};
|
||||||
|
createNotSupportWeakRefError(api: string, message: string): NotSupportWeakRefError;
|
||||||
|
createNotSupportBufferError(api: string, message: string): NotSupportBufferError;
|
||||||
|
createReference(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership): Reference;
|
||||||
|
createReferenceWithData(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): Reference;
|
||||||
|
createReferenceWithFinalizer(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback?: napi_finalize, finalize_data?: void_p, finalize_hint?: void_p): Reference;
|
||||||
|
createDeferred<T = any>(value: IDeferrdValue<T>): Deferred<T>;
|
||||||
|
adjustAmountOfExternalAllocatedMemory(changeInBytes: number | bigint): bigint;
|
||||||
|
createEnv(filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any): Env;
|
||||||
|
createTrackedFinalizer(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
getCurrentScope(): HandleScope | null;
|
||||||
|
addToCurrentScope<V>(value: V): Handle<V>;
|
||||||
|
openScope(envObject?: Env): HandleScope;
|
||||||
|
closeScope(envObject?: Env, _scope?: HandleScope): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
addCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
removeCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
runCleanup(): void;
|
||||||
|
increaseWaitingRequestCounter(): void;
|
||||||
|
decreaseWaitingRequestCounter(): void;
|
||||||
|
setCanCallIntoJs(value: boolean): void;
|
||||||
|
setStopping(value: boolean): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
/**
|
||||||
|
* Destroy the context and call cleanup hooks.
|
||||||
|
* Associated {@link Env | Env} will be destroyed.
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ContextOptions {
|
||||||
|
onExternalMemoryChange?: (current: bigint, old: bigint, delta: bigint) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function createContext(options?: ContextOptions): Context;
|
||||||
|
|
||||||
|
export declare class Deferred<T = any> implements IStoreValue {
|
||||||
|
static create<T = any>(ctx: Context, value: IDeferrdValue<T>): Deferred;
|
||||||
|
id: number;
|
||||||
|
ctx: Context;
|
||||||
|
value: IDeferrdValue<T>;
|
||||||
|
constructor(ctx: Context, value: IDeferrdValue<T>);
|
||||||
|
resolve(value: T): void;
|
||||||
|
reject(reason?: any): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class EmnapiError extends Error {
|
||||||
|
constructor(message?: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare abstract class Env implements IStoreValue {
|
||||||
|
readonly ctx: Context;
|
||||||
|
moduleApiVersion: number;
|
||||||
|
makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void;
|
||||||
|
makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void;
|
||||||
|
abort: (msg?: string) => never;
|
||||||
|
id: number;
|
||||||
|
openHandleScopes: number;
|
||||||
|
instanceData: TrackedFinalizer | null;
|
||||||
|
tryCatch: TryCatch;
|
||||||
|
refs: number;
|
||||||
|
reflist: RefTracker;
|
||||||
|
finalizing_reflist: RefTracker;
|
||||||
|
pendingFinalizers: RefTracker[];
|
||||||
|
lastError: {
|
||||||
|
errorCode: napi_status;
|
||||||
|
engineErrorCode: number;
|
||||||
|
engineReserved: Ptr;
|
||||||
|
};
|
||||||
|
inGcFinalizer: boolean;
|
||||||
|
constructor(ctx: Context, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never);
|
||||||
|
/** @virtual */
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
terminatedOrTerminating(): boolean;
|
||||||
|
ref(): void;
|
||||||
|
unref(): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
ensureHandleId(value: any): napi_value;
|
||||||
|
clearLastError(): napi_status;
|
||||||
|
setLastError(error_code: napi_status, engine_error_code?: uint32_t, engine_reserved?: void_p): napi_status;
|
||||||
|
getReturnStatus(): napi_status;
|
||||||
|
callIntoModule<T>(fn: (env: Env) => T, handleException?: (envObject: Env, value: any) => void): T;
|
||||||
|
/** @virtual */
|
||||||
|
abstract callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
invokeFinalizerFromGC(finalizer: RefTracker): void;
|
||||||
|
checkGCAccess(): void;
|
||||||
|
/** @virtual */
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
dequeueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
deleteMe(): void;
|
||||||
|
dispose(): void;
|
||||||
|
private readonly _bindingMap;
|
||||||
|
initObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
getObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
setInstanceData(data: number, finalize_cb: number, finalize_hint: number): void;
|
||||||
|
getInstanceData(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare interface External_2 extends Record<any, any> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare const External_2: {
|
||||||
|
new (value: number | bigint): External_2;
|
||||||
|
prototype: null;
|
||||||
|
};
|
||||||
|
export { External_2 as External }
|
||||||
|
|
||||||
|
export declare class Finalizer {
|
||||||
|
envObject: Env;
|
||||||
|
private _finalizeCallback;
|
||||||
|
private _finalizeData;
|
||||||
|
private _finalizeHint;
|
||||||
|
private _makeDynCall_vppp;
|
||||||
|
constructor(envObject: Env, _finalizeCallback?: napi_finalize, _finalizeData?: void_p, _finalizeHint?: void_p);
|
||||||
|
callback(): napi_finalize;
|
||||||
|
data(): void_p;
|
||||||
|
hint(): void_p;
|
||||||
|
resetEnv(): void;
|
||||||
|
resetFinalizer(): void;
|
||||||
|
callFinalizer(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function getDefaultContext(): Context;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function getExternalValue(external: External_2): number | bigint;
|
||||||
|
|
||||||
|
export declare class Handle<S> {
|
||||||
|
id: number;
|
||||||
|
value: S;
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
data(): void_p;
|
||||||
|
isNumber(): boolean;
|
||||||
|
isBigInt(): boolean;
|
||||||
|
isString(): boolean;
|
||||||
|
isFunction(): boolean;
|
||||||
|
isExternal(): boolean;
|
||||||
|
isObject(): boolean;
|
||||||
|
isArray(): boolean;
|
||||||
|
isArrayBuffer(): boolean;
|
||||||
|
isTypedArray(): boolean;
|
||||||
|
isBuffer(BufferConstructor?: BufferCtor): boolean;
|
||||||
|
isDataView(): boolean;
|
||||||
|
isDate(): boolean;
|
||||||
|
isPromise(): boolean;
|
||||||
|
isBoolean(): boolean;
|
||||||
|
isUndefined(): boolean;
|
||||||
|
isSymbol(): boolean;
|
||||||
|
isNull(): boolean;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleScope {
|
||||||
|
handleStore: HandleStore;
|
||||||
|
id: number;
|
||||||
|
parent: HandleScope | null;
|
||||||
|
child: HandleScope | null;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
private _escapeCalled;
|
||||||
|
callbackInfo: ICallbackInfo;
|
||||||
|
constructor(handleStore: HandleStore, id: number, parentScope: HandleScope | null, start: number, end?: number);
|
||||||
|
add<V>(value: V): Handle<V>;
|
||||||
|
addExternal(data: void_p): Handle<object>;
|
||||||
|
dispose(): void;
|
||||||
|
escape(handle: number): Handle<any> | null;
|
||||||
|
escapeCalled(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleStore {
|
||||||
|
static UNDEFINED: ConstHandle<undefined>;
|
||||||
|
static NULL: ConstHandle<null>;
|
||||||
|
static FALSE: ConstHandle<false>;
|
||||||
|
static TRUE: ConstHandle<true>;
|
||||||
|
static GLOBAL: ConstHandle<typeof globalThis>;
|
||||||
|
static MIN_ID: 6;
|
||||||
|
private readonly _values;
|
||||||
|
private _next;
|
||||||
|
push<S>(value: S): Handle<S>;
|
||||||
|
erase(start: number, end: number): void;
|
||||||
|
get(id: Ptr): Handle<any> | undefined;
|
||||||
|
swap(a: number, b: number): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ICallbackInfo {
|
||||||
|
thiz: any;
|
||||||
|
data: void_p;
|
||||||
|
args: ArrayLike<any>;
|
||||||
|
fn: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IDeferrdValue<T = any> {
|
||||||
|
resolve: (value: T) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IReferenceBinding {
|
||||||
|
wrapped: number;
|
||||||
|
tag: Uint32Array | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isExternal(object: unknown): object is External_2;
|
||||||
|
|
||||||
|
export declare function isReferenceType(v: any): v is object;
|
||||||
|
|
||||||
|
export declare interface IStoreValue {
|
||||||
|
id: number;
|
||||||
|
dispose(): void;
|
||||||
|
[x: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const NAPI_VERSION_EXPERIMENTAL = Version.NAPI_VERSION_EXPERIMENTAL;
|
||||||
|
|
||||||
|
export declare const NODE_API_DEFAULT_MODULE_API_VERSION = Version.NODE_API_DEFAULT_MODULE_API_VERSION;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MAX = Version.NODE_API_SUPPORTED_VERSION_MAX;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MIN = Version.NODE_API_SUPPORTED_VERSION_MIN;
|
||||||
|
|
||||||
|
export declare class NodeEnv extends Env {
|
||||||
|
filename: string;
|
||||||
|
private readonly nodeBinding?;
|
||||||
|
destructing: boolean;
|
||||||
|
finalizationScheduled: boolean;
|
||||||
|
constructor(ctx: Context, filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any);
|
||||||
|
deleteMe(): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
triggerFatalException(err: any): void;
|
||||||
|
callbackIntoModule<T>(enforceUncaughtExceptionPolicy: boolean, fn: (env: Env) => T): T;
|
||||||
|
callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
callFinalizerInternal(forceUncaught: int, cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
drainFinalizerQueue(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportBufferError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportWeakRefError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Persistent<T> {
|
||||||
|
private _ref;
|
||||||
|
private _param;
|
||||||
|
private _callback;
|
||||||
|
private static readonly _registry;
|
||||||
|
constructor(value: T);
|
||||||
|
setWeak<P>(param: P, callback: (param: P) => void): void;
|
||||||
|
clearWeak(): void;
|
||||||
|
reset(): void;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
deref(): T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Reference extends RefTracker implements IStoreValue {
|
||||||
|
private static weakCallback;
|
||||||
|
id: number;
|
||||||
|
envObject: Env;
|
||||||
|
private readonly canBeWeak;
|
||||||
|
private _refcount;
|
||||||
|
private readonly _ownership;
|
||||||
|
persistent: Persistent<object>;
|
||||||
|
static create(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, _unused1?: void_p, _unused2?: void_p, _unused3?: void_p): Reference;
|
||||||
|
protected constructor(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership);
|
||||||
|
ref(): number;
|
||||||
|
unref(): number;
|
||||||
|
get(envObject?: Env): napi_value;
|
||||||
|
/** @virtual */
|
||||||
|
resetFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
data(): void_p;
|
||||||
|
refcount(): number;
|
||||||
|
ownership(): ReferenceOwnership;
|
||||||
|
/** @virtual */
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
private _setWeak;
|
||||||
|
finalize(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare enum ReferenceOwnership {
|
||||||
|
kRuntime = 0,
|
||||||
|
kUserland = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithData extends Reference {
|
||||||
|
private readonly _data;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): ReferenceWithData;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithFinalizer extends Reference {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): ReferenceWithFinalizer;
|
||||||
|
private constructor();
|
||||||
|
resetFinalizer(): void;
|
||||||
|
data(): void_p;
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class RefTracker {
|
||||||
|
/** @virtual */
|
||||||
|
dispose(): void;
|
||||||
|
/** @virtual */
|
||||||
|
finalize(): void;
|
||||||
|
private _next;
|
||||||
|
private _prev;
|
||||||
|
link(list: RefTracker): void;
|
||||||
|
unlink(): void;
|
||||||
|
static finalizeAll(list: RefTracker): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ScopeStore {
|
||||||
|
private readonly _rootScope;
|
||||||
|
currentScope: HandleScope;
|
||||||
|
private readonly _values;
|
||||||
|
constructor();
|
||||||
|
get(id: number): HandleScope | undefined;
|
||||||
|
openScope(handleStore: HandleStore): HandleScope;
|
||||||
|
closeScope(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Store<V extends IStoreValue> {
|
||||||
|
protected _values: Array<V | undefined>;
|
||||||
|
private _freeList;
|
||||||
|
private _size;
|
||||||
|
constructor();
|
||||||
|
add(value: V): void;
|
||||||
|
get(id: Ptr): V | undefined;
|
||||||
|
has(id: Ptr): boolean;
|
||||||
|
remove(id: Ptr): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TrackedFinalizer extends RefTracker {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
dispose(): void;
|
||||||
|
finalize(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TryCatch {
|
||||||
|
private _exception;
|
||||||
|
private _caught;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
hasCaught(): boolean;
|
||||||
|
exception(): any;
|
||||||
|
setError(err: any): void;
|
||||||
|
reset(): void;
|
||||||
|
extractException(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
export { }
|
||||||
+673
@@ -0,0 +1,673 @@
|
|||||||
|
export declare type Ptr = number | bigint
|
||||||
|
|
||||||
|
export declare interface IBuffer extends Uint8Array {}
|
||||||
|
export declare interface BufferCtor {
|
||||||
|
readonly prototype: IBuffer
|
||||||
|
/** @deprecated */
|
||||||
|
new (...args: any[]): IBuffer
|
||||||
|
from: {
|
||||||
|
(buffer: ArrayBufferLike): IBuffer
|
||||||
|
(buffer: ArrayBufferLike, byteOffset: number, length: number): IBuffer
|
||||||
|
}
|
||||||
|
alloc: (size: number) => IBuffer
|
||||||
|
isBuffer: (obj: unknown) => obj is IBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum GlobalHandle {
|
||||||
|
UNDEFINED = 1,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
GLOBAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum Version {
|
||||||
|
NODE_API_SUPPORTED_VERSION_MIN = 1,
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION = 8,
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX = 10,
|
||||||
|
NAPI_VERSION_EXPERIMENTAL = 2147483647 // INT_MAX
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type Pointer<T> = number
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type PointerPointer<T> = number
|
||||||
|
export declare type FunctionPointer<T extends (...args: any[]) => any> = Pointer<T>
|
||||||
|
export declare type Const<T> = T
|
||||||
|
|
||||||
|
export declare type void_p = Pointer<void>
|
||||||
|
export declare type void_pp = Pointer<void_p>
|
||||||
|
export declare type bool = number
|
||||||
|
export declare type char = number
|
||||||
|
export declare type char_p = Pointer<char>
|
||||||
|
export declare type unsigned_char = number
|
||||||
|
export declare type const_char = Const<char>
|
||||||
|
export declare type const_char_p = Pointer<const_char>
|
||||||
|
export declare type char16_t_p = number
|
||||||
|
export declare type const_char16_t_p = number
|
||||||
|
|
||||||
|
export declare type short = number
|
||||||
|
export declare type unsigned_short = number
|
||||||
|
export declare type int = number
|
||||||
|
export declare type unsigned_int = number
|
||||||
|
export declare type long = number
|
||||||
|
export declare type unsigned_long = number
|
||||||
|
export declare type long_long = bigint
|
||||||
|
export declare type unsigned_long_long = bigint
|
||||||
|
export declare type float = number
|
||||||
|
export declare type double = number
|
||||||
|
export declare type long_double = number
|
||||||
|
export declare type size_t = number
|
||||||
|
|
||||||
|
export declare type int8_t = number
|
||||||
|
export declare type uint8_t = number
|
||||||
|
export declare type int16_t = number
|
||||||
|
export declare type uint16_t = number
|
||||||
|
export declare type int32_t = number
|
||||||
|
export declare type uint32_t = number
|
||||||
|
export declare type int64_t = bigint
|
||||||
|
export declare type uint64_t = bigint
|
||||||
|
export declare type napi_env = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_value = Pointer<unknown>
|
||||||
|
export declare type napi_ref = Pointer<unknown>
|
||||||
|
export declare type napi_deferred = Pointer<unknown>
|
||||||
|
export declare type napi_handle_scope = Pointer<unknown>
|
||||||
|
export declare type napi_escapable_handle_scope = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_addon_register_func = FunctionPointer<(env: napi_env, exports: napi_value) => napi_value>
|
||||||
|
|
||||||
|
export declare type napi_callback_info = Pointer<unknown>
|
||||||
|
export declare type napi_callback = FunctionPointer<(env: napi_env, info: napi_callback_info) => napi_value>
|
||||||
|
|
||||||
|
export declare interface napi_extended_error_info {
|
||||||
|
error_message: const_char_p
|
||||||
|
engine_reserved: void_p
|
||||||
|
engine_error_code: uint32_t
|
||||||
|
error_code: napi_status
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_property_descriptor {
|
||||||
|
// One of utf8name or name should be NULL.
|
||||||
|
utf8name: const_char_p
|
||||||
|
name: napi_value
|
||||||
|
|
||||||
|
method: napi_callback
|
||||||
|
getter: napi_callback
|
||||||
|
setter: napi_callback
|
||||||
|
value: napi_value
|
||||||
|
/* napi_property_attributes */
|
||||||
|
attributes: number
|
||||||
|
data: void_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type napi_finalize = FunctionPointer<(
|
||||||
|
env: napi_env,
|
||||||
|
finalize_data: void_p,
|
||||||
|
finalize_hint: void_p
|
||||||
|
) => void>
|
||||||
|
|
||||||
|
export declare interface node_module {
|
||||||
|
nm_version: int32_t
|
||||||
|
nm_flags: uint32_t
|
||||||
|
nm_filename: Pointer<const_char>
|
||||||
|
nm_register_func: napi_addon_register_func
|
||||||
|
nm_modname: Pointer<const_char>
|
||||||
|
nm_priv: Pointer<void>
|
||||||
|
reserved: PointerPointer<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_node_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
release: const_char_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface emnapi_emscripten_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_status {
|
||||||
|
napi_ok,
|
||||||
|
napi_invalid_arg,
|
||||||
|
napi_object_expected,
|
||||||
|
napi_string_expected,
|
||||||
|
napi_name_expected,
|
||||||
|
napi_function_expected,
|
||||||
|
napi_number_expected,
|
||||||
|
napi_boolean_expected,
|
||||||
|
napi_array_expected,
|
||||||
|
napi_generic_failure,
|
||||||
|
napi_pending_exception,
|
||||||
|
napi_cancelled,
|
||||||
|
napi_escape_called_twice,
|
||||||
|
napi_handle_scope_mismatch,
|
||||||
|
napi_callback_scope_mismatch,
|
||||||
|
napi_queue_full,
|
||||||
|
napi_closing,
|
||||||
|
napi_bigint_expected,
|
||||||
|
napi_date_expected,
|
||||||
|
napi_arraybuffer_expected,
|
||||||
|
napi_detachable_arraybuffer_expected,
|
||||||
|
napi_would_deadlock, // unused
|
||||||
|
napi_no_external_buffers_allowed,
|
||||||
|
napi_cannot_run_js
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_property_attributes {
|
||||||
|
napi_default = 0,
|
||||||
|
napi_writable = 1 << 0,
|
||||||
|
napi_enumerable = 1 << 1,
|
||||||
|
napi_configurable = 1 << 2,
|
||||||
|
|
||||||
|
// Used with napi_define_class to distinguish static properties
|
||||||
|
// from instance properties. Ignored by napi_define_properties.
|
||||||
|
napi_static = 1 << 10,
|
||||||
|
|
||||||
|
/// #ifdef NAPI_EXPERIMENTAL
|
||||||
|
// Default for class methods.
|
||||||
|
napi_default_method = napi_writable | napi_configurable,
|
||||||
|
|
||||||
|
// Default for object properties, like in JS obj[prop].
|
||||||
|
napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable
|
||||||
|
/// #endif // NAPI_EXPERIMENTAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_valuetype {
|
||||||
|
napi_undefined,
|
||||||
|
napi_null,
|
||||||
|
napi_boolean,
|
||||||
|
napi_number,
|
||||||
|
napi_string,
|
||||||
|
napi_symbol,
|
||||||
|
napi_object,
|
||||||
|
napi_function,
|
||||||
|
napi_external,
|
||||||
|
napi_bigint
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_typedarray_type {
|
||||||
|
napi_int8_array,
|
||||||
|
napi_uint8_array,
|
||||||
|
napi_uint8_clamped_array,
|
||||||
|
napi_int16_array,
|
||||||
|
napi_uint16_array,
|
||||||
|
napi_int32_array,
|
||||||
|
napi_uint32_array,
|
||||||
|
napi_float32_array,
|
||||||
|
napi_float64_array,
|
||||||
|
napi_bigint64_array,
|
||||||
|
napi_biguint64_array,
|
||||||
|
napi_float16_array,
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_collection_mode {
|
||||||
|
napi_key_include_prototypes,
|
||||||
|
napi_key_own_only
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_filter {
|
||||||
|
napi_key_all_properties = 0,
|
||||||
|
napi_key_writable = 1,
|
||||||
|
napi_key_enumerable = 1 << 1,
|
||||||
|
napi_key_configurable = 1 << 2,
|
||||||
|
napi_key_skip_strings = 1 << 3,
|
||||||
|
napi_key_skip_symbols = 1 << 4
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_conversion {
|
||||||
|
napi_key_keep_numbers,
|
||||||
|
napi_key_numbers_to_strings
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum emnapi_memory_view_type {
|
||||||
|
emnapi_int8_array,
|
||||||
|
emnapi_uint8_array,
|
||||||
|
emnapi_uint8_clamped_array,
|
||||||
|
emnapi_int16_array,
|
||||||
|
emnapi_uint16_array,
|
||||||
|
emnapi_int32_array,
|
||||||
|
emnapi_uint32_array,
|
||||||
|
emnapi_float32_array,
|
||||||
|
emnapi_float64_array,
|
||||||
|
emnapi_bigint64_array,
|
||||||
|
emnapi_biguint64_array,
|
||||||
|
emnapi_float16_array,
|
||||||
|
emnapi_data_view = -1,
|
||||||
|
emnapi_buffer = -2
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_call_mode {
|
||||||
|
napi_tsfn_nonblocking,
|
||||||
|
napi_tsfn_blocking
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_release_mode {
|
||||||
|
napi_tsfn_release,
|
||||||
|
napi_tsfn_abort
|
||||||
|
}
|
||||||
|
export declare type CleanupHookCallbackFunction = number | ((arg: number) => void);
|
||||||
|
|
||||||
|
export declare class ConstHandle<S extends undefined | null | boolean | typeof globalThis> extends Handle<S> {
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Context {
|
||||||
|
private _isStopping;
|
||||||
|
private _canCallIntoJs;
|
||||||
|
private _suppressDestroy;
|
||||||
|
envStore: Store<Env>;
|
||||||
|
scopeStore: ScopeStore;
|
||||||
|
refStore: Store<Reference>;
|
||||||
|
deferredStore: Store<Deferred<any>>;
|
||||||
|
handleStore: HandleStore;
|
||||||
|
private readonly refCounter?;
|
||||||
|
private readonly cleanupQueue;
|
||||||
|
private readonly _externalMemory;
|
||||||
|
feature: {
|
||||||
|
supportReflect: boolean;
|
||||||
|
supportFinalizer: boolean;
|
||||||
|
supportWeakSymbol: boolean;
|
||||||
|
supportBigInt: boolean;
|
||||||
|
supportNewFunction: boolean;
|
||||||
|
canSetFunctionName: boolean;
|
||||||
|
setImmediate: (callback: () => void) => void;
|
||||||
|
Buffer: BufferCtor | undefined;
|
||||||
|
MessageChannel: {
|
||||||
|
new (): MessageChannel;
|
||||||
|
prototype: MessageChannel;
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
constructor(options?: ContextOptions);
|
||||||
|
/**
|
||||||
|
* Suppress the destroy on `beforeExit` event in Node.js.
|
||||||
|
* Call this method if you want to keep the context and
|
||||||
|
* all associated {@link Env | Env} alive,
|
||||||
|
* this also means that cleanup hooks will not be called.
|
||||||
|
* After call this method, you should call
|
||||||
|
* {@link Context.destroy | `Context.prototype.destroy`} method manually.
|
||||||
|
*/
|
||||||
|
suppressDestroy(): void;
|
||||||
|
getRuntimeVersions(): {
|
||||||
|
version: string;
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX: Version;
|
||||||
|
NAPI_VERSION_EXPERIMENTAL: Version;
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION: Version;
|
||||||
|
};
|
||||||
|
createNotSupportWeakRefError(api: string, message: string): NotSupportWeakRefError;
|
||||||
|
createNotSupportBufferError(api: string, message: string): NotSupportBufferError;
|
||||||
|
createReference(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership): Reference;
|
||||||
|
createReferenceWithData(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): Reference;
|
||||||
|
createReferenceWithFinalizer(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback?: napi_finalize, finalize_data?: void_p, finalize_hint?: void_p): Reference;
|
||||||
|
createDeferred<T = any>(value: IDeferrdValue<T>): Deferred<T>;
|
||||||
|
adjustAmountOfExternalAllocatedMemory(changeInBytes: number | bigint): bigint;
|
||||||
|
createEnv(filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any): Env;
|
||||||
|
createTrackedFinalizer(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
getCurrentScope(): HandleScope | null;
|
||||||
|
addToCurrentScope<V>(value: V): Handle<V>;
|
||||||
|
openScope(envObject?: Env): HandleScope;
|
||||||
|
closeScope(envObject?: Env, _scope?: HandleScope): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
addCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
removeCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
runCleanup(): void;
|
||||||
|
increaseWaitingRequestCounter(): void;
|
||||||
|
decreaseWaitingRequestCounter(): void;
|
||||||
|
setCanCallIntoJs(value: boolean): void;
|
||||||
|
setStopping(value: boolean): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
/**
|
||||||
|
* Destroy the context and call cleanup hooks.
|
||||||
|
* Associated {@link Env | Env} will be destroyed.
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ContextOptions {
|
||||||
|
onExternalMemoryChange?: (current: bigint, old: bigint, delta: bigint) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function createContext(options?: ContextOptions): Context;
|
||||||
|
|
||||||
|
export declare class Deferred<T = any> implements IStoreValue {
|
||||||
|
static create<T = any>(ctx: Context, value: IDeferrdValue<T>): Deferred;
|
||||||
|
id: number;
|
||||||
|
ctx: Context;
|
||||||
|
value: IDeferrdValue<T>;
|
||||||
|
constructor(ctx: Context, value: IDeferrdValue<T>);
|
||||||
|
resolve(value: T): void;
|
||||||
|
reject(reason?: any): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class EmnapiError extends Error {
|
||||||
|
constructor(message?: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare abstract class Env implements IStoreValue {
|
||||||
|
readonly ctx: Context;
|
||||||
|
moduleApiVersion: number;
|
||||||
|
makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void;
|
||||||
|
makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void;
|
||||||
|
abort: (msg?: string) => never;
|
||||||
|
id: number;
|
||||||
|
openHandleScopes: number;
|
||||||
|
instanceData: TrackedFinalizer | null;
|
||||||
|
tryCatch: TryCatch;
|
||||||
|
refs: number;
|
||||||
|
reflist: RefTracker;
|
||||||
|
finalizing_reflist: RefTracker;
|
||||||
|
pendingFinalizers: RefTracker[];
|
||||||
|
lastError: {
|
||||||
|
errorCode: napi_status;
|
||||||
|
engineErrorCode: number;
|
||||||
|
engineReserved: Ptr;
|
||||||
|
};
|
||||||
|
inGcFinalizer: boolean;
|
||||||
|
constructor(ctx: Context, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never);
|
||||||
|
/** @virtual */
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
terminatedOrTerminating(): boolean;
|
||||||
|
ref(): void;
|
||||||
|
unref(): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
ensureHandleId(value: any): napi_value;
|
||||||
|
clearLastError(): napi_status;
|
||||||
|
setLastError(error_code: napi_status, engine_error_code?: uint32_t, engine_reserved?: void_p): napi_status;
|
||||||
|
getReturnStatus(): napi_status;
|
||||||
|
callIntoModule<T>(fn: (env: Env) => T, handleException?: (envObject: Env, value: any) => void): T;
|
||||||
|
/** @virtual */
|
||||||
|
abstract callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
invokeFinalizerFromGC(finalizer: RefTracker): void;
|
||||||
|
checkGCAccess(): void;
|
||||||
|
/** @virtual */
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
dequeueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
deleteMe(): void;
|
||||||
|
dispose(): void;
|
||||||
|
private readonly _bindingMap;
|
||||||
|
initObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
getObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
setInstanceData(data: number, finalize_cb: number, finalize_hint: number): void;
|
||||||
|
getInstanceData(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare interface External_2 extends Record<any, any> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare const External_2: {
|
||||||
|
new (value: number | bigint): External_2;
|
||||||
|
prototype: null;
|
||||||
|
};
|
||||||
|
export { External_2 as External }
|
||||||
|
|
||||||
|
export declare class Finalizer {
|
||||||
|
envObject: Env;
|
||||||
|
private _finalizeCallback;
|
||||||
|
private _finalizeData;
|
||||||
|
private _finalizeHint;
|
||||||
|
private _makeDynCall_vppp;
|
||||||
|
constructor(envObject: Env, _finalizeCallback?: napi_finalize, _finalizeData?: void_p, _finalizeHint?: void_p);
|
||||||
|
callback(): napi_finalize;
|
||||||
|
data(): void_p;
|
||||||
|
hint(): void_p;
|
||||||
|
resetEnv(): void;
|
||||||
|
resetFinalizer(): void;
|
||||||
|
callFinalizer(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function getDefaultContext(): Context;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function getExternalValue(external: External_2): number | bigint;
|
||||||
|
|
||||||
|
export declare class Handle<S> {
|
||||||
|
id: number;
|
||||||
|
value: S;
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
data(): void_p;
|
||||||
|
isNumber(): boolean;
|
||||||
|
isBigInt(): boolean;
|
||||||
|
isString(): boolean;
|
||||||
|
isFunction(): boolean;
|
||||||
|
isExternal(): boolean;
|
||||||
|
isObject(): boolean;
|
||||||
|
isArray(): boolean;
|
||||||
|
isArrayBuffer(): boolean;
|
||||||
|
isTypedArray(): boolean;
|
||||||
|
isBuffer(BufferConstructor?: BufferCtor): boolean;
|
||||||
|
isDataView(): boolean;
|
||||||
|
isDate(): boolean;
|
||||||
|
isPromise(): boolean;
|
||||||
|
isBoolean(): boolean;
|
||||||
|
isUndefined(): boolean;
|
||||||
|
isSymbol(): boolean;
|
||||||
|
isNull(): boolean;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleScope {
|
||||||
|
handleStore: HandleStore;
|
||||||
|
id: number;
|
||||||
|
parent: HandleScope | null;
|
||||||
|
child: HandleScope | null;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
private _escapeCalled;
|
||||||
|
callbackInfo: ICallbackInfo;
|
||||||
|
constructor(handleStore: HandleStore, id: number, parentScope: HandleScope | null, start: number, end?: number);
|
||||||
|
add<V>(value: V): Handle<V>;
|
||||||
|
addExternal(data: void_p): Handle<object>;
|
||||||
|
dispose(): void;
|
||||||
|
escape(handle: number): Handle<any> | null;
|
||||||
|
escapeCalled(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleStore {
|
||||||
|
static UNDEFINED: ConstHandle<undefined>;
|
||||||
|
static NULL: ConstHandle<null>;
|
||||||
|
static FALSE: ConstHandle<false>;
|
||||||
|
static TRUE: ConstHandle<true>;
|
||||||
|
static GLOBAL: ConstHandle<typeof globalThis>;
|
||||||
|
static MIN_ID: 6;
|
||||||
|
private readonly _values;
|
||||||
|
private _next;
|
||||||
|
push<S>(value: S): Handle<S>;
|
||||||
|
erase(start: number, end: number): void;
|
||||||
|
get(id: Ptr): Handle<any> | undefined;
|
||||||
|
swap(a: number, b: number): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ICallbackInfo {
|
||||||
|
thiz: any;
|
||||||
|
data: void_p;
|
||||||
|
args: ArrayLike<any>;
|
||||||
|
fn: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IDeferrdValue<T = any> {
|
||||||
|
resolve: (value: T) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IReferenceBinding {
|
||||||
|
wrapped: number;
|
||||||
|
tag: Uint32Array | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isExternal(object: unknown): object is External_2;
|
||||||
|
|
||||||
|
export declare function isReferenceType(v: any): v is object;
|
||||||
|
|
||||||
|
export declare interface IStoreValue {
|
||||||
|
id: number;
|
||||||
|
dispose(): void;
|
||||||
|
[x: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const NAPI_VERSION_EXPERIMENTAL = Version.NAPI_VERSION_EXPERIMENTAL;
|
||||||
|
|
||||||
|
export declare const NODE_API_DEFAULT_MODULE_API_VERSION = Version.NODE_API_DEFAULT_MODULE_API_VERSION;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MAX = Version.NODE_API_SUPPORTED_VERSION_MAX;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MIN = Version.NODE_API_SUPPORTED_VERSION_MIN;
|
||||||
|
|
||||||
|
export declare class NodeEnv extends Env {
|
||||||
|
filename: string;
|
||||||
|
private readonly nodeBinding?;
|
||||||
|
destructing: boolean;
|
||||||
|
finalizationScheduled: boolean;
|
||||||
|
constructor(ctx: Context, filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any);
|
||||||
|
deleteMe(): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
triggerFatalException(err: any): void;
|
||||||
|
callbackIntoModule<T>(enforceUncaughtExceptionPolicy: boolean, fn: (env: Env) => T): T;
|
||||||
|
callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
callFinalizerInternal(forceUncaught: int, cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
drainFinalizerQueue(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportBufferError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportWeakRefError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Persistent<T> {
|
||||||
|
private _ref;
|
||||||
|
private _param;
|
||||||
|
private _callback;
|
||||||
|
private static readonly _registry;
|
||||||
|
constructor(value: T);
|
||||||
|
setWeak<P>(param: P, callback: (param: P) => void): void;
|
||||||
|
clearWeak(): void;
|
||||||
|
reset(): void;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
deref(): T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Reference extends RefTracker implements IStoreValue {
|
||||||
|
private static weakCallback;
|
||||||
|
id: number;
|
||||||
|
envObject: Env;
|
||||||
|
private readonly canBeWeak;
|
||||||
|
private _refcount;
|
||||||
|
private readonly _ownership;
|
||||||
|
persistent: Persistent<object>;
|
||||||
|
static create(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, _unused1?: void_p, _unused2?: void_p, _unused3?: void_p): Reference;
|
||||||
|
protected constructor(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership);
|
||||||
|
ref(): number;
|
||||||
|
unref(): number;
|
||||||
|
get(envObject?: Env): napi_value;
|
||||||
|
/** @virtual */
|
||||||
|
resetFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
data(): void_p;
|
||||||
|
refcount(): number;
|
||||||
|
ownership(): ReferenceOwnership;
|
||||||
|
/** @virtual */
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
private _setWeak;
|
||||||
|
finalize(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare enum ReferenceOwnership {
|
||||||
|
kRuntime = 0,
|
||||||
|
kUserland = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithData extends Reference {
|
||||||
|
private readonly _data;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): ReferenceWithData;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithFinalizer extends Reference {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): ReferenceWithFinalizer;
|
||||||
|
private constructor();
|
||||||
|
resetFinalizer(): void;
|
||||||
|
data(): void_p;
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class RefTracker {
|
||||||
|
/** @virtual */
|
||||||
|
dispose(): void;
|
||||||
|
/** @virtual */
|
||||||
|
finalize(): void;
|
||||||
|
private _next;
|
||||||
|
private _prev;
|
||||||
|
link(list: RefTracker): void;
|
||||||
|
unlink(): void;
|
||||||
|
static finalizeAll(list: RefTracker): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ScopeStore {
|
||||||
|
private readonly _rootScope;
|
||||||
|
currentScope: HandleScope;
|
||||||
|
private readonly _values;
|
||||||
|
constructor();
|
||||||
|
get(id: number): HandleScope | undefined;
|
||||||
|
openScope(handleStore: HandleStore): HandleScope;
|
||||||
|
closeScope(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Store<V extends IStoreValue> {
|
||||||
|
protected _values: Array<V | undefined>;
|
||||||
|
private _freeList;
|
||||||
|
private _size;
|
||||||
|
constructor();
|
||||||
|
add(value: V): void;
|
||||||
|
get(id: Ptr): V | undefined;
|
||||||
|
has(id: Ptr): boolean;
|
||||||
|
remove(id: Ptr): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TrackedFinalizer extends RefTracker {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
dispose(): void;
|
||||||
|
finalize(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TryCatch {
|
||||||
|
private _exception;
|
||||||
|
private _caught;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
hasCaught(): boolean;
|
||||||
|
exception(): any;
|
||||||
|
setError(err: any): void;
|
||||||
|
reset(): void;
|
||||||
|
extractException(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
export { }
|
||||||
|
|
||||||
|
export as namespace emnapi;
|
||||||
Generated
Vendored
+1438
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+426
@@ -0,0 +1,426 @@
|
|||||||
|
declare namespace emnapi {
|
||||||
|
|
||||||
|
export type CleanupHookCallbackFunction = number | ((arg: number) => void);
|
||||||
|
|
||||||
|
export class ConstHandle<S extends undefined | null | boolean | typeof globalThis> extends Handle<S> {
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Context {
|
||||||
|
private _isStopping;
|
||||||
|
private _canCallIntoJs;
|
||||||
|
private _suppressDestroy;
|
||||||
|
envStore: Store<Env>;
|
||||||
|
scopeStore: ScopeStore;
|
||||||
|
refStore: Store<Reference>;
|
||||||
|
deferredStore: Store<Deferred<any>>;
|
||||||
|
handleStore: HandleStore;
|
||||||
|
private readonly refCounter?;
|
||||||
|
private readonly cleanupQueue;
|
||||||
|
private readonly _externalMemory;
|
||||||
|
feature: {
|
||||||
|
supportReflect: boolean;
|
||||||
|
supportFinalizer: boolean;
|
||||||
|
supportWeakSymbol: boolean;
|
||||||
|
supportBigInt: boolean;
|
||||||
|
supportNewFunction: boolean;
|
||||||
|
canSetFunctionName: boolean;
|
||||||
|
setImmediate: (callback: () => void) => void;
|
||||||
|
Buffer: BufferCtor | undefined;
|
||||||
|
MessageChannel: {
|
||||||
|
new (): MessageChannel;
|
||||||
|
prototype: MessageChannel;
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
constructor(options?: ContextOptions);
|
||||||
|
/**
|
||||||
|
* Suppress the destroy on `beforeExit` event in Node.js.
|
||||||
|
* Call this method if you want to keep the context and
|
||||||
|
* all associated {@link Env | Env} alive,
|
||||||
|
* this also means that cleanup hooks will not be called.
|
||||||
|
* After call this method, you should call
|
||||||
|
* {@link Context.destroy | `Context.prototype.destroy`} method manually.
|
||||||
|
*/
|
||||||
|
suppressDestroy(): void;
|
||||||
|
getRuntimeVersions(): {
|
||||||
|
version: string;
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX: Version;
|
||||||
|
NAPI_VERSION_EXPERIMENTAL: Version;
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION: Version;
|
||||||
|
};
|
||||||
|
createNotSupportWeakRefError(api: string, message: string): NotSupportWeakRefError;
|
||||||
|
createNotSupportBufferError(api: string, message: string): NotSupportBufferError;
|
||||||
|
createReference(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership): Reference;
|
||||||
|
createReferenceWithData(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): Reference;
|
||||||
|
createReferenceWithFinalizer(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback?: napi_finalize, finalize_data?: void_p, finalize_hint?: void_p): Reference;
|
||||||
|
createDeferred<T = any>(value: IDeferrdValue<T>): Deferred<T>;
|
||||||
|
adjustAmountOfExternalAllocatedMemory(changeInBytes: number | bigint): bigint;
|
||||||
|
createEnv(filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any): Env;
|
||||||
|
createTrackedFinalizer(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
getCurrentScope(): HandleScope | null;
|
||||||
|
addToCurrentScope<V>(value: V): Handle<V>;
|
||||||
|
openScope(envObject?: Env): HandleScope;
|
||||||
|
closeScope(envObject?: Env, _scope?: HandleScope): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
addCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
removeCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
runCleanup(): void;
|
||||||
|
increaseWaitingRequestCounter(): void;
|
||||||
|
decreaseWaitingRequestCounter(): void;
|
||||||
|
setCanCallIntoJs(value: boolean): void;
|
||||||
|
setStopping(value: boolean): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
/**
|
||||||
|
* Destroy the context and call cleanup hooks.
|
||||||
|
* Associated {@link Env | Env} will be destroyed.
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContextOptions {
|
||||||
|
onExternalMemoryChange?: (current: bigint, old: bigint, delta: bigint) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createContext(options?: ContextOptions): Context;
|
||||||
|
|
||||||
|
export class Deferred<T = any> implements IStoreValue {
|
||||||
|
static create<T = any>(ctx: Context, value: IDeferrdValue<T>): Deferred;
|
||||||
|
id: number;
|
||||||
|
ctx: Context;
|
||||||
|
value: IDeferrdValue<T>;
|
||||||
|
constructor(ctx: Context, value: IDeferrdValue<T>);
|
||||||
|
resolve(value: T): void;
|
||||||
|
reject(reason?: any): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EmnapiError extends Error {
|
||||||
|
constructor(message?: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class Env implements IStoreValue {
|
||||||
|
readonly ctx: Context;
|
||||||
|
moduleApiVersion: number;
|
||||||
|
makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void;
|
||||||
|
makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void;
|
||||||
|
abort: (msg?: string) => never;
|
||||||
|
id: number;
|
||||||
|
openHandleScopes: number;
|
||||||
|
instanceData: TrackedFinalizer | null;
|
||||||
|
tryCatch: TryCatch;
|
||||||
|
refs: number;
|
||||||
|
reflist: RefTracker;
|
||||||
|
finalizing_reflist: RefTracker;
|
||||||
|
pendingFinalizers: RefTracker[];
|
||||||
|
lastError: {
|
||||||
|
errorCode: napi_status;
|
||||||
|
engineErrorCode: number;
|
||||||
|
engineReserved: Ptr;
|
||||||
|
};
|
||||||
|
inGcFinalizer: boolean;
|
||||||
|
constructor(ctx: Context, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never);
|
||||||
|
/** @virtual */
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
terminatedOrTerminating(): boolean;
|
||||||
|
ref(): void;
|
||||||
|
unref(): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
ensureHandleId(value: any): napi_value;
|
||||||
|
clearLastError(): napi_status;
|
||||||
|
setLastError(error_code: napi_status, engine_error_code?: uint32_t, engine_reserved?: void_p): napi_status;
|
||||||
|
getReturnStatus(): napi_status;
|
||||||
|
callIntoModule<T>(fn: (env: Env) => T, handleException?: (envObject: Env, value: any) => void): T;
|
||||||
|
/** @virtual */
|
||||||
|
abstract callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
invokeFinalizerFromGC(finalizer: RefTracker): void;
|
||||||
|
checkGCAccess(): void;
|
||||||
|
/** @virtual */
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
dequeueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
deleteMe(): void;
|
||||||
|
dispose(): void;
|
||||||
|
private readonly _bindingMap;
|
||||||
|
initObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
getObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
setInstanceData(data: number, finalize_cb: number, finalize_hint: number): void;
|
||||||
|
getInstanceData(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
interface External_2 extends Record<any, any> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
const External_2: {
|
||||||
|
new (value: number | bigint): External_2;
|
||||||
|
prototype: null;
|
||||||
|
};
|
||||||
|
export { External_2 as External }
|
||||||
|
|
||||||
|
export class Finalizer {
|
||||||
|
envObject: Env;
|
||||||
|
private _finalizeCallback;
|
||||||
|
private _finalizeData;
|
||||||
|
private _finalizeHint;
|
||||||
|
private _makeDynCall_vppp;
|
||||||
|
constructor(envObject: Env, _finalizeCallback?: napi_finalize, _finalizeData?: void_p, _finalizeHint?: void_p);
|
||||||
|
callback(): napi_finalize;
|
||||||
|
data(): void_p;
|
||||||
|
hint(): void_p;
|
||||||
|
resetEnv(): void;
|
||||||
|
resetFinalizer(): void;
|
||||||
|
callFinalizer(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefaultContext(): Context;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export function getExternalValue(external: External_2): number | bigint;
|
||||||
|
|
||||||
|
export class Handle<S> {
|
||||||
|
id: number;
|
||||||
|
value: S;
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
data(): void_p;
|
||||||
|
isNumber(): boolean;
|
||||||
|
isBigInt(): boolean;
|
||||||
|
isString(): boolean;
|
||||||
|
isFunction(): boolean;
|
||||||
|
isExternal(): boolean;
|
||||||
|
isObject(): boolean;
|
||||||
|
isArray(): boolean;
|
||||||
|
isArrayBuffer(): boolean;
|
||||||
|
isTypedArray(): boolean;
|
||||||
|
isBuffer(BufferConstructor?: BufferCtor): boolean;
|
||||||
|
isDataView(): boolean;
|
||||||
|
isDate(): boolean;
|
||||||
|
isPromise(): boolean;
|
||||||
|
isBoolean(): boolean;
|
||||||
|
isUndefined(): boolean;
|
||||||
|
isSymbol(): boolean;
|
||||||
|
isNull(): boolean;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HandleScope {
|
||||||
|
handleStore: HandleStore;
|
||||||
|
id: number;
|
||||||
|
parent: HandleScope | null;
|
||||||
|
child: HandleScope | null;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
private _escapeCalled;
|
||||||
|
callbackInfo: ICallbackInfo;
|
||||||
|
constructor(handleStore: HandleStore, id: number, parentScope: HandleScope | null, start: number, end?: number);
|
||||||
|
add<V>(value: V): Handle<V>;
|
||||||
|
addExternal(data: void_p): Handle<object>;
|
||||||
|
dispose(): void;
|
||||||
|
escape(handle: number): Handle<any> | null;
|
||||||
|
escapeCalled(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HandleStore {
|
||||||
|
static UNDEFINED: ConstHandle<undefined>;
|
||||||
|
static NULL: ConstHandle<null>;
|
||||||
|
static FALSE: ConstHandle<false>;
|
||||||
|
static TRUE: ConstHandle<true>;
|
||||||
|
static GLOBAL: ConstHandle<typeof globalThis>;
|
||||||
|
static MIN_ID: 6;
|
||||||
|
private readonly _values;
|
||||||
|
private _next;
|
||||||
|
push<S>(value: S): Handle<S>;
|
||||||
|
erase(start: number, end: number): void;
|
||||||
|
get(id: Ptr): Handle<any> | undefined;
|
||||||
|
swap(a: number, b: number): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICallbackInfo {
|
||||||
|
thiz: any;
|
||||||
|
data: void_p;
|
||||||
|
args: ArrayLike<any>;
|
||||||
|
fn: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDeferrdValue<T = any> {
|
||||||
|
resolve: (value: T) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReferenceBinding {
|
||||||
|
wrapped: number;
|
||||||
|
tag: Uint32Array | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export function isExternal(object: unknown): object is External_2;
|
||||||
|
|
||||||
|
export function isReferenceType(v: any): v is object;
|
||||||
|
|
||||||
|
export interface IStoreValue {
|
||||||
|
id: number;
|
||||||
|
dispose(): void;
|
||||||
|
[x: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NAPI_VERSION_EXPERIMENTAL = Version.NAPI_VERSION_EXPERIMENTAL;
|
||||||
|
|
||||||
|
export const NODE_API_DEFAULT_MODULE_API_VERSION = Version.NODE_API_DEFAULT_MODULE_API_VERSION;
|
||||||
|
|
||||||
|
export const NODE_API_SUPPORTED_VERSION_MAX = Version.NODE_API_SUPPORTED_VERSION_MAX;
|
||||||
|
|
||||||
|
export const NODE_API_SUPPORTED_VERSION_MIN = Version.NODE_API_SUPPORTED_VERSION_MIN;
|
||||||
|
|
||||||
|
export class NodeEnv extends Env {
|
||||||
|
filename: string;
|
||||||
|
private readonly nodeBinding?;
|
||||||
|
destructing: boolean;
|
||||||
|
finalizationScheduled: boolean;
|
||||||
|
constructor(ctx: Context, filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any);
|
||||||
|
deleteMe(): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
triggerFatalException(err: any): void;
|
||||||
|
callbackIntoModule<T>(enforceUncaughtExceptionPolicy: boolean, fn: (env: Env) => T): T;
|
||||||
|
callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
callFinalizerInternal(forceUncaught: int, cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
drainFinalizerQueue(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotSupportBufferError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotSupportWeakRefError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Persistent<T> {
|
||||||
|
private _ref;
|
||||||
|
private _param;
|
||||||
|
private _callback;
|
||||||
|
private static readonly _registry;
|
||||||
|
constructor(value: T);
|
||||||
|
setWeak<P>(param: P, callback: (param: P) => void): void;
|
||||||
|
clearWeak(): void;
|
||||||
|
reset(): void;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
deref(): T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Reference extends RefTracker implements IStoreValue {
|
||||||
|
private static weakCallback;
|
||||||
|
id: number;
|
||||||
|
envObject: Env;
|
||||||
|
private readonly canBeWeak;
|
||||||
|
private _refcount;
|
||||||
|
private readonly _ownership;
|
||||||
|
persistent: Persistent<object>;
|
||||||
|
static create(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, _unused1?: void_p, _unused2?: void_p, _unused3?: void_p): Reference;
|
||||||
|
protected constructor(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership);
|
||||||
|
ref(): number;
|
||||||
|
unref(): number;
|
||||||
|
get(envObject?: Env): napi_value;
|
||||||
|
/** @virtual */
|
||||||
|
resetFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
data(): void_p;
|
||||||
|
refcount(): number;
|
||||||
|
ownership(): ReferenceOwnership;
|
||||||
|
/** @virtual */
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
private _setWeak;
|
||||||
|
finalize(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ReferenceOwnership {
|
||||||
|
kRuntime = 0,
|
||||||
|
kUserland = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReferenceWithData extends Reference {
|
||||||
|
private readonly _data;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): ReferenceWithData;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReferenceWithFinalizer extends Reference {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): ReferenceWithFinalizer;
|
||||||
|
private constructor();
|
||||||
|
resetFinalizer(): void;
|
||||||
|
data(): void_p;
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RefTracker {
|
||||||
|
/** @virtual */
|
||||||
|
dispose(): void;
|
||||||
|
/** @virtual */
|
||||||
|
finalize(): void;
|
||||||
|
private _next;
|
||||||
|
private _prev;
|
||||||
|
link(list: RefTracker): void;
|
||||||
|
unlink(): void;
|
||||||
|
static finalizeAll(list: RefTracker): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ScopeStore {
|
||||||
|
private readonly _rootScope;
|
||||||
|
currentScope: HandleScope;
|
||||||
|
private readonly _values;
|
||||||
|
constructor();
|
||||||
|
get(id: number): HandleScope | undefined;
|
||||||
|
openScope(handleStore: HandleStore): HandleScope;
|
||||||
|
closeScope(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Store<V extends IStoreValue> {
|
||||||
|
protected _values: Array<V | undefined>;
|
||||||
|
private _freeList;
|
||||||
|
private _size;
|
||||||
|
constructor();
|
||||||
|
add(value: V): void;
|
||||||
|
get(id: Ptr): V | undefined;
|
||||||
|
has(id: Ptr): boolean;
|
||||||
|
remove(id: Ptr): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TrackedFinalizer extends RefTracker {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
dispose(): void;
|
||||||
|
finalize(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TryCatch {
|
||||||
|
private _exception;
|
||||||
|
private _caught;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
hasCaught(): boolean;
|
||||||
|
exception(): any;
|
||||||
|
setError(err: any): void;
|
||||||
|
reset(): void;
|
||||||
|
extractException(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const version: string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+1509
File diff suppressed because it is too large
Load Diff
+1510
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+671
@@ -0,0 +1,671 @@
|
|||||||
|
export declare type Ptr = number | bigint
|
||||||
|
|
||||||
|
export declare interface IBuffer extends Uint8Array {}
|
||||||
|
export declare interface BufferCtor {
|
||||||
|
readonly prototype: IBuffer
|
||||||
|
/** @deprecated */
|
||||||
|
new (...args: any[]): IBuffer
|
||||||
|
from: {
|
||||||
|
(buffer: ArrayBufferLike): IBuffer
|
||||||
|
(buffer: ArrayBufferLike, byteOffset: number, length: number): IBuffer
|
||||||
|
}
|
||||||
|
alloc: (size: number) => IBuffer
|
||||||
|
isBuffer: (obj: unknown) => obj is IBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum GlobalHandle {
|
||||||
|
UNDEFINED = 1,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
TRUE,
|
||||||
|
GLOBAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum Version {
|
||||||
|
NODE_API_SUPPORTED_VERSION_MIN = 1,
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION = 8,
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX = 10,
|
||||||
|
NAPI_VERSION_EXPERIMENTAL = 2147483647 // INT_MAX
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type Pointer<T> = number
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export declare type PointerPointer<T> = number
|
||||||
|
export declare type FunctionPointer<T extends (...args: any[]) => any> = Pointer<T>
|
||||||
|
export declare type Const<T> = T
|
||||||
|
|
||||||
|
export declare type void_p = Pointer<void>
|
||||||
|
export declare type void_pp = Pointer<void_p>
|
||||||
|
export declare type bool = number
|
||||||
|
export declare type char = number
|
||||||
|
export declare type char_p = Pointer<char>
|
||||||
|
export declare type unsigned_char = number
|
||||||
|
export declare type const_char = Const<char>
|
||||||
|
export declare type const_char_p = Pointer<const_char>
|
||||||
|
export declare type char16_t_p = number
|
||||||
|
export declare type const_char16_t_p = number
|
||||||
|
|
||||||
|
export declare type short = number
|
||||||
|
export declare type unsigned_short = number
|
||||||
|
export declare type int = number
|
||||||
|
export declare type unsigned_int = number
|
||||||
|
export declare type long = number
|
||||||
|
export declare type unsigned_long = number
|
||||||
|
export declare type long_long = bigint
|
||||||
|
export declare type unsigned_long_long = bigint
|
||||||
|
export declare type float = number
|
||||||
|
export declare type double = number
|
||||||
|
export declare type long_double = number
|
||||||
|
export declare type size_t = number
|
||||||
|
|
||||||
|
export declare type int8_t = number
|
||||||
|
export declare type uint8_t = number
|
||||||
|
export declare type int16_t = number
|
||||||
|
export declare type uint16_t = number
|
||||||
|
export declare type int32_t = number
|
||||||
|
export declare type uint32_t = number
|
||||||
|
export declare type int64_t = bigint
|
||||||
|
export declare type uint64_t = bigint
|
||||||
|
export declare type napi_env = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_value = Pointer<unknown>
|
||||||
|
export declare type napi_ref = Pointer<unknown>
|
||||||
|
export declare type napi_deferred = Pointer<unknown>
|
||||||
|
export declare type napi_handle_scope = Pointer<unknown>
|
||||||
|
export declare type napi_escapable_handle_scope = Pointer<unknown>
|
||||||
|
|
||||||
|
export declare type napi_addon_register_func = FunctionPointer<(env: napi_env, exports: napi_value) => napi_value>
|
||||||
|
|
||||||
|
export declare type napi_callback_info = Pointer<unknown>
|
||||||
|
export declare type napi_callback = FunctionPointer<(env: napi_env, info: napi_callback_info) => napi_value>
|
||||||
|
|
||||||
|
export declare interface napi_extended_error_info {
|
||||||
|
error_message: const_char_p
|
||||||
|
engine_reserved: void_p
|
||||||
|
engine_error_code: uint32_t
|
||||||
|
error_code: napi_status
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_property_descriptor {
|
||||||
|
// One of utf8name or name should be NULL.
|
||||||
|
utf8name: const_char_p
|
||||||
|
name: napi_value
|
||||||
|
|
||||||
|
method: napi_callback
|
||||||
|
getter: napi_callback
|
||||||
|
setter: napi_callback
|
||||||
|
value: napi_value
|
||||||
|
/* napi_property_attributes */
|
||||||
|
attributes: number
|
||||||
|
data: void_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type napi_finalize = FunctionPointer<(
|
||||||
|
env: napi_env,
|
||||||
|
finalize_data: void_p,
|
||||||
|
finalize_hint: void_p
|
||||||
|
) => void>
|
||||||
|
|
||||||
|
export declare interface node_module {
|
||||||
|
nm_version: int32_t
|
||||||
|
nm_flags: uint32_t
|
||||||
|
nm_filename: Pointer<const_char>
|
||||||
|
nm_register_func: napi_addon_register_func
|
||||||
|
nm_modname: Pointer<const_char>
|
||||||
|
nm_priv: Pointer<void>
|
||||||
|
reserved: PointerPointer<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface napi_node_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
release: const_char_p
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface emnapi_emscripten_version {
|
||||||
|
major: uint32_t
|
||||||
|
minor: uint32_t
|
||||||
|
patch: uint32_t
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_status {
|
||||||
|
napi_ok,
|
||||||
|
napi_invalid_arg,
|
||||||
|
napi_object_expected,
|
||||||
|
napi_string_expected,
|
||||||
|
napi_name_expected,
|
||||||
|
napi_function_expected,
|
||||||
|
napi_number_expected,
|
||||||
|
napi_boolean_expected,
|
||||||
|
napi_array_expected,
|
||||||
|
napi_generic_failure,
|
||||||
|
napi_pending_exception,
|
||||||
|
napi_cancelled,
|
||||||
|
napi_escape_called_twice,
|
||||||
|
napi_handle_scope_mismatch,
|
||||||
|
napi_callback_scope_mismatch,
|
||||||
|
napi_queue_full,
|
||||||
|
napi_closing,
|
||||||
|
napi_bigint_expected,
|
||||||
|
napi_date_expected,
|
||||||
|
napi_arraybuffer_expected,
|
||||||
|
napi_detachable_arraybuffer_expected,
|
||||||
|
napi_would_deadlock, // unused
|
||||||
|
napi_no_external_buffers_allowed,
|
||||||
|
napi_cannot_run_js
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_property_attributes {
|
||||||
|
napi_default = 0,
|
||||||
|
napi_writable = 1 << 0,
|
||||||
|
napi_enumerable = 1 << 1,
|
||||||
|
napi_configurable = 1 << 2,
|
||||||
|
|
||||||
|
// Used with napi_define_class to distinguish static properties
|
||||||
|
// from instance properties. Ignored by napi_define_properties.
|
||||||
|
napi_static = 1 << 10,
|
||||||
|
|
||||||
|
/// #ifdef NAPI_EXPERIMENTAL
|
||||||
|
// Default for class methods.
|
||||||
|
napi_default_method = napi_writable | napi_configurable,
|
||||||
|
|
||||||
|
// Default for object properties, like in JS obj[prop].
|
||||||
|
napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable
|
||||||
|
/// #endif // NAPI_EXPERIMENTAL
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_valuetype {
|
||||||
|
napi_undefined,
|
||||||
|
napi_null,
|
||||||
|
napi_boolean,
|
||||||
|
napi_number,
|
||||||
|
napi_string,
|
||||||
|
napi_symbol,
|
||||||
|
napi_object,
|
||||||
|
napi_function,
|
||||||
|
napi_external,
|
||||||
|
napi_bigint
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_typedarray_type {
|
||||||
|
napi_int8_array,
|
||||||
|
napi_uint8_array,
|
||||||
|
napi_uint8_clamped_array,
|
||||||
|
napi_int16_array,
|
||||||
|
napi_uint16_array,
|
||||||
|
napi_int32_array,
|
||||||
|
napi_uint32_array,
|
||||||
|
napi_float32_array,
|
||||||
|
napi_float64_array,
|
||||||
|
napi_bigint64_array,
|
||||||
|
napi_biguint64_array,
|
||||||
|
napi_float16_array,
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_collection_mode {
|
||||||
|
napi_key_include_prototypes,
|
||||||
|
napi_key_own_only
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_filter {
|
||||||
|
napi_key_all_properties = 0,
|
||||||
|
napi_key_writable = 1,
|
||||||
|
napi_key_enumerable = 1 << 1,
|
||||||
|
napi_key_configurable = 1 << 2,
|
||||||
|
napi_key_skip_strings = 1 << 3,
|
||||||
|
napi_key_skip_symbols = 1 << 4
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_key_conversion {
|
||||||
|
napi_key_keep_numbers,
|
||||||
|
napi_key_numbers_to_strings
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum emnapi_memory_view_type {
|
||||||
|
emnapi_int8_array,
|
||||||
|
emnapi_uint8_array,
|
||||||
|
emnapi_uint8_clamped_array,
|
||||||
|
emnapi_int16_array,
|
||||||
|
emnapi_uint16_array,
|
||||||
|
emnapi_int32_array,
|
||||||
|
emnapi_uint32_array,
|
||||||
|
emnapi_float32_array,
|
||||||
|
emnapi_float64_array,
|
||||||
|
emnapi_bigint64_array,
|
||||||
|
emnapi_biguint64_array,
|
||||||
|
emnapi_float16_array,
|
||||||
|
emnapi_data_view = -1,
|
||||||
|
emnapi_buffer = -2
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_call_mode {
|
||||||
|
napi_tsfn_nonblocking,
|
||||||
|
napi_tsfn_blocking
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const enum napi_threadsafe_function_release_mode {
|
||||||
|
napi_tsfn_release,
|
||||||
|
napi_tsfn_abort
|
||||||
|
}
|
||||||
|
export declare type CleanupHookCallbackFunction = number | ((arg: number) => void);
|
||||||
|
|
||||||
|
export declare class ConstHandle<S extends undefined | null | boolean | typeof globalThis> extends Handle<S> {
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Context {
|
||||||
|
private _isStopping;
|
||||||
|
private _canCallIntoJs;
|
||||||
|
private _suppressDestroy;
|
||||||
|
envStore: Store<Env>;
|
||||||
|
scopeStore: ScopeStore;
|
||||||
|
refStore: Store<Reference>;
|
||||||
|
deferredStore: Store<Deferred<any>>;
|
||||||
|
handleStore: HandleStore;
|
||||||
|
private readonly refCounter?;
|
||||||
|
private readonly cleanupQueue;
|
||||||
|
private readonly _externalMemory;
|
||||||
|
feature: {
|
||||||
|
supportReflect: boolean;
|
||||||
|
supportFinalizer: boolean;
|
||||||
|
supportWeakSymbol: boolean;
|
||||||
|
supportBigInt: boolean;
|
||||||
|
supportNewFunction: boolean;
|
||||||
|
canSetFunctionName: boolean;
|
||||||
|
setImmediate: (callback: () => void) => void;
|
||||||
|
Buffer: BufferCtor | undefined;
|
||||||
|
MessageChannel: {
|
||||||
|
new (): MessageChannel;
|
||||||
|
prototype: MessageChannel;
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
constructor(options?: ContextOptions);
|
||||||
|
/**
|
||||||
|
* Suppress the destroy on `beforeExit` event in Node.js.
|
||||||
|
* Call this method if you want to keep the context and
|
||||||
|
* all associated {@link Env | Env} alive,
|
||||||
|
* this also means that cleanup hooks will not be called.
|
||||||
|
* After call this method, you should call
|
||||||
|
* {@link Context.destroy | `Context.prototype.destroy`} method manually.
|
||||||
|
*/
|
||||||
|
suppressDestroy(): void;
|
||||||
|
getRuntimeVersions(): {
|
||||||
|
version: string;
|
||||||
|
NODE_API_SUPPORTED_VERSION_MAX: Version;
|
||||||
|
NAPI_VERSION_EXPERIMENTAL: Version;
|
||||||
|
NODE_API_DEFAULT_MODULE_API_VERSION: Version;
|
||||||
|
};
|
||||||
|
createNotSupportWeakRefError(api: string, message: string): NotSupportWeakRefError;
|
||||||
|
createNotSupportBufferError(api: string, message: string): NotSupportBufferError;
|
||||||
|
createReference(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership): Reference;
|
||||||
|
createReferenceWithData(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): Reference;
|
||||||
|
createReferenceWithFinalizer(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback?: napi_finalize, finalize_data?: void_p, finalize_hint?: void_p): Reference;
|
||||||
|
createDeferred<T = any>(value: IDeferrdValue<T>): Deferred<T>;
|
||||||
|
adjustAmountOfExternalAllocatedMemory(changeInBytes: number | bigint): bigint;
|
||||||
|
createEnv(filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any): Env;
|
||||||
|
createTrackedFinalizer(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
getCurrentScope(): HandleScope | null;
|
||||||
|
addToCurrentScope<V>(value: V): Handle<V>;
|
||||||
|
openScope(envObject?: Env): HandleScope;
|
||||||
|
closeScope(envObject?: Env, _scope?: HandleScope): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
addCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
removeCleanupHook(envObject: Env, fn: CleanupHookCallbackFunction, arg: number): void;
|
||||||
|
runCleanup(): void;
|
||||||
|
increaseWaitingRequestCounter(): void;
|
||||||
|
decreaseWaitingRequestCounter(): void;
|
||||||
|
setCanCallIntoJs(value: boolean): void;
|
||||||
|
setStopping(value: boolean): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
/**
|
||||||
|
* Destroy the context and call cleanup hooks.
|
||||||
|
* Associated {@link Env | Env} will be destroyed.
|
||||||
|
*/
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ContextOptions {
|
||||||
|
onExternalMemoryChange?: (current: bigint, old: bigint, delta: bigint) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function createContext(options?: ContextOptions): Context;
|
||||||
|
|
||||||
|
export declare class Deferred<T = any> implements IStoreValue {
|
||||||
|
static create<T = any>(ctx: Context, value: IDeferrdValue<T>): Deferred;
|
||||||
|
id: number;
|
||||||
|
ctx: Context;
|
||||||
|
value: IDeferrdValue<T>;
|
||||||
|
constructor(ctx: Context, value: IDeferrdValue<T>);
|
||||||
|
resolve(value: T): void;
|
||||||
|
reject(reason?: any): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class EmnapiError extends Error {
|
||||||
|
constructor(message?: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare abstract class Env implements IStoreValue {
|
||||||
|
readonly ctx: Context;
|
||||||
|
moduleApiVersion: number;
|
||||||
|
makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void;
|
||||||
|
makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void;
|
||||||
|
abort: (msg?: string) => never;
|
||||||
|
id: number;
|
||||||
|
openHandleScopes: number;
|
||||||
|
instanceData: TrackedFinalizer | null;
|
||||||
|
tryCatch: TryCatch;
|
||||||
|
refs: number;
|
||||||
|
reflist: RefTracker;
|
||||||
|
finalizing_reflist: RefTracker;
|
||||||
|
pendingFinalizers: RefTracker[];
|
||||||
|
lastError: {
|
||||||
|
errorCode: napi_status;
|
||||||
|
engineErrorCode: number;
|
||||||
|
engineReserved: Ptr;
|
||||||
|
};
|
||||||
|
inGcFinalizer: boolean;
|
||||||
|
constructor(ctx: Context, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never);
|
||||||
|
/** @virtual */
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
terminatedOrTerminating(): boolean;
|
||||||
|
ref(): void;
|
||||||
|
unref(): void;
|
||||||
|
ensureHandle<S>(value: S): Handle<S>;
|
||||||
|
ensureHandleId(value: any): napi_value;
|
||||||
|
clearLastError(): napi_status;
|
||||||
|
setLastError(error_code: napi_status, engine_error_code?: uint32_t, engine_reserved?: void_p): napi_status;
|
||||||
|
getReturnStatus(): napi_status;
|
||||||
|
callIntoModule<T>(fn: (env: Env) => T, handleException?: (envObject: Env, value: any) => void): T;
|
||||||
|
/** @virtual */
|
||||||
|
abstract callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
invokeFinalizerFromGC(finalizer: RefTracker): void;
|
||||||
|
checkGCAccess(): void;
|
||||||
|
/** @virtual */
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
dequeueFinalizer(finalizer: RefTracker): void;
|
||||||
|
/** @virtual */
|
||||||
|
deleteMe(): void;
|
||||||
|
dispose(): void;
|
||||||
|
private readonly _bindingMap;
|
||||||
|
initObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
getObjectBinding<S extends object>(value: S): IReferenceBinding;
|
||||||
|
setInstanceData(data: number, finalize_cb: number, finalize_hint: number): void;
|
||||||
|
getInstanceData(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare interface External_2 extends Record<any, any> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare const External_2: {
|
||||||
|
new (value: number | bigint): External_2;
|
||||||
|
prototype: null;
|
||||||
|
};
|
||||||
|
export { External_2 as External }
|
||||||
|
|
||||||
|
export declare class Finalizer {
|
||||||
|
envObject: Env;
|
||||||
|
private _finalizeCallback;
|
||||||
|
private _finalizeData;
|
||||||
|
private _finalizeHint;
|
||||||
|
private _makeDynCall_vppp;
|
||||||
|
constructor(envObject: Env, _finalizeCallback?: napi_finalize, _finalizeData?: void_p, _finalizeHint?: void_p);
|
||||||
|
callback(): napi_finalize;
|
||||||
|
data(): void_p;
|
||||||
|
hint(): void_p;
|
||||||
|
resetEnv(): void;
|
||||||
|
resetFinalizer(): void;
|
||||||
|
callFinalizer(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare function getDefaultContext(): Context;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function getExternalValue(external: External_2): number | bigint;
|
||||||
|
|
||||||
|
export declare class Handle<S> {
|
||||||
|
id: number;
|
||||||
|
value: S;
|
||||||
|
constructor(id: number, value: S);
|
||||||
|
data(): void_p;
|
||||||
|
isNumber(): boolean;
|
||||||
|
isBigInt(): boolean;
|
||||||
|
isString(): boolean;
|
||||||
|
isFunction(): boolean;
|
||||||
|
isExternal(): boolean;
|
||||||
|
isObject(): boolean;
|
||||||
|
isArray(): boolean;
|
||||||
|
isArrayBuffer(): boolean;
|
||||||
|
isTypedArray(): boolean;
|
||||||
|
isBuffer(BufferConstructor?: BufferCtor): boolean;
|
||||||
|
isDataView(): boolean;
|
||||||
|
isDate(): boolean;
|
||||||
|
isPromise(): boolean;
|
||||||
|
isBoolean(): boolean;
|
||||||
|
isUndefined(): boolean;
|
||||||
|
isSymbol(): boolean;
|
||||||
|
isNull(): boolean;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleScope {
|
||||||
|
handleStore: HandleStore;
|
||||||
|
id: number;
|
||||||
|
parent: HandleScope | null;
|
||||||
|
child: HandleScope | null;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
private _escapeCalled;
|
||||||
|
callbackInfo: ICallbackInfo;
|
||||||
|
constructor(handleStore: HandleStore, id: number, parentScope: HandleScope | null, start: number, end?: number);
|
||||||
|
add<V>(value: V): Handle<V>;
|
||||||
|
addExternal(data: void_p): Handle<object>;
|
||||||
|
dispose(): void;
|
||||||
|
escape(handle: number): Handle<any> | null;
|
||||||
|
escapeCalled(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class HandleStore {
|
||||||
|
static UNDEFINED: ConstHandle<undefined>;
|
||||||
|
static NULL: ConstHandle<null>;
|
||||||
|
static FALSE: ConstHandle<false>;
|
||||||
|
static TRUE: ConstHandle<true>;
|
||||||
|
static GLOBAL: ConstHandle<typeof globalThis>;
|
||||||
|
static MIN_ID: 6;
|
||||||
|
private readonly _values;
|
||||||
|
private _next;
|
||||||
|
push<S>(value: S): Handle<S>;
|
||||||
|
erase(start: number, end: number): void;
|
||||||
|
get(id: Ptr): Handle<any> | undefined;
|
||||||
|
swap(a: number, b: number): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface ICallbackInfo {
|
||||||
|
thiz: any;
|
||||||
|
data: void_p;
|
||||||
|
args: ArrayLike<any>;
|
||||||
|
fn: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IDeferrdValue<T = any> {
|
||||||
|
resolve: (value: T) => void;
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare interface IReferenceBinding {
|
||||||
|
wrapped: number;
|
||||||
|
tag: Uint32Array | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isExternal(object: unknown): object is External_2;
|
||||||
|
|
||||||
|
export declare function isReferenceType(v: any): v is object;
|
||||||
|
|
||||||
|
export declare interface IStoreValue {
|
||||||
|
id: number;
|
||||||
|
dispose(): void;
|
||||||
|
[x: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const NAPI_VERSION_EXPERIMENTAL = Version.NAPI_VERSION_EXPERIMENTAL;
|
||||||
|
|
||||||
|
export declare const NODE_API_DEFAULT_MODULE_API_VERSION = Version.NODE_API_DEFAULT_MODULE_API_VERSION;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MAX = Version.NODE_API_SUPPORTED_VERSION_MAX;
|
||||||
|
|
||||||
|
export declare const NODE_API_SUPPORTED_VERSION_MIN = Version.NODE_API_SUPPORTED_VERSION_MIN;
|
||||||
|
|
||||||
|
export declare class NodeEnv extends Env {
|
||||||
|
filename: string;
|
||||||
|
private readonly nodeBinding?;
|
||||||
|
destructing: boolean;
|
||||||
|
finalizationScheduled: boolean;
|
||||||
|
constructor(ctx: Context, filename: string, moduleApiVersion: number, makeDynCall_vppp: (cb: Ptr) => (a: Ptr, b: Ptr, c: Ptr) => void, makeDynCall_vp: (cb: Ptr) => (a: Ptr) => void, abort: (msg?: string) => never, nodeBinding?: any);
|
||||||
|
deleteMe(): void;
|
||||||
|
canCallIntoJs(): boolean;
|
||||||
|
triggerFatalException(err: any): void;
|
||||||
|
callbackIntoModule<T>(enforceUncaughtExceptionPolicy: boolean, fn: (env: Env) => T): T;
|
||||||
|
callFinalizer(cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
callFinalizerInternal(forceUncaught: int, cb: napi_finalize, data: void_p, hint: void_p): void;
|
||||||
|
enqueueFinalizer(finalizer: RefTracker): void;
|
||||||
|
drainFinalizerQueue(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportBufferError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class NotSupportWeakRefError extends EmnapiError {
|
||||||
|
constructor(api: string, message: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Persistent<T> {
|
||||||
|
private _ref;
|
||||||
|
private _param;
|
||||||
|
private _callback;
|
||||||
|
private static readonly _registry;
|
||||||
|
constructor(value: T);
|
||||||
|
setWeak<P>(param: P, callback: (param: P) => void): void;
|
||||||
|
clearWeak(): void;
|
||||||
|
reset(): void;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
deref(): T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Reference extends RefTracker implements IStoreValue {
|
||||||
|
private static weakCallback;
|
||||||
|
id: number;
|
||||||
|
envObject: Env;
|
||||||
|
private readonly canBeWeak;
|
||||||
|
private _refcount;
|
||||||
|
private readonly _ownership;
|
||||||
|
persistent: Persistent<object>;
|
||||||
|
static create(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, _unused1?: void_p, _unused2?: void_p, _unused3?: void_p): Reference;
|
||||||
|
protected constructor(envObject: Env, handle_id: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership);
|
||||||
|
ref(): number;
|
||||||
|
unref(): number;
|
||||||
|
get(envObject?: Env): napi_value;
|
||||||
|
/** @virtual */
|
||||||
|
resetFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
data(): void_p;
|
||||||
|
refcount(): number;
|
||||||
|
ownership(): ReferenceOwnership;
|
||||||
|
/** @virtual */
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
/** @virtual */
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
private _setWeak;
|
||||||
|
finalize(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare enum ReferenceOwnership {
|
||||||
|
kRuntime = 0,
|
||||||
|
kUserland = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithData extends Reference {
|
||||||
|
private readonly _data;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, data: void_p): ReferenceWithData;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ReferenceWithFinalizer extends Reference {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, value: napi_value, initialRefcount: uint32_t, ownership: ReferenceOwnership, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): ReferenceWithFinalizer;
|
||||||
|
private constructor();
|
||||||
|
resetFinalizer(): void;
|
||||||
|
data(): void_p;
|
||||||
|
protected callUserFinalizer(): void;
|
||||||
|
protected invokeFinalizerFromGC(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class RefTracker {
|
||||||
|
/** @virtual */
|
||||||
|
dispose(): void;
|
||||||
|
/** @virtual */
|
||||||
|
finalize(): void;
|
||||||
|
private _next;
|
||||||
|
private _prev;
|
||||||
|
link(list: RefTracker): void;
|
||||||
|
unlink(): void;
|
||||||
|
static finalizeAll(list: RefTracker): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class ScopeStore {
|
||||||
|
private readonly _rootScope;
|
||||||
|
currentScope: HandleScope;
|
||||||
|
private readonly _values;
|
||||||
|
constructor();
|
||||||
|
get(id: number): HandleScope | undefined;
|
||||||
|
openScope(handleStore: HandleStore): HandleScope;
|
||||||
|
closeScope(): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class Store<V extends IStoreValue> {
|
||||||
|
protected _values: Array<V | undefined>;
|
||||||
|
private _freeList;
|
||||||
|
private _size;
|
||||||
|
constructor();
|
||||||
|
add(value: V): void;
|
||||||
|
get(id: Ptr): V | undefined;
|
||||||
|
has(id: Ptr): boolean;
|
||||||
|
remove(id: Ptr): void;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TrackedFinalizer extends RefTracker {
|
||||||
|
private _finalizer;
|
||||||
|
static create(envObject: Env, finalize_callback: napi_finalize, finalize_data: void_p, finalize_hint: void_p): TrackedFinalizer;
|
||||||
|
private constructor();
|
||||||
|
data(): void_p;
|
||||||
|
dispose(): void;
|
||||||
|
finalize(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare class TryCatch {
|
||||||
|
private _exception;
|
||||||
|
private _caught;
|
||||||
|
isEmpty(): boolean;
|
||||||
|
hasCaught(): boolean;
|
||||||
|
exception(): any;
|
||||||
|
setError(err: any): void;
|
||||||
|
reset(): void;
|
||||||
|
extractException(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare const version: string;
|
||||||
|
|
||||||
|
export { }
|
||||||
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1350
File diff suppressed because it is too large
Load Diff
+5
@@ -0,0 +1,5 @@
|
|||||||
|
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
|
||||||
|
module.exports = require('./dist/emnapi.cjs.min.js')
|
||||||
|
} else {
|
||||||
|
module.exports = require('./dist/emnapi.cjs.js')
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "@emnapi/runtime",
|
||||||
|
"version": "1.11.1",
|
||||||
|
"description": "emnapi runtime",
|
||||||
|
"main": "index.js",
|
||||||
|
"module": "./dist/emnapi.esm-bundler.js",
|
||||||
|
"types": "./dist/emnapi.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": {
|
||||||
|
"module": "./dist/emnapi.d.ts",
|
||||||
|
"import": "./dist/emnapi.d.mts",
|
||||||
|
"default": "./dist/emnapi.d.ts"
|
||||||
|
},
|
||||||
|
"module": "./dist/emnapi.esm-bundler.js",
|
||||||
|
"import": "./dist/emnapi.mjs",
|
||||||
|
"default": "./index.js"
|
||||||
|
},
|
||||||
|
"./dist/emnapi.cjs.min": {
|
||||||
|
"types": "./dist/emnapi.d.ts",
|
||||||
|
"default": "./dist/emnapi.cjs.min.js"
|
||||||
|
},
|
||||||
|
"./dist/emnapi.min.mjs": {
|
||||||
|
"types": "./dist/emnapi.d.mts",
|
||||||
|
"default": "./dist/emnapi.min.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "node ./script/build.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/toyobayashi/emnapi.git"
|
||||||
|
},
|
||||||
|
"author": "toyobayashi",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/toyobayashi/emnapi/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/toyobayashi/emnapi#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021-present Toyobayashi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
+203
@@ -0,0 +1,203 @@
|
|||||||
|
# @emnapi/wasi-threads
|
||||||
|
|
||||||
|
This package makes [wasi-threads proposal](https://github.com/WebAssembly/wasi-threads) based WASI modules work in Node.js and browser.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
`index.html`
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="./node_modules/@tybys/wasm-util/dist/wasm-util.js"></script>
|
||||||
|
<script src="./node_modules/@emnapi/wasi-threads/dist/wasi-threads.js"></script>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
If your application will block browser main thread (for example `pthread_join`), please run it in worker instead.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
// pthread_join (Atomics.wait) cannot be called in browser main thread
|
||||||
|
new Worker('./index.js')
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
`index.js`
|
||||||
|
|
||||||
|
```js
|
||||||
|
const ENVIRONMENT_IS_NODE =
|
||||||
|
typeof process === 'object' && process !== null &&
|
||||||
|
typeof process.versions === 'object' && process.versions !== null &&
|
||||||
|
typeof process.versions.node === 'string';
|
||||||
|
|
||||||
|
(function (main) {
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
main(require)
|
||||||
|
} else {
|
||||||
|
if (typeof importScripts === 'function') {
|
||||||
|
importScripts('./node_modules/@tybys/wasm-util/dist/wasm-util.js')
|
||||||
|
importScripts('./node_modules/@emnapi/wasi-threads/dist/wasi-threads.js')
|
||||||
|
}
|
||||||
|
const nodeWasi = { WASI: globalThis.wasmUtil.WASI }
|
||||||
|
const nodeWorkerThreads = {
|
||||||
|
Worker: globalThis.Worker
|
||||||
|
}
|
||||||
|
const _require = function (request) {
|
||||||
|
if (request === 'node:wasi' || request === 'wasi') return nodeWasi
|
||||||
|
if (request === 'node:worker_threads' || request === 'worker_threads') return nodeWorkerThreads
|
||||||
|
if (request === '@emnapi/wasi-threads') return globalThis.wasiThreads
|
||||||
|
throw new Error('Can not find module: ' + request)
|
||||||
|
}
|
||||||
|
main(_require)
|
||||||
|
}
|
||||||
|
})(async function (require) {
|
||||||
|
const { WASI } = require('wasi')
|
||||||
|
const { Worker } = require('worker_threads')
|
||||||
|
const { WASIThreads } = require('@emnapi/wasi-threads')
|
||||||
|
|
||||||
|
const wasi = new WASI({
|
||||||
|
version: 'preview1'
|
||||||
|
})
|
||||||
|
const wasiThreads = new WASIThreads({
|
||||||
|
wasi,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avoid Atomics.wait() deadlock during thread creation in browser
|
||||||
|
* see https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size
|
||||||
|
*/
|
||||||
|
reuseWorker: ENVIRONMENT_IS_NODE
|
||||||
|
? false
|
||||||
|
: {
|
||||||
|
size: 4 /** greater than actual needs (2) */,
|
||||||
|
strict: true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronous thread creation
|
||||||
|
* pthread_create will not return until thread worker actually starts
|
||||||
|
*/
|
||||||
|
waitThreadStart: typeof window === 'undefined' ? 1000 : false,
|
||||||
|
|
||||||
|
onCreateWorker: () => {
|
||||||
|
return new Worker('./worker.js', {
|
||||||
|
execArgv: ['--experimental-wasi-unstable-preview1']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const memory = new WebAssembly.Memory({
|
||||||
|
initial: 16777216 / 65536,
|
||||||
|
maximum: 2147483648 / 65536,
|
||||||
|
shared: true
|
||||||
|
})
|
||||||
|
let input
|
||||||
|
const file = 'path/to/your/wasi-module.wasm'
|
||||||
|
try {
|
||||||
|
input = require('fs').readFileSync(require('path').join(__dirname, file))
|
||||||
|
} catch (err) {
|
||||||
|
const response = await fetch(file)
|
||||||
|
input = await response.arrayBuffer()
|
||||||
|
}
|
||||||
|
let { module, instance } = await WebAssembly.instantiate(input, {
|
||||||
|
env: { memory },
|
||||||
|
wasi_snapshot_preview1: wasi.wasiImport,
|
||||||
|
...wasiThreads.getImportObject()
|
||||||
|
})
|
||||||
|
|
||||||
|
wasiThreads.setup(instance, module, memory)
|
||||||
|
await wasiThreads.preloadWorkers()
|
||||||
|
|
||||||
|
if (typeof instance.exports._start === 'function') {
|
||||||
|
return wasi.start(instance)
|
||||||
|
} else {
|
||||||
|
wasi.initialize(instance)
|
||||||
|
// instance.exports.exported_wasm_function()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
`worker.js`
|
||||||
|
|
||||||
|
```js
|
||||||
|
(function (main) {
|
||||||
|
const ENVIRONMENT_IS_NODE =
|
||||||
|
typeof process === 'object' && process !== null &&
|
||||||
|
typeof process.versions === 'object' && process.versions !== null &&
|
||||||
|
typeof process.versions.node === 'string'
|
||||||
|
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
const _require = function (request) {
|
||||||
|
return require(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
const _init = function () {
|
||||||
|
const nodeWorkerThreads = require('worker_threads')
|
||||||
|
const parentPort = nodeWorkerThreads.parentPort
|
||||||
|
|
||||||
|
parentPort.on('message', (data) => {
|
||||||
|
globalThis.onmessage({ data })
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign(globalThis, {
|
||||||
|
self: globalThis,
|
||||||
|
require,
|
||||||
|
Worker: nodeWorkerThreads.Worker,
|
||||||
|
importScripts: function (f) {
|
||||||
|
(0, eval)(require('fs').readFileSync(f, 'utf8') + '//# sourceURL=' + f)
|
||||||
|
},
|
||||||
|
postMessage: function (msg) {
|
||||||
|
parentPort.postMessage(msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
main(_require, _init)
|
||||||
|
} else {
|
||||||
|
importScripts('./node_modules/@tybys/wasm-util/dist/wasm-util.js')
|
||||||
|
importScripts('./node_modules/@emnapi/wasi-threads/dist/wasi-threads.js')
|
||||||
|
|
||||||
|
const nodeWasi = { WASI: globalThis.wasmUtil.WASI }
|
||||||
|
const _require = function (request) {
|
||||||
|
if (request === '@emnapi/wasi-threads') return globalThis.wasiThreads
|
||||||
|
if (request === 'node:wasi' || request === 'wasi') return nodeWasi
|
||||||
|
throw new Error('Can not find module: ' + request)
|
||||||
|
}
|
||||||
|
const _init = function () {}
|
||||||
|
main(_require, _init)
|
||||||
|
}
|
||||||
|
})(function main (require, init) {
|
||||||
|
init()
|
||||||
|
|
||||||
|
const { WASI } = require('wasi')
|
||||||
|
const { ThreadMessageHandler, WASIThreads } = require('@emnapi/wasi-threads')
|
||||||
|
|
||||||
|
const handler = new ThreadMessageHandler({
|
||||||
|
async onLoad ({ wasmModule, wasmMemory }) {
|
||||||
|
const wasi = new WASI({
|
||||||
|
version: 'preview1'
|
||||||
|
})
|
||||||
|
|
||||||
|
const wasiThreads = new WASIThreads({
|
||||||
|
wasi,
|
||||||
|
childThread: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const originalInstance = await WebAssembly.instantiate(wasmModule, {
|
||||||
|
env: {
|
||||||
|
memory: wasmMemory,
|
||||||
|
},
|
||||||
|
wasi_snapshot_preview1: wasi.wasiImport,
|
||||||
|
...wasiThreads.getImportObject()
|
||||||
|
})
|
||||||
|
|
||||||
|
// must call `initialize` instead of `start` in child thread
|
||||||
|
const instance = wasiThreads.initialize(originalInstance, wasmModule, wasmMemory)
|
||||||
|
|
||||||
|
return { module: wasmModule, instance }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
globalThis.onmessage = function (e) {
|
||||||
|
handler.handle(e)
|
||||||
|
// handle other messages
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
Generated
Vendored
+885
@@ -0,0 +1,885 @@
|
|||||||
|
const _WebAssembly = typeof WebAssembly !== 'undefined'
|
||||||
|
? WebAssembly
|
||||||
|
: typeof WXWebAssembly !== 'undefined'
|
||||||
|
? WXWebAssembly
|
||||||
|
: undefined;
|
||||||
|
const ENVIRONMENT_IS_NODE = typeof process === 'object' && process !== null &&
|
||||||
|
typeof process.versions === 'object' && process.versions !== null &&
|
||||||
|
typeof process.versions.node === 'string';
|
||||||
|
function getPostMessage(options) {
|
||||||
|
return typeof (options === null || options === void 0 ? void 0 : options.postMessage) === 'function'
|
||||||
|
? options.postMessage
|
||||||
|
: typeof postMessage === 'function'
|
||||||
|
? postMessage
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
function serizeErrorToBuffer(sab, code, error) {
|
||||||
|
const i32array = new Int32Array(sab);
|
||||||
|
Atomics.store(i32array, 0, code);
|
||||||
|
if (code > 1 && error) {
|
||||||
|
const name = error.name;
|
||||||
|
const message = error.message;
|
||||||
|
const stack = error.stack;
|
||||||
|
const nameBuffer = new TextEncoder().encode(name);
|
||||||
|
const messageBuffer = new TextEncoder().encode(message);
|
||||||
|
const stackBuffer = new TextEncoder().encode(stack);
|
||||||
|
Atomics.store(i32array, 1, nameBuffer.length);
|
||||||
|
Atomics.store(i32array, 2, messageBuffer.length);
|
||||||
|
Atomics.store(i32array, 3, stackBuffer.length);
|
||||||
|
const buffer = new Uint8Array(sab);
|
||||||
|
buffer.set(nameBuffer, 16);
|
||||||
|
buffer.set(messageBuffer, 16 + nameBuffer.length);
|
||||||
|
buffer.set(stackBuffer, 16 + nameBuffer.length + messageBuffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function deserizeErrorFromBuffer(sab) {
|
||||||
|
var _a, _b;
|
||||||
|
const i32array = new Int32Array(sab);
|
||||||
|
const status = Atomics.load(i32array, 0);
|
||||||
|
if (status <= 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const nameLength = Atomics.load(i32array, 1);
|
||||||
|
const messageLength = Atomics.load(i32array, 2);
|
||||||
|
const stackLength = Atomics.load(i32array, 3);
|
||||||
|
const buffer = new Uint8Array(sab);
|
||||||
|
const nameBuffer = buffer.slice(16, 16 + nameLength);
|
||||||
|
const messageBuffer = buffer.slice(16 + nameLength, 16 + nameLength + messageLength);
|
||||||
|
const stackBuffer = buffer.slice(16 + nameLength + messageLength, 16 + nameLength + messageLength + stackLength);
|
||||||
|
const name = new TextDecoder().decode(nameBuffer);
|
||||||
|
const message = new TextDecoder().decode(messageBuffer);
|
||||||
|
const stack = new TextDecoder().decode(stackBuffer);
|
||||||
|
const ErrorConstructor = (_a = globalThis[name]) !== null && _a !== void 0 ? _a : (name === 'RuntimeError' ? ((_b = _WebAssembly.RuntimeError) !== null && _b !== void 0 ? _b : Error) : Error);
|
||||||
|
const error = new ErrorConstructor(message);
|
||||||
|
Object.defineProperty(error, 'stack', {
|
||||||
|
value: stack,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
function isSharedArrayBuffer(value) {
|
||||||
|
return ((typeof SharedArrayBuffer === 'function' && value instanceof SharedArrayBuffer) ||
|
||||||
|
(Object.prototype.toString.call(value) === '[object SharedArrayBuffer]'));
|
||||||
|
}
|
||||||
|
function isTrapError(e) {
|
||||||
|
try {
|
||||||
|
return e instanceof _WebAssembly.RuntimeError;
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMessage(type, payload) {
|
||||||
|
return {
|
||||||
|
__emnapi__: {
|
||||||
|
type,
|
||||||
|
payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const WASI_THREADS_MAX_TID = 0x1FFFFFFF;
|
||||||
|
function checkSharedWasmMemory(wasmMemory) {
|
||||||
|
if (wasmMemory) {
|
||||||
|
if (!isSharedArrayBuffer(wasmMemory.buffer)) {
|
||||||
|
throw new Error('Multithread features require shared wasm memory. ' +
|
||||||
|
'Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, ' +
|
||||||
|
'then create WebAssembly.Memory with `shared: true` option');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof SharedArrayBuffer === 'undefined') {
|
||||||
|
throw new Error('Current environment does not support SharedArrayBuffer, threads are not available!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getReuseWorker(value) {
|
||||||
|
var _a;
|
||||||
|
if (typeof value === 'boolean') {
|
||||||
|
return value ? { size: 0, strict: false } : false;
|
||||||
|
}
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
if (!(value >= 0)) {
|
||||||
|
throw new RangeError('reuseWorker: size must be a non-negative integer');
|
||||||
|
}
|
||||||
|
return { size: value, strict: false };
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size = (_a = Number(value.size)) !== null && _a !== void 0 ? _a : 0;
|
||||||
|
const strict = Boolean(value.strict);
|
||||||
|
if (!(size > 0) && strict) {
|
||||||
|
throw new RangeError('reuseWorker: size must be set to positive integer if strict is set to true');
|
||||||
|
}
|
||||||
|
return { size, strict };
|
||||||
|
}
|
||||||
|
let nextWorkerID = 0;
|
||||||
|
class ThreadManager {
|
||||||
|
get nextWorkerID() { return nextWorkerID; }
|
||||||
|
constructor(options) {
|
||||||
|
var _a;
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.wasmModule = null;
|
||||||
|
this.wasmMemory = null;
|
||||||
|
this.messageEvents = new WeakMap();
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('ThreadManager(): options is not provided');
|
||||||
|
}
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this._childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._childThread = false;
|
||||||
|
}
|
||||||
|
if (this._childThread) {
|
||||||
|
this._onCreateWorker = undefined;
|
||||||
|
this._reuseWorker = false;
|
||||||
|
this._beforeLoad = undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._onCreateWorker = options.onCreateWorker;
|
||||||
|
this._reuseWorker = getReuseWorker(options.reuseWorker);
|
||||||
|
this._beforeLoad = options.beforeLoad;
|
||||||
|
}
|
||||||
|
this.printErr = (_a = options.printErr) !== null && _a !== void 0 ? _a : console.error.bind(console);
|
||||||
|
this.threadSpawn = options.threadSpawn;
|
||||||
|
}
|
||||||
|
init() {
|
||||||
|
if (!this._childThread) {
|
||||||
|
this.initMainThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initMainThread() {
|
||||||
|
this.preparePool();
|
||||||
|
}
|
||||||
|
preparePool() {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this._reuseWorker.size) {
|
||||||
|
let pthreadPoolSize = this._reuseWorker.size;
|
||||||
|
while (pthreadPoolSize--) {
|
||||||
|
const worker = this.allocateUnusedWorker();
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.once('message', () => { });
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shouldPreloadWorkers() {
|
||||||
|
return !this._childThread && this._reuseWorker && this._reuseWorker.size > 0;
|
||||||
|
}
|
||||||
|
loadWasmModuleToAllWorkers() {
|
||||||
|
const promises = Array(this.unusedWorkers.length);
|
||||||
|
for (let i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
const worker = this.unusedWorkers[i];
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.ref();
|
||||||
|
promises[i] = this.loadWasmModuleToWorker(worker).then((w) => {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
return w;
|
||||||
|
}, (e) => {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.all(promises).catch((err) => {
|
||||||
|
this.terminateAllThreads();
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
preloadWorkers() {
|
||||||
|
if (this.shouldPreloadWorkers()) {
|
||||||
|
return this.loadWasmModuleToAllWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
setup(wasmModule, wasmMemory) {
|
||||||
|
this.wasmModule = wasmModule;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
}
|
||||||
|
markId(worker) {
|
||||||
|
if (worker.__emnapi_tid)
|
||||||
|
return worker.__emnapi_tid;
|
||||||
|
const tid = nextWorkerID + 43;
|
||||||
|
nextWorkerID = (nextWorkerID + 1) % (WASI_THREADS_MAX_TID - 42);
|
||||||
|
this.pthreads[tid] = worker;
|
||||||
|
worker.__emnapi_tid = tid;
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
returnWorkerToPool(worker) {
|
||||||
|
var tid = worker.__emnapi_tid;
|
||||||
|
if (tid !== undefined) {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
}
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadWasmModuleToWorker(worker, sab) {
|
||||||
|
if (worker.whenLoaded)
|
||||||
|
return worker.whenLoaded;
|
||||||
|
const err = this.printErr;
|
||||||
|
const beforeLoad = this._beforeLoad;
|
||||||
|
const _this = this;
|
||||||
|
worker.whenLoaded = new Promise((resolve, reject) => {
|
||||||
|
const handleError = function (e) {
|
||||||
|
let message = 'worker sent an error!';
|
||||||
|
if (worker.__emnapi_tid !== undefined) {
|
||||||
|
message = 'worker (tid = ' + worker.__emnapi_tid + ') sent an error!';
|
||||||
|
}
|
||||||
|
if ('message' in e) {
|
||||||
|
err(message + ' ' + e.message);
|
||||||
|
if (e.message.indexOf('RuntimeError') !== -1 || e.message.indexOf('unreachable') !== -1) {
|
||||||
|
try {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err(message);
|
||||||
|
}
|
||||||
|
reject(e);
|
||||||
|
throw e;
|
||||||
|
};
|
||||||
|
const handleMessage = (data) => {
|
||||||
|
if (data.__emnapi__) {
|
||||||
|
const type = data.__emnapi__.type;
|
||||||
|
const payload = data.__emnapi__.payload;
|
||||||
|
if (type === 'loaded') {
|
||||||
|
worker.loaded = true;
|
||||||
|
if (ENVIRONMENT_IS_NODE && !worker.__emnapi_tid) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
resolve(worker);
|
||||||
|
}
|
||||||
|
else if (type === 'cleanup-thread') {
|
||||||
|
if (payload.tid in this.pthreads) {
|
||||||
|
this.cleanThread(worker, payload.tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 'spawn-thread') {
|
||||||
|
this.threadSpawn(payload.startArg, payload.errorOrTid);
|
||||||
|
}
|
||||||
|
else if (type === 'terminate-all-threads') {
|
||||||
|
this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.onmessage = (e) => {
|
||||||
|
handleMessage(e.data);
|
||||||
|
this.fireMessageEvent(worker, e);
|
||||||
|
};
|
||||||
|
worker.onerror = handleError;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.on('message', function (data) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onmessage) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
worker.on('error', function (e) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
||||||
|
});
|
||||||
|
worker.on('detachedExit', function () { });
|
||||||
|
}
|
||||||
|
if (typeof beforeLoad === 'function') {
|
||||||
|
beforeLoad(worker);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
worker.postMessage(createMessage('load', {
|
||||||
|
wasmModule: this.wasmModule,
|
||||||
|
wasmMemory: this.wasmMemory,
|
||||||
|
sab
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
checkSharedWasmMemory(this.wasmMemory);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return worker.whenLoaded;
|
||||||
|
}
|
||||||
|
allocateUnusedWorker() {
|
||||||
|
const _onCreateWorker = this._onCreateWorker;
|
||||||
|
if (typeof _onCreateWorker !== 'function') {
|
||||||
|
throw new TypeError('`options.onCreateWorker` is not provided');
|
||||||
|
}
|
||||||
|
const worker = _onCreateWorker({ type: 'thread', name: 'emnapi-pthread' });
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
getNewWorker(sab) {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this.unusedWorkers.length === 0) {
|
||||||
|
if (this._reuseWorker.strict) {
|
||||||
|
if (!ENVIRONMENT_IS_NODE) {
|
||||||
|
const err = this.printErr;
|
||||||
|
err('Tried to spawn a new thread, but the thread pool is exhausted.\n' +
|
||||||
|
'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const worker = this.allocateUnusedWorker();
|
||||||
|
this.loadWasmModuleToWorker(worker, sab);
|
||||||
|
}
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
}
|
||||||
|
const worker = this.allocateUnusedWorker();
|
||||||
|
this.loadWasmModuleToWorker(worker, sab);
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
}
|
||||||
|
cleanThread(worker, tid, force) {
|
||||||
|
if (!force && this._reuseWorker) {
|
||||||
|
this.returnWorkerToPool(worker);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
this.terminateWorker(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminateWorker(worker) {
|
||||||
|
var _a;
|
||||||
|
const tid = worker.__emnapi_tid;
|
||||||
|
worker.terminate();
|
||||||
|
(_a = this.messageEvents.get(worker)) === null || _a === void 0 ? void 0 : _a.clear();
|
||||||
|
this.messageEvents.delete(worker);
|
||||||
|
worker.onmessage = (e) => {
|
||||||
|
if (e.data.__emnapi__) {
|
||||||
|
const err = this.printErr;
|
||||||
|
err('received "' + e.data.__emnapi__.type + '" command from terminated worker: ' + tid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
terminateAllThreads() {
|
||||||
|
const runningWorkers = Object.values(this.pthreads);
|
||||||
|
for (let i = 0; i < runningWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(runningWorkers[i]);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(this.unusedWorkers[i]);
|
||||||
|
}
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.preparePool();
|
||||||
|
}
|
||||||
|
addMessageEventListener(worker, onMessage) {
|
||||||
|
let listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners) {
|
||||||
|
listeners = new Set();
|
||||||
|
this.messageEvents.set(worker, listeners);
|
||||||
|
}
|
||||||
|
listeners.add(onMessage);
|
||||||
|
return () => {
|
||||||
|
listeners === null || listeners === void 0 ? void 0 : listeners.delete(onMessage);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fireMessageEvent(worker, e) {
|
||||||
|
const listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners)
|
||||||
|
return;
|
||||||
|
const err = this.printErr;
|
||||||
|
listeners.forEach((listener) => {
|
||||||
|
try {
|
||||||
|
listener(e);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
err(e.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const kIsProxy = Symbol('kIsProxy');
|
||||||
|
function createInstanceProxy(instance, memory) {
|
||||||
|
if (instance[kIsProxy])
|
||||||
|
return instance;
|
||||||
|
const originalExports = instance.exports;
|
||||||
|
const createHandler = function (target) {
|
||||||
|
const handlers = [
|
||||||
|
'apply',
|
||||||
|
'construct',
|
||||||
|
'defineProperty',
|
||||||
|
'deleteProperty',
|
||||||
|
'get',
|
||||||
|
'getOwnPropertyDescriptor',
|
||||||
|
'getPrototypeOf',
|
||||||
|
'has',
|
||||||
|
'isExtensible',
|
||||||
|
'ownKeys',
|
||||||
|
'preventExtensions',
|
||||||
|
'set',
|
||||||
|
'setPrototypeOf'
|
||||||
|
];
|
||||||
|
const handler = {};
|
||||||
|
for (let i = 0; i < handlers.length; i++) {
|
||||||
|
const name = handlers[i];
|
||||||
|
handler[name] = function () {
|
||||||
|
const args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
args.unshift(target);
|
||||||
|
return Reflect[name].apply(Reflect, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
};
|
||||||
|
const handler = createHandler(originalExports);
|
||||||
|
const _initialize = () => { };
|
||||||
|
const _start = () => 0;
|
||||||
|
handler.get = function (_target, p, receiver) {
|
||||||
|
var _a;
|
||||||
|
if (p === 'memory') {
|
||||||
|
return (_a = (typeof memory === 'function' ? memory() : memory)) !== null && _a !== void 0 ? _a : Reflect.get(originalExports, p, receiver);
|
||||||
|
}
|
||||||
|
if (p === '_initialize') {
|
||||||
|
return p in originalExports ? _initialize : undefined;
|
||||||
|
}
|
||||||
|
if (p === '_start') {
|
||||||
|
return p in originalExports ? _start : undefined;
|
||||||
|
}
|
||||||
|
return Reflect.get(originalExports, p, receiver);
|
||||||
|
};
|
||||||
|
handler.has = function (_target, p) {
|
||||||
|
if (p === 'memory')
|
||||||
|
return true;
|
||||||
|
return Reflect.has(originalExports, p);
|
||||||
|
};
|
||||||
|
const exportsProxy = new Proxy(Object.create(null), handler);
|
||||||
|
return new Proxy(instance, {
|
||||||
|
get(target, p, receiver) {
|
||||||
|
if (p === 'exports') {
|
||||||
|
return exportsProxy;
|
||||||
|
}
|
||||||
|
if (p === kIsProxy) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Reflect.get(target, p, receiver);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const patchedWasiInstances = new WeakMap();
|
||||||
|
class WASIThreads {
|
||||||
|
constructor(options) {
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('WASIThreads(): options is not provided');
|
||||||
|
}
|
||||||
|
if (!options.wasi) {
|
||||||
|
throw new TypeError('WASIThreads(): options.wasi is not provided');
|
||||||
|
}
|
||||||
|
patchedWasiInstances.set(this, new WeakSet());
|
||||||
|
const wasi = options.wasi;
|
||||||
|
patchWasiInstance(this, wasi);
|
||||||
|
this.wasi = wasi;
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this.childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.childThread = false;
|
||||||
|
}
|
||||||
|
this.PThread = undefined;
|
||||||
|
if ('threadManager' in options) {
|
||||||
|
if (typeof options.threadManager === 'function') {
|
||||||
|
this.PThread = options.threadManager();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.PThread = options.threadManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!this.childThread) {
|
||||||
|
this.PThread = new ThreadManager(options);
|
||||||
|
this.PThread.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let waitThreadStart = false;
|
||||||
|
if ('waitThreadStart' in options) {
|
||||||
|
waitThreadStart = typeof options.waitThreadStart === 'number' ? options.waitThreadStart : Boolean(options.waitThreadStart);
|
||||||
|
}
|
||||||
|
const postMessage = getPostMessage(options);
|
||||||
|
if (this.childThread && typeof postMessage !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMessage;
|
||||||
|
const wasm64 = Boolean(options.wasm64);
|
||||||
|
const threadSpawn = (startArg, errorOrTid) => {
|
||||||
|
var _a;
|
||||||
|
const EAGAIN = 6;
|
||||||
|
const isNewABI = errorOrTid !== undefined;
|
||||||
|
try {
|
||||||
|
checkSharedWasmMemory(this.wasmMemory);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
(_a = this.PThread) === null || _a === void 0 ? void 0 : _a.printErr(err.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct, 0, 1);
|
||||||
|
Atomics.store(struct, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isNewABI) {
|
||||||
|
const malloc = this.wasmInstance.exports.malloc;
|
||||||
|
errorOrTid = wasm64 ? Number(malloc(BigInt(8))) : (malloc(8) >>> 0);
|
||||||
|
if (!errorOrTid) {
|
||||||
|
return -48;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const _free = this.wasmInstance.exports.free;
|
||||||
|
const free = wasm64 ? (ptr) => { _free(BigInt(ptr)); } : _free;
|
||||||
|
const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, 0);
|
||||||
|
if (this.childThread) {
|
||||||
|
postMessage(createMessage('spawn-thread', {
|
||||||
|
startArg,
|
||||||
|
errorOrTid: errorOrTid
|
||||||
|
}));
|
||||||
|
Atomics.wait(struct, 1, 0);
|
||||||
|
const isError = Atomics.load(struct, 0);
|
||||||
|
const result = Atomics.load(struct, 1);
|
||||||
|
if (isNewABI) {
|
||||||
|
return isError;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return isError ? -result : result;
|
||||||
|
}
|
||||||
|
const shouldWait = waitThreadStart || (waitThreadStart === 0);
|
||||||
|
let sab;
|
||||||
|
if (shouldWait) {
|
||||||
|
sab = new Int32Array(new SharedArrayBuffer(16 + 8192));
|
||||||
|
Atomics.store(sab, 0, 0);
|
||||||
|
}
|
||||||
|
let worker;
|
||||||
|
let tid;
|
||||||
|
const PThread = this.PThread;
|
||||||
|
try {
|
||||||
|
worker = PThread.getNewWorker(sab);
|
||||||
|
if (!worker) {
|
||||||
|
throw new Error('failed to get new worker');
|
||||||
|
}
|
||||||
|
tid = PThread.markId(worker);
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
worker.postMessage(createMessage('start', {
|
||||||
|
tid,
|
||||||
|
arg: startArg,
|
||||||
|
sab
|
||||||
|
}));
|
||||||
|
if (shouldWait) {
|
||||||
|
if (typeof waitThreadStart === 'number') {
|
||||||
|
const waitResult = Atomics.wait(sab, 0, 0, waitThreadStart);
|
||||||
|
if (waitResult === 'timed-out') {
|
||||||
|
throw new Error('Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Atomics.wait(sab, 0, 0);
|
||||||
|
}
|
||||||
|
const r = Atomics.load(sab, 0);
|
||||||
|
if (r > 1) {
|
||||||
|
throw deserizeErrorFromBuffer(sab.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (worker !== undefined && tid !== undefined) {
|
||||||
|
try {
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 1);
|
||||||
|
Atomics.store(struct, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
PThread === null || PThread === void 0 ? void 0 : PThread.printErr(e.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, tid);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
if (!shouldWait) {
|
||||||
|
worker.whenLoaded.catch((err) => {
|
||||||
|
delete worker.whenLoaded;
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isNewABI) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
this.threadSpawn = threadSpawn;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.threadSpawn = threadSpawn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getImportObject() {
|
||||||
|
return {
|
||||||
|
wasi: {
|
||||||
|
'thread-spawn': this.threadSpawn
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
setup(wasmInstance, wasmModule, wasmMemory) {
|
||||||
|
wasmMemory !== null && wasmMemory !== void 0 ? wasmMemory : (wasmMemory = wasmInstance.exports.memory);
|
||||||
|
this.wasmInstance = wasmInstance;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.setup(wasmModule, wasmMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preloadWorkers() {
|
||||||
|
if (this.PThread) {
|
||||||
|
return this.PThread.preloadWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
initialize(instance, module, memory) {
|
||||||
|
const exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
const wasi = this.wasi;
|
||||||
|
if (('_start' in exports) && (typeof exports._start === 'function')) {
|
||||||
|
if (this.childThread) {
|
||||||
|
wasi.start(instance);
|
||||||
|
try {
|
||||||
|
const kStarted = getWasiSymbol(wasi, 'kStarted');
|
||||||
|
wasi[kStarted] = false;
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setupInstance(wasi, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wasi.initialize(instance);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
start(instance, module, memory) {
|
||||||
|
const exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
const exitCode = this.wasi.start(instance);
|
||||||
|
return { exitCode, instance };
|
||||||
|
}
|
||||||
|
terminateAllThreads() {
|
||||||
|
var _a;
|
||||||
|
if (!this.childThread) {
|
||||||
|
(_a = this.PThread) === null || _a === void 0 ? void 0 : _a.terminateAllThreads();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.postMessage(createMessage('terminate-all-threads', {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function patchWasiInstance(wasiThreads, wasi) {
|
||||||
|
const patched = patchedWasiInstances.get(wasiThreads);
|
||||||
|
if (patched.has(wasi)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const _this = wasiThreads;
|
||||||
|
const wasiImport = wasi.wasiImport;
|
||||||
|
if (wasiImport) {
|
||||||
|
const proc_exit = wasiImport.proc_exit;
|
||||||
|
wasiImport.proc_exit = function (code) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
return proc_exit.call(this, code);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!_this.childThread) {
|
||||||
|
const start = wasi.start;
|
||||||
|
if (typeof start === 'function') {
|
||||||
|
wasi.start = function (instance) {
|
||||||
|
try {
|
||||||
|
return start.call(this, instance);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (isTrapError(err)) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patched.add(wasi);
|
||||||
|
}
|
||||||
|
function getWasiSymbol(wasi, description) {
|
||||||
|
const symbols = Object.getOwnPropertySymbols(wasi);
|
||||||
|
const selectDescription = (description) => (s) => {
|
||||||
|
if (s.description) {
|
||||||
|
return s.description === description;
|
||||||
|
}
|
||||||
|
return s.toString() === `Symbol(${description})`;
|
||||||
|
};
|
||||||
|
if (Array.isArray(description)) {
|
||||||
|
return description.map(d => symbols.filter(selectDescription(d))[0]);
|
||||||
|
}
|
||||||
|
return symbols.filter(selectDescription(description))[0];
|
||||||
|
}
|
||||||
|
function setupInstance(wasi, instance) {
|
||||||
|
const [kInstance, kSetMemory] = getWasiSymbol(wasi, ['kInstance', 'kSetMemory']);
|
||||||
|
wasi[kInstance] = instance;
|
||||||
|
wasi[kSetMemory](instance.exports.memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreadMessageHandler {
|
||||||
|
constructor(options) {
|
||||||
|
const postMsg = getPostMessage(options);
|
||||||
|
if (typeof postMsg !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMsg;
|
||||||
|
this.onLoad = options === null || options === void 0 ? void 0 : options.onLoad;
|
||||||
|
this.onError = typeof (options === null || options === void 0 ? void 0 : options.onError) === 'function' ? options.onError : (_type, err) => { throw err; };
|
||||||
|
this.instance = undefined;
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
}
|
||||||
|
instantiate(data) {
|
||||||
|
if (typeof this.onLoad === 'function') {
|
||||||
|
return this.onLoad(data);
|
||||||
|
}
|
||||||
|
throw new Error('ThreadMessageHandler.prototype.instantiate is not implemented');
|
||||||
|
}
|
||||||
|
handle(e) {
|
||||||
|
var _a;
|
||||||
|
if ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.__emnapi__) {
|
||||||
|
const type = e.data.__emnapi__.type;
|
||||||
|
const payload = e.data.__emnapi__.payload;
|
||||||
|
try {
|
||||||
|
if (type === 'load') {
|
||||||
|
this._load(payload);
|
||||||
|
}
|
||||||
|
else if (type === 'start') {
|
||||||
|
this.handleAfterLoad(e, () => {
|
||||||
|
this._start(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.onError(err, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_load(payload) {
|
||||||
|
if (this.instance !== undefined)
|
||||||
|
return;
|
||||||
|
let source;
|
||||||
|
try {
|
||||||
|
source = this.instantiate(payload);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this._loaded(err, null, payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const then = source && 'then' in source ? source.then : undefined;
|
||||||
|
if (typeof then === 'function') {
|
||||||
|
then.call(source, (source) => { this._loaded(null, source, payload); }, (err) => { this._loaded(err, null, payload); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._loaded(null, source, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_start(payload) {
|
||||||
|
const wasi_thread_start = this.instance.exports.wasi_thread_start;
|
||||||
|
if (typeof wasi_thread_start !== 'function') {
|
||||||
|
const err = new TypeError('wasi_thread_start is not exported');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
const postMessage = this.postMessage;
|
||||||
|
const tid = payload.tid;
|
||||||
|
const startArg = payload.arg;
|
||||||
|
notifyPthreadCreateResult(payload.sab, 1);
|
||||||
|
try {
|
||||||
|
wasi_thread_start(tid, startArg);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err !== 'unwind') {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postMessage(createMessage('cleanup-thread', { tid }));
|
||||||
|
}
|
||||||
|
_loaded(err, source, payload) {
|
||||||
|
if (err) {
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
if (source == null) {
|
||||||
|
const err = new TypeError('onLoad should return an object');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
const instance = source.instance;
|
||||||
|
if (!instance) {
|
||||||
|
const err = new TypeError('onLoad should return an object which includes "instance"');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
this.instance = instance;
|
||||||
|
const postMessage = this.postMessage;
|
||||||
|
postMessage(createMessage('loaded', {}));
|
||||||
|
const messages = this.messagesBeforeLoad;
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
for (let i = 0; i < messages.length; i++) {
|
||||||
|
const data = messages[i];
|
||||||
|
this.handle({ data });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleAfterLoad(e, f) {
|
||||||
|
if (this.instance !== undefined) {
|
||||||
|
f.call(this, e);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.messagesBeforeLoad.push(e.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function notifyPthreadCreateResult(sab, result, error) {
|
||||||
|
if (sab) {
|
||||||
|
serizeErrorToBuffer(sab.buffer, result, error);
|
||||||
|
Atomics.notify(sab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.ThreadManager = ThreadManager;
|
||||||
|
exports.ThreadMessageHandler = ThreadMessageHandler;
|
||||||
|
exports.WASIThreads = WASIThreads;
|
||||||
|
exports.createInstanceProxy = createInstanceProxy;
|
||||||
|
exports.isSharedArrayBuffer = isSharedArrayBuffer;
|
||||||
|
exports.isTrapError = isTrapError;
|
||||||
Generated
Vendored
+271
@@ -0,0 +1,271 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+271
@@ -0,0 +1,271 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
Vendored
+273
@@ -0,0 +1,273 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
|
|
||||||
|
export as namespace wasiThreads;
|
||||||
Generated
Vendored
+933
@@ -0,0 +1,933 @@
|
|||||||
|
var _WebAssembly = typeof WebAssembly !== 'undefined'
|
||||||
|
? WebAssembly
|
||||||
|
: typeof WXWebAssembly !== 'undefined'
|
||||||
|
? WXWebAssembly
|
||||||
|
: undefined;
|
||||||
|
var ENVIRONMENT_IS_NODE = typeof process === 'object' && process !== null &&
|
||||||
|
typeof process.versions === 'object' && process.versions !== null &&
|
||||||
|
typeof process.versions.node === 'string';
|
||||||
|
function getPostMessage(options) {
|
||||||
|
return typeof (options === null || options === void 0 ? void 0 : options.postMessage) === 'function'
|
||||||
|
? options.postMessage
|
||||||
|
: typeof postMessage === 'function'
|
||||||
|
? postMessage
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
function serizeErrorToBuffer(sab, code, error) {
|
||||||
|
var i32array = new Int32Array(sab);
|
||||||
|
Atomics.store(i32array, 0, code);
|
||||||
|
if (code > 1 && error) {
|
||||||
|
var name_1 = error.name;
|
||||||
|
var message = error.message;
|
||||||
|
var stack = error.stack;
|
||||||
|
var nameBuffer = new TextEncoder().encode(name_1);
|
||||||
|
var messageBuffer = new TextEncoder().encode(message);
|
||||||
|
var stackBuffer = new TextEncoder().encode(stack);
|
||||||
|
Atomics.store(i32array, 1, nameBuffer.length);
|
||||||
|
Atomics.store(i32array, 2, messageBuffer.length);
|
||||||
|
Atomics.store(i32array, 3, stackBuffer.length);
|
||||||
|
var buffer = new Uint8Array(sab);
|
||||||
|
buffer.set(nameBuffer, 16);
|
||||||
|
buffer.set(messageBuffer, 16 + nameBuffer.length);
|
||||||
|
buffer.set(stackBuffer, 16 + nameBuffer.length + messageBuffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function deserizeErrorFromBuffer(sab) {
|
||||||
|
var _a, _b;
|
||||||
|
var i32array = new Int32Array(sab);
|
||||||
|
var status = Atomics.load(i32array, 0);
|
||||||
|
if (status <= 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var nameLength = Atomics.load(i32array, 1);
|
||||||
|
var messageLength = Atomics.load(i32array, 2);
|
||||||
|
var stackLength = Atomics.load(i32array, 3);
|
||||||
|
var buffer = new Uint8Array(sab);
|
||||||
|
var nameBuffer = buffer.slice(16, 16 + nameLength);
|
||||||
|
var messageBuffer = buffer.slice(16 + nameLength, 16 + nameLength + messageLength);
|
||||||
|
var stackBuffer = buffer.slice(16 + nameLength + messageLength, 16 + nameLength + messageLength + stackLength);
|
||||||
|
var name = new TextDecoder().decode(nameBuffer);
|
||||||
|
var message = new TextDecoder().decode(messageBuffer);
|
||||||
|
var stack = new TextDecoder().decode(stackBuffer);
|
||||||
|
var ErrorConstructor = (_a = globalThis[name]) !== null && _a !== void 0 ? _a : (name === 'RuntimeError' ? ((_b = _WebAssembly.RuntimeError) !== null && _b !== void 0 ? _b : Error) : Error);
|
||||||
|
var error = new ErrorConstructor(message);
|
||||||
|
Object.defineProperty(error, 'stack', {
|
||||||
|
value: stack,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
function isSharedArrayBuffer(value) {
|
||||||
|
return ((typeof SharedArrayBuffer === 'function' && value instanceof SharedArrayBuffer) ||
|
||||||
|
(Object.prototype.toString.call(value) === '[object SharedArrayBuffer]'));
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
function isTrapError(e) {
|
||||||
|
try {
|
||||||
|
return e instanceof _WebAssembly.RuntimeError;
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMessage(type, payload) {
|
||||||
|
return {
|
||||||
|
__emnapi__: {
|
||||||
|
type: type,
|
||||||
|
payload: payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var WASI_THREADS_MAX_TID = 0x1FFFFFFF;
|
||||||
|
function checkSharedWasmMemory(wasmMemory) {
|
||||||
|
if (wasmMemory) {
|
||||||
|
if (!isSharedArrayBuffer(wasmMemory.buffer)) {
|
||||||
|
throw new Error('Multithread features require shared wasm memory. ' +
|
||||||
|
'Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, ' +
|
||||||
|
'then create WebAssembly.Memory with `shared: true` option');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof SharedArrayBuffer === 'undefined') {
|
||||||
|
throw new Error('Current environment does not support SharedArrayBuffer, threads are not available!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getReuseWorker(value) {
|
||||||
|
var _a;
|
||||||
|
if (typeof value === 'boolean') {
|
||||||
|
return value ? { size: 0, strict: false } : false;
|
||||||
|
}
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
if (!(value >= 0)) {
|
||||||
|
throw new RangeError('reuseWorker: size must be a non-negative integer');
|
||||||
|
}
|
||||||
|
return { size: value, strict: false };
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var size = (_a = Number(value.size)) !== null && _a !== void 0 ? _a : 0;
|
||||||
|
var strict = Boolean(value.strict);
|
||||||
|
if (!(size > 0) && strict) {
|
||||||
|
throw new RangeError('reuseWorker: size must be set to positive integer if strict is set to true');
|
||||||
|
}
|
||||||
|
return { size: size, strict: strict };
|
||||||
|
}
|
||||||
|
var nextWorkerID = 0;
|
||||||
|
/** @public */
|
||||||
|
var ThreadManager = /*#__PURE__*/ (function () {
|
||||||
|
function ThreadManager(options) {
|
||||||
|
var _a;
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.wasmModule = null;
|
||||||
|
this.wasmMemory = null;
|
||||||
|
this.messageEvents = new WeakMap();
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('ThreadManager(): options is not provided');
|
||||||
|
}
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this._childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._childThread = false;
|
||||||
|
}
|
||||||
|
if (this._childThread) {
|
||||||
|
this._onCreateWorker = undefined;
|
||||||
|
this._reuseWorker = false;
|
||||||
|
this._beforeLoad = undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._onCreateWorker = options.onCreateWorker;
|
||||||
|
this._reuseWorker = getReuseWorker(options.reuseWorker);
|
||||||
|
this._beforeLoad = options.beforeLoad;
|
||||||
|
}
|
||||||
|
this.printErr = (_a = options.printErr) !== null && _a !== void 0 ? _a : console.error.bind(console);
|
||||||
|
this.threadSpawn = options.threadSpawn;
|
||||||
|
}
|
||||||
|
Object.defineProperty(ThreadManager.prototype, "nextWorkerID", {
|
||||||
|
get: function () { return nextWorkerID; },
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
ThreadManager.prototype.init = function () {
|
||||||
|
if (!this._childThread) {
|
||||||
|
this.initMainThread();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.initMainThread = function () {
|
||||||
|
this.preparePool();
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.preparePool = function () {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this._reuseWorker.size) {
|
||||||
|
var pthreadPoolSize = this._reuseWorker.size;
|
||||||
|
while (pthreadPoolSize--) {
|
||||||
|
var worker = this.allocateUnusedWorker();
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
// https://github.com/nodejs/node/issues/53036
|
||||||
|
worker.once('message', function () { });
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.shouldPreloadWorkers = function () {
|
||||||
|
return !this._childThread && this._reuseWorker && this._reuseWorker.size > 0;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.loadWasmModuleToAllWorkers = function () {
|
||||||
|
var _this_1 = this;
|
||||||
|
var promises = Array(this.unusedWorkers.length);
|
||||||
|
var _loop_1 = function (i) {
|
||||||
|
var worker = this_1.unusedWorkers[i];
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.ref();
|
||||||
|
promises[i] = this_1.loadWasmModuleToWorker(worker).then(function (w) {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
return w;
|
||||||
|
}, function (e) {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var this_1 = this;
|
||||||
|
for (var i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
_loop_1(i);
|
||||||
|
}
|
||||||
|
return Promise.all(promises).catch(function (err) {
|
||||||
|
_this_1.terminateAllThreads();
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.preloadWorkers = function () {
|
||||||
|
if (this.shouldPreloadWorkers()) {
|
||||||
|
return this.loadWasmModuleToAllWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.setup = function (wasmModule, wasmMemory) {
|
||||||
|
this.wasmModule = wasmModule;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.markId = function (worker) {
|
||||||
|
if (worker.__emnapi_tid)
|
||||||
|
return worker.__emnapi_tid;
|
||||||
|
var tid = nextWorkerID + 43;
|
||||||
|
nextWorkerID = (nextWorkerID + 1) % (WASI_THREADS_MAX_TID - 42);
|
||||||
|
this.pthreads[tid] = worker;
|
||||||
|
worker.__emnapi_tid = tid;
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.returnWorkerToPool = function (worker) {
|
||||||
|
var tid = worker.__emnapi_tid;
|
||||||
|
if (tid !== undefined) {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
}
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.loadWasmModuleToWorker = function (worker, sab) {
|
||||||
|
var _this_1 = this;
|
||||||
|
if (worker.whenLoaded)
|
||||||
|
return worker.whenLoaded;
|
||||||
|
var err = this.printErr;
|
||||||
|
var beforeLoad = this._beforeLoad;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
var _this = this;
|
||||||
|
worker.whenLoaded = new Promise(function (resolve, reject) {
|
||||||
|
var handleError = function (e) {
|
||||||
|
var message = 'worker sent an error!';
|
||||||
|
if (worker.__emnapi_tid !== undefined) {
|
||||||
|
message = 'worker (tid = ' + worker.__emnapi_tid + ') sent an error!';
|
||||||
|
}
|
||||||
|
if ('message' in e) {
|
||||||
|
err(message + ' ' + e.message);
|
||||||
|
if (e.message.indexOf('RuntimeError') !== -1 || e.message.indexOf('unreachable') !== -1) {
|
||||||
|
try {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err(message);
|
||||||
|
}
|
||||||
|
reject(e);
|
||||||
|
throw e;
|
||||||
|
};
|
||||||
|
var handleMessage = function (data) {
|
||||||
|
if (data.__emnapi__) {
|
||||||
|
var type = data.__emnapi__.type;
|
||||||
|
var payload = data.__emnapi__.payload;
|
||||||
|
if (type === 'loaded') {
|
||||||
|
worker.loaded = true;
|
||||||
|
if (ENVIRONMENT_IS_NODE && !worker.__emnapi_tid) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
resolve(worker);
|
||||||
|
// if (payload.err) {
|
||||||
|
// err('failed to load in child thread: ' + (payload.err.message || payload.err))
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else if (type === 'cleanup-thread') {
|
||||||
|
if (payload.tid in _this_1.pthreads) {
|
||||||
|
_this_1.cleanThread(worker, payload.tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 'spawn-thread') {
|
||||||
|
_this_1.threadSpawn(payload.startArg, payload.errorOrTid);
|
||||||
|
}
|
||||||
|
else if (type === 'terminate-all-threads') {
|
||||||
|
_this_1.terminateAllThreads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.onmessage = function (e) {
|
||||||
|
handleMessage(e.data);
|
||||||
|
_this_1.fireMessageEvent(worker, e);
|
||||||
|
};
|
||||||
|
worker.onerror = handleError;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.on('message', function (data) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onmessage) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
worker.on('error', function (e) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
||||||
|
});
|
||||||
|
worker.on('detachedExit', function () { });
|
||||||
|
}
|
||||||
|
if (typeof beforeLoad === 'function') {
|
||||||
|
beforeLoad(worker);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
worker.postMessage(createMessage('load', {
|
||||||
|
wasmModule: _this_1.wasmModule,
|
||||||
|
wasmMemory: _this_1.wasmMemory,
|
||||||
|
sab: sab
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
checkSharedWasmMemory(_this_1.wasmMemory);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return worker.whenLoaded;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.allocateUnusedWorker = function () {
|
||||||
|
var _onCreateWorker = this._onCreateWorker;
|
||||||
|
if (typeof _onCreateWorker !== 'function') {
|
||||||
|
throw new TypeError('`options.onCreateWorker` is not provided');
|
||||||
|
}
|
||||||
|
var worker = _onCreateWorker({ type: 'thread', name: 'emnapi-pthread' });
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
return worker;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.getNewWorker = function (sab) {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this.unusedWorkers.length === 0) {
|
||||||
|
if (this._reuseWorker.strict) {
|
||||||
|
if (!ENVIRONMENT_IS_NODE) {
|
||||||
|
var err = this.printErr;
|
||||||
|
err('Tried to spawn a new thread, but the thread pool is exhausted.\n' +
|
||||||
|
'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var worker_1 = this.allocateUnusedWorker();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
this.loadWasmModuleToWorker(worker_1, sab);
|
||||||
|
}
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
}
|
||||||
|
var worker = this.allocateUnusedWorker();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
this.loadWasmModuleToWorker(worker, sab);
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.cleanThread = function (worker, tid, force) {
|
||||||
|
if (!force && this._reuseWorker) {
|
||||||
|
this.returnWorkerToPool(worker);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
this.terminateWorker(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.terminateWorker = function (worker) {
|
||||||
|
var _this_1 = this;
|
||||||
|
var _a;
|
||||||
|
var tid = worker.__emnapi_tid;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
worker.terminate();
|
||||||
|
(_a = this.messageEvents.get(worker)) === null || _a === void 0 ? void 0 : _a.clear();
|
||||||
|
this.messageEvents.delete(worker);
|
||||||
|
worker.onmessage = function (e) {
|
||||||
|
if (e.data.__emnapi__) {
|
||||||
|
var err = _this_1.printErr;
|
||||||
|
err('received "' + e.data.__emnapi__.type + '" command from terminated worker: ' + tid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.terminateAllThreads = function () {
|
||||||
|
var runningWorkers = Object.values(this.pthreads);
|
||||||
|
for (var i = 0; i < runningWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(runningWorkers[i]);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(this.unusedWorkers[i]);
|
||||||
|
}
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.preparePool();
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.addMessageEventListener = function (worker, onMessage) {
|
||||||
|
var listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners) {
|
||||||
|
listeners = new Set();
|
||||||
|
this.messageEvents.set(worker, listeners);
|
||||||
|
}
|
||||||
|
listeners.add(onMessage);
|
||||||
|
return function () {
|
||||||
|
listeners === null || listeners === void 0 ? void 0 : listeners.delete(onMessage);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.fireMessageEvent = function (worker, e) {
|
||||||
|
var listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners)
|
||||||
|
return;
|
||||||
|
var err = this.printErr;
|
||||||
|
listeners.forEach(function (listener) {
|
||||||
|
try {
|
||||||
|
listener(e);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
err(e.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return ThreadManager;
|
||||||
|
}());
|
||||||
|
|
||||||
|
var kIsProxy = Symbol('kIsProxy');
|
||||||
|
/** @public */
|
||||||
|
function createInstanceProxy(instance, memory) {
|
||||||
|
if (instance[kIsProxy])
|
||||||
|
return instance;
|
||||||
|
// https://github.com/nodejs/help/issues/4102
|
||||||
|
var originalExports = instance.exports;
|
||||||
|
var createHandler = function (target) {
|
||||||
|
var handlers = [
|
||||||
|
'apply',
|
||||||
|
'construct',
|
||||||
|
'defineProperty',
|
||||||
|
'deleteProperty',
|
||||||
|
'get',
|
||||||
|
'getOwnPropertyDescriptor',
|
||||||
|
'getPrototypeOf',
|
||||||
|
'has',
|
||||||
|
'isExtensible',
|
||||||
|
'ownKeys',
|
||||||
|
'preventExtensions',
|
||||||
|
'set',
|
||||||
|
'setPrototypeOf'
|
||||||
|
];
|
||||||
|
var handler = {};
|
||||||
|
var _loop_1 = function (i) {
|
||||||
|
var name_1 = handlers[i];
|
||||||
|
handler[name_1] = function () {
|
||||||
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
args.unshift(target);
|
||||||
|
return Reflect[name_1].apply(Reflect, args);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for (var i = 0; i < handlers.length; i++) {
|
||||||
|
_loop_1(i);
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
};
|
||||||
|
var handler = createHandler(originalExports);
|
||||||
|
var _initialize = function () { };
|
||||||
|
var _start = function () { return 0; };
|
||||||
|
handler.get = function (_target, p, receiver) {
|
||||||
|
var _a;
|
||||||
|
if (p === 'memory') {
|
||||||
|
return (_a = (typeof memory === 'function' ? memory() : memory)) !== null && _a !== void 0 ? _a : Reflect.get(originalExports, p, receiver);
|
||||||
|
}
|
||||||
|
if (p === '_initialize') {
|
||||||
|
return p in originalExports ? _initialize : undefined;
|
||||||
|
}
|
||||||
|
if (p === '_start') {
|
||||||
|
return p in originalExports ? _start : undefined;
|
||||||
|
}
|
||||||
|
return Reflect.get(originalExports, p, receiver);
|
||||||
|
};
|
||||||
|
handler.has = function (_target, p) {
|
||||||
|
if (p === 'memory')
|
||||||
|
return true;
|
||||||
|
return Reflect.has(originalExports, p);
|
||||||
|
};
|
||||||
|
var exportsProxy = new Proxy(Object.create(null), handler);
|
||||||
|
return new Proxy(instance, {
|
||||||
|
get: function (target, p, receiver) {
|
||||||
|
if (p === 'exports') {
|
||||||
|
return exportsProxy;
|
||||||
|
}
|
||||||
|
if (p === kIsProxy) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Reflect.get(target, p, receiver);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var patchedWasiInstances = new WeakMap();
|
||||||
|
/** @public */
|
||||||
|
var WASIThreads = /*#__PURE__*/ (function () {
|
||||||
|
function WASIThreads(options) {
|
||||||
|
var _this_1 = this;
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('WASIThreads(): options is not provided');
|
||||||
|
}
|
||||||
|
if (!options.wasi) {
|
||||||
|
throw new TypeError('WASIThreads(): options.wasi is not provided');
|
||||||
|
}
|
||||||
|
patchedWasiInstances.set(this, new WeakSet());
|
||||||
|
var wasi = options.wasi;
|
||||||
|
patchWasiInstance(this, wasi);
|
||||||
|
this.wasi = wasi;
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this.childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.childThread = false;
|
||||||
|
}
|
||||||
|
this.PThread = undefined;
|
||||||
|
if ('threadManager' in options) {
|
||||||
|
if (typeof options.threadManager === 'function') {
|
||||||
|
this.PThread = options.threadManager();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.PThread = options.threadManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!this.childThread) {
|
||||||
|
this.PThread = new ThreadManager(options);
|
||||||
|
this.PThread.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var waitThreadStart = false;
|
||||||
|
if ('waitThreadStart' in options) {
|
||||||
|
waitThreadStart = typeof options.waitThreadStart === 'number' ? options.waitThreadStart : Boolean(options.waitThreadStart);
|
||||||
|
}
|
||||||
|
var postMessage = getPostMessage(options);
|
||||||
|
if (this.childThread && typeof postMessage !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMessage;
|
||||||
|
var wasm64 = Boolean(options.wasm64);
|
||||||
|
var threadSpawn = function (startArg, errorOrTid) {
|
||||||
|
var _a;
|
||||||
|
var EAGAIN = 6;
|
||||||
|
var isNewABI = errorOrTid !== undefined;
|
||||||
|
try {
|
||||||
|
checkSharedWasmMemory(_this_1.wasmMemory);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
(_a = _this_1.PThread) === null || _a === void 0 ? void 0 : _a.printErr(err.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
var struct_1 = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct_1, 0, 1);
|
||||||
|
Atomics.store(struct_1, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct_1, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isNewABI) {
|
||||||
|
var malloc = _this_1.wasmInstance.exports.malloc;
|
||||||
|
errorOrTid = wasm64 ? Number(malloc(BigInt(8))) : (malloc(8) >>> 0);
|
||||||
|
if (!errorOrTid) {
|
||||||
|
return -48; /* ENOMEM */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var _free = _this_1.wasmInstance.exports.free;
|
||||||
|
var free = wasm64 ? function (ptr) { _free(BigInt(ptr)); } : _free;
|
||||||
|
var struct = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, 0);
|
||||||
|
if (_this_1.childThread) {
|
||||||
|
postMessage(createMessage('spawn-thread', {
|
||||||
|
startArg: startArg,
|
||||||
|
errorOrTid: errorOrTid
|
||||||
|
}));
|
||||||
|
Atomics.wait(struct, 1, 0);
|
||||||
|
var isError = Atomics.load(struct, 0);
|
||||||
|
var result = Atomics.load(struct, 1);
|
||||||
|
if (isNewABI) {
|
||||||
|
return isError;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return isError ? -result : result;
|
||||||
|
}
|
||||||
|
var shouldWait = waitThreadStart || (waitThreadStart === 0);
|
||||||
|
var sab;
|
||||||
|
if (shouldWait) {
|
||||||
|
sab = new Int32Array(new SharedArrayBuffer(16 + 8192));
|
||||||
|
Atomics.store(sab, 0, 0);
|
||||||
|
}
|
||||||
|
var worker;
|
||||||
|
var tid;
|
||||||
|
var PThread = _this_1.PThread;
|
||||||
|
try {
|
||||||
|
worker = PThread.getNewWorker(sab);
|
||||||
|
if (!worker) {
|
||||||
|
throw new Error('failed to get new worker');
|
||||||
|
}
|
||||||
|
tid = PThread.markId(worker);
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
worker.postMessage(createMessage('start', {
|
||||||
|
tid: tid,
|
||||||
|
arg: startArg,
|
||||||
|
sab: sab
|
||||||
|
}));
|
||||||
|
if (shouldWait) {
|
||||||
|
if (typeof waitThreadStart === 'number') {
|
||||||
|
var waitResult = Atomics.wait(sab, 0, 0, waitThreadStart);
|
||||||
|
if (waitResult === 'timed-out') {
|
||||||
|
throw new Error('Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Atomics.wait(sab, 0, 0);
|
||||||
|
}
|
||||||
|
var r = Atomics.load(sab, 0);
|
||||||
|
if (r > 1) {
|
||||||
|
throw deserizeErrorFromBuffer(sab.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (worker !== undefined && tid !== undefined) {
|
||||||
|
try {
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 1);
|
||||||
|
Atomics.store(struct, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
PThread === null || PThread === void 0 ? void 0 : PThread.printErr(e.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, tid);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
if (!shouldWait) {
|
||||||
|
worker.whenLoaded.catch(function (err) {
|
||||||
|
delete worker.whenLoaded;
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isNewABI) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
this.threadSpawn = threadSpawn;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.threadSpawn = threadSpawn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WASIThreads.prototype.getImportObject = function () {
|
||||||
|
return {
|
||||||
|
wasi: {
|
||||||
|
'thread-spawn': this.threadSpawn
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
WASIThreads.prototype.setup = function (wasmInstance, wasmModule, wasmMemory) {
|
||||||
|
wasmMemory !== null && wasmMemory !== void 0 ? wasmMemory : (wasmMemory = wasmInstance.exports.memory);
|
||||||
|
this.wasmInstance = wasmInstance;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.setup(wasmModule, wasmMemory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
WASIThreads.prototype.preloadWorkers = function () {
|
||||||
|
if (this.PThread) {
|
||||||
|
return this.PThread.preloadWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
WASIThreads.prototype.initialize = function (instance, module, memory) {
|
||||||
|
var exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
var wasi = this.wasi;
|
||||||
|
if (('_start' in exports) && (typeof exports._start === 'function')) {
|
||||||
|
if (this.childThread) {
|
||||||
|
wasi.start(instance);
|
||||||
|
try {
|
||||||
|
var kStarted = getWasiSymbol(wasi, 'kStarted');
|
||||||
|
wasi[kStarted] = false;
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setupInstance(wasi, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wasi.initialize(instance);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
WASIThreads.prototype.start = function (instance, module, memory) {
|
||||||
|
var exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
var exitCode = this.wasi.start(instance);
|
||||||
|
return { exitCode: exitCode, instance: instance };
|
||||||
|
};
|
||||||
|
WASIThreads.prototype.terminateAllThreads = function () {
|
||||||
|
var _a;
|
||||||
|
if (!this.childThread) {
|
||||||
|
(_a = this.PThread) === null || _a === void 0 ? void 0 : _a.terminateAllThreads();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.postMessage(createMessage('terminate-all-threads', {}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return WASIThreads;
|
||||||
|
}());
|
||||||
|
function patchWasiInstance(wasiThreads, wasi) {
|
||||||
|
var patched = patchedWasiInstances.get(wasiThreads);
|
||||||
|
if (patched.has(wasi)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var _this = wasiThreads;
|
||||||
|
var wasiImport = wasi.wasiImport;
|
||||||
|
if (wasiImport) {
|
||||||
|
var proc_exit_1 = wasiImport.proc_exit;
|
||||||
|
wasiImport.proc_exit = function (code) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
return proc_exit_1.call(this, code);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!_this.childThread) {
|
||||||
|
var start_1 = wasi.start;
|
||||||
|
if (typeof start_1 === 'function') {
|
||||||
|
wasi.start = function (instance) {
|
||||||
|
try {
|
||||||
|
return start_1.call(this, instance);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (isTrapError(err)) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patched.add(wasi);
|
||||||
|
}
|
||||||
|
function getWasiSymbol(wasi, description) {
|
||||||
|
var symbols = Object.getOwnPropertySymbols(wasi);
|
||||||
|
var selectDescription = function (description) { return function (s) {
|
||||||
|
if (s.description) {
|
||||||
|
return s.description === description;
|
||||||
|
}
|
||||||
|
return s.toString() === "Symbol(".concat(description, ")");
|
||||||
|
}; };
|
||||||
|
if (Array.isArray(description)) {
|
||||||
|
return description.map(function (d) { return symbols.filter(selectDescription(d))[0]; });
|
||||||
|
}
|
||||||
|
return symbols.filter(selectDescription(description))[0];
|
||||||
|
}
|
||||||
|
function setupInstance(wasi, instance) {
|
||||||
|
var _a = getWasiSymbol(wasi, ['kInstance', 'kSetMemory']), kInstance = _a[0], kSetMemory = _a[1];
|
||||||
|
wasi[kInstance] = instance;
|
||||||
|
wasi[kSetMemory](instance.exports.memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
var ThreadMessageHandler = /*#__PURE__*/ (function () {
|
||||||
|
function ThreadMessageHandler(options) {
|
||||||
|
var postMsg = getPostMessage(options);
|
||||||
|
if (typeof postMsg !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMsg;
|
||||||
|
this.onLoad = options === null || options === void 0 ? void 0 : options.onLoad;
|
||||||
|
this.onError = typeof (options === null || options === void 0 ? void 0 : options.onError) === 'function' ? options.onError : function (_type, err) { throw err; };
|
||||||
|
this.instance = undefined;
|
||||||
|
// this.module = undefined
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
}
|
||||||
|
/** @virtual */
|
||||||
|
ThreadMessageHandler.prototype.instantiate = function (data) {
|
||||||
|
if (typeof this.onLoad === 'function') {
|
||||||
|
return this.onLoad(data);
|
||||||
|
}
|
||||||
|
throw new Error('ThreadMessageHandler.prototype.instantiate is not implemented');
|
||||||
|
};
|
||||||
|
/** @virtual */
|
||||||
|
ThreadMessageHandler.prototype.handle = function (e) {
|
||||||
|
var _this = this;
|
||||||
|
var _a;
|
||||||
|
if ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.__emnapi__) {
|
||||||
|
var type = e.data.__emnapi__.type;
|
||||||
|
var payload_1 = e.data.__emnapi__.payload;
|
||||||
|
try {
|
||||||
|
if (type === 'load') {
|
||||||
|
this._load(payload_1);
|
||||||
|
}
|
||||||
|
else if (type === 'start') {
|
||||||
|
this.handleAfterLoad(e, function () {
|
||||||
|
_this._start(payload_1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.onError(err, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype._load = function (payload) {
|
||||||
|
var _this = this;
|
||||||
|
if (this.instance !== undefined)
|
||||||
|
return;
|
||||||
|
var source;
|
||||||
|
try {
|
||||||
|
source = this.instantiate(payload);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this._loaded(err, null, payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var then = source && 'then' in source ? source.then : undefined;
|
||||||
|
if (typeof then === 'function') {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
then.call(source, function (source) { _this._loaded(null, source, payload); }, function (err) { _this._loaded(err, null, payload); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._loaded(null, source, payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype._start = function (payload) {
|
||||||
|
var wasi_thread_start = this.instance.exports.wasi_thread_start;
|
||||||
|
if (typeof wasi_thread_start !== 'function') {
|
||||||
|
var err = new TypeError('wasi_thread_start is not exported');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
var postMessage = this.postMessage;
|
||||||
|
var tid = payload.tid;
|
||||||
|
var startArg = payload.arg;
|
||||||
|
notifyPthreadCreateResult(payload.sab, 1);
|
||||||
|
try {
|
||||||
|
wasi_thread_start(tid, startArg);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err !== 'unwind') {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postMessage(createMessage('cleanup-thread', { tid: tid }));
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype._loaded = function (err, source, payload) {
|
||||||
|
if (err) {
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
if (source == null) {
|
||||||
|
var err_1 = new TypeError('onLoad should return an object');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err_1);
|
||||||
|
throw err_1;
|
||||||
|
}
|
||||||
|
var instance = source.instance;
|
||||||
|
if (!instance) {
|
||||||
|
var err_2 = new TypeError('onLoad should return an object which includes "instance"');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err_2);
|
||||||
|
throw err_2;
|
||||||
|
}
|
||||||
|
this.instance = instance;
|
||||||
|
var postMessage = this.postMessage;
|
||||||
|
postMessage(createMessage('loaded', {}));
|
||||||
|
var messages = this.messagesBeforeLoad;
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
var data = messages[i];
|
||||||
|
this.handle({ data: data });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype.handleAfterLoad = function (e, f) {
|
||||||
|
if (this.instance !== undefined) {
|
||||||
|
f.call(this, e);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.messagesBeforeLoad.push(e.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return ThreadMessageHandler;
|
||||||
|
}());
|
||||||
|
function notifyPthreadCreateResult(sab, result, error) {
|
||||||
|
if (sab) {
|
||||||
|
serizeErrorToBuffer(sab.buffer, result, error);
|
||||||
|
Atomics.notify(sab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ThreadManager, ThreadMessageHandler, WASIThreads, createInstanceProxy, isSharedArrayBuffer, isTrapError };
|
||||||
Generated
Vendored
+945
@@ -0,0 +1,945 @@
|
|||||||
|
(function (global, factory) {
|
||||||
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||||
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||||
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.wasiThreads = {}));
|
||||||
|
})(this, (function (exports) {
|
||||||
|
var _WebAssembly = typeof WebAssembly !== 'undefined'
|
||||||
|
? WebAssembly
|
||||||
|
: typeof WXWebAssembly !== 'undefined'
|
||||||
|
? WXWebAssembly
|
||||||
|
: undefined;
|
||||||
|
var ENVIRONMENT_IS_NODE = typeof process === 'object' && process !== null &&
|
||||||
|
typeof process.versions === 'object' && process.versions !== null &&
|
||||||
|
typeof process.versions.node === 'string';
|
||||||
|
function getPostMessage(options) {
|
||||||
|
return typeof (options === null || options === void 0 ? void 0 : options.postMessage) === 'function'
|
||||||
|
? options.postMessage
|
||||||
|
: typeof postMessage === 'function'
|
||||||
|
? postMessage
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
function serizeErrorToBuffer(sab, code, error) {
|
||||||
|
var i32array = new Int32Array(sab);
|
||||||
|
Atomics.store(i32array, 0, code);
|
||||||
|
if (code > 1 && error) {
|
||||||
|
var name_1 = error.name;
|
||||||
|
var message = error.message;
|
||||||
|
var stack = error.stack;
|
||||||
|
var nameBuffer = new TextEncoder().encode(name_1);
|
||||||
|
var messageBuffer = new TextEncoder().encode(message);
|
||||||
|
var stackBuffer = new TextEncoder().encode(stack);
|
||||||
|
Atomics.store(i32array, 1, nameBuffer.length);
|
||||||
|
Atomics.store(i32array, 2, messageBuffer.length);
|
||||||
|
Atomics.store(i32array, 3, stackBuffer.length);
|
||||||
|
var buffer = new Uint8Array(sab);
|
||||||
|
buffer.set(nameBuffer, 16);
|
||||||
|
buffer.set(messageBuffer, 16 + nameBuffer.length);
|
||||||
|
buffer.set(stackBuffer, 16 + nameBuffer.length + messageBuffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function deserizeErrorFromBuffer(sab) {
|
||||||
|
var _a, _b;
|
||||||
|
var i32array = new Int32Array(sab);
|
||||||
|
var status = Atomics.load(i32array, 0);
|
||||||
|
if (status <= 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var nameLength = Atomics.load(i32array, 1);
|
||||||
|
var messageLength = Atomics.load(i32array, 2);
|
||||||
|
var stackLength = Atomics.load(i32array, 3);
|
||||||
|
var buffer = new Uint8Array(sab);
|
||||||
|
var nameBuffer = buffer.slice(16, 16 + nameLength);
|
||||||
|
var messageBuffer = buffer.slice(16 + nameLength, 16 + nameLength + messageLength);
|
||||||
|
var stackBuffer = buffer.slice(16 + nameLength + messageLength, 16 + nameLength + messageLength + stackLength);
|
||||||
|
var name = new TextDecoder().decode(nameBuffer);
|
||||||
|
var message = new TextDecoder().decode(messageBuffer);
|
||||||
|
var stack = new TextDecoder().decode(stackBuffer);
|
||||||
|
var ErrorConstructor = (_a = globalThis[name]) !== null && _a !== void 0 ? _a : (name === 'RuntimeError' ? ((_b = _WebAssembly.RuntimeError) !== null && _b !== void 0 ? _b : Error) : Error);
|
||||||
|
var error = new ErrorConstructor(message);
|
||||||
|
Object.defineProperty(error, 'stack', {
|
||||||
|
value: stack,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
function isSharedArrayBuffer(value) {
|
||||||
|
return ((typeof SharedArrayBuffer === 'function' && value instanceof SharedArrayBuffer) ||
|
||||||
|
(Object.prototype.toString.call(value) === '[object SharedArrayBuffer]'));
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
function isTrapError(e) {
|
||||||
|
try {
|
||||||
|
return e instanceof _WebAssembly.RuntimeError;
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMessage(type, payload) {
|
||||||
|
return {
|
||||||
|
__emnapi__: {
|
||||||
|
type: type,
|
||||||
|
payload: payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var WASI_THREADS_MAX_TID = 0x1FFFFFFF;
|
||||||
|
function checkSharedWasmMemory(wasmMemory) {
|
||||||
|
if (wasmMemory) {
|
||||||
|
if (!isSharedArrayBuffer(wasmMemory.buffer)) {
|
||||||
|
throw new Error('Multithread features require shared wasm memory. ' +
|
||||||
|
'Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, ' +
|
||||||
|
'then create WebAssembly.Memory with `shared: true` option');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof SharedArrayBuffer === 'undefined') {
|
||||||
|
throw new Error('Current environment does not support SharedArrayBuffer, threads are not available!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getReuseWorker(value) {
|
||||||
|
var _a;
|
||||||
|
if (typeof value === 'boolean') {
|
||||||
|
return value ? { size: 0, strict: false } : false;
|
||||||
|
}
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
if (!(value >= 0)) {
|
||||||
|
throw new RangeError('reuseWorker: size must be a non-negative integer');
|
||||||
|
}
|
||||||
|
return { size: value, strict: false };
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var size = (_a = Number(value.size)) !== null && _a !== void 0 ? _a : 0;
|
||||||
|
var strict = Boolean(value.strict);
|
||||||
|
if (!(size > 0) && strict) {
|
||||||
|
throw new RangeError('reuseWorker: size must be set to positive integer if strict is set to true');
|
||||||
|
}
|
||||||
|
return { size: size, strict: strict };
|
||||||
|
}
|
||||||
|
var nextWorkerID = 0;
|
||||||
|
/** @public */
|
||||||
|
var ThreadManager = /*#__PURE__*/ (function () {
|
||||||
|
function ThreadManager(options) {
|
||||||
|
var _a;
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.wasmModule = null;
|
||||||
|
this.wasmMemory = null;
|
||||||
|
this.messageEvents = new WeakMap();
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('ThreadManager(): options is not provided');
|
||||||
|
}
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this._childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._childThread = false;
|
||||||
|
}
|
||||||
|
if (this._childThread) {
|
||||||
|
this._onCreateWorker = undefined;
|
||||||
|
this._reuseWorker = false;
|
||||||
|
this._beforeLoad = undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._onCreateWorker = options.onCreateWorker;
|
||||||
|
this._reuseWorker = getReuseWorker(options.reuseWorker);
|
||||||
|
this._beforeLoad = options.beforeLoad;
|
||||||
|
}
|
||||||
|
this.printErr = (_a = options.printErr) !== null && _a !== void 0 ? _a : console.error.bind(console);
|
||||||
|
this.threadSpawn = options.threadSpawn;
|
||||||
|
}
|
||||||
|
Object.defineProperty(ThreadManager.prototype, "nextWorkerID", {
|
||||||
|
get: function () { return nextWorkerID; },
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
ThreadManager.prototype.init = function () {
|
||||||
|
if (!this._childThread) {
|
||||||
|
this.initMainThread();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.initMainThread = function () {
|
||||||
|
this.preparePool();
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.preparePool = function () {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this._reuseWorker.size) {
|
||||||
|
var pthreadPoolSize = this._reuseWorker.size;
|
||||||
|
while (pthreadPoolSize--) {
|
||||||
|
var worker = this.allocateUnusedWorker();
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
// https://github.com/nodejs/node/issues/53036
|
||||||
|
worker.once('message', function () { });
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.shouldPreloadWorkers = function () {
|
||||||
|
return !this._childThread && this._reuseWorker && this._reuseWorker.size > 0;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.loadWasmModuleToAllWorkers = function () {
|
||||||
|
var _this_1 = this;
|
||||||
|
var promises = Array(this.unusedWorkers.length);
|
||||||
|
var _loop_1 = function (i) {
|
||||||
|
var worker = this_1.unusedWorkers[i];
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.ref();
|
||||||
|
promises[i] = this_1.loadWasmModuleToWorker(worker).then(function (w) {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
return w;
|
||||||
|
}, function (e) {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var this_1 = this;
|
||||||
|
for (var i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
_loop_1(i);
|
||||||
|
}
|
||||||
|
return Promise.all(promises).catch(function (err) {
|
||||||
|
_this_1.terminateAllThreads();
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.preloadWorkers = function () {
|
||||||
|
if (this.shouldPreloadWorkers()) {
|
||||||
|
return this.loadWasmModuleToAllWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.setup = function (wasmModule, wasmMemory) {
|
||||||
|
this.wasmModule = wasmModule;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.markId = function (worker) {
|
||||||
|
if (worker.__emnapi_tid)
|
||||||
|
return worker.__emnapi_tid;
|
||||||
|
var tid = nextWorkerID + 43;
|
||||||
|
nextWorkerID = (nextWorkerID + 1) % (WASI_THREADS_MAX_TID - 42);
|
||||||
|
this.pthreads[tid] = worker;
|
||||||
|
worker.__emnapi_tid = tid;
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.returnWorkerToPool = function (worker) {
|
||||||
|
var tid = worker.__emnapi_tid;
|
||||||
|
if (tid !== undefined) {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
}
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.loadWasmModuleToWorker = function (worker, sab) {
|
||||||
|
var _this_1 = this;
|
||||||
|
if (worker.whenLoaded)
|
||||||
|
return worker.whenLoaded;
|
||||||
|
var err = this.printErr;
|
||||||
|
var beforeLoad = this._beforeLoad;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
var _this = this;
|
||||||
|
worker.whenLoaded = new Promise(function (resolve, reject) {
|
||||||
|
var handleError = function (e) {
|
||||||
|
var message = 'worker sent an error!';
|
||||||
|
if (worker.__emnapi_tid !== undefined) {
|
||||||
|
message = 'worker (tid = ' + worker.__emnapi_tid + ') sent an error!';
|
||||||
|
}
|
||||||
|
if ('message' in e) {
|
||||||
|
err(message + ' ' + e.message);
|
||||||
|
if (e.message.indexOf('RuntimeError') !== -1 || e.message.indexOf('unreachable') !== -1) {
|
||||||
|
try {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err(message);
|
||||||
|
}
|
||||||
|
reject(e);
|
||||||
|
throw e;
|
||||||
|
};
|
||||||
|
var handleMessage = function (data) {
|
||||||
|
if (data.__emnapi__) {
|
||||||
|
var type = data.__emnapi__.type;
|
||||||
|
var payload = data.__emnapi__.payload;
|
||||||
|
if (type === 'loaded') {
|
||||||
|
worker.loaded = true;
|
||||||
|
if (ENVIRONMENT_IS_NODE && !worker.__emnapi_tid) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
resolve(worker);
|
||||||
|
// if (payload.err) {
|
||||||
|
// err('failed to load in child thread: ' + (payload.err.message || payload.err))
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
else if (type === 'cleanup-thread') {
|
||||||
|
if (payload.tid in _this_1.pthreads) {
|
||||||
|
_this_1.cleanThread(worker, payload.tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 'spawn-thread') {
|
||||||
|
_this_1.threadSpawn(payload.startArg, payload.errorOrTid);
|
||||||
|
}
|
||||||
|
else if (type === 'terminate-all-threads') {
|
||||||
|
_this_1.terminateAllThreads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.onmessage = function (e) {
|
||||||
|
handleMessage(e.data);
|
||||||
|
_this_1.fireMessageEvent(worker, e);
|
||||||
|
};
|
||||||
|
worker.onerror = handleError;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.on('message', function (data) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onmessage) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
worker.on('error', function (e) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
||||||
|
});
|
||||||
|
worker.on('detachedExit', function () { });
|
||||||
|
}
|
||||||
|
if (typeof beforeLoad === 'function') {
|
||||||
|
beforeLoad(worker);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
worker.postMessage(createMessage('load', {
|
||||||
|
wasmModule: _this_1.wasmModule,
|
||||||
|
wasmMemory: _this_1.wasmMemory,
|
||||||
|
sab: sab
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
checkSharedWasmMemory(_this_1.wasmMemory);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return worker.whenLoaded;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.allocateUnusedWorker = function () {
|
||||||
|
var _onCreateWorker = this._onCreateWorker;
|
||||||
|
if (typeof _onCreateWorker !== 'function') {
|
||||||
|
throw new TypeError('`options.onCreateWorker` is not provided');
|
||||||
|
}
|
||||||
|
var worker = _onCreateWorker({ type: 'thread', name: 'emnapi-pthread' });
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
return worker;
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.getNewWorker = function (sab) {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this.unusedWorkers.length === 0) {
|
||||||
|
if (this._reuseWorker.strict) {
|
||||||
|
if (!ENVIRONMENT_IS_NODE) {
|
||||||
|
var err = this.printErr;
|
||||||
|
err('Tried to spawn a new thread, but the thread pool is exhausted.\n' +
|
||||||
|
'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var worker_1 = this.allocateUnusedWorker();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
this.loadWasmModuleToWorker(worker_1, sab);
|
||||||
|
}
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
}
|
||||||
|
var worker = this.allocateUnusedWorker();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
this.loadWasmModuleToWorker(worker, sab);
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.cleanThread = function (worker, tid, force) {
|
||||||
|
if (!force && this._reuseWorker) {
|
||||||
|
this.returnWorkerToPool(worker);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
this.terminateWorker(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.terminateWorker = function (worker) {
|
||||||
|
var _this_1 = this;
|
||||||
|
var _a;
|
||||||
|
var tid = worker.__emnapi_tid;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
worker.terminate();
|
||||||
|
(_a = this.messageEvents.get(worker)) === null || _a === void 0 ? void 0 : _a.clear();
|
||||||
|
this.messageEvents.delete(worker);
|
||||||
|
worker.onmessage = function (e) {
|
||||||
|
if (e.data.__emnapi__) {
|
||||||
|
var err = _this_1.printErr;
|
||||||
|
err('received "' + e.data.__emnapi__.type + '" command from terminated worker: ' + tid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.terminateAllThreads = function () {
|
||||||
|
var runningWorkers = Object.values(this.pthreads);
|
||||||
|
for (var i = 0; i < runningWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(runningWorkers[i]);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(this.unusedWorkers[i]);
|
||||||
|
}
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.preparePool();
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.addMessageEventListener = function (worker, onMessage) {
|
||||||
|
var listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners) {
|
||||||
|
listeners = new Set();
|
||||||
|
this.messageEvents.set(worker, listeners);
|
||||||
|
}
|
||||||
|
listeners.add(onMessage);
|
||||||
|
return function () {
|
||||||
|
listeners === null || listeners === void 0 ? void 0 : listeners.delete(onMessage);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ThreadManager.prototype.fireMessageEvent = function (worker, e) {
|
||||||
|
var listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners)
|
||||||
|
return;
|
||||||
|
var err = this.printErr;
|
||||||
|
listeners.forEach(function (listener) {
|
||||||
|
try {
|
||||||
|
listener(e);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
err(e.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return ThreadManager;
|
||||||
|
}());
|
||||||
|
|
||||||
|
var kIsProxy = Symbol('kIsProxy');
|
||||||
|
/** @public */
|
||||||
|
function createInstanceProxy(instance, memory) {
|
||||||
|
if (instance[kIsProxy])
|
||||||
|
return instance;
|
||||||
|
// https://github.com/nodejs/help/issues/4102
|
||||||
|
var originalExports = instance.exports;
|
||||||
|
var createHandler = function (target) {
|
||||||
|
var handlers = [
|
||||||
|
'apply',
|
||||||
|
'construct',
|
||||||
|
'defineProperty',
|
||||||
|
'deleteProperty',
|
||||||
|
'get',
|
||||||
|
'getOwnPropertyDescriptor',
|
||||||
|
'getPrototypeOf',
|
||||||
|
'has',
|
||||||
|
'isExtensible',
|
||||||
|
'ownKeys',
|
||||||
|
'preventExtensions',
|
||||||
|
'set',
|
||||||
|
'setPrototypeOf'
|
||||||
|
];
|
||||||
|
var handler = {};
|
||||||
|
var _loop_1 = function (i) {
|
||||||
|
var name_1 = handlers[i];
|
||||||
|
handler[name_1] = function () {
|
||||||
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
args.unshift(target);
|
||||||
|
return Reflect[name_1].apply(Reflect, args);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for (var i = 0; i < handlers.length; i++) {
|
||||||
|
_loop_1(i);
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
};
|
||||||
|
var handler = createHandler(originalExports);
|
||||||
|
var _initialize = function () { };
|
||||||
|
var _start = function () { return 0; };
|
||||||
|
handler.get = function (_target, p, receiver) {
|
||||||
|
var _a;
|
||||||
|
if (p === 'memory') {
|
||||||
|
return (_a = (typeof memory === 'function' ? memory() : memory)) !== null && _a !== void 0 ? _a : Reflect.get(originalExports, p, receiver);
|
||||||
|
}
|
||||||
|
if (p === '_initialize') {
|
||||||
|
return p in originalExports ? _initialize : undefined;
|
||||||
|
}
|
||||||
|
if (p === '_start') {
|
||||||
|
return p in originalExports ? _start : undefined;
|
||||||
|
}
|
||||||
|
return Reflect.get(originalExports, p, receiver);
|
||||||
|
};
|
||||||
|
handler.has = function (_target, p) {
|
||||||
|
if (p === 'memory')
|
||||||
|
return true;
|
||||||
|
return Reflect.has(originalExports, p);
|
||||||
|
};
|
||||||
|
var exportsProxy = new Proxy(Object.create(null), handler);
|
||||||
|
return new Proxy(instance, {
|
||||||
|
get: function (target, p, receiver) {
|
||||||
|
if (p === 'exports') {
|
||||||
|
return exportsProxy;
|
||||||
|
}
|
||||||
|
if (p === kIsProxy) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Reflect.get(target, p, receiver);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var patchedWasiInstances = new WeakMap();
|
||||||
|
/** @public */
|
||||||
|
var WASIThreads = /*#__PURE__*/ (function () {
|
||||||
|
function WASIThreads(options) {
|
||||||
|
var _this_1 = this;
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('WASIThreads(): options is not provided');
|
||||||
|
}
|
||||||
|
if (!options.wasi) {
|
||||||
|
throw new TypeError('WASIThreads(): options.wasi is not provided');
|
||||||
|
}
|
||||||
|
patchedWasiInstances.set(this, new WeakSet());
|
||||||
|
var wasi = options.wasi;
|
||||||
|
patchWasiInstance(this, wasi);
|
||||||
|
this.wasi = wasi;
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this.childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.childThread = false;
|
||||||
|
}
|
||||||
|
this.PThread = undefined;
|
||||||
|
if ('threadManager' in options) {
|
||||||
|
if (typeof options.threadManager === 'function') {
|
||||||
|
this.PThread = options.threadManager();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.PThread = options.threadManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!this.childThread) {
|
||||||
|
this.PThread = new ThreadManager(options);
|
||||||
|
this.PThread.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var waitThreadStart = false;
|
||||||
|
if ('waitThreadStart' in options) {
|
||||||
|
waitThreadStart = typeof options.waitThreadStart === 'number' ? options.waitThreadStart : Boolean(options.waitThreadStart);
|
||||||
|
}
|
||||||
|
var postMessage = getPostMessage(options);
|
||||||
|
if (this.childThread && typeof postMessage !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMessage;
|
||||||
|
var wasm64 = Boolean(options.wasm64);
|
||||||
|
var threadSpawn = function (startArg, errorOrTid) {
|
||||||
|
var _a;
|
||||||
|
var EAGAIN = 6;
|
||||||
|
var isNewABI = errorOrTid !== undefined;
|
||||||
|
try {
|
||||||
|
checkSharedWasmMemory(_this_1.wasmMemory);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
(_a = _this_1.PThread) === null || _a === void 0 ? void 0 : _a.printErr(err.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
var struct_1 = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct_1, 0, 1);
|
||||||
|
Atomics.store(struct_1, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct_1, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isNewABI) {
|
||||||
|
var malloc = _this_1.wasmInstance.exports.malloc;
|
||||||
|
errorOrTid = wasm64 ? Number(malloc(BigInt(8))) : (malloc(8) >>> 0);
|
||||||
|
if (!errorOrTid) {
|
||||||
|
return -48; /* ENOMEM */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var _free = _this_1.wasmInstance.exports.free;
|
||||||
|
var free = wasm64 ? function (ptr) { _free(BigInt(ptr)); } : _free;
|
||||||
|
var struct = new Int32Array(_this_1.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, 0);
|
||||||
|
if (_this_1.childThread) {
|
||||||
|
postMessage(createMessage('spawn-thread', {
|
||||||
|
startArg: startArg,
|
||||||
|
errorOrTid: errorOrTid
|
||||||
|
}));
|
||||||
|
Atomics.wait(struct, 1, 0);
|
||||||
|
var isError = Atomics.load(struct, 0);
|
||||||
|
var result = Atomics.load(struct, 1);
|
||||||
|
if (isNewABI) {
|
||||||
|
return isError;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return isError ? -result : result;
|
||||||
|
}
|
||||||
|
var shouldWait = waitThreadStart || (waitThreadStart === 0);
|
||||||
|
var sab;
|
||||||
|
if (shouldWait) {
|
||||||
|
sab = new Int32Array(new SharedArrayBuffer(16 + 8192));
|
||||||
|
Atomics.store(sab, 0, 0);
|
||||||
|
}
|
||||||
|
var worker;
|
||||||
|
var tid;
|
||||||
|
var PThread = _this_1.PThread;
|
||||||
|
try {
|
||||||
|
worker = PThread.getNewWorker(sab);
|
||||||
|
if (!worker) {
|
||||||
|
throw new Error('failed to get new worker');
|
||||||
|
}
|
||||||
|
tid = PThread.markId(worker);
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
worker.postMessage(createMessage('start', {
|
||||||
|
tid: tid,
|
||||||
|
arg: startArg,
|
||||||
|
sab: sab
|
||||||
|
}));
|
||||||
|
if (shouldWait) {
|
||||||
|
if (typeof waitThreadStart === 'number') {
|
||||||
|
var waitResult = Atomics.wait(sab, 0, 0, waitThreadStart);
|
||||||
|
if (waitResult === 'timed-out') {
|
||||||
|
throw new Error('Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Atomics.wait(sab, 0, 0);
|
||||||
|
}
|
||||||
|
var r = Atomics.load(sab, 0);
|
||||||
|
if (r > 1) {
|
||||||
|
throw deserizeErrorFromBuffer(sab.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (worker !== undefined && tid !== undefined) {
|
||||||
|
try {
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 1);
|
||||||
|
Atomics.store(struct, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
PThread === null || PThread === void 0 ? void 0 : PThread.printErr(e.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, tid);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
if (!shouldWait) {
|
||||||
|
worker.whenLoaded.catch(function (err) {
|
||||||
|
delete worker.whenLoaded;
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isNewABI) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
this.threadSpawn = threadSpawn;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.threadSpawn = threadSpawn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WASIThreads.prototype.getImportObject = function () {
|
||||||
|
return {
|
||||||
|
wasi: {
|
||||||
|
'thread-spawn': this.threadSpawn
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
WASIThreads.prototype.setup = function (wasmInstance, wasmModule, wasmMemory) {
|
||||||
|
wasmMemory !== null && wasmMemory !== void 0 ? wasmMemory : (wasmMemory = wasmInstance.exports.memory);
|
||||||
|
this.wasmInstance = wasmInstance;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.setup(wasmModule, wasmMemory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
WASIThreads.prototype.preloadWorkers = function () {
|
||||||
|
if (this.PThread) {
|
||||||
|
return this.PThread.preloadWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
WASIThreads.prototype.initialize = function (instance, module, memory) {
|
||||||
|
var exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
var wasi = this.wasi;
|
||||||
|
if (('_start' in exports) && (typeof exports._start === 'function')) {
|
||||||
|
if (this.childThread) {
|
||||||
|
wasi.start(instance);
|
||||||
|
try {
|
||||||
|
var kStarted = getWasiSymbol(wasi, 'kStarted');
|
||||||
|
wasi[kStarted] = false;
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setupInstance(wasi, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wasi.initialize(instance);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
WASIThreads.prototype.start = function (instance, module, memory) {
|
||||||
|
var exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
var exitCode = this.wasi.start(instance);
|
||||||
|
return { exitCode: exitCode, instance: instance };
|
||||||
|
};
|
||||||
|
WASIThreads.prototype.terminateAllThreads = function () {
|
||||||
|
var _a;
|
||||||
|
if (!this.childThread) {
|
||||||
|
(_a = this.PThread) === null || _a === void 0 ? void 0 : _a.terminateAllThreads();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.postMessage(createMessage('terminate-all-threads', {}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return WASIThreads;
|
||||||
|
}());
|
||||||
|
function patchWasiInstance(wasiThreads, wasi) {
|
||||||
|
var patched = patchedWasiInstances.get(wasiThreads);
|
||||||
|
if (patched.has(wasi)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var _this = wasiThreads;
|
||||||
|
var wasiImport = wasi.wasiImport;
|
||||||
|
if (wasiImport) {
|
||||||
|
var proc_exit_1 = wasiImport.proc_exit;
|
||||||
|
wasiImport.proc_exit = function (code) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
return proc_exit_1.call(this, code);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!_this.childThread) {
|
||||||
|
var start_1 = wasi.start;
|
||||||
|
if (typeof start_1 === 'function') {
|
||||||
|
wasi.start = function (instance) {
|
||||||
|
try {
|
||||||
|
return start_1.call(this, instance);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (isTrapError(err)) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patched.add(wasi);
|
||||||
|
}
|
||||||
|
function getWasiSymbol(wasi, description) {
|
||||||
|
var symbols = Object.getOwnPropertySymbols(wasi);
|
||||||
|
var selectDescription = function (description) { return function (s) {
|
||||||
|
if (s.description) {
|
||||||
|
return s.description === description;
|
||||||
|
}
|
||||||
|
return s.toString() === "Symbol(".concat(description, ")");
|
||||||
|
}; };
|
||||||
|
if (Array.isArray(description)) {
|
||||||
|
return description.map(function (d) { return symbols.filter(selectDescription(d))[0]; });
|
||||||
|
}
|
||||||
|
return symbols.filter(selectDescription(description))[0];
|
||||||
|
}
|
||||||
|
function setupInstance(wasi, instance) {
|
||||||
|
var _a = getWasiSymbol(wasi, ['kInstance', 'kSetMemory']), kInstance = _a[0], kSetMemory = _a[1];
|
||||||
|
wasi[kInstance] = instance;
|
||||||
|
wasi[kSetMemory](instance.exports.memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
var ThreadMessageHandler = /*#__PURE__*/ (function () {
|
||||||
|
function ThreadMessageHandler(options) {
|
||||||
|
var postMsg = getPostMessage(options);
|
||||||
|
if (typeof postMsg !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMsg;
|
||||||
|
this.onLoad = options === null || options === void 0 ? void 0 : options.onLoad;
|
||||||
|
this.onError = typeof (options === null || options === void 0 ? void 0 : options.onError) === 'function' ? options.onError : function (_type, err) { throw err; };
|
||||||
|
this.instance = undefined;
|
||||||
|
// this.module = undefined
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
}
|
||||||
|
/** @virtual */
|
||||||
|
ThreadMessageHandler.prototype.instantiate = function (data) {
|
||||||
|
if (typeof this.onLoad === 'function') {
|
||||||
|
return this.onLoad(data);
|
||||||
|
}
|
||||||
|
throw new Error('ThreadMessageHandler.prototype.instantiate is not implemented');
|
||||||
|
};
|
||||||
|
/** @virtual */
|
||||||
|
ThreadMessageHandler.prototype.handle = function (e) {
|
||||||
|
var _this = this;
|
||||||
|
var _a;
|
||||||
|
if ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.__emnapi__) {
|
||||||
|
var type = e.data.__emnapi__.type;
|
||||||
|
var payload_1 = e.data.__emnapi__.payload;
|
||||||
|
try {
|
||||||
|
if (type === 'load') {
|
||||||
|
this._load(payload_1);
|
||||||
|
}
|
||||||
|
else if (type === 'start') {
|
||||||
|
this.handleAfterLoad(e, function () {
|
||||||
|
_this._start(payload_1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.onError(err, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype._load = function (payload) {
|
||||||
|
var _this = this;
|
||||||
|
if (this.instance !== undefined)
|
||||||
|
return;
|
||||||
|
var source;
|
||||||
|
try {
|
||||||
|
source = this.instantiate(payload);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this._loaded(err, null, payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var then = source && 'then' in source ? source.then : undefined;
|
||||||
|
if (typeof then === 'function') {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
then.call(source, function (source) { _this._loaded(null, source, payload); }, function (err) { _this._loaded(err, null, payload); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._loaded(null, source, payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype._start = function (payload) {
|
||||||
|
var wasi_thread_start = this.instance.exports.wasi_thread_start;
|
||||||
|
if (typeof wasi_thread_start !== 'function') {
|
||||||
|
var err = new TypeError('wasi_thread_start is not exported');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
var postMessage = this.postMessage;
|
||||||
|
var tid = payload.tid;
|
||||||
|
var startArg = payload.arg;
|
||||||
|
notifyPthreadCreateResult(payload.sab, 1);
|
||||||
|
try {
|
||||||
|
wasi_thread_start(tid, startArg);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err !== 'unwind') {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postMessage(createMessage('cleanup-thread', { tid: tid }));
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype._loaded = function (err, source, payload) {
|
||||||
|
if (err) {
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
if (source == null) {
|
||||||
|
var err_1 = new TypeError('onLoad should return an object');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err_1);
|
||||||
|
throw err_1;
|
||||||
|
}
|
||||||
|
var instance = source.instance;
|
||||||
|
if (!instance) {
|
||||||
|
var err_2 = new TypeError('onLoad should return an object which includes "instance"');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err_2);
|
||||||
|
throw err_2;
|
||||||
|
}
|
||||||
|
this.instance = instance;
|
||||||
|
var postMessage = this.postMessage;
|
||||||
|
postMessage(createMessage('loaded', {}));
|
||||||
|
var messages = this.messagesBeforeLoad;
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
var data = messages[i];
|
||||||
|
this.handle({ data: data });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ThreadMessageHandler.prototype.handleAfterLoad = function (e, f) {
|
||||||
|
if (this.instance !== undefined) {
|
||||||
|
f.call(this, e);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.messagesBeforeLoad.push(e.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return ThreadMessageHandler;
|
||||||
|
}());
|
||||||
|
function notifyPthreadCreateResult(sab, result, error) {
|
||||||
|
if (sab) {
|
||||||
|
serizeErrorToBuffer(sab.buffer, result, error);
|
||||||
|
Atomics.notify(sab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.ThreadManager = ThreadManager;
|
||||||
|
exports.ThreadMessageHandler = ThreadMessageHandler;
|
||||||
|
exports.WASIThreads = WASIThreads;
|
||||||
|
exports.createInstanceProxy = createInstanceProxy;
|
||||||
|
exports.isSharedArrayBuffer = isSharedArrayBuffer;
|
||||||
|
exports.isTrapError = isTrapError;
|
||||||
|
|
||||||
|
}));
|
||||||
Generated
Vendored
+271
@@ -0,0 +1,271 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import type { Worker as Worker_2 } from 'worker_threads';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseOptions {
|
||||||
|
wasi: WASIInstance;
|
||||||
|
version?: 'preview1';
|
||||||
|
wasm64?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ChildThreadOptions extends BaseOptions {
|
||||||
|
childThread: true;
|
||||||
|
postMessage?: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CleanupThreadPayload {
|
||||||
|
tid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandInfo<T extends CommandType> {
|
||||||
|
type: T;
|
||||||
|
payload: CommandPayloadMap[T];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface CommandPayloadMap {
|
||||||
|
load: LoadPayload;
|
||||||
|
loaded: LoadedPayload;
|
||||||
|
start: StartPayload;
|
||||||
|
'cleanup-thread': CleanupThreadPayload;
|
||||||
|
'terminate-all-threads': TerminateAllThreadsPayload;
|
||||||
|
'spawn-thread': SpawnThreadPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type CommandType = keyof CommandPayloadMap;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createInstanceProxy(instance: WebAssembly.Instance, memory?: WebAssembly.Memory | (() => WebAssembly.Memory)): WebAssembly.Instance;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isSharedArrayBuffer(value: any): value is SharedArrayBuffer;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function isTrapError(e: Error): e is WebAssembly.RuntimeError;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadedPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface LoadPayload {
|
||||||
|
wasmModule: WebAssembly.Module;
|
||||||
|
wasmMemory: WebAssembly.Memory;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadBaseOptions extends BaseOptions {
|
||||||
|
waitThreadStart?: boolean | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type MainThreadOptions = MainThreadOptionsWithThreadManager | MainThreadOptionsCreateThreadManager;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsCreateThreadManager extends MainThreadBaseOptions, ThreadManagerOptionsMain {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MainThreadOptionsWithThreadManager extends MainThreadBaseOptions {
|
||||||
|
threadManager?: ThreadManager | (() => ThreadManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MessageEventData<T extends CommandType> {
|
||||||
|
__emnapi__: CommandInfo<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReuseWorkerOptions {
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size | PTHREAD_POOL_SIZE}
|
||||||
|
*/
|
||||||
|
size: number;
|
||||||
|
/**
|
||||||
|
* @see {@link https://emscripten.org/docs/tools_reference/settings_reference.html#pthread-pool-size-strict | PTHREAD_POOL_SIZE_STRICT}
|
||||||
|
*/
|
||||||
|
strict?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SpawnThreadPayload {
|
||||||
|
startArg: number;
|
||||||
|
errorOrTid: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartPayload {
|
||||||
|
tid: number;
|
||||||
|
arg: number;
|
||||||
|
sab?: Int32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StartResult {
|
||||||
|
exitCode: number;
|
||||||
|
instance: WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface TerminateAllThreadsPayload {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadManager {
|
||||||
|
unusedWorkers: WorkerLike[];
|
||||||
|
pthreads: Record<number, WorkerLike>;
|
||||||
|
get nextWorkerID(): number;
|
||||||
|
wasmModule: WebAssembly.Module | null;
|
||||||
|
wasmMemory: WebAssembly.Memory | null;
|
||||||
|
private readonly messageEvents;
|
||||||
|
private readonly _childThread;
|
||||||
|
private readonly _onCreateWorker;
|
||||||
|
private readonly _reuseWorker;
|
||||||
|
private readonly _beforeLoad?;
|
||||||
|
/* Excluded from this release type: printErr */
|
||||||
|
threadSpawn?: ((startArg: number, errorOrTid?: number) => number);
|
||||||
|
constructor(options: ThreadManagerOptions);
|
||||||
|
init(): void;
|
||||||
|
initMainThread(): void;
|
||||||
|
private preparePool;
|
||||||
|
shouldPreloadWorkers(): boolean;
|
||||||
|
loadWasmModuleToAllWorkers(): Promise<WorkerLike[]>;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
setup(wasmModule: WebAssembly.Module, wasmMemory: WebAssembly.Memory): void;
|
||||||
|
markId(worker: WorkerLike): number;
|
||||||
|
returnWorkerToPool(worker: WorkerLike): void;
|
||||||
|
loadWasmModuleToWorker(worker: WorkerLike, sab?: Int32Array): Promise<WorkerLike>;
|
||||||
|
allocateUnusedWorker(): WorkerLike;
|
||||||
|
getNewWorker(sab?: Int32Array): WorkerLike | undefined;
|
||||||
|
cleanThread(worker: WorkerLike, tid: number, force?: boolean): void;
|
||||||
|
terminateWorker(worker: WorkerLike): void;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
addMessageEventListener(worker: WorkerLike, onMessage: (e: WorkerMessageEvent) => void): () => void;
|
||||||
|
fireMessageEvent(worker: WorkerLike, e: WorkerMessageEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ThreadManagerOptions = ThreadManagerOptionsMain | ThreadManagerOptionsChild;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsBase {
|
||||||
|
printErr?: (message: string) => void;
|
||||||
|
threadSpawn?: (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsChild extends ThreadManagerOptionsBase {
|
||||||
|
childThread: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadManagerOptionsMain extends ThreadManagerOptionsBase {
|
||||||
|
beforeLoad?: (worker: WorkerLike) => any;
|
||||||
|
reuseWorker?: boolean | number | ReuseWorkerOptions;
|
||||||
|
onCreateWorker: WorkerFactory;
|
||||||
|
childThread?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ThreadMessageHandler {
|
||||||
|
protected instance: WebAssembly.Instance | undefined;
|
||||||
|
private messagesBeforeLoad;
|
||||||
|
protected postMessage: (message: any) => void;
|
||||||
|
protected onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
protected onError: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
constructor(options?: ThreadMessageHandlerOptions);
|
||||||
|
/** @virtual */
|
||||||
|
instantiate(data: LoadPayload): WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
/** @virtual */
|
||||||
|
handle(e: WorkerMessageEvent<MessageEventData<WorkerMessageType>>): void;
|
||||||
|
private _load;
|
||||||
|
private _start;
|
||||||
|
protected _loaded(err: Error | null, source: WebAssembly.WebAssemblyInstantiatedSource | null, payload: LoadPayload): void;
|
||||||
|
protected handleAfterLoad<E extends WorkerMessageEvent>(e: E, f: (e: E) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ThreadMessageHandlerOptions {
|
||||||
|
onLoad?: (data: LoadPayload) => WebAssembly.WebAssemblyInstantiatedSource | PromiseLike<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
onError?: (error: Error, type: WorkerMessageType) => void;
|
||||||
|
postMessage?: (message: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIInstance {
|
||||||
|
readonly wasiImport?: Record<string, any>;
|
||||||
|
initialize(instance: object): void;
|
||||||
|
start(instance: object): number;
|
||||||
|
getImportObject?(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASIThreads {
|
||||||
|
PThread: ThreadManager | undefined;
|
||||||
|
private wasmMemory;
|
||||||
|
private wasmInstance;
|
||||||
|
private readonly threadSpawn;
|
||||||
|
readonly childThread: boolean;
|
||||||
|
private readonly postMessage;
|
||||||
|
readonly wasi: WASIInstance;
|
||||||
|
constructor(options: WASIThreadsOptions);
|
||||||
|
getImportObject(): {
|
||||||
|
wasi: WASIThreadsImports;
|
||||||
|
};
|
||||||
|
setup(wasmInstance: WebAssembly.Instance, wasmModule: WebAssembly.Module, wasmMemory?: WebAssembly.Memory): void;
|
||||||
|
preloadWorkers(): Promise<WorkerLike[]>;
|
||||||
|
/**
|
||||||
|
* It's ok to call this method to a WASI command module.
|
||||||
|
*
|
||||||
|
* in child thread, must call this method instead of {@link WASIThreads.start} even if it's a WASI command module
|
||||||
|
*
|
||||||
|
* @returns A proxied WebAssembly instance if in child thread, other wise the original instance
|
||||||
|
*/
|
||||||
|
initialize(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): WebAssembly.Instance;
|
||||||
|
/**
|
||||||
|
* Equivalent to calling {@link WASIThreads.initialize} and then calling {@link WASIInstance.start}
|
||||||
|
* ```js
|
||||||
|
* this.initialize(instance, module, memory)
|
||||||
|
* this.wasi.start(instance)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
start(instance: WebAssembly.Instance, module: WebAssembly.Module, memory?: WebAssembly.Memory): StartResult;
|
||||||
|
terminateAllThreads(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIThreadsImports {
|
||||||
|
'thread-spawn': (startArg: number, errorOrTid?: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WASIThreadsOptions = MainThreadOptions | ChildThreadOptions;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerFactory = (ctx: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
}) => WorkerLike;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerLike = (Worker | Worker_2) & {
|
||||||
|
whenLoaded?: Promise<WorkerLike>;
|
||||||
|
loaded?: boolean;
|
||||||
|
__emnapi_tid?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WorkerMessageEvent<T = any> {
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type WorkerMessageType = 'load' | 'start';
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+880
@@ -0,0 +1,880 @@
|
|||||||
|
const _WebAssembly = typeof WebAssembly !== 'undefined'
|
||||||
|
? WebAssembly
|
||||||
|
: typeof WXWebAssembly !== 'undefined'
|
||||||
|
? WXWebAssembly
|
||||||
|
: undefined;
|
||||||
|
const ENVIRONMENT_IS_NODE = typeof process === 'object' && process !== null &&
|
||||||
|
typeof process.versions === 'object' && process.versions !== null &&
|
||||||
|
typeof process.versions.node === 'string';
|
||||||
|
function getPostMessage(options) {
|
||||||
|
return typeof (options === null || options === void 0 ? void 0 : options.postMessage) === 'function'
|
||||||
|
? options.postMessage
|
||||||
|
: typeof postMessage === 'function'
|
||||||
|
? postMessage
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
function serizeErrorToBuffer(sab, code, error) {
|
||||||
|
const i32array = new Int32Array(sab);
|
||||||
|
Atomics.store(i32array, 0, code);
|
||||||
|
if (code > 1 && error) {
|
||||||
|
const name = error.name;
|
||||||
|
const message = error.message;
|
||||||
|
const stack = error.stack;
|
||||||
|
const nameBuffer = new TextEncoder().encode(name);
|
||||||
|
const messageBuffer = new TextEncoder().encode(message);
|
||||||
|
const stackBuffer = new TextEncoder().encode(stack);
|
||||||
|
Atomics.store(i32array, 1, nameBuffer.length);
|
||||||
|
Atomics.store(i32array, 2, messageBuffer.length);
|
||||||
|
Atomics.store(i32array, 3, stackBuffer.length);
|
||||||
|
const buffer = new Uint8Array(sab);
|
||||||
|
buffer.set(nameBuffer, 16);
|
||||||
|
buffer.set(messageBuffer, 16 + nameBuffer.length);
|
||||||
|
buffer.set(stackBuffer, 16 + nameBuffer.length + messageBuffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function deserizeErrorFromBuffer(sab) {
|
||||||
|
var _a, _b;
|
||||||
|
const i32array = new Int32Array(sab);
|
||||||
|
const status = Atomics.load(i32array, 0);
|
||||||
|
if (status <= 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const nameLength = Atomics.load(i32array, 1);
|
||||||
|
const messageLength = Atomics.load(i32array, 2);
|
||||||
|
const stackLength = Atomics.load(i32array, 3);
|
||||||
|
const buffer = new Uint8Array(sab);
|
||||||
|
const nameBuffer = buffer.slice(16, 16 + nameLength);
|
||||||
|
const messageBuffer = buffer.slice(16 + nameLength, 16 + nameLength + messageLength);
|
||||||
|
const stackBuffer = buffer.slice(16 + nameLength + messageLength, 16 + nameLength + messageLength + stackLength);
|
||||||
|
const name = new TextDecoder().decode(nameBuffer);
|
||||||
|
const message = new TextDecoder().decode(messageBuffer);
|
||||||
|
const stack = new TextDecoder().decode(stackBuffer);
|
||||||
|
const ErrorConstructor = (_a = globalThis[name]) !== null && _a !== void 0 ? _a : (name === 'RuntimeError' ? ((_b = _WebAssembly.RuntimeError) !== null && _b !== void 0 ? _b : Error) : Error);
|
||||||
|
const error = new ErrorConstructor(message);
|
||||||
|
Object.defineProperty(error, 'stack', {
|
||||||
|
value: stack,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
function isSharedArrayBuffer(value) {
|
||||||
|
return ((typeof SharedArrayBuffer === 'function' && value instanceof SharedArrayBuffer) ||
|
||||||
|
(Object.prototype.toString.call(value) === '[object SharedArrayBuffer]'));
|
||||||
|
}
|
||||||
|
function isTrapError(e) {
|
||||||
|
try {
|
||||||
|
return e instanceof _WebAssembly.RuntimeError;
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMessage(type, payload) {
|
||||||
|
return {
|
||||||
|
__emnapi__: {
|
||||||
|
type,
|
||||||
|
payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const WASI_THREADS_MAX_TID = 0x1FFFFFFF;
|
||||||
|
function checkSharedWasmMemory(wasmMemory) {
|
||||||
|
if (wasmMemory) {
|
||||||
|
if (!isSharedArrayBuffer(wasmMemory.buffer)) {
|
||||||
|
throw new Error('Multithread features require shared wasm memory. ' +
|
||||||
|
'Try to compile with `-matomics -mbulk-memory` and use `--import-memory --shared-memory` during linking, ' +
|
||||||
|
'then create WebAssembly.Memory with `shared: true` option');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof SharedArrayBuffer === 'undefined') {
|
||||||
|
throw new Error('Current environment does not support SharedArrayBuffer, threads are not available!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getReuseWorker(value) {
|
||||||
|
var _a;
|
||||||
|
if (typeof value === 'boolean') {
|
||||||
|
return value ? { size: 0, strict: false } : false;
|
||||||
|
}
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
if (!(value >= 0)) {
|
||||||
|
throw new RangeError('reuseWorker: size must be a non-negative integer');
|
||||||
|
}
|
||||||
|
return { size: value, strict: false };
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size = (_a = Number(value.size)) !== null && _a !== void 0 ? _a : 0;
|
||||||
|
const strict = Boolean(value.strict);
|
||||||
|
if (!(size > 0) && strict) {
|
||||||
|
throw new RangeError('reuseWorker: size must be set to positive integer if strict is set to true');
|
||||||
|
}
|
||||||
|
return { size, strict };
|
||||||
|
}
|
||||||
|
let nextWorkerID = 0;
|
||||||
|
class ThreadManager {
|
||||||
|
get nextWorkerID() { return nextWorkerID; }
|
||||||
|
constructor(options) {
|
||||||
|
var _a;
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.wasmModule = null;
|
||||||
|
this.wasmMemory = null;
|
||||||
|
this.messageEvents = new WeakMap();
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('ThreadManager(): options is not provided');
|
||||||
|
}
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this._childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._childThread = false;
|
||||||
|
}
|
||||||
|
if (this._childThread) {
|
||||||
|
this._onCreateWorker = undefined;
|
||||||
|
this._reuseWorker = false;
|
||||||
|
this._beforeLoad = undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._onCreateWorker = options.onCreateWorker;
|
||||||
|
this._reuseWorker = getReuseWorker(options.reuseWorker);
|
||||||
|
this._beforeLoad = options.beforeLoad;
|
||||||
|
}
|
||||||
|
this.printErr = (_a = options.printErr) !== null && _a !== void 0 ? _a : console.error.bind(console);
|
||||||
|
this.threadSpawn = options.threadSpawn;
|
||||||
|
}
|
||||||
|
init() {
|
||||||
|
if (!this._childThread) {
|
||||||
|
this.initMainThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initMainThread() {
|
||||||
|
this.preparePool();
|
||||||
|
}
|
||||||
|
preparePool() {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this._reuseWorker.size) {
|
||||||
|
let pthreadPoolSize = this._reuseWorker.size;
|
||||||
|
while (pthreadPoolSize--) {
|
||||||
|
const worker = this.allocateUnusedWorker();
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.once('message', () => { });
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shouldPreloadWorkers() {
|
||||||
|
return !this._childThread && this._reuseWorker && this._reuseWorker.size > 0;
|
||||||
|
}
|
||||||
|
loadWasmModuleToAllWorkers() {
|
||||||
|
const promises = Array(this.unusedWorkers.length);
|
||||||
|
for (let i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
const worker = this.unusedWorkers[i];
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.ref();
|
||||||
|
promises[i] = this.loadWasmModuleToWorker(worker).then((w) => {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
return w;
|
||||||
|
}, (e) => {
|
||||||
|
if (ENVIRONMENT_IS_NODE)
|
||||||
|
worker.unref();
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.all(promises).catch((err) => {
|
||||||
|
this.terminateAllThreads();
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
preloadWorkers() {
|
||||||
|
if (this.shouldPreloadWorkers()) {
|
||||||
|
return this.loadWasmModuleToAllWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
setup(wasmModule, wasmMemory) {
|
||||||
|
this.wasmModule = wasmModule;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
}
|
||||||
|
markId(worker) {
|
||||||
|
if (worker.__emnapi_tid)
|
||||||
|
return worker.__emnapi_tid;
|
||||||
|
const tid = nextWorkerID + 43;
|
||||||
|
nextWorkerID = (nextWorkerID + 1) % (WASI_THREADS_MAX_TID - 42);
|
||||||
|
this.pthreads[tid] = worker;
|
||||||
|
worker.__emnapi_tid = tid;
|
||||||
|
return tid;
|
||||||
|
}
|
||||||
|
returnWorkerToPool(worker) {
|
||||||
|
var tid = worker.__emnapi_tid;
|
||||||
|
if (tid !== undefined) {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
}
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadWasmModuleToWorker(worker, sab) {
|
||||||
|
if (worker.whenLoaded)
|
||||||
|
return worker.whenLoaded;
|
||||||
|
const err = this.printErr;
|
||||||
|
const beforeLoad = this._beforeLoad;
|
||||||
|
const _this = this;
|
||||||
|
worker.whenLoaded = new Promise((resolve, reject) => {
|
||||||
|
const handleError = function (e) {
|
||||||
|
let message = 'worker sent an error!';
|
||||||
|
if (worker.__emnapi_tid !== undefined) {
|
||||||
|
message = 'worker (tid = ' + worker.__emnapi_tid + ') sent an error!';
|
||||||
|
}
|
||||||
|
if ('message' in e) {
|
||||||
|
err(message + ' ' + e.message);
|
||||||
|
if (e.message.indexOf('RuntimeError') !== -1 || e.message.indexOf('unreachable') !== -1) {
|
||||||
|
try {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err(message);
|
||||||
|
}
|
||||||
|
reject(e);
|
||||||
|
throw e;
|
||||||
|
};
|
||||||
|
const handleMessage = (data) => {
|
||||||
|
if (data.__emnapi__) {
|
||||||
|
const type = data.__emnapi__.type;
|
||||||
|
const payload = data.__emnapi__.payload;
|
||||||
|
if (type === 'loaded') {
|
||||||
|
worker.loaded = true;
|
||||||
|
if (ENVIRONMENT_IS_NODE && !worker.__emnapi_tid) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
resolve(worker);
|
||||||
|
}
|
||||||
|
else if (type === 'cleanup-thread') {
|
||||||
|
if (payload.tid in this.pthreads) {
|
||||||
|
this.cleanThread(worker, payload.tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 'spawn-thread') {
|
||||||
|
this.threadSpawn(payload.startArg, payload.errorOrTid);
|
||||||
|
}
|
||||||
|
else if (type === 'terminate-all-threads') {
|
||||||
|
this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.onmessage = (e) => {
|
||||||
|
handleMessage(e.data);
|
||||||
|
this.fireMessageEvent(worker, e);
|
||||||
|
};
|
||||||
|
worker.onerror = handleError;
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.on('message', function (data) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onmessage) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
worker.on('error', function (e) {
|
||||||
|
var _a, _b;
|
||||||
|
(_b = (_a = worker).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
||||||
|
});
|
||||||
|
worker.on('detachedExit', function () { });
|
||||||
|
}
|
||||||
|
if (typeof beforeLoad === 'function') {
|
||||||
|
beforeLoad(worker);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
worker.postMessage(createMessage('load', {
|
||||||
|
wasmModule: this.wasmModule,
|
||||||
|
wasmMemory: this.wasmMemory,
|
||||||
|
sab
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
checkSharedWasmMemory(this.wasmMemory);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return worker.whenLoaded;
|
||||||
|
}
|
||||||
|
allocateUnusedWorker() {
|
||||||
|
const _onCreateWorker = this._onCreateWorker;
|
||||||
|
if (typeof _onCreateWorker !== 'function') {
|
||||||
|
throw new TypeError('`options.onCreateWorker` is not provided');
|
||||||
|
}
|
||||||
|
const worker = _onCreateWorker({ type: 'thread', name: 'emnapi-pthread' });
|
||||||
|
this.unusedWorkers.push(worker);
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
getNewWorker(sab) {
|
||||||
|
if (this._reuseWorker) {
|
||||||
|
if (this.unusedWorkers.length === 0) {
|
||||||
|
if (this._reuseWorker.strict) {
|
||||||
|
if (!ENVIRONMENT_IS_NODE) {
|
||||||
|
const err = this.printErr;
|
||||||
|
err('Tried to spawn a new thread, but the thread pool is exhausted.\n' +
|
||||||
|
'This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const worker = this.allocateUnusedWorker();
|
||||||
|
this.loadWasmModuleToWorker(worker, sab);
|
||||||
|
}
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
}
|
||||||
|
const worker = this.allocateUnusedWorker();
|
||||||
|
this.loadWasmModuleToWorker(worker, sab);
|
||||||
|
return this.unusedWorkers.pop();
|
||||||
|
}
|
||||||
|
cleanThread(worker, tid, force) {
|
||||||
|
if (!force && this._reuseWorker) {
|
||||||
|
this.returnWorkerToPool(worker);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete this.pthreads[tid];
|
||||||
|
this.terminateWorker(worker);
|
||||||
|
delete worker.__emnapi_tid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminateWorker(worker) {
|
||||||
|
var _a;
|
||||||
|
const tid = worker.__emnapi_tid;
|
||||||
|
worker.terminate();
|
||||||
|
(_a = this.messageEvents.get(worker)) === null || _a === void 0 ? void 0 : _a.clear();
|
||||||
|
this.messageEvents.delete(worker);
|
||||||
|
worker.onmessage = (e) => {
|
||||||
|
if (e.data.__emnapi__) {
|
||||||
|
const err = this.printErr;
|
||||||
|
err('received "' + e.data.__emnapi__.type + '" command from terminated worker: ' + tid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
terminateAllThreads() {
|
||||||
|
const runningWorkers = Object.values(this.pthreads);
|
||||||
|
for (let i = 0; i < runningWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(runningWorkers[i]);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this.unusedWorkers.length; ++i) {
|
||||||
|
this.terminateWorker(this.unusedWorkers[i]);
|
||||||
|
}
|
||||||
|
this.unusedWorkers = [];
|
||||||
|
this.pthreads = Object.create(null);
|
||||||
|
this.preparePool();
|
||||||
|
}
|
||||||
|
addMessageEventListener(worker, onMessage) {
|
||||||
|
let listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners) {
|
||||||
|
listeners = new Set();
|
||||||
|
this.messageEvents.set(worker, listeners);
|
||||||
|
}
|
||||||
|
listeners.add(onMessage);
|
||||||
|
return () => {
|
||||||
|
listeners === null || listeners === void 0 ? void 0 : listeners.delete(onMessage);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fireMessageEvent(worker, e) {
|
||||||
|
const listeners = this.messageEvents.get(worker);
|
||||||
|
if (!listeners)
|
||||||
|
return;
|
||||||
|
const err = this.printErr;
|
||||||
|
listeners.forEach((listener) => {
|
||||||
|
try {
|
||||||
|
listener(e);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
err(e.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const kIsProxy = Symbol('kIsProxy');
|
||||||
|
function createInstanceProxy(instance, memory) {
|
||||||
|
if (instance[kIsProxy])
|
||||||
|
return instance;
|
||||||
|
const originalExports = instance.exports;
|
||||||
|
const createHandler = function (target) {
|
||||||
|
const handlers = [
|
||||||
|
'apply',
|
||||||
|
'construct',
|
||||||
|
'defineProperty',
|
||||||
|
'deleteProperty',
|
||||||
|
'get',
|
||||||
|
'getOwnPropertyDescriptor',
|
||||||
|
'getPrototypeOf',
|
||||||
|
'has',
|
||||||
|
'isExtensible',
|
||||||
|
'ownKeys',
|
||||||
|
'preventExtensions',
|
||||||
|
'set',
|
||||||
|
'setPrototypeOf'
|
||||||
|
];
|
||||||
|
const handler = {};
|
||||||
|
for (let i = 0; i < handlers.length; i++) {
|
||||||
|
const name = handlers[i];
|
||||||
|
handler[name] = function () {
|
||||||
|
const args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
args.unshift(target);
|
||||||
|
return Reflect[name].apply(Reflect, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
};
|
||||||
|
const handler = createHandler(originalExports);
|
||||||
|
const _initialize = () => { };
|
||||||
|
const _start = () => 0;
|
||||||
|
handler.get = function (_target, p, receiver) {
|
||||||
|
var _a;
|
||||||
|
if (p === 'memory') {
|
||||||
|
return (_a = (typeof memory === 'function' ? memory() : memory)) !== null && _a !== void 0 ? _a : Reflect.get(originalExports, p, receiver);
|
||||||
|
}
|
||||||
|
if (p === '_initialize') {
|
||||||
|
return p in originalExports ? _initialize : undefined;
|
||||||
|
}
|
||||||
|
if (p === '_start') {
|
||||||
|
return p in originalExports ? _start : undefined;
|
||||||
|
}
|
||||||
|
return Reflect.get(originalExports, p, receiver);
|
||||||
|
};
|
||||||
|
handler.has = function (_target, p) {
|
||||||
|
if (p === 'memory')
|
||||||
|
return true;
|
||||||
|
return Reflect.has(originalExports, p);
|
||||||
|
};
|
||||||
|
const exportsProxy = new Proxy(Object.create(null), handler);
|
||||||
|
return new Proxy(instance, {
|
||||||
|
get(target, p, receiver) {
|
||||||
|
if (p === 'exports') {
|
||||||
|
return exportsProxy;
|
||||||
|
}
|
||||||
|
if (p === kIsProxy) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Reflect.get(target, p, receiver);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const patchedWasiInstances = new WeakMap();
|
||||||
|
class WASIThreads {
|
||||||
|
constructor(options) {
|
||||||
|
if (!options) {
|
||||||
|
throw new TypeError('WASIThreads(): options is not provided');
|
||||||
|
}
|
||||||
|
if (!options.wasi) {
|
||||||
|
throw new TypeError('WASIThreads(): options.wasi is not provided');
|
||||||
|
}
|
||||||
|
patchedWasiInstances.set(this, new WeakSet());
|
||||||
|
const wasi = options.wasi;
|
||||||
|
patchWasiInstance(this, wasi);
|
||||||
|
this.wasi = wasi;
|
||||||
|
if ('childThread' in options) {
|
||||||
|
this.childThread = Boolean(options.childThread);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.childThread = false;
|
||||||
|
}
|
||||||
|
this.PThread = undefined;
|
||||||
|
if ('threadManager' in options) {
|
||||||
|
if (typeof options.threadManager === 'function') {
|
||||||
|
this.PThread = options.threadManager();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.PThread = options.threadManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!this.childThread) {
|
||||||
|
this.PThread = new ThreadManager(options);
|
||||||
|
this.PThread.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let waitThreadStart = false;
|
||||||
|
if ('waitThreadStart' in options) {
|
||||||
|
waitThreadStart = typeof options.waitThreadStart === 'number' ? options.waitThreadStart : Boolean(options.waitThreadStart);
|
||||||
|
}
|
||||||
|
const postMessage = getPostMessage(options);
|
||||||
|
if (this.childThread && typeof postMessage !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMessage;
|
||||||
|
const wasm64 = Boolean(options.wasm64);
|
||||||
|
const threadSpawn = (startArg, errorOrTid) => {
|
||||||
|
var _a;
|
||||||
|
const EAGAIN = 6;
|
||||||
|
const isNewABI = errorOrTid !== undefined;
|
||||||
|
try {
|
||||||
|
checkSharedWasmMemory(this.wasmMemory);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
(_a = this.PThread) === null || _a === void 0 ? void 0 : _a.printErr(err.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct, 0, 1);
|
||||||
|
Atomics.store(struct, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isNewABI) {
|
||||||
|
const malloc = this.wasmInstance.exports.malloc;
|
||||||
|
errorOrTid = wasm64 ? Number(malloc(BigInt(8))) : (malloc(8) >>> 0);
|
||||||
|
if (!errorOrTid) {
|
||||||
|
return -48;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const _free = this.wasmInstance.exports.free;
|
||||||
|
const free = wasm64 ? (ptr) => { _free(BigInt(ptr)); } : _free;
|
||||||
|
const struct = new Int32Array(this.wasmMemory.buffer, errorOrTid, 2);
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, 0);
|
||||||
|
if (this.childThread) {
|
||||||
|
postMessage(createMessage('spawn-thread', {
|
||||||
|
startArg,
|
||||||
|
errorOrTid: errorOrTid
|
||||||
|
}));
|
||||||
|
Atomics.wait(struct, 1, 0);
|
||||||
|
const isError = Atomics.load(struct, 0);
|
||||||
|
const result = Atomics.load(struct, 1);
|
||||||
|
if (isNewABI) {
|
||||||
|
return isError;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return isError ? -result : result;
|
||||||
|
}
|
||||||
|
const shouldWait = waitThreadStart || (waitThreadStart === 0);
|
||||||
|
let sab;
|
||||||
|
if (shouldWait) {
|
||||||
|
sab = new Int32Array(new SharedArrayBuffer(16 + 8192));
|
||||||
|
Atomics.store(sab, 0, 0);
|
||||||
|
}
|
||||||
|
let worker;
|
||||||
|
let tid;
|
||||||
|
const PThread = this.PThread;
|
||||||
|
try {
|
||||||
|
worker = PThread.getNewWorker(sab);
|
||||||
|
if (!worker) {
|
||||||
|
throw new Error('failed to get new worker');
|
||||||
|
}
|
||||||
|
tid = PThread.markId(worker);
|
||||||
|
if (ENVIRONMENT_IS_NODE) {
|
||||||
|
worker.unref();
|
||||||
|
}
|
||||||
|
worker.postMessage(createMessage('start', {
|
||||||
|
tid,
|
||||||
|
arg: startArg,
|
||||||
|
sab
|
||||||
|
}));
|
||||||
|
if (shouldWait) {
|
||||||
|
if (typeof waitThreadStart === 'number') {
|
||||||
|
const waitResult = Atomics.wait(sab, 0, 0, waitThreadStart);
|
||||||
|
if (waitResult === 'timed-out') {
|
||||||
|
throw new Error('Spawning thread timed out. Please check if the worker is created successfully and if message is handled properly in the worker.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Atomics.wait(sab, 0, 0);
|
||||||
|
}
|
||||||
|
const r = Atomics.load(sab, 0);
|
||||||
|
if (r > 1) {
|
||||||
|
throw deserizeErrorFromBuffer(sab.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (worker !== undefined && tid !== undefined) {
|
||||||
|
try {
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 1);
|
||||||
|
Atomics.store(struct, 1, EAGAIN);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
PThread === null || PThread === void 0 ? void 0 : PThread.printErr(e.stack);
|
||||||
|
if (isNewABI) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
Atomics.store(struct, 0, 0);
|
||||||
|
Atomics.store(struct, 1, tid);
|
||||||
|
Atomics.notify(struct, 1);
|
||||||
|
if (!shouldWait) {
|
||||||
|
worker.whenLoaded.catch((err) => {
|
||||||
|
delete worker.whenLoaded;
|
||||||
|
PThread.cleanThread(worker, tid, true);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isNewABI) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
free(errorOrTid);
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
this.threadSpawn = threadSpawn;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.threadSpawn = threadSpawn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getImportObject() {
|
||||||
|
return {
|
||||||
|
wasi: {
|
||||||
|
'thread-spawn': this.threadSpawn
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
setup(wasmInstance, wasmModule, wasmMemory) {
|
||||||
|
wasmMemory !== null && wasmMemory !== void 0 ? wasmMemory : (wasmMemory = wasmInstance.exports.memory);
|
||||||
|
this.wasmInstance = wasmInstance;
|
||||||
|
this.wasmMemory = wasmMemory;
|
||||||
|
if (this.PThread) {
|
||||||
|
this.PThread.setup(wasmModule, wasmMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preloadWorkers() {
|
||||||
|
if (this.PThread) {
|
||||||
|
return this.PThread.preloadWorkers();
|
||||||
|
}
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
initialize(instance, module, memory) {
|
||||||
|
const exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
const wasi = this.wasi;
|
||||||
|
if (('_start' in exports) && (typeof exports._start === 'function')) {
|
||||||
|
if (this.childThread) {
|
||||||
|
wasi.start(instance);
|
||||||
|
try {
|
||||||
|
const kStarted = getWasiSymbol(wasi, 'kStarted');
|
||||||
|
wasi[kStarted] = false;
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setupInstance(wasi, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wasi.initialize(instance);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
start(instance, module, memory) {
|
||||||
|
const exports = instance.exports;
|
||||||
|
memory !== null && memory !== void 0 ? memory : (memory = exports.memory);
|
||||||
|
if (this.childThread) {
|
||||||
|
instance = createInstanceProxy(instance, memory);
|
||||||
|
}
|
||||||
|
this.setup(instance, module, memory);
|
||||||
|
const exitCode = this.wasi.start(instance);
|
||||||
|
return { exitCode, instance };
|
||||||
|
}
|
||||||
|
terminateAllThreads() {
|
||||||
|
var _a;
|
||||||
|
if (!this.childThread) {
|
||||||
|
(_a = this.PThread) === null || _a === void 0 ? void 0 : _a.terminateAllThreads();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.postMessage(createMessage('terminate-all-threads', {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function patchWasiInstance(wasiThreads, wasi) {
|
||||||
|
const patched = patchedWasiInstances.get(wasiThreads);
|
||||||
|
if (patched.has(wasi)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const _this = wasiThreads;
|
||||||
|
const wasiImport = wasi.wasiImport;
|
||||||
|
if (wasiImport) {
|
||||||
|
const proc_exit = wasiImport.proc_exit;
|
||||||
|
wasiImport.proc_exit = function (code) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
return proc_exit.call(this, code);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!_this.childThread) {
|
||||||
|
const start = wasi.start;
|
||||||
|
if (typeof start === 'function') {
|
||||||
|
wasi.start = function (instance) {
|
||||||
|
try {
|
||||||
|
return start.call(this, instance);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (isTrapError(err)) {
|
||||||
|
_this.terminateAllThreads();
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patched.add(wasi);
|
||||||
|
}
|
||||||
|
function getWasiSymbol(wasi, description) {
|
||||||
|
const symbols = Object.getOwnPropertySymbols(wasi);
|
||||||
|
const selectDescription = (description) => (s) => {
|
||||||
|
if (s.description) {
|
||||||
|
return s.description === description;
|
||||||
|
}
|
||||||
|
return s.toString() === `Symbol(${description})`;
|
||||||
|
};
|
||||||
|
if (Array.isArray(description)) {
|
||||||
|
return description.map(d => symbols.filter(selectDescription(d))[0]);
|
||||||
|
}
|
||||||
|
return symbols.filter(selectDescription(description))[0];
|
||||||
|
}
|
||||||
|
function setupInstance(wasi, instance) {
|
||||||
|
const [kInstance, kSetMemory] = getWasiSymbol(wasi, ['kInstance', 'kSetMemory']);
|
||||||
|
wasi[kInstance] = instance;
|
||||||
|
wasi[kSetMemory](instance.exports.memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThreadMessageHandler {
|
||||||
|
constructor(options) {
|
||||||
|
const postMsg = getPostMessage(options);
|
||||||
|
if (typeof postMsg !== 'function') {
|
||||||
|
throw new TypeError('options.postMessage is not a function');
|
||||||
|
}
|
||||||
|
this.postMessage = postMsg;
|
||||||
|
this.onLoad = options === null || options === void 0 ? void 0 : options.onLoad;
|
||||||
|
this.onError = typeof (options === null || options === void 0 ? void 0 : options.onError) === 'function' ? options.onError : (_type, err) => { throw err; };
|
||||||
|
this.instance = undefined;
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
}
|
||||||
|
instantiate(data) {
|
||||||
|
if (typeof this.onLoad === 'function') {
|
||||||
|
return this.onLoad(data);
|
||||||
|
}
|
||||||
|
throw new Error('ThreadMessageHandler.prototype.instantiate is not implemented');
|
||||||
|
}
|
||||||
|
handle(e) {
|
||||||
|
var _a;
|
||||||
|
if ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.__emnapi__) {
|
||||||
|
const type = e.data.__emnapi__.type;
|
||||||
|
const payload = e.data.__emnapi__.payload;
|
||||||
|
try {
|
||||||
|
if (type === 'load') {
|
||||||
|
this._load(payload);
|
||||||
|
}
|
||||||
|
else if (type === 'start') {
|
||||||
|
this.handleAfterLoad(e, () => {
|
||||||
|
this._start(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.onError(err, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_load(payload) {
|
||||||
|
if (this.instance !== undefined)
|
||||||
|
return;
|
||||||
|
let source;
|
||||||
|
try {
|
||||||
|
source = this.instantiate(payload);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this._loaded(err, null, payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const then = source && 'then' in source ? source.then : undefined;
|
||||||
|
if (typeof then === 'function') {
|
||||||
|
then.call(source, (source) => { this._loaded(null, source, payload); }, (err) => { this._loaded(err, null, payload); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._loaded(null, source, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_start(payload) {
|
||||||
|
const wasi_thread_start = this.instance.exports.wasi_thread_start;
|
||||||
|
if (typeof wasi_thread_start !== 'function') {
|
||||||
|
const err = new TypeError('wasi_thread_start is not exported');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
const postMessage = this.postMessage;
|
||||||
|
const tid = payload.tid;
|
||||||
|
const startArg = payload.arg;
|
||||||
|
notifyPthreadCreateResult(payload.sab, 1);
|
||||||
|
try {
|
||||||
|
wasi_thread_start(tid, startArg);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err !== 'unwind') {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postMessage(createMessage('cleanup-thread', { tid }));
|
||||||
|
}
|
||||||
|
_loaded(err, source, payload) {
|
||||||
|
if (err) {
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
if (source == null) {
|
||||||
|
const err = new TypeError('onLoad should return an object');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
const instance = source.instance;
|
||||||
|
if (!instance) {
|
||||||
|
const err = new TypeError('onLoad should return an object which includes "instance"');
|
||||||
|
notifyPthreadCreateResult(payload.sab, 2, err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
this.instance = instance;
|
||||||
|
const postMessage = this.postMessage;
|
||||||
|
postMessage(createMessage('loaded', {}));
|
||||||
|
const messages = this.messagesBeforeLoad;
|
||||||
|
this.messagesBeforeLoad = [];
|
||||||
|
for (let i = 0; i < messages.length; i++) {
|
||||||
|
const data = messages[i];
|
||||||
|
this.handle({ data });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleAfterLoad(e, f) {
|
||||||
|
if (this.instance !== undefined) {
|
||||||
|
f.call(this, e);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.messagesBeforeLoad.push(e.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function notifyPthreadCreateResult(sab, result, error) {
|
||||||
|
if (sab) {
|
||||||
|
serizeErrorToBuffer(sab.buffer, result, error);
|
||||||
|
Atomics.notify(sab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ThreadManager, ThreadMessageHandler, WASIThreads, createInstanceProxy, isSharedArrayBuffer, isTrapError };
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
|
||||||
|
module.exports = require('./dist/wasi-threads.cjs.min.js')
|
||||||
|
} else {
|
||||||
|
module.exports = require('./dist/wasi-threads.cjs.js')
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "@emnapi/wasi-threads",
|
||||||
|
"version": "1.2.2",
|
||||||
|
"description": "WASI threads proposal implementation in JavaScript",
|
||||||
|
"main": "index.js",
|
||||||
|
"module": "./dist/wasi-threads.esm-bundler.js",
|
||||||
|
"types": "./dist/wasi-threads.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": {
|
||||||
|
"module": "./dist/wasi-threads.d.ts",
|
||||||
|
"import": "./dist/wasi-threads.d.mts",
|
||||||
|
"default": "./dist/wasi-threads.d.ts"
|
||||||
|
},
|
||||||
|
"module": "./dist/wasi-threads.esm-bundler.js",
|
||||||
|
"import": "./dist/wasi-threads.mjs",
|
||||||
|
"default": "./index.js"
|
||||||
|
},
|
||||||
|
"./dist/wasi-threads.cjs.min": {
|
||||||
|
"types": "./dist/wasi-threads.d.ts",
|
||||||
|
"default": "./dist/wasi-threads.cjs.min.js"
|
||||||
|
},
|
||||||
|
"./dist/wasi-threads.min.mjs": {
|
||||||
|
"types": "./dist/wasi-threads.d.mts",
|
||||||
|
"default": "./dist/wasi-threads.min.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "node ./script/build.js",
|
||||||
|
"build:test": "node ./test/build.js",
|
||||||
|
"test": "node ./test/index.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/toyobayashi/emnapi.git"
|
||||||
|
},
|
||||||
|
"author": "toyobayashi",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/toyobayashi/emnapi/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/toyobayashi/emnapi#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
Vendored
+321
@@ -0,0 +1,321 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {unknown} value
|
||||||
|
*/
|
||||||
|
const getType = (value) => {
|
||||||
|
if (value === undefined) return 0
|
||||||
|
if (value === null) return 1
|
||||||
|
if (isBuffer(value)) return 10
|
||||||
|
const t = typeof value;
|
||||||
|
if (t === 'boolean') return 2
|
||||||
|
if (t === 'number') return 3
|
||||||
|
if (t === 'string') return 4
|
||||||
|
if (t === 'object') return 6
|
||||||
|
if (t === 'bigint') return 9
|
||||||
|
return -1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {unknown} value
|
||||||
|
* @returns {value is Uint8Array}
|
||||||
|
*/
|
||||||
|
const isBuffer = (value) => {
|
||||||
|
const BufferCtor = globalThis.Buffer;
|
||||||
|
if (typeof BufferCtor?.isBuffer === 'function') {
|
||||||
|
return BufferCtor.isBuffer(value)
|
||||||
|
}
|
||||||
|
return value instanceof Uint8Array && value.constructor?.name === 'Buffer'
|
||||||
|
};
|
||||||
|
|
||||||
|
const RESPONSE_HEADER_SIZE = 16;
|
||||||
|
const RESPONSE_PAYLOAD_SIZE = 10240;
|
||||||
|
const RESPONSE_BUFFER_SIZE = RESPONSE_HEADER_SIZE + RESPONSE_PAYLOAD_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Int32Array} sab
|
||||||
|
* @param {Uint8Array} payload
|
||||||
|
*/
|
||||||
|
const writeResponsePayload = (sab, payload) => {
|
||||||
|
if (payload.length > RESPONSE_PAYLOAD_SIZE) {
|
||||||
|
throw new RangeError('payload overflow')
|
||||||
|
}
|
||||||
|
new Uint8Array(sab.buffer).set(payload, RESPONSE_HEADER_SIZE);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('memfs').IFs} memfs
|
||||||
|
* @param {any} value
|
||||||
|
* @param {ReturnType<typeof getType>} type
|
||||||
|
* @returns {Uint8Array}
|
||||||
|
*/
|
||||||
|
const encodeValue = (memfs, value, type) => {
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
return new Uint8Array(0)
|
||||||
|
case 2: {
|
||||||
|
const view = new Int32Array(1);
|
||||||
|
view[0] = value ? 1 : 0;
|
||||||
|
return new Uint8Array(view.buffer)
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
const view = new Float64Array(1);
|
||||||
|
view[0] = value;
|
||||||
|
return new Uint8Array(view.buffer)
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
const view = new TextEncoder().encode(value);
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
return new Uint8Array(value)
|
||||||
|
case 6: {
|
||||||
|
function storeConstructor(obj, memfs, processed = new WeakSet()) {
|
||||||
|
if (!obj || typeof obj !== 'object') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed.has(obj)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
processed.add(obj);
|
||||||
|
|
||||||
|
const [entry] =
|
||||||
|
Object.entries(memfs).filter(([_, v]) => v === obj.constructor)[0] ??
|
||||||
|
[];
|
||||||
|
if (entry) {
|
||||||
|
Object.defineProperty(obj, '__constructor__', {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
value: entry,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const value of Object.values(obj)) {
|
||||||
|
storeConstructor(value, memfs, processed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
storeConstructor(value, memfs);
|
||||||
|
|
||||||
|
const json = JSON.stringify(value, (_, value) => {
|
||||||
|
if (typeof value === 'bigint') {
|
||||||
|
return `BigInt(${String(value)})`
|
||||||
|
}
|
||||||
|
if (value instanceof Error) {
|
||||||
|
return {
|
||||||
|
...value,
|
||||||
|
message: value.message,
|
||||||
|
stack: value.stack,
|
||||||
|
__error__: value.constructor.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
});
|
||||||
|
const view = new TextEncoder().encode(json);
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
case 9: {
|
||||||
|
return new TextEncoder().encode(String(value))
|
||||||
|
}
|
||||||
|
case -1:
|
||||||
|
default:
|
||||||
|
throw new Error('unsupported data')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {typeof import('memfs')} memfs
|
||||||
|
* @param {Uint8Array} payload
|
||||||
|
* @param {number} type
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
|
const decodeValue = (memfs, payload, type) => {
|
||||||
|
if (type === 0) return undefined
|
||||||
|
if (type === 1) return null
|
||||||
|
if (type === 2)
|
||||||
|
return Boolean(new Int32Array(payload.buffer, payload.byteOffset, 1)[0])
|
||||||
|
if (type === 3)
|
||||||
|
return new Float64Array(payload.buffer, payload.byteOffset, 1)[0]
|
||||||
|
if (type === 4) return new TextDecoder().decode(payload.slice())
|
||||||
|
if (type === 10) {
|
||||||
|
const BufferCtor = globalThis.Buffer;
|
||||||
|
if (typeof BufferCtor?.from === 'function') {
|
||||||
|
return BufferCtor.from(payload)
|
||||||
|
}
|
||||||
|
return payload.slice()
|
||||||
|
}
|
||||||
|
if (type === 6) {
|
||||||
|
const obj = JSON.parse(
|
||||||
|
new TextDecoder().decode(payload.slice()),
|
||||||
|
(_key, value) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const matched = value.match(/^BigInt\((-?\d+)\)$/);
|
||||||
|
if (matched && matched[1]) {
|
||||||
|
return BigInt(matched[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function loadConstructor(obj, memfs, processed = new WeakSet()) {
|
||||||
|
if (!obj || typeof obj !== 'object') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed.has(obj)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
processed.add(obj);
|
||||||
|
|
||||||
|
if (obj.__constructor__) {
|
||||||
|
const ctor = obj.__constructor__;
|
||||||
|
delete obj.__constructor__;
|
||||||
|
Object.setPrototypeOf(obj, memfs[ctor].prototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const value of Object.values(obj)) {
|
||||||
|
loadConstructor(value, memfs, processed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConstructor(obj, memfs);
|
||||||
|
|
||||||
|
if (obj.__error__) {
|
||||||
|
const name = obj.__error__;
|
||||||
|
const ErrorConstructor = globalThis[name] || Error;
|
||||||
|
delete obj.__error__;
|
||||||
|
const err = new ErrorConstructor(obj.message);
|
||||||
|
Object.defineProperty(err, 'stack', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
value: err.stack,
|
||||||
|
});
|
||||||
|
Object.defineProperty(err, Symbol.toStringTag, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
value: name,
|
||||||
|
});
|
||||||
|
for (const [k, v] of Object.entries(obj)) {
|
||||||
|
if (k === 'message' || k === 'stack') continue
|
||||||
|
err[k] = v;
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
if (type === 9) {
|
||||||
|
return BigInt(new TextDecoder().decode(payload.slice()))
|
||||||
|
}
|
||||||
|
throw new Error('unsupported data')
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('memfs').IFs} fs
|
||||||
|
* @returns {(e: { data: { __fs__: { sab: Int32Array, type: keyof import('memfs').IFs, payload: any[] } } }) => void}
|
||||||
|
*/
|
||||||
|
// oxlint-disable-next-line no-unused-vars -- fixed in an upcoming release
|
||||||
|
const createOnMessage = (fs) =>
|
||||||
|
function onMessage(e) {
|
||||||
|
if (e.data.__fs__) {
|
||||||
|
/**
|
||||||
|
* 0..4 status(int32_t): 21(waiting) 0(success) 1(error)
|
||||||
|
* 5..8 type(napi_valuetype): 0(undefined) 1(null) 2(boolean) 3(number) 4(string) 6(jsonstring) 9(bigint) 10(buffer) -1(unsupported)
|
||||||
|
* 9..16 payload_size(uint32_t) <= 10240
|
||||||
|
* 16..16 + payload_size payload_content
|
||||||
|
*/
|
||||||
|
const { sab, type, payload } = e.data.__fs__;
|
||||||
|
const fn = fs[type];
|
||||||
|
try {
|
||||||
|
const ret = fn.apply(fs, payload);
|
||||||
|
const t = getType(ret);
|
||||||
|
Atomics.store(sab, 1, t);
|
||||||
|
const v = encodeValue(fs, ret, t);
|
||||||
|
Atomics.store(sab, 2, v.length);
|
||||||
|
writeResponsePayload(sab, v);
|
||||||
|
Atomics.store(sab, 0, 0); // success
|
||||||
|
} catch (/** @type {any} */ err) {
|
||||||
|
let t = getType(err);
|
||||||
|
let v;
|
||||||
|
try {
|
||||||
|
if (t === -1) {
|
||||||
|
throw new Error('unsupported data')
|
||||||
|
}
|
||||||
|
v = encodeValue(fs, err, t);
|
||||||
|
} catch {
|
||||||
|
const fallback = (() => {
|
||||||
|
try {
|
||||||
|
return String(err)
|
||||||
|
} catch {
|
||||||
|
return 'Unserializable thrown value'
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
t = getType(fallback);
|
||||||
|
v = encodeValue(fs, fallback, t);
|
||||||
|
}
|
||||||
|
if (v.length > RESPONSE_PAYLOAD_SIZE) {
|
||||||
|
const overflowErr = new RangeError('payload overflow');
|
||||||
|
t = getType(overflowErr);
|
||||||
|
v = encodeValue(fs, overflowErr, t);
|
||||||
|
}
|
||||||
|
Atomics.store(sab, 1, t);
|
||||||
|
Atomics.store(sab, 2, v.length);
|
||||||
|
writeResponsePayload(sab, v);
|
||||||
|
Atomics.store(sab, 0, 1); // error
|
||||||
|
} finally {
|
||||||
|
Atomics.notify(sab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {typeof import('memfs')} memfs
|
||||||
|
*/
|
||||||
|
const createFsProxy = (memfs) =>
|
||||||
|
new Proxy(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
get(_target, p, _receiver) {
|
||||||
|
/**
|
||||||
|
* @param {any[]} args
|
||||||
|
*/
|
||||||
|
return function (...args) {
|
||||||
|
const sab = new SharedArrayBuffer(RESPONSE_BUFFER_SIZE);
|
||||||
|
const i32arr = new Int32Array(sab);
|
||||||
|
Atomics.store(i32arr, 0, 21);
|
||||||
|
|
||||||
|
postMessage({
|
||||||
|
__fs__: {
|
||||||
|
sab: i32arr,
|
||||||
|
type: p,
|
||||||
|
payload: args,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Atomics.wait(i32arr, 0, 21);
|
||||||
|
|
||||||
|
const status = Atomics.load(i32arr, 0);
|
||||||
|
const type = Atomics.load(i32arr, 1);
|
||||||
|
const size = Atomics.load(i32arr, 2);
|
||||||
|
const content = new Uint8Array(sab, RESPONSE_HEADER_SIZE, size);
|
||||||
|
const value = decodeValue(memfs, content, type);
|
||||||
|
if (status === 1) {
|
||||||
|
throw value
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
exports.createFsProxy = createFsProxy;
|
||||||
|
exports.createOnMessage = createOnMessage;
|
||||||
+25127
File diff suppressed because one or more lines are too long
+316
@@ -0,0 +1,316 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {unknown} value
|
||||||
|
*/
|
||||||
|
const getType = (value) => {
|
||||||
|
if (value === undefined) return 0
|
||||||
|
if (value === null) return 1
|
||||||
|
if (isBuffer(value)) return 10
|
||||||
|
const t = typeof value
|
||||||
|
if (t === 'boolean') return 2
|
||||||
|
if (t === 'number') return 3
|
||||||
|
if (t === 'string') return 4
|
||||||
|
if (t === 'object') return 6
|
||||||
|
if (t === 'bigint') return 9
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {unknown} value
|
||||||
|
* @returns {value is Uint8Array}
|
||||||
|
*/
|
||||||
|
const isBuffer = (value) => {
|
||||||
|
const BufferCtor = globalThis.Buffer
|
||||||
|
if (typeof BufferCtor?.isBuffer === 'function') {
|
||||||
|
return BufferCtor.isBuffer(value)
|
||||||
|
}
|
||||||
|
return value instanceof Uint8Array && value.constructor?.name === 'Buffer'
|
||||||
|
}
|
||||||
|
|
||||||
|
const RESPONSE_HEADER_SIZE = 16
|
||||||
|
const RESPONSE_PAYLOAD_SIZE = 10240
|
||||||
|
const RESPONSE_BUFFER_SIZE = RESPONSE_HEADER_SIZE + RESPONSE_PAYLOAD_SIZE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Int32Array} sab
|
||||||
|
* @param {Uint8Array} payload
|
||||||
|
*/
|
||||||
|
const writeResponsePayload = (sab, payload) => {
|
||||||
|
if (payload.length > RESPONSE_PAYLOAD_SIZE) {
|
||||||
|
throw new RangeError('payload overflow')
|
||||||
|
}
|
||||||
|
new Uint8Array(sab.buffer).set(payload, RESPONSE_HEADER_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('memfs').IFs} memfs
|
||||||
|
* @param {any} value
|
||||||
|
* @param {ReturnType<typeof getType>} type
|
||||||
|
* @returns {Uint8Array}
|
||||||
|
*/
|
||||||
|
const encodeValue = (memfs, value, type) => {
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
return new Uint8Array(0)
|
||||||
|
case 2: {
|
||||||
|
const view = new Int32Array(1)
|
||||||
|
view[0] = value ? 1 : 0
|
||||||
|
return new Uint8Array(view.buffer)
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
const view = new Float64Array(1)
|
||||||
|
view[0] = value
|
||||||
|
return new Uint8Array(view.buffer)
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
const view = new TextEncoder().encode(value)
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
return new Uint8Array(value)
|
||||||
|
case 6: {
|
||||||
|
function storeConstructor(obj, memfs, processed = new WeakSet()) {
|
||||||
|
if (!obj || typeof obj !== 'object') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed.has(obj)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
processed.add(obj)
|
||||||
|
|
||||||
|
const [entry] =
|
||||||
|
Object.entries(memfs).filter(([_, v]) => v === obj.constructor)[0] ??
|
||||||
|
[]
|
||||||
|
if (entry) {
|
||||||
|
Object.defineProperty(obj, '__constructor__', {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
value: entry,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const value of Object.values(obj)) {
|
||||||
|
storeConstructor(value, memfs, processed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
storeConstructor(value, memfs)
|
||||||
|
|
||||||
|
const json = JSON.stringify(value, (_, value) => {
|
||||||
|
if (typeof value === 'bigint') {
|
||||||
|
return `BigInt(${String(value)})`
|
||||||
|
}
|
||||||
|
if (value instanceof Error) {
|
||||||
|
return {
|
||||||
|
...value,
|
||||||
|
message: value.message,
|
||||||
|
stack: value.stack,
|
||||||
|
__error__: value.constructor.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
})
|
||||||
|
const view = new TextEncoder().encode(json)
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
case 9: {
|
||||||
|
return new TextEncoder().encode(String(value))
|
||||||
|
}
|
||||||
|
case -1:
|
||||||
|
default:
|
||||||
|
throw new Error('unsupported data')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {typeof import('memfs')} memfs
|
||||||
|
* @param {Uint8Array} payload
|
||||||
|
* @param {number} type
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
|
const decodeValue = (memfs, payload, type) => {
|
||||||
|
if (type === 0) return undefined
|
||||||
|
if (type === 1) return null
|
||||||
|
if (type === 2)
|
||||||
|
return Boolean(new Int32Array(payload.buffer, payload.byteOffset, 1)[0])
|
||||||
|
if (type === 3)
|
||||||
|
return new Float64Array(payload.buffer, payload.byteOffset, 1)[0]
|
||||||
|
if (type === 4) return new TextDecoder().decode(payload.slice())
|
||||||
|
if (type === 10) {
|
||||||
|
const BufferCtor = globalThis.Buffer
|
||||||
|
if (typeof BufferCtor?.from === 'function') {
|
||||||
|
return BufferCtor.from(payload)
|
||||||
|
}
|
||||||
|
return payload.slice()
|
||||||
|
}
|
||||||
|
if (type === 6) {
|
||||||
|
const obj = JSON.parse(
|
||||||
|
new TextDecoder().decode(payload.slice()),
|
||||||
|
(_key, value) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const matched = value.match(/^BigInt\((-?\d+)\)$/)
|
||||||
|
if (matched && matched[1]) {
|
||||||
|
return BigInt(matched[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
function loadConstructor(obj, memfs, processed = new WeakSet()) {
|
||||||
|
if (!obj || typeof obj !== 'object') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed.has(obj)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
processed.add(obj)
|
||||||
|
|
||||||
|
if (obj.__constructor__) {
|
||||||
|
const ctor = obj.__constructor__
|
||||||
|
delete obj.__constructor__
|
||||||
|
Object.setPrototypeOf(obj, memfs[ctor].prototype)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const value of Object.values(obj)) {
|
||||||
|
loadConstructor(value, memfs, processed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConstructor(obj, memfs)
|
||||||
|
|
||||||
|
if (obj.__error__) {
|
||||||
|
const name = obj.__error__
|
||||||
|
const ErrorConstructor = globalThis[name] || Error
|
||||||
|
delete obj.__error__
|
||||||
|
const err = new ErrorConstructor(obj.message)
|
||||||
|
Object.defineProperty(err, 'stack', {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
value: err.stack,
|
||||||
|
})
|
||||||
|
Object.defineProperty(err, Symbol.toStringTag, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
value: name,
|
||||||
|
})
|
||||||
|
for (const [k, v] of Object.entries(obj)) {
|
||||||
|
if (k === 'message' || k === 'stack') continue
|
||||||
|
err[k] = v
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
if (type === 9) {
|
||||||
|
return BigInt(new TextDecoder().decode(payload.slice()))
|
||||||
|
}
|
||||||
|
throw new Error('unsupported data')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('memfs').IFs} fs
|
||||||
|
* @returns {(e: { data: { __fs__: { sab: Int32Array, type: keyof import('memfs').IFs, payload: any[] } } }) => void}
|
||||||
|
*/
|
||||||
|
// oxlint-disable-next-line no-unused-vars -- fixed in an upcoming release
|
||||||
|
export const createOnMessage = (fs) =>
|
||||||
|
function onMessage(e) {
|
||||||
|
if (e.data.__fs__) {
|
||||||
|
/**
|
||||||
|
* 0..4 status(int32_t): 21(waiting) 0(success) 1(error)
|
||||||
|
* 5..8 type(napi_valuetype): 0(undefined) 1(null) 2(boolean) 3(number) 4(string) 6(jsonstring) 9(bigint) 10(buffer) -1(unsupported)
|
||||||
|
* 9..16 payload_size(uint32_t) <= 10240
|
||||||
|
* 16..16 + payload_size payload_content
|
||||||
|
*/
|
||||||
|
const { sab, type, payload } = e.data.__fs__
|
||||||
|
const fn = fs[type]
|
||||||
|
try {
|
||||||
|
const ret = fn.apply(fs, payload)
|
||||||
|
const t = getType(ret)
|
||||||
|
Atomics.store(sab, 1, t)
|
||||||
|
const v = encodeValue(fs, ret, t)
|
||||||
|
Atomics.store(sab, 2, v.length)
|
||||||
|
writeResponsePayload(sab, v)
|
||||||
|
Atomics.store(sab, 0, 0) // success
|
||||||
|
} catch (/** @type {any} */ err) {
|
||||||
|
let t = getType(err)
|
||||||
|
let v
|
||||||
|
try {
|
||||||
|
if (t === -1) {
|
||||||
|
throw new Error('unsupported data')
|
||||||
|
}
|
||||||
|
v = encodeValue(fs, err, t)
|
||||||
|
} catch {
|
||||||
|
const fallback = (() => {
|
||||||
|
try {
|
||||||
|
return String(err)
|
||||||
|
} catch {
|
||||||
|
return 'Unserializable thrown value'
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
t = getType(fallback)
|
||||||
|
v = encodeValue(fs, fallback, t)
|
||||||
|
}
|
||||||
|
if (v.length > RESPONSE_PAYLOAD_SIZE) {
|
||||||
|
const overflowErr = new RangeError('payload overflow')
|
||||||
|
t = getType(overflowErr)
|
||||||
|
v = encodeValue(fs, overflowErr, t)
|
||||||
|
}
|
||||||
|
Atomics.store(sab, 1, t)
|
||||||
|
Atomics.store(sab, 2, v.length)
|
||||||
|
writeResponsePayload(sab, v)
|
||||||
|
Atomics.store(sab, 0, 1) // error
|
||||||
|
} finally {
|
||||||
|
Atomics.notify(sab, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {typeof import('memfs')} memfs
|
||||||
|
*/
|
||||||
|
export const createFsProxy = (memfs) =>
|
||||||
|
new Proxy(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
get(_target, p, _receiver) {
|
||||||
|
/**
|
||||||
|
* @param {any[]} args
|
||||||
|
*/
|
||||||
|
return function (...args) {
|
||||||
|
const sab = new SharedArrayBuffer(RESPONSE_BUFFER_SIZE)
|
||||||
|
const i32arr = new Int32Array(sab)
|
||||||
|
Atomics.store(i32arr, 0, 21)
|
||||||
|
|
||||||
|
postMessage({
|
||||||
|
__fs__: {
|
||||||
|
sab: i32arr,
|
||||||
|
type: p,
|
||||||
|
payload: args,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
Atomics.wait(i32arr, 0, 21)
|
||||||
|
|
||||||
|
const status = Atomics.load(i32arr, 0)
|
||||||
|
const type = Atomics.load(i32arr, 1)
|
||||||
|
const size = Atomics.load(i32arr, 2)
|
||||||
|
const content = new Uint8Array(sab, RESPONSE_HEADER_SIZE, size)
|
||||||
|
const value = decodeValue(memfs, content, type)
|
||||||
|
if (status === 1) {
|
||||||
|
throw value
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"name": "@napi-rs/wasm-runtime",
|
||||||
|
"version": "1.1.6",
|
||||||
|
"type": "module",
|
||||||
|
"description": "Runtime and polyfill for wasm targets",
|
||||||
|
"homepage": "https://napi.rs/",
|
||||||
|
"author": {
|
||||||
|
"name": "LongYinan",
|
||||||
|
"url": "https://github.com/Brooooooklyn"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/napi-rs/napi-rs.git",
|
||||||
|
"directory": "wasm-runtime"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"runtime.cjs",
|
||||||
|
"runtime.js",
|
||||||
|
"fs-proxy.js",
|
||||||
|
"dist/*.cjs",
|
||||||
|
"dist/*.js"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-alias": "^6.0.0",
|
||||||
|
"@rollup/plugin-commonjs": "^29.0.3",
|
||||||
|
"@rollup/plugin-inject": "^5.0.5",
|
||||||
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||||
|
"@rollup/plugin-replace": "^6.0.3",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"events": "^3.3.0",
|
||||||
|
"memfs": "^4.57.6",
|
||||||
|
"node-inspect-extracted": "^3.3.2",
|
||||||
|
"path-browserify": "^1.0.1",
|
||||||
|
"process": "^0.11.10",
|
||||||
|
"readable-stream": "^4.7.0",
|
||||||
|
"rollup": "^4.61.1",
|
||||||
|
"rollup-plugin-polyfill-node": "^0.13.0",
|
||||||
|
"tslib": "^2.8.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tybys/wasm-util": "^0.10.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emnapi/core": "^1.7.1",
|
||||||
|
"@emnapi/runtime": "^1.7.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c rollup.config.js",
|
||||||
|
"test": "node --test"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./runtime.js",
|
||||||
|
"require": "./runtime.cjs"
|
||||||
|
},
|
||||||
|
"./fs": {
|
||||||
|
"import": "./dist/fs.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
const { MessageHandler, instantiateNapiModuleSync, instantiateNapiModule } = require('@emnapi/core')
|
||||||
|
const { getDefaultContext } = require('@emnapi/runtime')
|
||||||
|
const { WASI } = require('@tybys/wasm-util')
|
||||||
|
|
||||||
|
const { createFsProxy, createOnMessage } = require('./dist/fs-proxy.cjs')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
MessageHandler,
|
||||||
|
instantiateNapiModule,
|
||||||
|
instantiateNapiModuleSync,
|
||||||
|
getDefaultContext,
|
||||||
|
WASI,
|
||||||
|
createFsProxy,
|
||||||
|
createOnMessage,
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
export {
|
||||||
|
instantiateNapiModuleSync,
|
||||||
|
instantiateNapiModule,
|
||||||
|
MessageHandler,
|
||||||
|
} from '@emnapi/core'
|
||||||
|
export { getDefaultContext } from '@emnapi/runtime'
|
||||||
|
export * from '@tybys/wasm-util'
|
||||||
|
export { createOnMessage, createFsProxy } from './fs-proxy.js'
|
||||||
+193
@@ -0,0 +1,193 @@
|
|||||||
|
# @tybys/wasm-util
|
||||||
|
|
||||||
|
WebAssembly related utils for browser environment
|
||||||
|
|
||||||
|
**The output code is ES2019**
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
All example code below need to be bundled by ES module bundlers like `webpack` / `rollup`, or specify import map in browser native ES module runtime.
|
||||||
|
|
||||||
|
### WASI polyfill for browser
|
||||||
|
|
||||||
|
The API is similar to the `require('wasi').WASI` in Node.js.
|
||||||
|
|
||||||
|
You can use `memfs-browser` to provide filesystem capability.
|
||||||
|
|
||||||
|
- Example: [https://github.com/toyobayashi/wasi-wabt](https://github.com/toyobayashi/wasi-wabt)
|
||||||
|
- Demo: [https://toyobayashi.github.io/wasi-wabt/](https://toyobayashi.github.io/wasi-wabt/)
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { load, WASI } from '@tybys/wasm-util'
|
||||||
|
import { Volume, createFsFromVolume } from 'memfs-browser'
|
||||||
|
|
||||||
|
const fs = createFsFromVolume(Volume.fromJSON({
|
||||||
|
'/home/wasi': null
|
||||||
|
}))
|
||||||
|
|
||||||
|
const wasi = new WASI({
|
||||||
|
args: ['chrome', 'file.wasm'],
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'development',
|
||||||
|
WASI_SDK_PATH: '/opt/wasi-sdk'
|
||||||
|
},
|
||||||
|
preopens: {
|
||||||
|
'/': '/'
|
||||||
|
},
|
||||||
|
fs,
|
||||||
|
|
||||||
|
// redirect stdout / stderr
|
||||||
|
|
||||||
|
// print (text) { console.log(text) },
|
||||||
|
// printErr (text) { console.error(text) }
|
||||||
|
})
|
||||||
|
|
||||||
|
const imports = {
|
||||||
|
wasi_snapshot_preview1: wasi.wasiImport
|
||||||
|
}
|
||||||
|
|
||||||
|
const { module, instance } = await load('/path/to/file.wasm', imports)
|
||||||
|
wasi.start(instance)
|
||||||
|
// wasi.initialize(instance)
|
||||||
|
```
|
||||||
|
|
||||||
|
Implemented syscalls: [wasi_snapshot_preview1](#wasi_snapshot_preview1)
|
||||||
|
|
||||||
|
### `load` / `loadSync`
|
||||||
|
|
||||||
|
`loadSync` has 4KB wasm size limit in browser.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// bundler
|
||||||
|
import { load, loadSync } from '@tybys/wasm-util'
|
||||||
|
|
||||||
|
const imports = { /* ... */ }
|
||||||
|
|
||||||
|
// using path
|
||||||
|
const { module, instance } = await load('/path/to/file.wasm', imports)
|
||||||
|
const { module, instance } = loadSync('/path/to/file.wasm', imports)
|
||||||
|
|
||||||
|
// using URL
|
||||||
|
const { module, instance } = await load(new URL('./file.wasm', import.meta.url), imports)
|
||||||
|
const { module, instance } = loadSync(new URL('./file.wasm', import.meta.url), imports)
|
||||||
|
|
||||||
|
// using Uint8Array
|
||||||
|
const buffer = new Uint8Array([
|
||||||
|
0x00, 0x61, 0x73, 0x6d,
|
||||||
|
0x01, 0x00, 0x00, 0x00
|
||||||
|
])
|
||||||
|
const { module, instance } = await load(buffer, imports)
|
||||||
|
const { module, instance } = loadSync(buffer, imports)
|
||||||
|
|
||||||
|
// auto asyncify
|
||||||
|
const {
|
||||||
|
module,
|
||||||
|
instance: asyncifiedInstance
|
||||||
|
} = await load(buffer, imports, { /* asyncify options */})
|
||||||
|
asyncifiedInstance.exports.fn() // => return Promise
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extend Memory instance
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Memory, extendMemory } from '@tybys/wasm-util'
|
||||||
|
|
||||||
|
const memory = new WebAssembly.Memory({ initial: 256 })
|
||||||
|
// const memory = instance.exports.memory
|
||||||
|
|
||||||
|
extendMemory(memory)
|
||||||
|
console.log(memory instanceof Memory)
|
||||||
|
console.log(memory instanceof WebAssembly.Memory)
|
||||||
|
// expose memory view getters like Emscripten
|
||||||
|
const { HEAPU8, HEAPU32, view } = memory
|
||||||
|
```
|
||||||
|
|
||||||
|
### Asyncify wrap
|
||||||
|
|
||||||
|
Build the C code using `clang`, `wasm-ld` and `wasm-opt`
|
||||||
|
|
||||||
|
```c
|
||||||
|
void async_sleep(int ms);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
async_sleep(200);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Asyncify } from '@tybys/wasm-util'
|
||||||
|
|
||||||
|
const asyncify = new Asyncify()
|
||||||
|
|
||||||
|
const imports = {
|
||||||
|
env: {
|
||||||
|
async_sleep: asyncify.wrapImportFunction(function (ms) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// async_sleep(200)
|
||||||
|
const bytes = await (await fetch('/asyncfied_by_wasm-opt.wasm')).arrayBuffer()
|
||||||
|
const { instance } = await WebAssembly.instantiate(bytes, imports)
|
||||||
|
const asyncifiedInstance = asyncify.init(instance.exports.memory, instance, {
|
||||||
|
wrapExports: ['_start']
|
||||||
|
})
|
||||||
|
|
||||||
|
const p = asyncifedInstance._start()
|
||||||
|
console.log(typeof p.then === 'function')
|
||||||
|
const now = Date.now()
|
||||||
|
await p
|
||||||
|
console.log(Date.now() - now >= 200)
|
||||||
|
```
|
||||||
|
|
||||||
|
### wasi_snapshot_preview1
|
||||||
|
|
||||||
|
- [x] args_get
|
||||||
|
- [x] args_sizes_get
|
||||||
|
- [x] environ_get
|
||||||
|
- [x] environ_sizes_get
|
||||||
|
- [x] clock_res_get
|
||||||
|
- [x] clock_time_get
|
||||||
|
- [ ] ~~fd_advise~~
|
||||||
|
- [x] fd_allocate
|
||||||
|
- [x] fd_close
|
||||||
|
- [x] fd_datasync
|
||||||
|
- [x] fd_fdstat_get
|
||||||
|
- [ ] ~~fd_fdstat_set_flags~~
|
||||||
|
- [x] fd_fdstat_set_rights
|
||||||
|
- [x] fd_filestat_get
|
||||||
|
- [x] fd_filestat_set_size
|
||||||
|
- [x] fd_filestat_set_times
|
||||||
|
- [x] fd_pread
|
||||||
|
- [x] fd_prestat_get
|
||||||
|
- [x] fd_prestat_dir_name
|
||||||
|
- [x] fd_pwrite
|
||||||
|
- [x] fd_read
|
||||||
|
- [x] fd_readdir
|
||||||
|
- [x] fd_renumber
|
||||||
|
- [x] fd_seek
|
||||||
|
- [x] fd_sync
|
||||||
|
- [x] fd_tell
|
||||||
|
- [x] fd_write
|
||||||
|
- [x] path_create_directory
|
||||||
|
- [x] path_filestat_get
|
||||||
|
- [x] path_filestat_set_times
|
||||||
|
- [x] path_link
|
||||||
|
- [x] path_open
|
||||||
|
- [x] path_readlink
|
||||||
|
- [x] path_remove_directory
|
||||||
|
- [x] path_rename
|
||||||
|
- [x] path_symlink
|
||||||
|
- [x] path_unlink_file
|
||||||
|
- [x] poll_oneoff (timer only)
|
||||||
|
- [x] proc_exit
|
||||||
|
- [ ] ~~proc_raise~~
|
||||||
|
- [x] sched_yield
|
||||||
|
- [x] random_get
|
||||||
|
- [ ] ~~sock_recv~~
|
||||||
|
- [ ] ~~sock_send~~
|
||||||
|
- [ ] ~~sock_shutdown~~
|
||||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
||||||
|
// It should be published with your NPM package. It should not be tracked by Git.
|
||||||
|
{
|
||||||
|
"tsdocVersion": "0.12",
|
||||||
|
"toolPackages": [
|
||||||
|
{
|
||||||
|
"packageName": "@microsoft/api-extractor",
|
||||||
|
"packageVersion": "7.34.4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Generated
Vendored
+423
@@ -0,0 +1,423 @@
|
|||||||
|
/**
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class Asyncify {
|
||||||
|
private value;
|
||||||
|
private exports;
|
||||||
|
private dataPtr;
|
||||||
|
init<T extends WebAssembly.Exports, U extends Array<Exclude<keyof T, AsyncifyExportName>>>(memory: WebAssembly.Memory, instance: {
|
||||||
|
readonly exports: T;
|
||||||
|
}, options: AsyncifyOptions): {
|
||||||
|
readonly exports: AsyncifyExports<T, U>;
|
||||||
|
};
|
||||||
|
private assertState;
|
||||||
|
wrapImportFunction<T extends Function>(f: T): T;
|
||||||
|
wrapImports<T extends WebAssembly.Imports>(imports: T): T;
|
||||||
|
wrapExportFunction<T extends Function>(f: T): AsyncifyExportFunction<T>;
|
||||||
|
wrapExports<T extends WebAssembly.Exports>(exports: T): AsyncifyExports<T, void>;
|
||||||
|
wrapExports<T extends WebAssembly.Exports, U extends Array<Exclude<keyof T, AsyncifyExportName>>>(exports: T, needWrap: U): AsyncifyExports<T, U>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type AsyncifyExportFunction<T> = T extends Callable ? (...args: Parameters<T>) => Promise<ReturnType<T>> : T;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type AsyncifyExportName = 'asyncify_get_state' | 'asyncify_start_unwind' | 'asyncify_stop_unwind' | 'asyncify_start_rewind' | 'asyncify_stop_rewind';
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type AsyncifyExports<T, U> = T extends Record<string, any> ? {
|
||||||
|
[P in keyof T]: T[P] extends Callable ? U extends Array<Exclude<keyof T, AsyncifyExportName>> ? P extends U[number] ? AsyncifyExportFunction<T[P]> : T[P] : AsyncifyExportFunction<T[P]> : T[P];
|
||||||
|
} : T;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function asyncifyLoad(asyncify: AsyncifyOptions, urlOrBuffer: string | URL | BufferSource | WebAssembly.Module, imports?: WebAssembly.Imports): Promise<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function asyncifyLoadSync(asyncify: AsyncifyOptions, buffer: BufferSource | WebAssembly.Module, imports?: WebAssembly.Imports): WebAssembly.WebAssemblyInstantiatedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface AsyncifyOptions {
|
||||||
|
wasm64?: boolean;
|
||||||
|
tryAllocate?: boolean | {
|
||||||
|
size?: number;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
wrapExports?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface AsyncWASIOptions extends WASIOptions {
|
||||||
|
fs: {
|
||||||
|
promises: IFsPromises;
|
||||||
|
};
|
||||||
|
asyncify?: Asyncify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BaseEncodingOptions {
|
||||||
|
encoding?: BufferEncoding_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface BigIntStats extends StatsBase<bigint> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare type BufferEncoding_2 = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
|
||||||
|
export { BufferEncoding_2 as BufferEncoding }
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type BufferEncodingOption = 'buffer' | {
|
||||||
|
encoding: 'buffer';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type Callable = (...args: any[]) => any;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function createAsyncWASI(options?: AsyncWASIOptions): Promise<WASI>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function extendMemory(memory: WebAssembly.Memory): Memory;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface FileHandle {
|
||||||
|
readonly fd: number;
|
||||||
|
datasync(): Promise<void>;
|
||||||
|
sync(): Promise<void>;
|
||||||
|
read<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{
|
||||||
|
bytesRead: number;
|
||||||
|
buffer: TBuffer;
|
||||||
|
}>;
|
||||||
|
stat(opts?: StatOptions & {
|
||||||
|
bigint?: false;
|
||||||
|
}): Promise<Stats>;
|
||||||
|
stat(opts: StatOptions & {
|
||||||
|
bigint: true;
|
||||||
|
}): Promise<BigIntStats>;
|
||||||
|
stat(opts?: StatOptions): Promise<Stats | BigIntStats>;
|
||||||
|
truncate(len?: number): Promise<void>;
|
||||||
|
utimes(atime: string | number | Date, mtime: string | number | Date): Promise<void>;
|
||||||
|
write<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{
|
||||||
|
bytesWritten: number;
|
||||||
|
buffer: TBuffer;
|
||||||
|
}>;
|
||||||
|
write(data: string | Uint8Array, position?: number, encoding?: BufferEncoding_2): Promise<{
|
||||||
|
bytesWritten: number;
|
||||||
|
buffer: string;
|
||||||
|
}>;
|
||||||
|
close(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface FinalizeBindingsOptions {
|
||||||
|
memory?: WebAssembly.Memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface IDirent {
|
||||||
|
isFile(): boolean;
|
||||||
|
isDirectory(): boolean;
|
||||||
|
isBlockDevice(): boolean;
|
||||||
|
isCharacterDevice(): boolean;
|
||||||
|
isSymbolicLink(): boolean;
|
||||||
|
isFIFO(): boolean;
|
||||||
|
isSocket(): boolean;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface IFs {
|
||||||
|
fstatSync(fd: number, options?: StatOptions & {
|
||||||
|
bigint?: false;
|
||||||
|
}): Stats;
|
||||||
|
fstatSync(fd: number, options: StatOptions & {
|
||||||
|
bigint: true;
|
||||||
|
}): BigIntStats;
|
||||||
|
fstatSync(fd: number, options?: StatOptions): Stats | BigIntStats;
|
||||||
|
statSync(path: PathLike, options?: StatOptions & {
|
||||||
|
bigint?: false;
|
||||||
|
}): Stats;
|
||||||
|
statSync(path: PathLike, options: StatOptions & {
|
||||||
|
bigint: true;
|
||||||
|
}): BigIntStats;
|
||||||
|
statSync(path: PathLike, options?: StatOptions): Stats | BigIntStats;
|
||||||
|
lstatSync(path: PathLike, options?: StatOptions & {
|
||||||
|
bigint?: false;
|
||||||
|
}): Stats;
|
||||||
|
lstatSync(path: PathLike, options: StatOptions & {
|
||||||
|
bigint: true;
|
||||||
|
}): BigIntStats;
|
||||||
|
lstatSync(path: PathLike, options?: StatOptions): Stats | BigIntStats;
|
||||||
|
utimesSync(path: PathLike, atime: string | number | Date, mtime: string | number | Date): void;
|
||||||
|
openSync(path: PathLike, flags: OpenMode, mode?: Mode): number;
|
||||||
|
readSync(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number | null): number;
|
||||||
|
readSync(fd: number, buffer: ArrayBufferView, opts?: ReadSyncOptions): number;
|
||||||
|
writeSync(fd: number, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
|
||||||
|
writeSync(fd: number, string: string, position?: number, encoding?: BufferEncoding_2): number;
|
||||||
|
closeSync(fd: number): void;
|
||||||
|
readlinkSync(path: PathLike, options?: BaseEncodingOptions | BufferEncoding_2): string;
|
||||||
|
readlinkSync(path: PathLike, options: BufferEncodingOption): Uint8Array;
|
||||||
|
readlinkSync(path: PathLike, options?: BaseEncodingOptions | string): string | Uint8Array;
|
||||||
|
realpathSync(path: PathLike, options?: BaseEncodingOptions | BufferEncoding_2): string;
|
||||||
|
realpathSync(path: PathLike, options: BufferEncodingOption): Uint8Array;
|
||||||
|
realpathSync(path: PathLike, options?: BaseEncodingOptions | string): string | Uint8Array;
|
||||||
|
truncateSync(path: PathLike, len?: number): void;
|
||||||
|
ftruncateSync(fd: number, len?: number): void;
|
||||||
|
fdatasyncSync(fd: number): void;
|
||||||
|
futimesSync(fd: number, atime: string | number | Date, mtime: string | number | Date): void;
|
||||||
|
readdirSync(path: PathLike, options?: {
|
||||||
|
encoding: BufferEncoding_2 | null;
|
||||||
|
withFileTypes?: false;
|
||||||
|
} | BufferEncoding_2): string[];
|
||||||
|
readdirSync(path: PathLike, options: {
|
||||||
|
encoding: 'buffer';
|
||||||
|
withFileTypes?: false;
|
||||||
|
} | 'buffer'): Uint8Array[];
|
||||||
|
readdirSync(path: PathLike, options?: BaseEncodingOptions & {
|
||||||
|
withFileTypes?: false;
|
||||||
|
} | BufferEncoding_2): string[] | Uint8Array[];
|
||||||
|
readdirSync(path: PathLike, options: BaseEncodingOptions & {
|
||||||
|
withFileTypes: true;
|
||||||
|
}): IDirent[];
|
||||||
|
fsyncSync(fd: number): void;
|
||||||
|
mkdirSync(path: PathLike, options: MakeDirectoryOptions & {
|
||||||
|
recursive: true;
|
||||||
|
}): string | undefined;
|
||||||
|
mkdirSync(path: PathLike, options?: Mode | (MakeDirectoryOptions & {
|
||||||
|
recursive?: false;
|
||||||
|
})): void;
|
||||||
|
mkdirSync(path: PathLike, options?: Mode | MakeDirectoryOptions): string | undefined;
|
||||||
|
rmdirSync(path: PathLike, options?: RmDirOptions): void;
|
||||||
|
linkSync(existingPath: PathLike, newPath: PathLike): void;
|
||||||
|
unlinkSync(path: PathLike): void;
|
||||||
|
renameSync(oldPath: PathLike, newPath: PathLike): void;
|
||||||
|
symlinkSync(target: PathLike, path: PathLike, type?: 'dir' | 'file' | 'junction'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface IFsPromises {
|
||||||
|
stat(path: PathLike, options?: StatOptions & {
|
||||||
|
bigint?: false;
|
||||||
|
}): Promise<Stats>;
|
||||||
|
stat(path: PathLike, options: StatOptions & {
|
||||||
|
bigint: true;
|
||||||
|
}): Promise<BigIntStats>;
|
||||||
|
stat(path: PathLike, options?: StatOptions): Promise<Stats | BigIntStats>;
|
||||||
|
lstat(path: PathLike, options?: StatOptions & {
|
||||||
|
bigint?: false;
|
||||||
|
}): Promise<Stats>;
|
||||||
|
lstat(path: PathLike, options: StatOptions & {
|
||||||
|
bigint: true;
|
||||||
|
}): Promise<BigIntStats>;
|
||||||
|
lstat(path: PathLike, options?: StatOptions): Promise<Stats | BigIntStats>;
|
||||||
|
utimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
|
||||||
|
open(path: PathLike, flags: OpenMode, mode?: Mode): Promise<FileHandle>;
|
||||||
|
read<TBuffer extends Uint8Array>(handle: FileHandle, buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{
|
||||||
|
bytesRead: number;
|
||||||
|
buffer: TBuffer;
|
||||||
|
}>;
|
||||||
|
write<TBuffer extends Uint8Array>(handle: FileHandle, buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{
|
||||||
|
bytesWritten: number;
|
||||||
|
buffer: TBuffer;
|
||||||
|
}>;
|
||||||
|
readlink(path: PathLike, options?: BaseEncodingOptions | BufferEncoding_2): Promise<string>;
|
||||||
|
readlink(path: PathLike, options: BufferEncodingOption): Promise<Uint8Array>;
|
||||||
|
readlink(path: PathLike, options?: BaseEncodingOptions | string): Promise<string | Uint8Array>;
|
||||||
|
realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding_2): Promise<string>;
|
||||||
|
realpath(path: PathLike, options: BufferEncodingOption): Promise<Uint8Array>;
|
||||||
|
realpath(path: PathLike, options?: BaseEncodingOptions | string): Promise<string | Uint8Array>;
|
||||||
|
truncate(path: PathLike, len?: number): Promise<void>;
|
||||||
|
ftruncate(handle: FileHandle, len?: number): Promise<void>;
|
||||||
|
fdatasync(handle: FileHandle): Promise<void>;
|
||||||
|
futimes(handle: FileHandle, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
|
||||||
|
readdir(path: PathLike, options?: {
|
||||||
|
encoding: BufferEncoding_2 | null;
|
||||||
|
withFileTypes?: false;
|
||||||
|
} | BufferEncoding_2): Promise<string[]>;
|
||||||
|
readdir(path: PathLike, options: {
|
||||||
|
encoding: 'buffer';
|
||||||
|
withFileTypes?: false;
|
||||||
|
} | 'buffer'): Promise<Uint8Array[]>;
|
||||||
|
readdir(path: PathLike, options?: BaseEncodingOptions & {
|
||||||
|
withFileTypes?: false;
|
||||||
|
} | BufferEncoding_2): Promise<string[] | Uint8Array[]>;
|
||||||
|
readdir(path: PathLike, options: BaseEncodingOptions & {
|
||||||
|
withFileTypes: true;
|
||||||
|
}): Promise<IDirent[]>;
|
||||||
|
fsync(handle: FileHandle): Promise<void>;
|
||||||
|
mkdir(path: PathLike, options: MakeDirectoryOptions & {
|
||||||
|
recursive: true;
|
||||||
|
}): Promise<string | undefined>;
|
||||||
|
mkdir(path: PathLike, options?: Mode | (MakeDirectoryOptions & {
|
||||||
|
recursive?: false;
|
||||||
|
})): Promise<void>;
|
||||||
|
mkdir(path: PathLike, options?: Mode | MakeDirectoryOptions): Promise<string | undefined>;
|
||||||
|
rmdir(path: PathLike, options?: RmDirOptions): Promise<void>;
|
||||||
|
link(existingPath: PathLike, newPath: PathLike): Promise<void>;
|
||||||
|
unlink(path: PathLike): Promise<void>;
|
||||||
|
rename(oldPath: PathLike, newPath: PathLike): Promise<void>;
|
||||||
|
symlink(target: PathLike, path: PathLike, type?: 'dir' | 'file' | 'junction'): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const kBindingName: unique symbol;
|
||||||
|
|
||||||
|
declare const kExitCode: unique symbol;
|
||||||
|
|
||||||
|
declare const kInstance: unique symbol;
|
||||||
|
|
||||||
|
declare const kSetMemory: unique symbol;
|
||||||
|
|
||||||
|
declare const kStarted: unique symbol;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function load(wasmInput: string | URL | BufferSource | WebAssembly.Module, imports?: WebAssembly.Imports): Promise<WebAssembly.WebAssemblyInstantiatedSource>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function loadSync(wasmInput: BufferSource | WebAssembly.Module, imports?: WebAssembly.Imports): WebAssembly.WebAssemblyInstantiatedSource;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface MakeDirectoryOptions {
|
||||||
|
recursive?: boolean;
|
||||||
|
mode?: Mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class Memory extends WebAssemblyMemory {
|
||||||
|
constructor(descriptor: WebAssembly.MemoryDescriptor);
|
||||||
|
get HEAP8(): Int8Array;
|
||||||
|
get HEAPU8(): Uint8Array;
|
||||||
|
get HEAP16(): Int16Array;
|
||||||
|
get HEAPU16(): Uint16Array;
|
||||||
|
get HEAP32(): Int32Array;
|
||||||
|
get HEAPU32(): Uint32Array;
|
||||||
|
get HEAP64(): BigInt64Array;
|
||||||
|
get HEAPU64(): BigUint64Array;
|
||||||
|
get HEAPF32(): Float32Array;
|
||||||
|
get HEAPF64(): Float64Array;
|
||||||
|
get view(): DataView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type Mode = number | string;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type OpenMode = number | string;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type PathLike = string | Uint8Array | URL;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type PromisifyExports<T, U> = T extends Record<string, any> ? {
|
||||||
|
[P in keyof T]: T[P] extends Callable ? U extends Array<keyof T> ? P extends U[number] ? AsyncifyExportFunction<T[P]> : T[P] : AsyncifyExportFunction<T[P]> : T[P];
|
||||||
|
} : T;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface ReadSyncOptions {
|
||||||
|
offset?: number;
|
||||||
|
length?: number;
|
||||||
|
position?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface RmDirOptions {
|
||||||
|
maxRetries?: number;
|
||||||
|
recursive?: boolean;
|
||||||
|
retryDelay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StatOptions {
|
||||||
|
bigint?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface Stats extends StatsBase<number> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StatsBase<T> {
|
||||||
|
isFile(): boolean;
|
||||||
|
isDirectory(): boolean;
|
||||||
|
isBlockDevice(): boolean;
|
||||||
|
isCharacterDevice(): boolean;
|
||||||
|
isSymbolicLink(): boolean;
|
||||||
|
isFIFO(): boolean;
|
||||||
|
isSocket(): boolean;
|
||||||
|
dev: T;
|
||||||
|
ino: T;
|
||||||
|
mode: T;
|
||||||
|
nlink: T;
|
||||||
|
uid: T;
|
||||||
|
gid: T;
|
||||||
|
rdev: T;
|
||||||
|
size: T;
|
||||||
|
blksize: T;
|
||||||
|
blocks: T;
|
||||||
|
atimeMs: T;
|
||||||
|
mtimeMs: T;
|
||||||
|
ctimeMs: T;
|
||||||
|
birthtimeMs: T;
|
||||||
|
atime: Date;
|
||||||
|
mtime: Date;
|
||||||
|
ctime: Date;
|
||||||
|
birthtime: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface SyncWASIOptions extends WASIOptions {
|
||||||
|
fs?: IFs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class WASI {
|
||||||
|
private [kSetMemory];
|
||||||
|
private [kStarted];
|
||||||
|
private [kExitCode];
|
||||||
|
private [kInstance];
|
||||||
|
private [kBindingName];
|
||||||
|
readonly wasiImport: Record<string, any>;
|
||||||
|
constructor(options?: SyncWASIOptions);
|
||||||
|
finalizeBindings(instance: WebAssembly.Instance, { memory }?: FinalizeBindingsOptions): void;
|
||||||
|
start(instance: WebAssembly.Instance): number | undefined | Promise<number> | Promise<undefined>;
|
||||||
|
initialize(instance: WebAssembly.Instance): void | Promise<void>;
|
||||||
|
getImportObject(): Record<string, Record<string, any>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface WASIOptions {
|
||||||
|
version?: 'unstable' | 'preview1';
|
||||||
|
args?: string[] | undefined;
|
||||||
|
env?: Record<string, string> | undefined;
|
||||||
|
preopens?: Record<string, string> | undefined;
|
||||||
|
/**
|
||||||
|
* @defaultValue `false`
|
||||||
|
*/
|
||||||
|
returnOnExit?: boolean | undefined;
|
||||||
|
print?: (str: string) => void;
|
||||||
|
printErr?: (str: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare const WebAssemblyMemory: {
|
||||||
|
new (descriptor: WebAssembly.MemoryDescriptor): WebAssembly.Memory;
|
||||||
|
prototype: WebAssembly.Memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function wrapAsyncExport<T extends Function = any>(f: Function): T;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function wrapAsyncImport<T extends (...args: any[]) => any>(f: T, parameterType: WebAssembly.ValueType[], returnType: WebAssembly.ValueType[]): (...args: [object, ...Parameters<T>]) => ReturnType<T>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function wrapExports<T extends WebAssembly.Exports>(exports: T): PromisifyExports<T, void>;
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare function wrapExports<T extends WebAssembly.Exports, U extends Array<keyof T>>(exports: T, needWrap: U): PromisifyExports<T, U>;
|
||||||
|
|
||||||
|
export { }
|
||||||
|
|
||||||
|
export as namespace wasmUtil;
|
||||||
Generated
Vendored
+2932
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+2932
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+2954
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+158
@@ -0,0 +1,158 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Asyncify = void 0;
|
||||||
|
const webassembly_1 = require("./webassembly");
|
||||||
|
const util_1 = require("./wasi/util");
|
||||||
|
const ignoreNames = [
|
||||||
|
'asyncify_get_state',
|
||||||
|
'asyncify_start_rewind',
|
||||||
|
'asyncify_start_unwind',
|
||||||
|
'asyncify_stop_rewind',
|
||||||
|
'asyncify_stop_unwind'
|
||||||
|
];
|
||||||
|
// const wrappedExports = new WeakMap<WebAssembly.Exports, WebAssembly.Exports>()
|
||||||
|
var AsyncifyState;
|
||||||
|
(function (AsyncifyState) {
|
||||||
|
AsyncifyState[AsyncifyState["NONE"] = 0] = "NONE";
|
||||||
|
AsyncifyState[AsyncifyState["UNWINDING"] = 1] = "UNWINDING";
|
||||||
|
AsyncifyState[AsyncifyState["REWINDING"] = 2] = "REWINDING";
|
||||||
|
})(AsyncifyState || (AsyncifyState = {}));
|
||||||
|
function tryAllocate(instance, wasm64, size, mallocName) {
|
||||||
|
if (typeof instance.exports[mallocName] !== 'function' || size <= 0) {
|
||||||
|
return {
|
||||||
|
wasm64,
|
||||||
|
dataPtr: 16,
|
||||||
|
start: wasm64 ? 32 : 24,
|
||||||
|
end: 1024
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const malloc = instance.exports[mallocName];
|
||||||
|
const dataPtr = wasm64 ? Number(malloc(BigInt(16) + BigInt(size))) : malloc(8 + size);
|
||||||
|
if (dataPtr === 0) {
|
||||||
|
throw new Error('Allocate asyncify data failed');
|
||||||
|
}
|
||||||
|
return wasm64
|
||||||
|
? { wasm64, dataPtr, start: dataPtr + 16, end: dataPtr + 16 + size }
|
||||||
|
: { wasm64, dataPtr, start: dataPtr + 8, end: dataPtr + 8 + size };
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
class Asyncify {
|
||||||
|
constructor() {
|
||||||
|
this.value = undefined;
|
||||||
|
this.exports = undefined;
|
||||||
|
this.dataPtr = 0;
|
||||||
|
}
|
||||||
|
init(memory, instance, options) {
|
||||||
|
var _a, _b;
|
||||||
|
if (this.exports) {
|
||||||
|
throw new Error('Asyncify has been initialized');
|
||||||
|
}
|
||||||
|
if (!(memory instanceof webassembly_1._WebAssembly.Memory)) {
|
||||||
|
throw new TypeError('Require WebAssembly.Memory object');
|
||||||
|
}
|
||||||
|
const exports = instance.exports;
|
||||||
|
for (let i = 0; i < ignoreNames.length; ++i) {
|
||||||
|
if (typeof exports[ignoreNames[i]] !== 'function') {
|
||||||
|
throw new TypeError('Invalid asyncify wasm');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let address;
|
||||||
|
const wasm64 = Boolean(options.wasm64);
|
||||||
|
if (!options.tryAllocate) {
|
||||||
|
address = {
|
||||||
|
wasm64,
|
||||||
|
dataPtr: 16,
|
||||||
|
start: wasm64 ? 32 : 24,
|
||||||
|
end: 1024
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (options.tryAllocate === true) {
|
||||||
|
address = tryAllocate(instance, wasm64, 4096, 'malloc');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
address = tryAllocate(instance, wasm64, (_a = options.tryAllocate.size) !== null && _a !== void 0 ? _a : 4096, (_b = options.tryAllocate.name) !== null && _b !== void 0 ? _b : 'malloc');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.dataPtr = address.dataPtr;
|
||||||
|
if (wasm64) {
|
||||||
|
new BigInt64Array(memory.buffer, this.dataPtr).set([BigInt(address.start), BigInt(address.end)]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new Int32Array(memory.buffer, this.dataPtr).set([address.start, address.end]);
|
||||||
|
}
|
||||||
|
this.exports = this.wrapExports(exports, options.wrapExports);
|
||||||
|
const asyncifiedInstance = Object.create(webassembly_1._WebAssembly.Instance.prototype);
|
||||||
|
Object.defineProperty(asyncifiedInstance, 'exports', { value: this.exports });
|
||||||
|
// Object.setPrototypeOf(instance, Instance.prototype)
|
||||||
|
return asyncifiedInstance;
|
||||||
|
}
|
||||||
|
assertState() {
|
||||||
|
if (this.exports.asyncify_get_state() !== AsyncifyState.NONE) {
|
||||||
|
throw new Error('Asyncify state error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapImportFunction(f) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
const _this = this;
|
||||||
|
return (function () {
|
||||||
|
// eslint-disable-next-line no-unreachable-loop
|
||||||
|
while (_this.exports.asyncify_get_state() === AsyncifyState.REWINDING) {
|
||||||
|
_this.exports.asyncify_stop_rewind();
|
||||||
|
return _this.value;
|
||||||
|
}
|
||||||
|
_this.assertState();
|
||||||
|
const v = f.apply(this, arguments);
|
||||||
|
if (!(0, util_1.isPromiseLike)(v))
|
||||||
|
return v;
|
||||||
|
_this.exports.asyncify_start_unwind(_this.dataPtr);
|
||||||
|
_this.value = v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
wrapImports(imports) {
|
||||||
|
const importObject = {};
|
||||||
|
Object.keys(imports).forEach(k => {
|
||||||
|
const mod = imports[k];
|
||||||
|
const newModule = {};
|
||||||
|
Object.keys(mod).forEach(name => {
|
||||||
|
const importValue = mod[name];
|
||||||
|
if (typeof importValue === 'function') {
|
||||||
|
newModule[name] = this.wrapImportFunction(importValue);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newModule[name] = importValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
importObject[k] = newModule;
|
||||||
|
});
|
||||||
|
return importObject;
|
||||||
|
}
|
||||||
|
wrapExportFunction(f) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
const _this = this;
|
||||||
|
return (async function () {
|
||||||
|
_this.assertState();
|
||||||
|
let ret = f.apply(this, arguments);
|
||||||
|
while (_this.exports.asyncify_get_state() === AsyncifyState.UNWINDING) {
|
||||||
|
_this.exports.asyncify_stop_unwind();
|
||||||
|
_this.value = await _this.value;
|
||||||
|
_this.assertState();
|
||||||
|
_this.exports.asyncify_start_rewind(_this.dataPtr);
|
||||||
|
ret = f.call(this);
|
||||||
|
}
|
||||||
|
_this.assertState();
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
wrapExports(exports, needWrap) {
|
||||||
|
return (0, util_1.wrapInstanceExports)(exports, (exportValue, name) => {
|
||||||
|
let ignore = ignoreNames.indexOf(name) !== -1 || typeof exportValue !== 'function';
|
||||||
|
if (Array.isArray(needWrap)) {
|
||||||
|
ignore = ignore || (needWrap.indexOf(name) === -1);
|
||||||
|
}
|
||||||
|
return ignore ? exportValue : this.wrapExportFunction(exportValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Asyncify = Asyncify;
|
||||||
|
//# sourceMappingURL=asyncify.js.map
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
"use strict";
|
||||||
|
/**
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const tslib_1 = require("tslib");
|
||||||
|
tslib_1.__exportStar(require("./asyncify"), exports);
|
||||||
|
tslib_1.__exportStar(require("./load"), exports);
|
||||||
|
tslib_1.__exportStar(require("./wasi/index"), exports);
|
||||||
|
tslib_1.__exportStar(require("./memory"), exports);
|
||||||
|
tslib_1.__exportStar(require("./jspi"), exports);
|
||||||
|
tslib_1.__exportStar(require("./wasi/fs"), exports);
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.wrapExports = exports.wrapAsyncExport = exports.wrapAsyncImport = void 0;
|
||||||
|
const util_1 = require("./wasi/util");
|
||||||
|
const webassembly_1 = require("./webassembly");
|
||||||
|
function checkWebAssemblyFunction() {
|
||||||
|
const WebAssemblyFunction = webassembly_1._WebAssembly.Function;
|
||||||
|
if (typeof WebAssemblyFunction !== 'function') {
|
||||||
|
throw new Error('WebAssembly.Function is not supported in this environment.' +
|
||||||
|
' If you are using V8 based browser like Chrome, try to specify' +
|
||||||
|
' --js-flags="--wasm-staging --experimental-wasm-stack-switching"');
|
||||||
|
}
|
||||||
|
return WebAssemblyFunction;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
function wrapAsyncImport(f, parameterType, returnType) {
|
||||||
|
const WebAssemblyFunction = checkWebAssemblyFunction();
|
||||||
|
if (typeof f !== 'function') {
|
||||||
|
throw new TypeError('Function required');
|
||||||
|
}
|
||||||
|
const parameters = parameterType.slice(0);
|
||||||
|
parameters.unshift('externref');
|
||||||
|
return new WebAssemblyFunction({ parameters, results: returnType }, f, { suspending: 'first' });
|
||||||
|
}
|
||||||
|
exports.wrapAsyncImport = wrapAsyncImport;
|
||||||
|
/** @public */
|
||||||
|
function wrapAsyncExport(f) {
|
||||||
|
const WebAssemblyFunction = checkWebAssemblyFunction();
|
||||||
|
if (typeof f !== 'function') {
|
||||||
|
throw new TypeError('Function required');
|
||||||
|
}
|
||||||
|
return new WebAssemblyFunction({ parameters: [...WebAssemblyFunction.type(f).parameters.slice(1)], results: ['externref'] }, f, { promising: 'first' });
|
||||||
|
}
|
||||||
|
exports.wrapAsyncExport = wrapAsyncExport;
|
||||||
|
/** @public */
|
||||||
|
function wrapExports(exports, needWrap) {
|
||||||
|
return (0, util_1.wrapInstanceExports)(exports, (exportValue, name) => {
|
||||||
|
let ignore = typeof exportValue !== 'function';
|
||||||
|
if (Array.isArray(needWrap)) {
|
||||||
|
ignore = ignore || (needWrap.indexOf(name) === -1);
|
||||||
|
}
|
||||||
|
return ignore ? exportValue : wrapAsyncExport(exportValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.wrapExports = wrapExports;
|
||||||
|
//# sourceMappingURL=jspi.js.map
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.asyncifyLoadSync = exports.loadSync = exports.asyncifyLoad = exports.load = void 0;
|
||||||
|
const webassembly_1 = require("./webassembly");
|
||||||
|
const asyncify_1 = require("./asyncify");
|
||||||
|
function validateImports(imports) {
|
||||||
|
if (imports && typeof imports !== 'object') {
|
||||||
|
throw new TypeError('imports must be an object or undefined');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function fetchWasm(urlOrBuffer, imports) {
|
||||||
|
if (typeof wx !== 'undefined' && typeof __wxConfig !== 'undefined') {
|
||||||
|
return webassembly_1._WebAssembly.instantiate(urlOrBuffer, imports);
|
||||||
|
}
|
||||||
|
return fetch(urlOrBuffer)
|
||||||
|
.then(response => response.arrayBuffer())
|
||||||
|
.then(buffer => webassembly_1._WebAssembly.instantiate(buffer, imports));
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
function load(wasmInput, imports) {
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
let source;
|
||||||
|
if (wasmInput instanceof ArrayBuffer || ArrayBuffer.isView(wasmInput)) {
|
||||||
|
return webassembly_1._WebAssembly.instantiate(wasmInput, imports);
|
||||||
|
}
|
||||||
|
if (wasmInput instanceof webassembly_1._WebAssembly.Module) {
|
||||||
|
return webassembly_1._WebAssembly.instantiate(wasmInput, imports).then((instance) => {
|
||||||
|
return { instance, module: wasmInput };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (typeof wasmInput !== 'string' && !(wasmInput instanceof URL)) {
|
||||||
|
throw new TypeError('Invalid source');
|
||||||
|
}
|
||||||
|
if (typeof webassembly_1._WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
let responsePromise;
|
||||||
|
try {
|
||||||
|
responsePromise = fetch(wasmInput);
|
||||||
|
source = webassembly_1._WebAssembly.instantiateStreaming(responsePromise, imports).catch(() => {
|
||||||
|
return fetchWasm(wasmInput, imports);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
source = fetchWasm(wasmInput, imports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
source = fetchWasm(wasmInput, imports);
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
exports.load = load;
|
||||||
|
/** @public */
|
||||||
|
function asyncifyLoad(asyncify, urlOrBuffer, imports) {
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
const asyncifyHelper = new asyncify_1.Asyncify();
|
||||||
|
imports = asyncifyHelper.wrapImports(imports);
|
||||||
|
return load(urlOrBuffer, imports).then(source => {
|
||||||
|
var _a;
|
||||||
|
const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
|
||||||
|
return { module: source.module, instance: asyncifyHelper.init(memory, source.instance, asyncify) };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.asyncifyLoad = asyncifyLoad;
|
||||||
|
/** @public */
|
||||||
|
function loadSync(wasmInput, imports) {
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
let module;
|
||||||
|
if ((wasmInput instanceof ArrayBuffer) || ArrayBuffer.isView(wasmInput)) {
|
||||||
|
module = new webassembly_1._WebAssembly.Module(wasmInput);
|
||||||
|
}
|
||||||
|
else if (wasmInput instanceof WebAssembly.Module) {
|
||||||
|
module = wasmInput;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new TypeError('Invalid source');
|
||||||
|
}
|
||||||
|
const instance = new webassembly_1._WebAssembly.Instance(module, imports);
|
||||||
|
const source = { instance, module };
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
exports.loadSync = loadSync;
|
||||||
|
/** @public */
|
||||||
|
function asyncifyLoadSync(asyncify, buffer, imports) {
|
||||||
|
var _a;
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
const asyncifyHelper = new asyncify_1.Asyncify();
|
||||||
|
imports = asyncifyHelper.wrapImports(imports);
|
||||||
|
const source = loadSync(buffer, imports);
|
||||||
|
const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
|
||||||
|
return { module: source.module, instance: asyncifyHelper.init(memory, source.instance, asyncify) };
|
||||||
|
}
|
||||||
|
exports.asyncifyLoadSync = asyncifyLoadSync;
|
||||||
|
//# sourceMappingURL=load.js.map
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.extendMemory = exports.Memory = exports.WebAssemblyMemory = void 0;
|
||||||
|
/* eslint-disable spaced-comment */
|
||||||
|
const webassembly_1 = require("./webassembly");
|
||||||
|
/** @public */
|
||||||
|
exports.WebAssemblyMemory = (function () { return webassembly_1._WebAssembly.Memory; })();
|
||||||
|
/** @public */
|
||||||
|
class Memory extends exports.WebAssemblyMemory {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor(descriptor) {
|
||||||
|
super(descriptor);
|
||||||
|
}
|
||||||
|
get HEAP8() { return new Int8Array(super.buffer); }
|
||||||
|
get HEAPU8() { return new Uint8Array(super.buffer); }
|
||||||
|
get HEAP16() { return new Int16Array(super.buffer); }
|
||||||
|
get HEAPU16() { return new Uint16Array(super.buffer); }
|
||||||
|
get HEAP32() { return new Int32Array(super.buffer); }
|
||||||
|
get HEAPU32() { return new Uint32Array(super.buffer); }
|
||||||
|
get HEAP64() { return new BigInt64Array(super.buffer); }
|
||||||
|
get HEAPU64() { return new BigUint64Array(super.buffer); }
|
||||||
|
get HEAPF32() { return new Float32Array(super.buffer); }
|
||||||
|
get HEAPF64() { return new Float64Array(super.buffer); }
|
||||||
|
get view() { return new DataView(super.buffer); }
|
||||||
|
}
|
||||||
|
exports.Memory = Memory;
|
||||||
|
/** @public */
|
||||||
|
function extendMemory(memory) {
|
||||||
|
if (Object.getPrototypeOf(memory) === webassembly_1._WebAssembly.Memory.prototype) {
|
||||||
|
Object.setPrototypeOf(memory, Memory.prototype);
|
||||||
|
}
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
exports.extendMemory = extendMemory;
|
||||||
|
//# sourceMappingURL=memory.js.map
|
||||||
Generated
Vendored
+103
@@ -0,0 +1,103 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.WasiError = exports.strerror = void 0;
|
||||||
|
const types_1 = require("./types");
|
||||||
|
function strerror(errno) {
|
||||||
|
switch (errno) {
|
||||||
|
case types_1.WasiErrno.ESUCCESS: return 'Success';
|
||||||
|
case types_1.WasiErrno.E2BIG: return 'Argument list too long';
|
||||||
|
case types_1.WasiErrno.EACCES: return 'Permission denied';
|
||||||
|
case types_1.WasiErrno.EADDRINUSE: return 'Address in use';
|
||||||
|
case types_1.WasiErrno.EADDRNOTAVAIL: return 'Address not available';
|
||||||
|
case types_1.WasiErrno.EAFNOSUPPORT: return 'Address family not supported by protocol';
|
||||||
|
case types_1.WasiErrno.EAGAIN: return 'Resource temporarily unavailable';
|
||||||
|
case types_1.WasiErrno.EALREADY: return 'Operation already in progress';
|
||||||
|
case types_1.WasiErrno.EBADF: return 'Bad file descriptor';
|
||||||
|
case types_1.WasiErrno.EBADMSG: return 'Bad message';
|
||||||
|
case types_1.WasiErrno.EBUSY: return 'Resource busy';
|
||||||
|
case types_1.WasiErrno.ECANCELED: return 'Operation canceled';
|
||||||
|
case types_1.WasiErrno.ECHILD: return 'No child process';
|
||||||
|
case types_1.WasiErrno.ECONNABORTED: return 'Connection aborted';
|
||||||
|
case types_1.WasiErrno.ECONNREFUSED: return 'Connection refused';
|
||||||
|
case types_1.WasiErrno.ECONNRESET: return 'Connection reset by peer';
|
||||||
|
case types_1.WasiErrno.EDEADLK: return 'Resource deadlock would occur';
|
||||||
|
case types_1.WasiErrno.EDESTADDRREQ: return 'Destination address required';
|
||||||
|
case types_1.WasiErrno.EDOM: return 'Domain error';
|
||||||
|
case types_1.WasiErrno.EDQUOT: return 'Quota exceeded';
|
||||||
|
case types_1.WasiErrno.EEXIST: return 'File exists';
|
||||||
|
case types_1.WasiErrno.EFAULT: return 'Bad address';
|
||||||
|
case types_1.WasiErrno.EFBIG: return 'File too large';
|
||||||
|
case types_1.WasiErrno.EHOSTUNREACH: return 'Host is unreachable';
|
||||||
|
case types_1.WasiErrno.EIDRM: return 'Identifier removed';
|
||||||
|
case types_1.WasiErrno.EILSEQ: return 'Illegal byte sequence';
|
||||||
|
case types_1.WasiErrno.EINPROGRESS: return 'Operation in progress';
|
||||||
|
case types_1.WasiErrno.EINTR: return 'Interrupted system call';
|
||||||
|
case types_1.WasiErrno.EINVAL: return 'Invalid argument';
|
||||||
|
case types_1.WasiErrno.EIO: return 'I/O error';
|
||||||
|
case types_1.WasiErrno.EISCONN: return 'Socket is connected';
|
||||||
|
case types_1.WasiErrno.EISDIR: return 'Is a directory';
|
||||||
|
case types_1.WasiErrno.ELOOP: return 'Symbolic link loop';
|
||||||
|
case types_1.WasiErrno.EMFILE: return 'No file descriptors available';
|
||||||
|
case types_1.WasiErrno.EMLINK: return 'Too many links';
|
||||||
|
case types_1.WasiErrno.EMSGSIZE: return 'Message too large';
|
||||||
|
case types_1.WasiErrno.EMULTIHOP: return 'Multihop attempted';
|
||||||
|
case types_1.WasiErrno.ENAMETOOLONG: return 'Filename too long';
|
||||||
|
case types_1.WasiErrno.ENETDOWN: return 'Network is down';
|
||||||
|
case types_1.WasiErrno.ENETRESET: return 'Connection reset by network';
|
||||||
|
case types_1.WasiErrno.ENETUNREACH: return 'Network unreachable';
|
||||||
|
case types_1.WasiErrno.ENFILE: return 'Too many files open in system';
|
||||||
|
case types_1.WasiErrno.ENOBUFS: return 'No buffer space available';
|
||||||
|
case types_1.WasiErrno.ENODEV: return 'No such device';
|
||||||
|
case types_1.WasiErrno.ENOENT: return 'No such file or directory';
|
||||||
|
case types_1.WasiErrno.ENOEXEC: return 'Exec format error';
|
||||||
|
case types_1.WasiErrno.ENOLCK: return 'No locks available';
|
||||||
|
case types_1.WasiErrno.ENOLINK: return 'Link has been severed';
|
||||||
|
case types_1.WasiErrno.ENOMEM: return 'Out of memory';
|
||||||
|
case types_1.WasiErrno.ENOMSG: return 'No message of the desired type';
|
||||||
|
case types_1.WasiErrno.ENOPROTOOPT: return 'Protocol not available';
|
||||||
|
case types_1.WasiErrno.ENOSPC: return 'No space left on device';
|
||||||
|
case types_1.WasiErrno.ENOSYS: return 'Function not implemented';
|
||||||
|
case types_1.WasiErrno.ENOTCONN: return 'Socket not connected';
|
||||||
|
case types_1.WasiErrno.ENOTDIR: return 'Not a directory';
|
||||||
|
case types_1.WasiErrno.ENOTEMPTY: return 'Directory not empty';
|
||||||
|
case types_1.WasiErrno.ENOTRECOVERABLE: return 'State not recoverable';
|
||||||
|
case types_1.WasiErrno.ENOTSOCK: return 'Not a socket';
|
||||||
|
case types_1.WasiErrno.ENOTSUP: return 'Not supported';
|
||||||
|
case types_1.WasiErrno.ENOTTY: return 'Not a tty';
|
||||||
|
case types_1.WasiErrno.ENXIO: return 'No such device or address';
|
||||||
|
case types_1.WasiErrno.EOVERFLOW: return 'Value too large for data type';
|
||||||
|
case types_1.WasiErrno.EOWNERDEAD: return 'Previous owner died';
|
||||||
|
case types_1.WasiErrno.EPERM: return 'Operation not permitted';
|
||||||
|
case types_1.WasiErrno.EPIPE: return 'Broken pipe';
|
||||||
|
case types_1.WasiErrno.EPROTO: return 'Protocol error';
|
||||||
|
case types_1.WasiErrno.EPROTONOSUPPORT: return 'Protocol not supported';
|
||||||
|
case types_1.WasiErrno.EPROTOTYPE: return 'Protocol wrong type for socket';
|
||||||
|
case types_1.WasiErrno.ERANGE: return 'Result not representable';
|
||||||
|
case types_1.WasiErrno.EROFS: return 'Read-only file system';
|
||||||
|
case types_1.WasiErrno.ESPIPE: return 'Invalid seek';
|
||||||
|
case types_1.WasiErrno.ESRCH: return 'No such process';
|
||||||
|
case types_1.WasiErrno.ESTALE: return 'Stale file handle';
|
||||||
|
case types_1.WasiErrno.ETIMEDOUT: return 'Operation timed out';
|
||||||
|
case types_1.WasiErrno.ETXTBSY: return 'Text file busy';
|
||||||
|
case types_1.WasiErrno.EXDEV: return 'Cross-device link';
|
||||||
|
case types_1.WasiErrno.ENOTCAPABLE: return 'Capabilities insufficient';
|
||||||
|
default: return 'Unknown error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.strerror = strerror;
|
||||||
|
class WasiError extends Error {
|
||||||
|
constructor(message, errno) {
|
||||||
|
super(message);
|
||||||
|
this.errno = errno;
|
||||||
|
}
|
||||||
|
getErrorMessage() {
|
||||||
|
return strerror(this.errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.WasiError = WasiError;
|
||||||
|
Object.defineProperty(WasiError.prototype, 'name', {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: 'WasiError'
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=error.js.map
|
||||||
+268
@@ -0,0 +1,268 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.AsyncTable = exports.SyncTable = exports.FileDescriptorTable = exports.toFileStat = exports.toFileType = exports.StandardOutput = exports.FileDescriptor = exports.concatBuffer = void 0;
|
||||||
|
const types_1 = require("./types");
|
||||||
|
const rights_1 = require("./rights");
|
||||||
|
const error_1 = require("./error");
|
||||||
|
function concatBuffer(buffers, size) {
|
||||||
|
let total = 0;
|
||||||
|
if (typeof size === 'number' && size >= 0) {
|
||||||
|
total = size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (let i = 0; i < buffers.length; i++) {
|
||||||
|
const buffer = buffers[i];
|
||||||
|
total += buffer.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let pos = 0;
|
||||||
|
const ret = new Uint8Array(total);
|
||||||
|
for (let i = 0; i < buffers.length; i++) {
|
||||||
|
const buffer = buffers[i];
|
||||||
|
ret.set(buffer, pos);
|
||||||
|
pos += buffer.length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
exports.concatBuffer = concatBuffer;
|
||||||
|
class FileDescriptor {
|
||||||
|
constructor(id, fd, path, realPath, type, rightsBase, rightsInheriting, preopen) {
|
||||||
|
this.id = id;
|
||||||
|
this.fd = fd;
|
||||||
|
this.path = path;
|
||||||
|
this.realPath = realPath;
|
||||||
|
this.type = type;
|
||||||
|
this.rightsBase = rightsBase;
|
||||||
|
this.rightsInheriting = rightsInheriting;
|
||||||
|
this.preopen = preopen;
|
||||||
|
this.pos = BigInt(0);
|
||||||
|
this.size = BigInt(0);
|
||||||
|
}
|
||||||
|
seek(offset, whence) {
|
||||||
|
if (whence === types_1.WasiWhence.SET) {
|
||||||
|
this.pos = BigInt(offset);
|
||||||
|
}
|
||||||
|
else if (whence === types_1.WasiWhence.CUR) {
|
||||||
|
this.pos += BigInt(offset);
|
||||||
|
}
|
||||||
|
else if (whence === types_1.WasiWhence.END) {
|
||||||
|
this.pos = BigInt(this.size) - BigInt(offset);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new error_1.WasiError('Unknown whence', types_1.WasiErrno.EIO);
|
||||||
|
}
|
||||||
|
return this.pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.FileDescriptor = FileDescriptor;
|
||||||
|
class StandardOutput extends FileDescriptor {
|
||||||
|
constructor(log, id, fd, path, realPath, type, rightsBase, rightsInheriting, preopen) {
|
||||||
|
super(id, fd, path, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
this._log = log;
|
||||||
|
this._buf = null;
|
||||||
|
}
|
||||||
|
write(buffer) {
|
||||||
|
const originalBuffer = buffer;
|
||||||
|
if (this._buf) {
|
||||||
|
buffer = concatBuffer([this._buf, buffer]);
|
||||||
|
this._buf = null;
|
||||||
|
}
|
||||||
|
if (buffer.indexOf(10) === -1) {
|
||||||
|
this._buf = buffer;
|
||||||
|
return originalBuffer.byteLength;
|
||||||
|
}
|
||||||
|
let written = 0;
|
||||||
|
let lastBegin = 0;
|
||||||
|
let index;
|
||||||
|
while ((index = buffer.indexOf(10, written)) !== -1) {
|
||||||
|
const str = new TextDecoder().decode(buffer.subarray(lastBegin, index));
|
||||||
|
this._log(str);
|
||||||
|
written += index - lastBegin + 1;
|
||||||
|
lastBegin = index + 1;
|
||||||
|
}
|
||||||
|
if (written < buffer.length) {
|
||||||
|
this._buf = buffer.slice(written);
|
||||||
|
}
|
||||||
|
return originalBuffer.byteLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.StandardOutput = StandardOutput;
|
||||||
|
function toFileType(stat) {
|
||||||
|
if (stat.isBlockDevice())
|
||||||
|
return types_1.WasiFileType.BLOCK_DEVICE;
|
||||||
|
if (stat.isCharacterDevice())
|
||||||
|
return types_1.WasiFileType.CHARACTER_DEVICE;
|
||||||
|
if (stat.isDirectory())
|
||||||
|
return types_1.WasiFileType.DIRECTORY;
|
||||||
|
if (stat.isSocket())
|
||||||
|
return types_1.WasiFileType.SOCKET_STREAM;
|
||||||
|
if (stat.isFile())
|
||||||
|
return types_1.WasiFileType.REGULAR_FILE;
|
||||||
|
if (stat.isSymbolicLink())
|
||||||
|
return types_1.WasiFileType.SYMBOLIC_LINK;
|
||||||
|
return types_1.WasiFileType.UNKNOWN;
|
||||||
|
}
|
||||||
|
exports.toFileType = toFileType;
|
||||||
|
function toFileStat(view, buf, stat) {
|
||||||
|
view.setBigUint64(buf, stat.dev, true);
|
||||||
|
view.setBigUint64(buf + 8, stat.ino, true);
|
||||||
|
view.setBigUint64(buf + 16, BigInt(toFileType(stat)), true);
|
||||||
|
view.setBigUint64(buf + 24, stat.nlink, true);
|
||||||
|
view.setBigUint64(buf + 32, stat.size, true);
|
||||||
|
view.setBigUint64(buf + 40, stat.atimeMs * BigInt(1000000), true);
|
||||||
|
view.setBigUint64(buf + 48, stat.mtimeMs * BigInt(1000000), true);
|
||||||
|
view.setBigUint64(buf + 56, stat.ctimeMs * BigInt(1000000), true);
|
||||||
|
}
|
||||||
|
exports.toFileStat = toFileStat;
|
||||||
|
class FileDescriptorTable {
|
||||||
|
constructor(options) {
|
||||||
|
this.used = 0;
|
||||||
|
this.size = options.size;
|
||||||
|
this.fds = Array(options.size);
|
||||||
|
this.stdio = [options.in, options.out, options.err];
|
||||||
|
this.print = options.print;
|
||||||
|
this.printErr = options.printErr;
|
||||||
|
this.insertStdio(options.in, 0, '<stdin>');
|
||||||
|
this.insertStdio(options.out, 1, '<stdout>');
|
||||||
|
this.insertStdio(options.err, 2, '<stderr>');
|
||||||
|
}
|
||||||
|
insertStdio(fd, expected, name) {
|
||||||
|
const type = types_1.WasiFileType.CHARACTER_DEVICE;
|
||||||
|
const { base, inheriting } = (0, rights_1.getRights)(this.stdio, fd, types_1.FileControlFlag.O_RDWR, type);
|
||||||
|
const wrap = this.insert(fd, name, name, type, base, inheriting, 0);
|
||||||
|
if (wrap.id !== expected) {
|
||||||
|
throw new error_1.WasiError(`id: ${wrap.id} !== expected: ${expected}`, types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
insert(fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen) {
|
||||||
|
var _a, _b;
|
||||||
|
let index = -1;
|
||||||
|
if (this.used >= this.size) {
|
||||||
|
const newSize = this.size * 2;
|
||||||
|
this.fds.length = newSize;
|
||||||
|
index = this.size;
|
||||||
|
this.size = newSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (let i = 0; i < this.size; ++i) {
|
||||||
|
if (this.fds[i] == null) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let entry;
|
||||||
|
if (mappedPath === '<stdout>') {
|
||||||
|
entry = new StandardOutput((_a = this.print) !== null && _a !== void 0 ? _a : console.log, index, fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
}
|
||||||
|
else if (mappedPath === '<stderr>') {
|
||||||
|
entry = new StandardOutput((_b = this.printErr) !== null && _b !== void 0 ? _b : console.error, index, fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry = new FileDescriptor(index, fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
}
|
||||||
|
this.fds[index] = entry;
|
||||||
|
this.used++;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
get(id, base, inheriting) {
|
||||||
|
if (id >= this.size) {
|
||||||
|
throw new error_1.WasiError('Invalid fd', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const entry = this.fds[id];
|
||||||
|
if (!entry || entry.id !== id) {
|
||||||
|
throw new error_1.WasiError('Bad file descriptor', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
/* Validate that the fd has the necessary rights. */
|
||||||
|
if ((~entry.rightsBase & base) !== BigInt(0) || (~entry.rightsInheriting & inheriting) !== BigInt(0)) {
|
||||||
|
throw new error_1.WasiError('Capabilities insufficient', types_1.WasiErrno.ENOTCAPABLE);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
remove(id) {
|
||||||
|
if (id >= this.size) {
|
||||||
|
throw new error_1.WasiError('Invalid fd', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const entry = this.fds[id];
|
||||||
|
if (!entry || entry.id !== id) {
|
||||||
|
throw new error_1.WasiError('Bad file descriptor', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
this.fds[id] = undefined;
|
||||||
|
this.used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.FileDescriptorTable = FileDescriptorTable;
|
||||||
|
class SyncTable extends FileDescriptorTable {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
this.fs = options.fs;
|
||||||
|
}
|
||||||
|
getFileTypeByFd(fd) {
|
||||||
|
const stats = this.fs.fstatSync(fd, { bigint: true });
|
||||||
|
return toFileType(stats);
|
||||||
|
}
|
||||||
|
insertPreopen(fd, mappedPath, realPath) {
|
||||||
|
const type = this.getFileTypeByFd(fd);
|
||||||
|
if (type !== types_1.WasiFileType.DIRECTORY) {
|
||||||
|
throw new error_1.WasiError(`Preopen not dir: ["${mappedPath}", "${realPath}"]`, types_1.WasiErrno.ENOTDIR);
|
||||||
|
}
|
||||||
|
const result = (0, rights_1.getRights)(this.stdio, fd, 0, type);
|
||||||
|
return this.insert(fd, mappedPath, realPath, type, result.base, result.inheriting, 1);
|
||||||
|
}
|
||||||
|
renumber(dst, src) {
|
||||||
|
if (dst === src)
|
||||||
|
return;
|
||||||
|
if (dst >= this.size || src >= this.size) {
|
||||||
|
throw new error_1.WasiError('Invalid fd', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const dstEntry = this.fds[dst];
|
||||||
|
const srcEntry = this.fds[src];
|
||||||
|
if (!dstEntry || !srcEntry || dstEntry.id !== dst || srcEntry.id !== src) {
|
||||||
|
throw new error_1.WasiError('Invalid fd', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
this.fs.closeSync(dstEntry.fd);
|
||||||
|
this.fds[dst] = this.fds[src];
|
||||||
|
this.fds[dst].id = dst;
|
||||||
|
this.fds[src] = undefined;
|
||||||
|
this.used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SyncTable = SyncTable;
|
||||||
|
class AsyncTable extends FileDescriptorTable {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
}
|
||||||
|
async getFileTypeByFd(fd) {
|
||||||
|
const stats = await fd.stat({ bigint: true });
|
||||||
|
return toFileType(stats);
|
||||||
|
}
|
||||||
|
async insertPreopen(fd, mappedPath, realPath) {
|
||||||
|
const type = await this.getFileTypeByFd(fd);
|
||||||
|
if (type !== types_1.WasiFileType.DIRECTORY) {
|
||||||
|
throw new error_1.WasiError(`Preopen not dir: ["${mappedPath}", "${realPath}"]`, types_1.WasiErrno.ENOTDIR);
|
||||||
|
}
|
||||||
|
const result = (0, rights_1.getRights)(this.stdio, fd.fd, 0, type);
|
||||||
|
return this.insert(fd, mappedPath, realPath, type, result.base, result.inheriting, 1);
|
||||||
|
}
|
||||||
|
async renumber(dst, src) {
|
||||||
|
if (dst === src)
|
||||||
|
return;
|
||||||
|
if (dst >= this.size || src >= this.size) {
|
||||||
|
throw new error_1.WasiError('Invalid fd', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const dstEntry = this.fds[dst];
|
||||||
|
const srcEntry = this.fds[src];
|
||||||
|
if (!dstEntry || !srcEntry || dstEntry.id !== dst || srcEntry.id !== src) {
|
||||||
|
throw new error_1.WasiError('Invalid fd', types_1.WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
await dstEntry.fd.close();
|
||||||
|
this.fds[dst] = this.fds[src];
|
||||||
|
this.fds[dst].id = dst;
|
||||||
|
this.fds[src] = undefined;
|
||||||
|
this.used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.AsyncTable = AsyncTable;
|
||||||
|
//# sourceMappingURL=fd.js.map
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
//# sourceMappingURL=fs.js.map
|
||||||
Generated
Vendored
+192
@@ -0,0 +1,192 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.createAsyncWASI = exports.WASI = void 0;
|
||||||
|
const preview1_1 = require("./preview1");
|
||||||
|
const util_1 = require("./util");
|
||||||
|
// eslint-disable-next-line spaced-comment
|
||||||
|
const kEmptyObject = /*#__PURE__*/ Object.freeze(/*#__PURE__*/ Object.create(null));
|
||||||
|
const kExitCode = Symbol('kExitCode');
|
||||||
|
const kSetMemory = Symbol('kSetMemory');
|
||||||
|
const kStarted = Symbol('kStarted');
|
||||||
|
const kInstance = Symbol('kInstance');
|
||||||
|
const kBindingName = Symbol('kBindingName');
|
||||||
|
function validateOptions(options) {
|
||||||
|
var _a;
|
||||||
|
(0, util_1.validateObject)(options, 'options');
|
||||||
|
let _WASI;
|
||||||
|
if (options.version !== undefined) {
|
||||||
|
(0, util_1.validateString)(options.version, 'options.version');
|
||||||
|
switch (options.version) {
|
||||||
|
case 'unstable':
|
||||||
|
_WASI = preview1_1.WASI;
|
||||||
|
this[kBindingName] = 'wasi_unstable';
|
||||||
|
break;
|
||||||
|
case 'preview1':
|
||||||
|
_WASI = preview1_1.WASI;
|
||||||
|
this[kBindingName] = 'wasi_snapshot_preview1';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new TypeError(`unsupported WASI version "${options.version}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_WASI = preview1_1.WASI;
|
||||||
|
this[kBindingName] = 'wasi_snapshot_preview1';
|
||||||
|
}
|
||||||
|
if (options.args !== undefined) {
|
||||||
|
(0, util_1.validateArray)(options.args, 'options.args');
|
||||||
|
}
|
||||||
|
const args = ((_a = options.args) !== null && _a !== void 0 ? _a : []).map(String);
|
||||||
|
const env = [];
|
||||||
|
if (options.env !== undefined) {
|
||||||
|
(0, util_1.validateObject)(options.env, 'options.env');
|
||||||
|
Object.entries(options.env).forEach(({ 0: key, 1: value }) => {
|
||||||
|
if (value !== undefined) {
|
||||||
|
env.push(`${key}=${value}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const preopens = [];
|
||||||
|
if (options.preopens !== undefined) {
|
||||||
|
(0, util_1.validateObject)(options.preopens, 'options.preopens');
|
||||||
|
Object.entries(options.preopens).forEach(({ 0: key, 1: value }) => preopens.push({ mappedPath: String(key), realPath: String(value) }));
|
||||||
|
}
|
||||||
|
if (preopens.length > 0) {
|
||||||
|
if (options.fs === undefined) {
|
||||||
|
throw new Error('filesystem is disabled, can not preopen directory');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
(0, util_1.validateObject)(options.fs, 'options.fs');
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
throw new TypeError('Node.js fs like implementation is not provided');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if (options.filesystem !== undefined) {
|
||||||
|
// validateObject(options.filesystem, 'options.filesystem')
|
||||||
|
// validateString(options.filesystem.type, 'options.filesystem.type')
|
||||||
|
// if (options.filesystem.type !== 'memfs' && options.filesystem.type !== 'file-system-access-api') {
|
||||||
|
// throw new Error(`Filesystem type ${(options.filesystem as any).type as string} is not supported, only "memfs" and "file-system-access-api" is supported currently`)
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// validateObject(options.filesystem.fs, 'options.filesystem.fs')
|
||||||
|
// } catch (_) {
|
||||||
|
// throw new Error('Node.js fs like implementation is not provided')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (options.print !== undefined)
|
||||||
|
(0, util_1.validateFunction)(options.print, 'options.print');
|
||||||
|
if (options.printErr !== undefined)
|
||||||
|
(0, util_1.validateFunction)(options.printErr, 'options.printErr');
|
||||||
|
if (options.returnOnExit !== undefined) {
|
||||||
|
(0, util_1.validateBoolean)(options.returnOnExit, 'options.returnOnExit');
|
||||||
|
}
|
||||||
|
// const { stdin = 0, stdout = 1, stderr = 2 } = options
|
||||||
|
// validateInt32(stdin, 'options.stdin', 0)
|
||||||
|
// validateInt32(stdout, 'options.stdout', 0)
|
||||||
|
// validateInt32(stderr, 'options.stderr', 0)
|
||||||
|
// const stdio = [stdin, stdout, stderr] as const
|
||||||
|
const stdio = [0, 1, 2];
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
env,
|
||||||
|
preopens,
|
||||||
|
stdio,
|
||||||
|
_WASI
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function initWASI(setMemory, wrap) {
|
||||||
|
this[kSetMemory] = setMemory;
|
||||||
|
this.wasiImport = wrap;
|
||||||
|
this[kStarted] = false;
|
||||||
|
this[kExitCode] = 0;
|
||||||
|
this[kInstance] = undefined;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
class WASI {
|
||||||
|
constructor(options = kEmptyObject) {
|
||||||
|
const { args, env, preopens, stdio, _WASI } = validateOptions.call(this, options);
|
||||||
|
const wrap = _WASI.createSync(args, env, preopens, stdio, options.fs, options.print, options.printErr);
|
||||||
|
const setMemory = wrap._setMemory;
|
||||||
|
delete wrap._setMemory;
|
||||||
|
initWASI.call(this, setMemory, wrap);
|
||||||
|
if (options.returnOnExit) {
|
||||||
|
wrap.proc_exit = wasiReturnOnProcExit.bind(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finalizeBindings(instance, _a) {
|
||||||
|
var _b;
|
||||||
|
var { memory = (_b = instance === null || instance === void 0 ? void 0 : instance.exports) === null || _b === void 0 ? void 0 : _b.memory } = _a === void 0 ? {} : _a;
|
||||||
|
if (this[kStarted]) {
|
||||||
|
throw new Error('WASI instance has already started');
|
||||||
|
}
|
||||||
|
(0, util_1.validateObject)(instance, 'instance');
|
||||||
|
(0, util_1.validateObject)(instance.exports, 'instance.exports');
|
||||||
|
this[kSetMemory](memory);
|
||||||
|
this[kInstance] = instance;
|
||||||
|
this[kStarted] = true;
|
||||||
|
}
|
||||||
|
// Must not export _initialize, must export _start
|
||||||
|
start(instance) {
|
||||||
|
this.finalizeBindings(instance);
|
||||||
|
const { _start, _initialize } = this[kInstance].exports;
|
||||||
|
(0, util_1.validateFunction)(_start, 'instance.exports._start');
|
||||||
|
(0, util_1.validateUndefined)(_initialize, 'instance.exports._initialize');
|
||||||
|
let ret;
|
||||||
|
try {
|
||||||
|
ret = _start();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err !== kExitCode) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret instanceof Promise) {
|
||||||
|
return ret.then(() => this[kExitCode], (err) => {
|
||||||
|
if (err !== kExitCode) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
return this[kExitCode];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this[kExitCode];
|
||||||
|
}
|
||||||
|
// Must not export _start, may optionally export _initialize
|
||||||
|
initialize(instance) {
|
||||||
|
this.finalizeBindings(instance);
|
||||||
|
const { _start, _initialize } = this[kInstance].exports;
|
||||||
|
(0, util_1.validateUndefined)(_start, 'instance.exports._start');
|
||||||
|
if (_initialize !== undefined) {
|
||||||
|
(0, util_1.validateFunction)(_initialize, 'instance.exports._initialize');
|
||||||
|
return _initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getImportObject() {
|
||||||
|
return { [this[kBindingName]]: this.wasiImport };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.WASI = WASI;
|
||||||
|
function wasiReturnOnProcExit(rval) {
|
||||||
|
this[kExitCode] = rval;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
||||||
|
throw kExitCode;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
async function createAsyncWASI(options = kEmptyObject) {
|
||||||
|
const _this = Object.create(WASI.prototype);
|
||||||
|
const { args, env, preopens, stdio, _WASI } = validateOptions.call(_this, options);
|
||||||
|
if (options.asyncify !== undefined) {
|
||||||
|
(0, util_1.validateObject)(options.asyncify, 'options.asyncify');
|
||||||
|
(0, util_1.validateFunction)(options.asyncify.wrapImportFunction, 'options.asyncify.wrapImportFunction');
|
||||||
|
}
|
||||||
|
const wrap = await _WASI.createAsync(args, env, preopens, stdio, options.fs, options.print, options.printErr, options.asyncify);
|
||||||
|
const setMemory = wrap._setMemory;
|
||||||
|
delete wrap._setMemory;
|
||||||
|
initWASI.call(_this, setMemory, wrap);
|
||||||
|
if (options.returnOnExit) {
|
||||||
|
wrap.proc_exit = wasiReturnOnProcExit.bind(_this);
|
||||||
|
}
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
exports.createAsyncWASI = createAsyncWASI;
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
Generated
Vendored
+316
@@ -0,0 +1,316 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.relative = exports.resolve = void 0;
|
||||||
|
const util_1 = require("./util");
|
||||||
|
const CHAR_DOT = 46; /* . */
|
||||||
|
const CHAR_FORWARD_SLASH = 47; /* / */
|
||||||
|
const CHAR_BACKWARD_SLASH = 92; /* \ */
|
||||||
|
const CHAR_COLON = 58; /* : */
|
||||||
|
const CHAR_UPPERCASE_A = 65; /* A */
|
||||||
|
const CHAR_UPPERCASE_Z = 90; /* Z */
|
||||||
|
const CHAR_LOWERCASE_A = 97; /* a */
|
||||||
|
const CHAR_LOWERCASE_Z = 122; /* z */
|
||||||
|
function isPathSeparatorWin(code) {
|
||||||
|
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
||||||
|
}
|
||||||
|
function isWindowsDeviceRoot(code) {
|
||||||
|
return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
|
||||||
|
(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
|
||||||
|
}
|
||||||
|
const _isWin32 = typeof process !== 'undefined' && process.platform === 'win32';
|
||||||
|
/**
|
||||||
|
* Windows variant of `resolve()`. Mirrors Node's `path.win32.resolve`
|
||||||
|
* semantics enough for the WASI shim's needs (drive-letter absolutes
|
||||||
|
* + UNC paths + per-drive cwd lookups via `process.env`/`process.cwd`).
|
||||||
|
*
|
||||||
|
* Why this is needed: on Windows, `FileDescriptor.realPath` is the
|
||||||
|
* host realpath returned by `fs.realpathSync(realPath, 'utf8')` — the
|
||||||
|
* backslash form `D:\…`. The POSIX-only `resolveImpl` below only
|
||||||
|
* treats `/` as a separator, reads `D` as non-`/`, decides realPath
|
||||||
|
* is "relative", and produces a garbage joined path. Downstream
|
||||||
|
* `fs.openSync(garbage)` then returns `EINVAL` and the WASI caller
|
||||||
|
* sees a permanent failure. This function gives us the correct
|
||||||
|
* Windows-style resolution without taking a Node-only `path` import
|
||||||
|
* (which would break browser bundles of this package).
|
||||||
|
*
|
||||||
|
* Cribbed from Node's `lib/path.js` `win32.resolve()` (MIT-licensed),
|
||||||
|
* trimmed to what WASI realpath resolution actually exercises.
|
||||||
|
*/
|
||||||
|
function resolveWin32(args) {
|
||||||
|
let resolvedDevice = '';
|
||||||
|
let resolvedTail = '';
|
||||||
|
let resolvedAbsolute = false;
|
||||||
|
for (let i = args.length - 1; i >= -1; i--) {
|
||||||
|
let path;
|
||||||
|
if (i >= 0) {
|
||||||
|
path = args[i];
|
||||||
|
(0, util_1.validateString)(path, 'path');
|
||||||
|
if (path.length === 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (resolvedDevice.length === 0) {
|
||||||
|
path = (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
||||||
|
? process.cwd()
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Look up per-drive cwd via the `=X:` env var convention; fall back
|
||||||
|
// to the global cwd if absent.
|
||||||
|
const envKey = `=${resolvedDevice}`;
|
||||||
|
const env = (typeof process !== 'undefined') ? process.env : undefined;
|
||||||
|
path = (env && typeof env[envKey] === 'string')
|
||||||
|
? env[envKey]
|
||||||
|
: (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
||||||
|
? process.cwd()
|
||||||
|
: '';
|
||||||
|
if (path === undefined ||
|
||||||
|
(path.slice(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() &&
|
||||||
|
path.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {
|
||||||
|
path = `${resolvedDevice}\\`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const len = path.length;
|
||||||
|
let rootEnd = 0;
|
||||||
|
let device = '';
|
||||||
|
let isAbsolute = false;
|
||||||
|
const code = path.charCodeAt(0);
|
||||||
|
if (len === 1) {
|
||||||
|
if (isPathSeparatorWin(code)) {
|
||||||
|
rootEnd = 1;
|
||||||
|
isAbsolute = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isPathSeparatorWin(code)) {
|
||||||
|
isAbsolute = true;
|
||||||
|
if (isPathSeparatorWin(path.charCodeAt(1))) {
|
||||||
|
// UNC path: `\\server\share\…`
|
||||||
|
let j = 2;
|
||||||
|
let last = j;
|
||||||
|
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
||||||
|
j++;
|
||||||
|
if (j < len && j !== last) {
|
||||||
|
const firstPart = path.slice(last, j);
|
||||||
|
last = j;
|
||||||
|
while (j < len && isPathSeparatorWin(path.charCodeAt(j)))
|
||||||
|
j++;
|
||||||
|
if (j < len && j !== last) {
|
||||||
|
last = j;
|
||||||
|
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
||||||
|
j++;
|
||||||
|
if (j === len || j !== last) {
|
||||||
|
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
|
||||||
|
rootEnd = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rootEnd = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
|
||||||
|
device = path.slice(0, 2);
|
||||||
|
rootEnd = 2;
|
||||||
|
if (len > 2 && isPathSeparatorWin(path.charCodeAt(2))) {
|
||||||
|
isAbsolute = true;
|
||||||
|
rootEnd = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (device.length > 0) {
|
||||||
|
if (resolvedDevice.length > 0) {
|
||||||
|
if (device.toLowerCase() !== resolvedDevice.toLowerCase())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolvedDevice = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resolvedAbsolute) {
|
||||||
|
if (resolvedDevice.length > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`;
|
||||||
|
resolvedAbsolute = isAbsolute;
|
||||||
|
if (isAbsolute && resolvedDevice.length > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isPathSeparatorWin);
|
||||||
|
return resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail || '.';
|
||||||
|
}
|
||||||
|
function isPosixPathSeparator(code) {
|
||||||
|
return code === CHAR_FORWARD_SLASH;
|
||||||
|
}
|
||||||
|
function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
|
||||||
|
let res = '';
|
||||||
|
let lastSegmentLength = 0;
|
||||||
|
let lastSlash = -1;
|
||||||
|
let dots = 0;
|
||||||
|
let code = 0;
|
||||||
|
for (let i = 0; i <= path.length; ++i) {
|
||||||
|
if (i < path.length) {
|
||||||
|
code = path.charCodeAt(i);
|
||||||
|
}
|
||||||
|
else if (isPathSeparator(code)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
code = CHAR_FORWARD_SLASH;
|
||||||
|
}
|
||||||
|
if (isPathSeparator(code)) {
|
||||||
|
if (lastSlash === i - 1 || dots === 1) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
else if (dots === 2) {
|
||||||
|
if (res.length < 2 || lastSegmentLength !== 2 ||
|
||||||
|
res.charCodeAt(res.length - 1) !== CHAR_DOT ||
|
||||||
|
res.charCodeAt(res.length - 2) !== CHAR_DOT) {
|
||||||
|
if (res.length > 2) {
|
||||||
|
const lastSlashIndex = res.indexOf(separator);
|
||||||
|
if (lastSlashIndex === -1) {
|
||||||
|
res = '';
|
||||||
|
lastSegmentLength = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = res.slice(0, lastSlashIndex);
|
||||||
|
lastSegmentLength =
|
||||||
|
res.length - 1 - res.indexOf(separator);
|
||||||
|
}
|
||||||
|
lastSlash = i;
|
||||||
|
dots = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (res.length !== 0) {
|
||||||
|
res = '';
|
||||||
|
lastSegmentLength = 0;
|
||||||
|
lastSlash = i;
|
||||||
|
dots = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowAboveRoot) {
|
||||||
|
res += res.length > 0 ? `${separator}..` : '..';
|
||||||
|
lastSegmentLength = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (res.length > 0) {
|
||||||
|
res += `${separator}${path.slice(lastSlash + 1, i)}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = path.slice(lastSlash + 1, i);
|
||||||
|
}
|
||||||
|
lastSegmentLength = i - lastSlash - 1;
|
||||||
|
}
|
||||||
|
lastSlash = i;
|
||||||
|
dots = 0;
|
||||||
|
}
|
||||||
|
else if (code === CHAR_DOT && dots !== -1) {
|
||||||
|
++dots;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dots = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
function resolve(...args) {
|
||||||
|
// On Windows, host paths are `D:\…` style. The POSIX-only resolver
|
||||||
|
// below treats `D` as a non-`/` character and produces garbage; route
|
||||||
|
// to the Windows-aware variant. POSIX hosts (Linux/macOS/browser)
|
||||||
|
// run the original code path unchanged — `_isWin32` is constant-folded
|
||||||
|
// away on those targets.
|
||||||
|
if (_isWin32)
|
||||||
|
return resolveWin32(args);
|
||||||
|
let resolvedPath = '';
|
||||||
|
let resolvedAbsolute = false;
|
||||||
|
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
||||||
|
const path = i >= 0 ? args[i] : '/';
|
||||||
|
(0, util_1.validateString)(path, 'path');
|
||||||
|
// Skip empty entries
|
||||||
|
if (path.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resolvedPath = `${path}/${resolvedPath}`;
|
||||||
|
resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH;
|
||||||
|
}
|
||||||
|
// At this point the path should be resolved to a full absolute path, but
|
||||||
|
// handle relative paths to be safe (might happen when process.cwd() fails)
|
||||||
|
// Normalize the path
|
||||||
|
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', isPosixPathSeparator);
|
||||||
|
if (resolvedAbsolute) {
|
||||||
|
return `/${resolvedPath}`;
|
||||||
|
}
|
||||||
|
return resolvedPath.length > 0 ? resolvedPath : '.';
|
||||||
|
}
|
||||||
|
exports.resolve = resolve;
|
||||||
|
function relative(from, to) {
|
||||||
|
(0, util_1.validateString)(from, 'from');
|
||||||
|
(0, util_1.validateString)(to, 'to');
|
||||||
|
if (from === to)
|
||||||
|
return '';
|
||||||
|
// Trim leading forward slashes.
|
||||||
|
from = resolve(from);
|
||||||
|
to = resolve(to);
|
||||||
|
if (from === to)
|
||||||
|
return '';
|
||||||
|
const fromStart = 1;
|
||||||
|
const fromEnd = from.length;
|
||||||
|
const fromLen = fromEnd - fromStart;
|
||||||
|
const toStart = 1;
|
||||||
|
const toLen = to.length - toStart;
|
||||||
|
// Compare paths to find the longest common path from root
|
||||||
|
const length = (fromLen < toLen ? fromLen : toLen);
|
||||||
|
let lastCommonSep = -1;
|
||||||
|
let i = 0;
|
||||||
|
for (; i < length; i++) {
|
||||||
|
const fromCode = from.charCodeAt(fromStart + i);
|
||||||
|
if (fromCode !== to.charCodeAt(toStart + i)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (fromCode === CHAR_FORWARD_SLASH) {
|
||||||
|
lastCommonSep = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i === length) {
|
||||||
|
if (toLen > length) {
|
||||||
|
if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {
|
||||||
|
// We get here if `from` is the exact base path for `to`.
|
||||||
|
// For example: from='/foo/bar'; to='/foo/bar/baz'
|
||||||
|
return to.slice(toStart + i + 1);
|
||||||
|
}
|
||||||
|
if (i === 0) {
|
||||||
|
// We get here if `from` is the root
|
||||||
|
// For example: from='/'; to='/foo'
|
||||||
|
return to.slice(toStart + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fromLen > length) {
|
||||||
|
if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {
|
||||||
|
// We get here if `to` is the exact base path for `from`.
|
||||||
|
// For example: from='/foo/bar/baz'; to='/foo/bar'
|
||||||
|
lastCommonSep = i;
|
||||||
|
}
|
||||||
|
else if (i === 0) {
|
||||||
|
// We get here if `to` is the root.
|
||||||
|
// For example: from='/foo/bar'; to='/'
|
||||||
|
lastCommonSep = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let out = '';
|
||||||
|
// Generate the relative path based on the path difference between `to`
|
||||||
|
// and `from`.
|
||||||
|
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
|
||||||
|
if (i === fromEnd ||
|
||||||
|
from.charCodeAt(i) === CHAR_FORWARD_SLASH) {
|
||||||
|
out += out.length === 0 ? '..' : '/..';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Lastly, append the rest of the destination (`to`) path that comes after
|
||||||
|
// the common path parts.
|
||||||
|
return `${out}${to.slice(toStart + lastCommonSep)}`;
|
||||||
|
}
|
||||||
|
exports.relative = relative;
|
||||||
|
//# sourceMappingURL=path.js.map
|
||||||
Generated
Vendored
+1599
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+141
@@ -0,0 +1,141 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.getRights = exports.TTY_INHERITING = exports.TTY_BASE = exports.SOCKET_INHERITING = exports.SOCKET_BASE = exports.DIRECTORY_INHERITING = exports.DIRECTORY_BASE = exports.REGULAR_FILE_INHERITING = exports.REGULAR_FILE_BASE = exports.CHARACTER_DEVICE_INHERITING = exports.CHARACTER_DEVICE_BASE = exports.BLOCK_DEVICE_INHERITING = exports.BLOCK_DEVICE_BASE = exports.RIGHTS_ALL = void 0;
|
||||||
|
/* eslint-disable spaced-comment */
|
||||||
|
const error_1 = require("./error");
|
||||||
|
const types_1 = require("./types");
|
||||||
|
exports.RIGHTS_ALL = types_1.WasiRights.FD_DATASYNC |
|
||||||
|
types_1.WasiRights.FD_READ |
|
||||||
|
types_1.WasiRights.FD_SEEK |
|
||||||
|
types_1.WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
types_1.WasiRights.FD_SYNC |
|
||||||
|
types_1.WasiRights.FD_TELL |
|
||||||
|
types_1.WasiRights.FD_WRITE |
|
||||||
|
types_1.WasiRights.FD_ADVISE |
|
||||||
|
types_1.WasiRights.FD_ALLOCATE |
|
||||||
|
types_1.WasiRights.PATH_CREATE_DIRECTORY |
|
||||||
|
types_1.WasiRights.PATH_CREATE_FILE |
|
||||||
|
types_1.WasiRights.PATH_LINK_SOURCE |
|
||||||
|
types_1.WasiRights.PATH_LINK_TARGET |
|
||||||
|
types_1.WasiRights.PATH_OPEN |
|
||||||
|
types_1.WasiRights.FD_READDIR |
|
||||||
|
types_1.WasiRights.PATH_READLINK |
|
||||||
|
types_1.WasiRights.PATH_RENAME_SOURCE |
|
||||||
|
types_1.WasiRights.PATH_RENAME_TARGET |
|
||||||
|
types_1.WasiRights.PATH_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.PATH_FILESTAT_SET_SIZE |
|
||||||
|
types_1.WasiRights.PATH_FILESTAT_SET_TIMES |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_SET_TIMES |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_SET_SIZE |
|
||||||
|
types_1.WasiRights.PATH_SYMLINK |
|
||||||
|
types_1.WasiRights.PATH_UNLINK_FILE |
|
||||||
|
types_1.WasiRights.PATH_REMOVE_DIRECTORY |
|
||||||
|
types_1.WasiRights.POLL_FD_READWRITE |
|
||||||
|
types_1.WasiRights.SOCK_SHUTDOWN |
|
||||||
|
types_1.WasiRights.SOCK_ACCEPT;
|
||||||
|
exports.BLOCK_DEVICE_BASE = exports.RIGHTS_ALL;
|
||||||
|
exports.BLOCK_DEVICE_INHERITING = exports.RIGHTS_ALL;
|
||||||
|
exports.CHARACTER_DEVICE_BASE = exports.RIGHTS_ALL;
|
||||||
|
exports.CHARACTER_DEVICE_INHERITING = exports.RIGHTS_ALL;
|
||||||
|
exports.REGULAR_FILE_BASE = types_1.WasiRights.FD_DATASYNC |
|
||||||
|
types_1.WasiRights.FD_READ |
|
||||||
|
types_1.WasiRights.FD_SEEK |
|
||||||
|
types_1.WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
types_1.WasiRights.FD_SYNC |
|
||||||
|
types_1.WasiRights.FD_TELL |
|
||||||
|
types_1.WasiRights.FD_WRITE |
|
||||||
|
types_1.WasiRights.FD_ADVISE |
|
||||||
|
types_1.WasiRights.FD_ALLOCATE |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_SET_SIZE |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_SET_TIMES |
|
||||||
|
types_1.WasiRights.POLL_FD_READWRITE;
|
||||||
|
exports.REGULAR_FILE_INHERITING = BigInt(0);
|
||||||
|
exports.DIRECTORY_BASE = types_1.WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
types_1.WasiRights.FD_SYNC |
|
||||||
|
types_1.WasiRights.FD_ADVISE |
|
||||||
|
types_1.WasiRights.PATH_CREATE_DIRECTORY |
|
||||||
|
types_1.WasiRights.PATH_CREATE_FILE |
|
||||||
|
types_1.WasiRights.PATH_LINK_SOURCE |
|
||||||
|
types_1.WasiRights.PATH_LINK_TARGET |
|
||||||
|
types_1.WasiRights.PATH_OPEN |
|
||||||
|
types_1.WasiRights.FD_READDIR |
|
||||||
|
types_1.WasiRights.PATH_READLINK |
|
||||||
|
types_1.WasiRights.PATH_RENAME_SOURCE |
|
||||||
|
types_1.WasiRights.PATH_RENAME_TARGET |
|
||||||
|
types_1.WasiRights.PATH_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.PATH_FILESTAT_SET_SIZE |
|
||||||
|
types_1.WasiRights.PATH_FILESTAT_SET_TIMES |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_SET_TIMES |
|
||||||
|
types_1.WasiRights.PATH_SYMLINK |
|
||||||
|
types_1.WasiRights.PATH_UNLINK_FILE |
|
||||||
|
types_1.WasiRights.PATH_REMOVE_DIRECTORY |
|
||||||
|
types_1.WasiRights.POLL_FD_READWRITE;
|
||||||
|
exports.DIRECTORY_INHERITING = exports.DIRECTORY_BASE | exports.REGULAR_FILE_BASE;
|
||||||
|
exports.SOCKET_BASE = (types_1.WasiRights.FD_READ |
|
||||||
|
types_1.WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
types_1.WasiRights.FD_WRITE |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.POLL_FD_READWRITE |
|
||||||
|
types_1.WasiRights.SOCK_SHUTDOWN);
|
||||||
|
exports.SOCKET_INHERITING = exports.RIGHTS_ALL;
|
||||||
|
exports.TTY_BASE = types_1.WasiRights.FD_READ |
|
||||||
|
types_1.WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
types_1.WasiRights.FD_WRITE |
|
||||||
|
types_1.WasiRights.FD_FILESTAT_GET |
|
||||||
|
types_1.WasiRights.POLL_FD_READWRITE;
|
||||||
|
exports.TTY_INHERITING = BigInt(0);
|
||||||
|
function getRights(stdio, fd, flags, type) {
|
||||||
|
const ret = {
|
||||||
|
base: BigInt(0),
|
||||||
|
inheriting: BigInt(0)
|
||||||
|
};
|
||||||
|
if (type === types_1.WasiFileType.UNKNOWN) {
|
||||||
|
throw new error_1.WasiError('Unknown file type', types_1.WasiErrno.EINVAL);
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case types_1.WasiFileType.REGULAR_FILE:
|
||||||
|
ret.base = exports.REGULAR_FILE_BASE;
|
||||||
|
ret.inheriting = exports.REGULAR_FILE_INHERITING;
|
||||||
|
break;
|
||||||
|
case types_1.WasiFileType.DIRECTORY:
|
||||||
|
ret.base = exports.DIRECTORY_BASE;
|
||||||
|
ret.inheriting = exports.DIRECTORY_INHERITING;
|
||||||
|
break;
|
||||||
|
case types_1.WasiFileType.SOCKET_STREAM:
|
||||||
|
case types_1.WasiFileType.SOCKET_DGRAM:
|
||||||
|
ret.base = exports.SOCKET_BASE;
|
||||||
|
ret.inheriting = exports.SOCKET_INHERITING;
|
||||||
|
break;
|
||||||
|
case types_1.WasiFileType.CHARACTER_DEVICE:
|
||||||
|
if (stdio.indexOf(fd) !== -1) {
|
||||||
|
ret.base = exports.TTY_BASE;
|
||||||
|
ret.inheriting = exports.TTY_INHERITING;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret.base = exports.CHARACTER_DEVICE_BASE;
|
||||||
|
ret.inheriting = exports.CHARACTER_DEVICE_INHERITING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case types_1.WasiFileType.BLOCK_DEVICE:
|
||||||
|
ret.base = exports.BLOCK_DEVICE_BASE;
|
||||||
|
ret.inheriting = exports.BLOCK_DEVICE_INHERITING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret.base = BigInt(0);
|
||||||
|
ret.inheriting = BigInt(0);
|
||||||
|
}
|
||||||
|
/* Disable read/write bits depending on access mode. */
|
||||||
|
const read_or_write_only = flags & (0 | 1 | 2);
|
||||||
|
if (read_or_write_only === 0) {
|
||||||
|
ret.base &= ~types_1.WasiRights.FD_WRITE;
|
||||||
|
}
|
||||||
|
else if (read_or_write_only === 1) {
|
||||||
|
ret.base &= ~types_1.WasiRights.FD_READ;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
exports.getRights = getRights;
|
||||||
|
//# sourceMappingURL=rights.js.map
|
||||||
Generated
Vendored
+220
@@ -0,0 +1,220 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.WasiSubclockflags = exports.WasiEventType = exports.WasiFstFlag = exports.WasiClockid = exports.WasiFdFlag = exports.WasiFileControlFlag = exports.FileControlFlag = exports.WasiWhence = exports.WasiRights = exports.WasiFileType = exports.WasiErrno = void 0;
|
||||||
|
/* eslint-disable spaced-comment */
|
||||||
|
var WasiErrno;
|
||||||
|
(function (WasiErrno) {
|
||||||
|
WasiErrno[WasiErrno["ESUCCESS"] = 0] = "ESUCCESS";
|
||||||
|
WasiErrno[WasiErrno["E2BIG"] = 1] = "E2BIG";
|
||||||
|
WasiErrno[WasiErrno["EACCES"] = 2] = "EACCES";
|
||||||
|
WasiErrno[WasiErrno["EADDRINUSE"] = 3] = "EADDRINUSE";
|
||||||
|
WasiErrno[WasiErrno["EADDRNOTAVAIL"] = 4] = "EADDRNOTAVAIL";
|
||||||
|
WasiErrno[WasiErrno["EAFNOSUPPORT"] = 5] = "EAFNOSUPPORT";
|
||||||
|
WasiErrno[WasiErrno["EAGAIN"] = 6] = "EAGAIN";
|
||||||
|
WasiErrno[WasiErrno["EALREADY"] = 7] = "EALREADY";
|
||||||
|
WasiErrno[WasiErrno["EBADF"] = 8] = "EBADF";
|
||||||
|
WasiErrno[WasiErrno["EBADMSG"] = 9] = "EBADMSG";
|
||||||
|
WasiErrno[WasiErrno["EBUSY"] = 10] = "EBUSY";
|
||||||
|
WasiErrno[WasiErrno["ECANCELED"] = 11] = "ECANCELED";
|
||||||
|
WasiErrno[WasiErrno["ECHILD"] = 12] = "ECHILD";
|
||||||
|
WasiErrno[WasiErrno["ECONNABORTED"] = 13] = "ECONNABORTED";
|
||||||
|
WasiErrno[WasiErrno["ECONNREFUSED"] = 14] = "ECONNREFUSED";
|
||||||
|
WasiErrno[WasiErrno["ECONNRESET"] = 15] = "ECONNRESET";
|
||||||
|
WasiErrno[WasiErrno["EDEADLK"] = 16] = "EDEADLK";
|
||||||
|
WasiErrno[WasiErrno["EDESTADDRREQ"] = 17] = "EDESTADDRREQ";
|
||||||
|
WasiErrno[WasiErrno["EDOM"] = 18] = "EDOM";
|
||||||
|
WasiErrno[WasiErrno["EDQUOT"] = 19] = "EDQUOT";
|
||||||
|
WasiErrno[WasiErrno["EEXIST"] = 20] = "EEXIST";
|
||||||
|
WasiErrno[WasiErrno["EFAULT"] = 21] = "EFAULT";
|
||||||
|
WasiErrno[WasiErrno["EFBIG"] = 22] = "EFBIG";
|
||||||
|
WasiErrno[WasiErrno["EHOSTUNREACH"] = 23] = "EHOSTUNREACH";
|
||||||
|
WasiErrno[WasiErrno["EIDRM"] = 24] = "EIDRM";
|
||||||
|
WasiErrno[WasiErrno["EILSEQ"] = 25] = "EILSEQ";
|
||||||
|
WasiErrno[WasiErrno["EINPROGRESS"] = 26] = "EINPROGRESS";
|
||||||
|
WasiErrno[WasiErrno["EINTR"] = 27] = "EINTR";
|
||||||
|
WasiErrno[WasiErrno["EINVAL"] = 28] = "EINVAL";
|
||||||
|
WasiErrno[WasiErrno["EIO"] = 29] = "EIO";
|
||||||
|
WasiErrno[WasiErrno["EISCONN"] = 30] = "EISCONN";
|
||||||
|
WasiErrno[WasiErrno["EISDIR"] = 31] = "EISDIR";
|
||||||
|
WasiErrno[WasiErrno["ELOOP"] = 32] = "ELOOP";
|
||||||
|
WasiErrno[WasiErrno["EMFILE"] = 33] = "EMFILE";
|
||||||
|
WasiErrno[WasiErrno["EMLINK"] = 34] = "EMLINK";
|
||||||
|
WasiErrno[WasiErrno["EMSGSIZE"] = 35] = "EMSGSIZE";
|
||||||
|
WasiErrno[WasiErrno["EMULTIHOP"] = 36] = "EMULTIHOP";
|
||||||
|
WasiErrno[WasiErrno["ENAMETOOLONG"] = 37] = "ENAMETOOLONG";
|
||||||
|
WasiErrno[WasiErrno["ENETDOWN"] = 38] = "ENETDOWN";
|
||||||
|
WasiErrno[WasiErrno["ENETRESET"] = 39] = "ENETRESET";
|
||||||
|
WasiErrno[WasiErrno["ENETUNREACH"] = 40] = "ENETUNREACH";
|
||||||
|
WasiErrno[WasiErrno["ENFILE"] = 41] = "ENFILE";
|
||||||
|
WasiErrno[WasiErrno["ENOBUFS"] = 42] = "ENOBUFS";
|
||||||
|
WasiErrno[WasiErrno["ENODEV"] = 43] = "ENODEV";
|
||||||
|
WasiErrno[WasiErrno["ENOENT"] = 44] = "ENOENT";
|
||||||
|
WasiErrno[WasiErrno["ENOEXEC"] = 45] = "ENOEXEC";
|
||||||
|
WasiErrno[WasiErrno["ENOLCK"] = 46] = "ENOLCK";
|
||||||
|
WasiErrno[WasiErrno["ENOLINK"] = 47] = "ENOLINK";
|
||||||
|
WasiErrno[WasiErrno["ENOMEM"] = 48] = "ENOMEM";
|
||||||
|
WasiErrno[WasiErrno["ENOMSG"] = 49] = "ENOMSG";
|
||||||
|
WasiErrno[WasiErrno["ENOPROTOOPT"] = 50] = "ENOPROTOOPT";
|
||||||
|
WasiErrno[WasiErrno["ENOSPC"] = 51] = "ENOSPC";
|
||||||
|
WasiErrno[WasiErrno["ENOSYS"] = 52] = "ENOSYS";
|
||||||
|
WasiErrno[WasiErrno["ENOTCONN"] = 53] = "ENOTCONN";
|
||||||
|
WasiErrno[WasiErrno["ENOTDIR"] = 54] = "ENOTDIR";
|
||||||
|
WasiErrno[WasiErrno["ENOTEMPTY"] = 55] = "ENOTEMPTY";
|
||||||
|
WasiErrno[WasiErrno["ENOTRECOVERABLE"] = 56] = "ENOTRECOVERABLE";
|
||||||
|
WasiErrno[WasiErrno["ENOTSOCK"] = 57] = "ENOTSOCK";
|
||||||
|
WasiErrno[WasiErrno["ENOTSUP"] = 58] = "ENOTSUP";
|
||||||
|
WasiErrno[WasiErrno["ENOTTY"] = 59] = "ENOTTY";
|
||||||
|
WasiErrno[WasiErrno["ENXIO"] = 60] = "ENXIO";
|
||||||
|
WasiErrno[WasiErrno["EOVERFLOW"] = 61] = "EOVERFLOW";
|
||||||
|
WasiErrno[WasiErrno["EOWNERDEAD"] = 62] = "EOWNERDEAD";
|
||||||
|
WasiErrno[WasiErrno["EPERM"] = 63] = "EPERM";
|
||||||
|
WasiErrno[WasiErrno["EPIPE"] = 64] = "EPIPE";
|
||||||
|
WasiErrno[WasiErrno["EPROTO"] = 65] = "EPROTO";
|
||||||
|
WasiErrno[WasiErrno["EPROTONOSUPPORT"] = 66] = "EPROTONOSUPPORT";
|
||||||
|
WasiErrno[WasiErrno["EPROTOTYPE"] = 67] = "EPROTOTYPE";
|
||||||
|
WasiErrno[WasiErrno["ERANGE"] = 68] = "ERANGE";
|
||||||
|
WasiErrno[WasiErrno["EROFS"] = 69] = "EROFS";
|
||||||
|
WasiErrno[WasiErrno["ESPIPE"] = 70] = "ESPIPE";
|
||||||
|
WasiErrno[WasiErrno["ESRCH"] = 71] = "ESRCH";
|
||||||
|
WasiErrno[WasiErrno["ESTALE"] = 72] = "ESTALE";
|
||||||
|
WasiErrno[WasiErrno["ETIMEDOUT"] = 73] = "ETIMEDOUT";
|
||||||
|
WasiErrno[WasiErrno["ETXTBSY"] = 74] = "ETXTBSY";
|
||||||
|
WasiErrno[WasiErrno["EXDEV"] = 75] = "EXDEV";
|
||||||
|
WasiErrno[WasiErrno["ENOTCAPABLE"] = 76] = "ENOTCAPABLE";
|
||||||
|
})(WasiErrno = exports.WasiErrno || (exports.WasiErrno = {}));
|
||||||
|
var WasiFileType;
|
||||||
|
(function (WasiFileType) {
|
||||||
|
WasiFileType[WasiFileType["UNKNOWN"] = 0] = "UNKNOWN";
|
||||||
|
WasiFileType[WasiFileType["BLOCK_DEVICE"] = 1] = "BLOCK_DEVICE";
|
||||||
|
WasiFileType[WasiFileType["CHARACTER_DEVICE"] = 2] = "CHARACTER_DEVICE";
|
||||||
|
WasiFileType[WasiFileType["DIRECTORY"] = 3] = "DIRECTORY";
|
||||||
|
WasiFileType[WasiFileType["REGULAR_FILE"] = 4] = "REGULAR_FILE";
|
||||||
|
WasiFileType[WasiFileType["SOCKET_DGRAM"] = 5] = "SOCKET_DGRAM";
|
||||||
|
WasiFileType[WasiFileType["SOCKET_STREAM"] = 6] = "SOCKET_STREAM";
|
||||||
|
WasiFileType[WasiFileType["SYMBOLIC_LINK"] = 7] = "SYMBOLIC_LINK";
|
||||||
|
})(WasiFileType = exports.WasiFileType || (exports.WasiFileType = {}));
|
||||||
|
const FD_DATASYNC = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(0));
|
||||||
|
const FD_READ = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(1));
|
||||||
|
const FD_SEEK = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(2));
|
||||||
|
const FD_FDSTAT_SET_FLAGS = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(3));
|
||||||
|
const FD_SYNC = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(4));
|
||||||
|
const FD_TELL = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(5));
|
||||||
|
const FD_WRITE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(6));
|
||||||
|
const FD_ADVISE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(7));
|
||||||
|
const FD_ALLOCATE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(8));
|
||||||
|
const PATH_CREATE_DIRECTORY = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(9));
|
||||||
|
const PATH_CREATE_FILE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(10));
|
||||||
|
const PATH_LINK_SOURCE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(11));
|
||||||
|
const PATH_LINK_TARGET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(12));
|
||||||
|
const PATH_OPEN = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(13));
|
||||||
|
const FD_READDIR = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(14));
|
||||||
|
const PATH_READLINK = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(15));
|
||||||
|
const PATH_RENAME_SOURCE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(16));
|
||||||
|
const PATH_RENAME_TARGET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(17));
|
||||||
|
const PATH_FILESTAT_GET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(18));
|
||||||
|
const PATH_FILESTAT_SET_SIZE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(19));
|
||||||
|
const PATH_FILESTAT_SET_TIMES = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(20));
|
||||||
|
const FD_FILESTAT_GET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(21));
|
||||||
|
const FD_FILESTAT_SET_SIZE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(22));
|
||||||
|
const FD_FILESTAT_SET_TIMES = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(23));
|
||||||
|
const PATH_SYMLINK = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(24));
|
||||||
|
const PATH_REMOVE_DIRECTORY = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(25));
|
||||||
|
const PATH_UNLINK_FILE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(26));
|
||||||
|
const POLL_FD_READWRITE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(27));
|
||||||
|
const SOCK_SHUTDOWN = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(28));
|
||||||
|
const SOCK_ACCEPT = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(29));
|
||||||
|
exports.WasiRights = {
|
||||||
|
FD_DATASYNC,
|
||||||
|
FD_READ,
|
||||||
|
FD_SEEK,
|
||||||
|
FD_FDSTAT_SET_FLAGS,
|
||||||
|
FD_SYNC,
|
||||||
|
FD_TELL,
|
||||||
|
FD_WRITE,
|
||||||
|
FD_ADVISE,
|
||||||
|
FD_ALLOCATE,
|
||||||
|
PATH_CREATE_DIRECTORY,
|
||||||
|
PATH_CREATE_FILE,
|
||||||
|
PATH_LINK_SOURCE,
|
||||||
|
PATH_LINK_TARGET,
|
||||||
|
PATH_OPEN,
|
||||||
|
FD_READDIR,
|
||||||
|
PATH_READLINK,
|
||||||
|
PATH_RENAME_SOURCE,
|
||||||
|
PATH_RENAME_TARGET,
|
||||||
|
PATH_FILESTAT_GET,
|
||||||
|
PATH_FILESTAT_SET_SIZE,
|
||||||
|
PATH_FILESTAT_SET_TIMES,
|
||||||
|
FD_FILESTAT_GET,
|
||||||
|
FD_FILESTAT_SET_SIZE,
|
||||||
|
FD_FILESTAT_SET_TIMES,
|
||||||
|
PATH_SYMLINK,
|
||||||
|
PATH_REMOVE_DIRECTORY,
|
||||||
|
PATH_UNLINK_FILE,
|
||||||
|
POLL_FD_READWRITE,
|
||||||
|
SOCK_SHUTDOWN,
|
||||||
|
SOCK_ACCEPT
|
||||||
|
};
|
||||||
|
var WasiWhence;
|
||||||
|
(function (WasiWhence) {
|
||||||
|
WasiWhence[WasiWhence["SET"] = 0] = "SET";
|
||||||
|
WasiWhence[WasiWhence["CUR"] = 1] = "CUR";
|
||||||
|
WasiWhence[WasiWhence["END"] = 2] = "END";
|
||||||
|
})(WasiWhence = exports.WasiWhence || (exports.WasiWhence = {}));
|
||||||
|
var FileControlFlag;
|
||||||
|
(function (FileControlFlag) {
|
||||||
|
FileControlFlag[FileControlFlag["O_RDONLY"] = 0] = "O_RDONLY";
|
||||||
|
FileControlFlag[FileControlFlag["O_WRONLY"] = 1] = "O_WRONLY";
|
||||||
|
FileControlFlag[FileControlFlag["O_RDWR"] = 2] = "O_RDWR";
|
||||||
|
FileControlFlag[FileControlFlag["O_CREAT"] = 64] = "O_CREAT";
|
||||||
|
FileControlFlag[FileControlFlag["O_EXCL"] = 128] = "O_EXCL";
|
||||||
|
FileControlFlag[FileControlFlag["O_NOCTTY"] = 256] = "O_NOCTTY";
|
||||||
|
FileControlFlag[FileControlFlag["O_TRUNC"] = 512] = "O_TRUNC";
|
||||||
|
FileControlFlag[FileControlFlag["O_APPEND"] = 1024] = "O_APPEND";
|
||||||
|
FileControlFlag[FileControlFlag["O_DIRECTORY"] = 65536] = "O_DIRECTORY";
|
||||||
|
FileControlFlag[FileControlFlag["O_NOATIME"] = 262144] = "O_NOATIME";
|
||||||
|
FileControlFlag[FileControlFlag["O_NOFOLLOW"] = 131072] = "O_NOFOLLOW";
|
||||||
|
FileControlFlag[FileControlFlag["O_SYNC"] = 1052672] = "O_SYNC";
|
||||||
|
FileControlFlag[FileControlFlag["O_DIRECT"] = 16384] = "O_DIRECT";
|
||||||
|
FileControlFlag[FileControlFlag["O_NONBLOCK"] = 2048] = "O_NONBLOCK";
|
||||||
|
})(FileControlFlag = exports.FileControlFlag || (exports.FileControlFlag = {}));
|
||||||
|
var WasiFileControlFlag;
|
||||||
|
(function (WasiFileControlFlag) {
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_CREAT"] = 1] = "O_CREAT";
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_DIRECTORY"] = 2] = "O_DIRECTORY";
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_EXCL"] = 4] = "O_EXCL";
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_TRUNC"] = 8] = "O_TRUNC";
|
||||||
|
})(WasiFileControlFlag = exports.WasiFileControlFlag || (exports.WasiFileControlFlag = {}));
|
||||||
|
var WasiFdFlag;
|
||||||
|
(function (WasiFdFlag) {
|
||||||
|
WasiFdFlag[WasiFdFlag["APPEND"] = 1] = "APPEND";
|
||||||
|
WasiFdFlag[WasiFdFlag["DSYNC"] = 2] = "DSYNC";
|
||||||
|
WasiFdFlag[WasiFdFlag["NONBLOCK"] = 4] = "NONBLOCK";
|
||||||
|
WasiFdFlag[WasiFdFlag["RSYNC"] = 8] = "RSYNC";
|
||||||
|
WasiFdFlag[WasiFdFlag["SYNC"] = 16] = "SYNC";
|
||||||
|
})(WasiFdFlag = exports.WasiFdFlag || (exports.WasiFdFlag = {}));
|
||||||
|
var WasiClockid;
|
||||||
|
(function (WasiClockid) {
|
||||||
|
WasiClockid[WasiClockid["REALTIME"] = 0] = "REALTIME";
|
||||||
|
WasiClockid[WasiClockid["MONOTONIC"] = 1] = "MONOTONIC";
|
||||||
|
WasiClockid[WasiClockid["PROCESS_CPUTIME_ID"] = 2] = "PROCESS_CPUTIME_ID";
|
||||||
|
WasiClockid[WasiClockid["THREAD_CPUTIME_ID"] = 3] = "THREAD_CPUTIME_ID";
|
||||||
|
})(WasiClockid = exports.WasiClockid || (exports.WasiClockid = {}));
|
||||||
|
var WasiFstFlag;
|
||||||
|
(function (WasiFstFlag) {
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_ATIM"] = 1] = "SET_ATIM";
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_ATIM_NOW"] = 2] = "SET_ATIM_NOW";
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_MTIM"] = 4] = "SET_MTIM";
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_MTIM_NOW"] = 8] = "SET_MTIM_NOW";
|
||||||
|
})(WasiFstFlag = exports.WasiFstFlag || (exports.WasiFstFlag = {}));
|
||||||
|
var WasiEventType;
|
||||||
|
(function (WasiEventType) {
|
||||||
|
WasiEventType[WasiEventType["CLOCK"] = 0] = "CLOCK";
|
||||||
|
WasiEventType[WasiEventType["FD_READ"] = 1] = "FD_READ";
|
||||||
|
WasiEventType[WasiEventType["FD_WRITE"] = 2] = "FD_WRITE";
|
||||||
|
})(WasiEventType = exports.WasiEventType || (exports.WasiEventType = {}));
|
||||||
|
var WasiSubclockflags;
|
||||||
|
(function (WasiSubclockflags) {
|
||||||
|
WasiSubclockflags[WasiSubclockflags["ABSTIME"] = 1] = "ABSTIME";
|
||||||
|
})(WasiSubclockflags = exports.WasiSubclockflags || (exports.WasiSubclockflags = {}));
|
||||||
|
//# sourceMappingURL=types.js.map
|
||||||
Generated
Vendored
+128
@@ -0,0 +1,128 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.unsharedSlice = exports.sleepBreakIf = exports.postMsg = exports.isMainThread = exports.wrapInstanceExports = exports.isPromiseLike = exports.validateInt32 = exports.validateUndefined = exports.validateFunction = exports.validateString = exports.validateBoolean = exports.validateArray = exports.validateObject = void 0;
|
||||||
|
/* eslint-disable spaced-comment */
|
||||||
|
function validateObject(value, name) {
|
||||||
|
if (value === null || typeof value !== 'object') {
|
||||||
|
throw new TypeError(`${name} must be an object. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateObject = validateObject;
|
||||||
|
function validateArray(value, name) {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
throw new TypeError(`${name} must be an array. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateArray = validateArray;
|
||||||
|
function validateBoolean(value, name) {
|
||||||
|
if (typeof value !== 'boolean') {
|
||||||
|
throw new TypeError(`${name} must be a boolean. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateBoolean = validateBoolean;
|
||||||
|
function validateString(value, name) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
throw new TypeError(`${name} must be a string. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateString = validateString;
|
||||||
|
function validateFunction(value, name) {
|
||||||
|
if (typeof value !== 'function') {
|
||||||
|
throw new TypeError(`${name} must be a function. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateFunction = validateFunction;
|
||||||
|
function validateUndefined(value, name) {
|
||||||
|
if (value !== undefined) {
|
||||||
|
throw new TypeError(`${name} must be undefined. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateUndefined = validateUndefined;
|
||||||
|
function validateInt32(value, name, min = -2147483648, max = 2147483647) {
|
||||||
|
if (typeof value !== 'number') {
|
||||||
|
throw new TypeError(`${name} must be a number. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
if (!Number.isInteger(value)) {
|
||||||
|
throw new RangeError(`${name} must be a integer.`);
|
||||||
|
}
|
||||||
|
if (value < min || value > max) {
|
||||||
|
throw new RangeError(`${name} must be >= ${min} && <= ${max}. Received ${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.validateInt32 = validateInt32;
|
||||||
|
function isPromiseLike(obj) {
|
||||||
|
return !!(obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function');
|
||||||
|
}
|
||||||
|
exports.isPromiseLike = isPromiseLike;
|
||||||
|
function wrapInstanceExports(exports, mapFn) {
|
||||||
|
const newExports = Object.create(null);
|
||||||
|
Object.keys(exports).forEach(name => {
|
||||||
|
const exportValue = exports[name];
|
||||||
|
Object.defineProperty(newExports, name, {
|
||||||
|
enumerable: true,
|
||||||
|
value: mapFn(exportValue, name)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return newExports;
|
||||||
|
}
|
||||||
|
exports.wrapInstanceExports = wrapInstanceExports;
|
||||||
|
const _require = /*#__PURE__*/ (function () {
|
||||||
|
let nativeRequire;
|
||||||
|
if (typeof __webpack_public_path__ !== 'undefined') {
|
||||||
|
nativeRequire = (function () {
|
||||||
|
return typeof __non_webpack_require__ !== 'undefined' ? __non_webpack_require__ : undefined;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nativeRequire = (function () {
|
||||||
|
return typeof __webpack_public_path__ !== 'undefined' ? (typeof __non_webpack_require__ !== 'undefined' ? __non_webpack_require__ : undefined) : (typeof require !== 'undefined' ? require : undefined);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
return nativeRequire;
|
||||||
|
})();
|
||||||
|
exports.isMainThread = (function () {
|
||||||
|
let worker_threads;
|
||||||
|
try {
|
||||||
|
worker_threads = _require('worker_threads');
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
if (!worker_threads) {
|
||||||
|
return typeof importScripts === 'undefined';
|
||||||
|
}
|
||||||
|
return worker_threads.isMainThread;
|
||||||
|
})();
|
||||||
|
exports.postMsg = exports.isMainThread
|
||||||
|
? () => { }
|
||||||
|
: /*#__PURE__*/ (function () {
|
||||||
|
let worker_threads;
|
||||||
|
try {
|
||||||
|
worker_threads = _require('worker_threads');
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
if (!worker_threads) {
|
||||||
|
return postMessage;
|
||||||
|
}
|
||||||
|
return function postMessage(data) {
|
||||||
|
worker_threads.parentPort.postMessage({ data });
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
function sleepBreakIf(delay, breakIf) {
|
||||||
|
const start = Date.now();
|
||||||
|
const end = start + delay;
|
||||||
|
let ret = false;
|
||||||
|
while (Date.now() < end) {
|
||||||
|
if (breakIf()) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
exports.sleepBreakIf = sleepBreakIf;
|
||||||
|
function unsharedSlice(view, start, end) {
|
||||||
|
return ((typeof SharedArrayBuffer === 'function' && view.buffer instanceof SharedArrayBuffer) || (Object.prototype.toString.call(view.buffer.constructor) === '[object SharedArrayBuffer]'))
|
||||||
|
? view.slice(start, end)
|
||||||
|
: view.subarray(start, end);
|
||||||
|
}
|
||||||
|
exports.unsharedSlice = unsharedSlice;
|
||||||
|
//# sourceMappingURL=util.js.map
|
||||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports._WebAssembly = void 0;
|
||||||
|
const _WebAssembly = typeof WebAssembly !== 'undefined'
|
||||||
|
? WebAssembly
|
||||||
|
: typeof WXWebAssembly !== 'undefined'
|
||||||
|
? WXWebAssembly
|
||||||
|
: undefined;
|
||||||
|
exports._WebAssembly = _WebAssembly;
|
||||||
|
if (!_WebAssembly) {
|
||||||
|
throw new Error('WebAssembly is not supported in this environment');
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=webassembly.js.map
|
||||||
Generated
Vendored
+153
@@ -0,0 +1,153 @@
|
|||||||
|
import { _WebAssembly } from "./webassembly.mjs";
|
||||||
|
import { isPromiseLike, wrapInstanceExports } from "./wasi/util.mjs";
|
||||||
|
const ignoreNames = [
|
||||||
|
'asyncify_get_state',
|
||||||
|
'asyncify_start_rewind',
|
||||||
|
'asyncify_start_unwind',
|
||||||
|
'asyncify_stop_rewind',
|
||||||
|
'asyncify_stop_unwind'
|
||||||
|
];
|
||||||
|
// const wrappedExports = new WeakMap<WebAssembly.Exports, WebAssembly.Exports>()
|
||||||
|
var AsyncifyState;
|
||||||
|
(function (AsyncifyState) {
|
||||||
|
AsyncifyState[AsyncifyState["NONE"] = 0] = "NONE";
|
||||||
|
AsyncifyState[AsyncifyState["UNWINDING"] = 1] = "UNWINDING";
|
||||||
|
AsyncifyState[AsyncifyState["REWINDING"] = 2] = "REWINDING";
|
||||||
|
})(AsyncifyState || (AsyncifyState = {}));
|
||||||
|
function tryAllocate(instance, wasm64, size, mallocName) {
|
||||||
|
if (typeof instance.exports[mallocName] !== 'function' || size <= 0) {
|
||||||
|
return {
|
||||||
|
wasm64,
|
||||||
|
dataPtr: 16,
|
||||||
|
start: wasm64 ? 32 : 24,
|
||||||
|
end: 1024
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const malloc = instance.exports[mallocName];
|
||||||
|
const dataPtr = wasm64 ? Number(malloc(BigInt(16) + BigInt(size))) : malloc(8 + size);
|
||||||
|
if (dataPtr === 0) {
|
||||||
|
throw new Error('Allocate asyncify data failed');
|
||||||
|
}
|
||||||
|
return wasm64
|
||||||
|
? { wasm64, dataPtr, start: dataPtr + 16, end: dataPtr + 16 + size }
|
||||||
|
: { wasm64, dataPtr, start: dataPtr + 8, end: dataPtr + 8 + size };
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export class Asyncify {
|
||||||
|
constructor() {
|
||||||
|
this.value = undefined;
|
||||||
|
this.exports = undefined;
|
||||||
|
this.dataPtr = 0;
|
||||||
|
}
|
||||||
|
init(memory, instance, options) {
|
||||||
|
var _a, _b;
|
||||||
|
if (this.exports) {
|
||||||
|
throw new Error('Asyncify has been initialized');
|
||||||
|
}
|
||||||
|
if (!(memory instanceof _WebAssembly.Memory)) {
|
||||||
|
throw new TypeError('Require WebAssembly.Memory object');
|
||||||
|
}
|
||||||
|
const exports = instance.exports;
|
||||||
|
for (let i = 0; i < ignoreNames.length; ++i) {
|
||||||
|
if (typeof exports[ignoreNames[i]] !== 'function') {
|
||||||
|
throw new TypeError('Invalid asyncify wasm');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let address;
|
||||||
|
const wasm64 = Boolean(options.wasm64);
|
||||||
|
if (!options.tryAllocate) {
|
||||||
|
address = {
|
||||||
|
wasm64,
|
||||||
|
dataPtr: 16,
|
||||||
|
start: wasm64 ? 32 : 24,
|
||||||
|
end: 1024
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (options.tryAllocate === true) {
|
||||||
|
address = tryAllocate(instance, wasm64, 4096, 'malloc');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
address = tryAllocate(instance, wasm64, (_a = options.tryAllocate.size) !== null && _a !== void 0 ? _a : 4096, (_b = options.tryAllocate.name) !== null && _b !== void 0 ? _b : 'malloc');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.dataPtr = address.dataPtr;
|
||||||
|
if (wasm64) {
|
||||||
|
new BigInt64Array(memory.buffer, this.dataPtr).set([BigInt(address.start), BigInt(address.end)]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new Int32Array(memory.buffer, this.dataPtr).set([address.start, address.end]);
|
||||||
|
}
|
||||||
|
this.exports = this.wrapExports(exports, options.wrapExports);
|
||||||
|
const asyncifiedInstance = Object.create(_WebAssembly.Instance.prototype);
|
||||||
|
Object.defineProperty(asyncifiedInstance, 'exports', { value: this.exports });
|
||||||
|
// Object.setPrototypeOf(instance, Instance.prototype)
|
||||||
|
return asyncifiedInstance;
|
||||||
|
}
|
||||||
|
assertState() {
|
||||||
|
if (this.exports.asyncify_get_state() !== AsyncifyState.NONE) {
|
||||||
|
throw new Error('Asyncify state error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapImportFunction(f) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
const _this = this;
|
||||||
|
return (function () {
|
||||||
|
// eslint-disable-next-line no-unreachable-loop
|
||||||
|
while (_this.exports.asyncify_get_state() === AsyncifyState.REWINDING) {
|
||||||
|
_this.exports.asyncify_stop_rewind();
|
||||||
|
return _this.value;
|
||||||
|
}
|
||||||
|
_this.assertState();
|
||||||
|
const v = f.apply(this, arguments);
|
||||||
|
if (!isPromiseLike(v))
|
||||||
|
return v;
|
||||||
|
_this.exports.asyncify_start_unwind(_this.dataPtr);
|
||||||
|
_this.value = v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
wrapImports(imports) {
|
||||||
|
const importObject = {};
|
||||||
|
Object.keys(imports).forEach(k => {
|
||||||
|
const mod = imports[k];
|
||||||
|
const newModule = {};
|
||||||
|
Object.keys(mod).forEach(name => {
|
||||||
|
const importValue = mod[name];
|
||||||
|
if (typeof importValue === 'function') {
|
||||||
|
newModule[name] = this.wrapImportFunction(importValue);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newModule[name] = importValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
importObject[k] = newModule;
|
||||||
|
});
|
||||||
|
return importObject;
|
||||||
|
}
|
||||||
|
wrapExportFunction(f) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
const _this = this;
|
||||||
|
return (async function () {
|
||||||
|
_this.assertState();
|
||||||
|
let ret = f.apply(this, arguments);
|
||||||
|
while (_this.exports.asyncify_get_state() === AsyncifyState.UNWINDING) {
|
||||||
|
_this.exports.asyncify_stop_unwind();
|
||||||
|
_this.value = await _this.value;
|
||||||
|
_this.assertState();
|
||||||
|
_this.exports.asyncify_start_rewind(_this.dataPtr);
|
||||||
|
ret = f.call(this);
|
||||||
|
}
|
||||||
|
_this.assertState();
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
wrapExports(exports, needWrap) {
|
||||||
|
return wrapInstanceExports(exports, (exportValue, name) => {
|
||||||
|
let ignore = ignoreNames.indexOf(name) !== -1 || typeof exportValue !== 'function';
|
||||||
|
if (Array.isArray(needWrap)) {
|
||||||
|
ignore = ignore || (needWrap.indexOf(name) === -1);
|
||||||
|
}
|
||||||
|
return ignore ? exportValue : this.wrapExportFunction(exportValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
export * from "./asyncify.mjs";
|
||||||
|
export * from "./load.mjs";
|
||||||
|
export * from "./wasi/index.mjs";
|
||||||
|
export * from "./memory.mjs";
|
||||||
|
export * from "./jspi.mjs";
|
||||||
|
export * from "./wasi/fs.mjs";
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
import { wrapInstanceExports } from "./wasi/util.mjs";
|
||||||
|
import { _WebAssembly } from "./webassembly.mjs";
|
||||||
|
function checkWebAssemblyFunction() {
|
||||||
|
const WebAssemblyFunction = _WebAssembly.Function;
|
||||||
|
if (typeof WebAssemblyFunction !== 'function') {
|
||||||
|
throw new Error('WebAssembly.Function is not supported in this environment.' +
|
||||||
|
' If you are using V8 based browser like Chrome, try to specify' +
|
||||||
|
' --js-flags="--wasm-staging --experimental-wasm-stack-switching"');
|
||||||
|
}
|
||||||
|
return WebAssemblyFunction;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function wrapAsyncImport(f, parameterType, returnType) {
|
||||||
|
const WebAssemblyFunction = checkWebAssemblyFunction();
|
||||||
|
if (typeof f !== 'function') {
|
||||||
|
throw new TypeError('Function required');
|
||||||
|
}
|
||||||
|
const parameters = parameterType.slice(0);
|
||||||
|
parameters.unshift('externref');
|
||||||
|
return new WebAssemblyFunction({ parameters, results: returnType }, f, { suspending: 'first' });
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function wrapAsyncExport(f) {
|
||||||
|
const WebAssemblyFunction = checkWebAssemblyFunction();
|
||||||
|
if (typeof f !== 'function') {
|
||||||
|
throw new TypeError('Function required');
|
||||||
|
}
|
||||||
|
return new WebAssemblyFunction({ parameters: [...WebAssemblyFunction.type(f).parameters.slice(1)], results: ['externref'] }, f, { promising: 'first' });
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function wrapExports(exports, needWrap) {
|
||||||
|
return wrapInstanceExports(exports, (exportValue, name) => {
|
||||||
|
let ignore = typeof exportValue !== 'function';
|
||||||
|
if (Array.isArray(needWrap)) {
|
||||||
|
ignore = ignore || (needWrap.indexOf(name) === -1);
|
||||||
|
}
|
||||||
|
return ignore ? exportValue : wrapAsyncExport(exportValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
import { _WebAssembly } from "./webassembly.mjs";
|
||||||
|
import { Asyncify } from "./asyncify.mjs";
|
||||||
|
function validateImports(imports) {
|
||||||
|
if (imports && typeof imports !== 'object') {
|
||||||
|
throw new TypeError('imports must be an object or undefined');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function fetchWasm(urlOrBuffer, imports) {
|
||||||
|
if (typeof wx !== 'undefined' && typeof __wxConfig !== 'undefined') {
|
||||||
|
return _WebAssembly.instantiate(urlOrBuffer, imports);
|
||||||
|
}
|
||||||
|
return fetch(urlOrBuffer)
|
||||||
|
.then(response => response.arrayBuffer())
|
||||||
|
.then(buffer => _WebAssembly.instantiate(buffer, imports));
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function load(wasmInput, imports) {
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
let source;
|
||||||
|
if (wasmInput instanceof ArrayBuffer || ArrayBuffer.isView(wasmInput)) {
|
||||||
|
return _WebAssembly.instantiate(wasmInput, imports);
|
||||||
|
}
|
||||||
|
if (wasmInput instanceof _WebAssembly.Module) {
|
||||||
|
return _WebAssembly.instantiate(wasmInput, imports).then((instance) => {
|
||||||
|
return { instance, module: wasmInput };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (typeof wasmInput !== 'string' && !(wasmInput instanceof URL)) {
|
||||||
|
throw new TypeError('Invalid source');
|
||||||
|
}
|
||||||
|
if (typeof _WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
let responsePromise;
|
||||||
|
try {
|
||||||
|
responsePromise = fetch(wasmInput);
|
||||||
|
source = _WebAssembly.instantiateStreaming(responsePromise, imports).catch(() => {
|
||||||
|
return fetchWasm(wasmInput, imports);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
source = fetchWasm(wasmInput, imports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
source = fetchWasm(wasmInput, imports);
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function asyncifyLoad(asyncify, urlOrBuffer, imports) {
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
const asyncifyHelper = new Asyncify();
|
||||||
|
imports = asyncifyHelper.wrapImports(imports);
|
||||||
|
return load(urlOrBuffer, imports).then(source => {
|
||||||
|
var _a;
|
||||||
|
const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
|
||||||
|
return { module: source.module, instance: asyncifyHelper.init(memory, source.instance, asyncify) };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function loadSync(wasmInput, imports) {
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
let module;
|
||||||
|
if ((wasmInput instanceof ArrayBuffer) || ArrayBuffer.isView(wasmInput)) {
|
||||||
|
module = new _WebAssembly.Module(wasmInput);
|
||||||
|
}
|
||||||
|
else if (wasmInput instanceof WebAssembly.Module) {
|
||||||
|
module = wasmInput;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new TypeError('Invalid source');
|
||||||
|
}
|
||||||
|
const instance = new _WebAssembly.Instance(module, imports);
|
||||||
|
const source = { instance, module };
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function asyncifyLoadSync(asyncify, buffer, imports) {
|
||||||
|
var _a;
|
||||||
|
validateImports(imports);
|
||||||
|
imports = imports !== null && imports !== void 0 ? imports : {};
|
||||||
|
const asyncifyHelper = new Asyncify();
|
||||||
|
imports = asyncifyHelper.wrapImports(imports);
|
||||||
|
const source = loadSync(buffer, imports);
|
||||||
|
const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
|
||||||
|
return { module: source.module, instance: asyncifyHelper.init(memory, source.instance, asyncify) };
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
import { _WebAssembly } from "./webassembly.mjs";
|
||||||
|
/** @public */
|
||||||
|
export const WebAssemblyMemory = /*#__PURE__*/ (function () { return _WebAssembly.Memory; })();
|
||||||
|
/** @public */
|
||||||
|
export class Memory extends WebAssemblyMemory {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor(descriptor) {
|
||||||
|
super(descriptor);
|
||||||
|
}
|
||||||
|
get HEAP8() { return new Int8Array(super.buffer); }
|
||||||
|
get HEAPU8() { return new Uint8Array(super.buffer); }
|
||||||
|
get HEAP16() { return new Int16Array(super.buffer); }
|
||||||
|
get HEAPU16() { return new Uint16Array(super.buffer); }
|
||||||
|
get HEAP32() { return new Int32Array(super.buffer); }
|
||||||
|
get HEAPU32() { return new Uint32Array(super.buffer); }
|
||||||
|
get HEAP64() { return new BigInt64Array(super.buffer); }
|
||||||
|
get HEAPU64() { return new BigUint64Array(super.buffer); }
|
||||||
|
get HEAPF32() { return new Float32Array(super.buffer); }
|
||||||
|
get HEAPF64() { return new Float64Array(super.buffer); }
|
||||||
|
get view() { return new DataView(super.buffer); }
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export function extendMemory(memory) {
|
||||||
|
if (Object.getPrototypeOf(memory) === _WebAssembly.Memory.prototype) {
|
||||||
|
Object.setPrototypeOf(memory, Memory.prototype);
|
||||||
|
}
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
|||||||
|
import { WasiErrno } from "./types.mjs";
|
||||||
|
export function strerror(errno) {
|
||||||
|
switch (errno) {
|
||||||
|
case WasiErrno.ESUCCESS: return 'Success';
|
||||||
|
case WasiErrno.E2BIG: return 'Argument list too long';
|
||||||
|
case WasiErrno.EACCES: return 'Permission denied';
|
||||||
|
case WasiErrno.EADDRINUSE: return 'Address in use';
|
||||||
|
case WasiErrno.EADDRNOTAVAIL: return 'Address not available';
|
||||||
|
case WasiErrno.EAFNOSUPPORT: return 'Address family not supported by protocol';
|
||||||
|
case WasiErrno.EAGAIN: return 'Resource temporarily unavailable';
|
||||||
|
case WasiErrno.EALREADY: return 'Operation already in progress';
|
||||||
|
case WasiErrno.EBADF: return 'Bad file descriptor';
|
||||||
|
case WasiErrno.EBADMSG: return 'Bad message';
|
||||||
|
case WasiErrno.EBUSY: return 'Resource busy';
|
||||||
|
case WasiErrno.ECANCELED: return 'Operation canceled';
|
||||||
|
case WasiErrno.ECHILD: return 'No child process';
|
||||||
|
case WasiErrno.ECONNABORTED: return 'Connection aborted';
|
||||||
|
case WasiErrno.ECONNREFUSED: return 'Connection refused';
|
||||||
|
case WasiErrno.ECONNRESET: return 'Connection reset by peer';
|
||||||
|
case WasiErrno.EDEADLK: return 'Resource deadlock would occur';
|
||||||
|
case WasiErrno.EDESTADDRREQ: return 'Destination address required';
|
||||||
|
case WasiErrno.EDOM: return 'Domain error';
|
||||||
|
case WasiErrno.EDQUOT: return 'Quota exceeded';
|
||||||
|
case WasiErrno.EEXIST: return 'File exists';
|
||||||
|
case WasiErrno.EFAULT: return 'Bad address';
|
||||||
|
case WasiErrno.EFBIG: return 'File too large';
|
||||||
|
case WasiErrno.EHOSTUNREACH: return 'Host is unreachable';
|
||||||
|
case WasiErrno.EIDRM: return 'Identifier removed';
|
||||||
|
case WasiErrno.EILSEQ: return 'Illegal byte sequence';
|
||||||
|
case WasiErrno.EINPROGRESS: return 'Operation in progress';
|
||||||
|
case WasiErrno.EINTR: return 'Interrupted system call';
|
||||||
|
case WasiErrno.EINVAL: return 'Invalid argument';
|
||||||
|
case WasiErrno.EIO: return 'I/O error';
|
||||||
|
case WasiErrno.EISCONN: return 'Socket is connected';
|
||||||
|
case WasiErrno.EISDIR: return 'Is a directory';
|
||||||
|
case WasiErrno.ELOOP: return 'Symbolic link loop';
|
||||||
|
case WasiErrno.EMFILE: return 'No file descriptors available';
|
||||||
|
case WasiErrno.EMLINK: return 'Too many links';
|
||||||
|
case WasiErrno.EMSGSIZE: return 'Message too large';
|
||||||
|
case WasiErrno.EMULTIHOP: return 'Multihop attempted';
|
||||||
|
case WasiErrno.ENAMETOOLONG: return 'Filename too long';
|
||||||
|
case WasiErrno.ENETDOWN: return 'Network is down';
|
||||||
|
case WasiErrno.ENETRESET: return 'Connection reset by network';
|
||||||
|
case WasiErrno.ENETUNREACH: return 'Network unreachable';
|
||||||
|
case WasiErrno.ENFILE: return 'Too many files open in system';
|
||||||
|
case WasiErrno.ENOBUFS: return 'No buffer space available';
|
||||||
|
case WasiErrno.ENODEV: return 'No such device';
|
||||||
|
case WasiErrno.ENOENT: return 'No such file or directory';
|
||||||
|
case WasiErrno.ENOEXEC: return 'Exec format error';
|
||||||
|
case WasiErrno.ENOLCK: return 'No locks available';
|
||||||
|
case WasiErrno.ENOLINK: return 'Link has been severed';
|
||||||
|
case WasiErrno.ENOMEM: return 'Out of memory';
|
||||||
|
case WasiErrno.ENOMSG: return 'No message of the desired type';
|
||||||
|
case WasiErrno.ENOPROTOOPT: return 'Protocol not available';
|
||||||
|
case WasiErrno.ENOSPC: return 'No space left on device';
|
||||||
|
case WasiErrno.ENOSYS: return 'Function not implemented';
|
||||||
|
case WasiErrno.ENOTCONN: return 'Socket not connected';
|
||||||
|
case WasiErrno.ENOTDIR: return 'Not a directory';
|
||||||
|
case WasiErrno.ENOTEMPTY: return 'Directory not empty';
|
||||||
|
case WasiErrno.ENOTRECOVERABLE: return 'State not recoverable';
|
||||||
|
case WasiErrno.ENOTSOCK: return 'Not a socket';
|
||||||
|
case WasiErrno.ENOTSUP: return 'Not supported';
|
||||||
|
case WasiErrno.ENOTTY: return 'Not a tty';
|
||||||
|
case WasiErrno.ENXIO: return 'No such device or address';
|
||||||
|
case WasiErrno.EOVERFLOW: return 'Value too large for data type';
|
||||||
|
case WasiErrno.EOWNERDEAD: return 'Previous owner died';
|
||||||
|
case WasiErrno.EPERM: return 'Operation not permitted';
|
||||||
|
case WasiErrno.EPIPE: return 'Broken pipe';
|
||||||
|
case WasiErrno.EPROTO: return 'Protocol error';
|
||||||
|
case WasiErrno.EPROTONOSUPPORT: return 'Protocol not supported';
|
||||||
|
case WasiErrno.EPROTOTYPE: return 'Protocol wrong type for socket';
|
||||||
|
case WasiErrno.ERANGE: return 'Result not representable';
|
||||||
|
case WasiErrno.EROFS: return 'Read-only file system';
|
||||||
|
case WasiErrno.ESPIPE: return 'Invalid seek';
|
||||||
|
case WasiErrno.ESRCH: return 'No such process';
|
||||||
|
case WasiErrno.ESTALE: return 'Stale file handle';
|
||||||
|
case WasiErrno.ETIMEDOUT: return 'Operation timed out';
|
||||||
|
case WasiErrno.ETXTBSY: return 'Text file busy';
|
||||||
|
case WasiErrno.EXDEV: return 'Cross-device link';
|
||||||
|
case WasiErrno.ENOTCAPABLE: return 'Capabilities insufficient';
|
||||||
|
default: return 'Unknown error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class WasiError extends Error {
|
||||||
|
constructor(message, errno) {
|
||||||
|
super(message);
|
||||||
|
this.errno = errno;
|
||||||
|
}
|
||||||
|
getErrorMessage() {
|
||||||
|
return strerror(this.errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.defineProperty(WasiError.prototype, 'name', {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
value: 'WasiError'
|
||||||
|
});
|
||||||
Generated
Vendored
+256
@@ -0,0 +1,256 @@
|
|||||||
|
import { WasiErrno, FileControlFlag, WasiFileType, WasiWhence } from "./types.mjs";
|
||||||
|
import { getRights } from "./rights.mjs";
|
||||||
|
import { WasiError } from "./error.mjs";
|
||||||
|
export function concatBuffer(buffers, size) {
|
||||||
|
let total = 0;
|
||||||
|
if (typeof size === 'number' && size >= 0) {
|
||||||
|
total = size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (let i = 0; i < buffers.length; i++) {
|
||||||
|
const buffer = buffers[i];
|
||||||
|
total += buffer.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let pos = 0;
|
||||||
|
const ret = new Uint8Array(total);
|
||||||
|
for (let i = 0; i < buffers.length; i++) {
|
||||||
|
const buffer = buffers[i];
|
||||||
|
ret.set(buffer, pos);
|
||||||
|
pos += buffer.length;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
export class FileDescriptor {
|
||||||
|
constructor(id, fd, path, realPath, type, rightsBase, rightsInheriting, preopen) {
|
||||||
|
this.id = id;
|
||||||
|
this.fd = fd;
|
||||||
|
this.path = path;
|
||||||
|
this.realPath = realPath;
|
||||||
|
this.type = type;
|
||||||
|
this.rightsBase = rightsBase;
|
||||||
|
this.rightsInheriting = rightsInheriting;
|
||||||
|
this.preopen = preopen;
|
||||||
|
this.pos = BigInt(0);
|
||||||
|
this.size = BigInt(0);
|
||||||
|
}
|
||||||
|
seek(offset, whence) {
|
||||||
|
if (whence === WasiWhence.SET) {
|
||||||
|
this.pos = BigInt(offset);
|
||||||
|
}
|
||||||
|
else if (whence === WasiWhence.CUR) {
|
||||||
|
this.pos += BigInt(offset);
|
||||||
|
}
|
||||||
|
else if (whence === WasiWhence.END) {
|
||||||
|
this.pos = BigInt(this.size) - BigInt(offset);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new WasiError('Unknown whence', WasiErrno.EIO);
|
||||||
|
}
|
||||||
|
return this.pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class StandardOutput extends FileDescriptor {
|
||||||
|
constructor(log, id, fd, path, realPath, type, rightsBase, rightsInheriting, preopen) {
|
||||||
|
super(id, fd, path, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
this._log = log;
|
||||||
|
this._buf = null;
|
||||||
|
}
|
||||||
|
write(buffer) {
|
||||||
|
const originalBuffer = buffer;
|
||||||
|
if (this._buf) {
|
||||||
|
buffer = concatBuffer([this._buf, buffer]);
|
||||||
|
this._buf = null;
|
||||||
|
}
|
||||||
|
if (buffer.indexOf(10) === -1) {
|
||||||
|
this._buf = buffer;
|
||||||
|
return originalBuffer.byteLength;
|
||||||
|
}
|
||||||
|
let written = 0;
|
||||||
|
let lastBegin = 0;
|
||||||
|
let index;
|
||||||
|
while ((index = buffer.indexOf(10, written)) !== -1) {
|
||||||
|
const str = new TextDecoder().decode(buffer.subarray(lastBegin, index));
|
||||||
|
this._log(str);
|
||||||
|
written += index - lastBegin + 1;
|
||||||
|
lastBegin = index + 1;
|
||||||
|
}
|
||||||
|
if (written < buffer.length) {
|
||||||
|
this._buf = buffer.slice(written);
|
||||||
|
}
|
||||||
|
return originalBuffer.byteLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function toFileType(stat) {
|
||||||
|
if (stat.isBlockDevice())
|
||||||
|
return WasiFileType.BLOCK_DEVICE;
|
||||||
|
if (stat.isCharacterDevice())
|
||||||
|
return WasiFileType.CHARACTER_DEVICE;
|
||||||
|
if (stat.isDirectory())
|
||||||
|
return WasiFileType.DIRECTORY;
|
||||||
|
if (stat.isSocket())
|
||||||
|
return WasiFileType.SOCKET_STREAM;
|
||||||
|
if (stat.isFile())
|
||||||
|
return WasiFileType.REGULAR_FILE;
|
||||||
|
if (stat.isSymbolicLink())
|
||||||
|
return WasiFileType.SYMBOLIC_LINK;
|
||||||
|
return WasiFileType.UNKNOWN;
|
||||||
|
}
|
||||||
|
export function toFileStat(view, buf, stat) {
|
||||||
|
view.setBigUint64(buf, stat.dev, true);
|
||||||
|
view.setBigUint64(buf + 8, stat.ino, true);
|
||||||
|
view.setBigUint64(buf + 16, BigInt(toFileType(stat)), true);
|
||||||
|
view.setBigUint64(buf + 24, stat.nlink, true);
|
||||||
|
view.setBigUint64(buf + 32, stat.size, true);
|
||||||
|
view.setBigUint64(buf + 40, stat.atimeMs * BigInt(1000000), true);
|
||||||
|
view.setBigUint64(buf + 48, stat.mtimeMs * BigInt(1000000), true);
|
||||||
|
view.setBigUint64(buf + 56, stat.ctimeMs * BigInt(1000000), true);
|
||||||
|
}
|
||||||
|
export class FileDescriptorTable {
|
||||||
|
constructor(options) {
|
||||||
|
this.used = 0;
|
||||||
|
this.size = options.size;
|
||||||
|
this.fds = Array(options.size);
|
||||||
|
this.stdio = [options.in, options.out, options.err];
|
||||||
|
this.print = options.print;
|
||||||
|
this.printErr = options.printErr;
|
||||||
|
this.insertStdio(options.in, 0, '<stdin>');
|
||||||
|
this.insertStdio(options.out, 1, '<stdout>');
|
||||||
|
this.insertStdio(options.err, 2, '<stderr>');
|
||||||
|
}
|
||||||
|
insertStdio(fd, expected, name) {
|
||||||
|
const type = WasiFileType.CHARACTER_DEVICE;
|
||||||
|
const { base, inheriting } = getRights(this.stdio, fd, FileControlFlag.O_RDWR, type);
|
||||||
|
const wrap = this.insert(fd, name, name, type, base, inheriting, 0);
|
||||||
|
if (wrap.id !== expected) {
|
||||||
|
throw new WasiError(`id: ${wrap.id} !== expected: ${expected}`, WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
insert(fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen) {
|
||||||
|
var _a, _b;
|
||||||
|
let index = -1;
|
||||||
|
if (this.used >= this.size) {
|
||||||
|
const newSize = this.size * 2;
|
||||||
|
this.fds.length = newSize;
|
||||||
|
index = this.size;
|
||||||
|
this.size = newSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (let i = 0; i < this.size; ++i) {
|
||||||
|
if (this.fds[i] == null) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let entry;
|
||||||
|
if (mappedPath === '<stdout>') {
|
||||||
|
entry = new StandardOutput((_a = this.print) !== null && _a !== void 0 ? _a : console.log, index, fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
}
|
||||||
|
else if (mappedPath === '<stderr>') {
|
||||||
|
entry = new StandardOutput((_b = this.printErr) !== null && _b !== void 0 ? _b : console.error, index, fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry = new FileDescriptor(index, fd, mappedPath, realPath, type, rightsBase, rightsInheriting, preopen);
|
||||||
|
}
|
||||||
|
this.fds[index] = entry;
|
||||||
|
this.used++;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
get(id, base, inheriting) {
|
||||||
|
if (id >= this.size) {
|
||||||
|
throw new WasiError('Invalid fd', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const entry = this.fds[id];
|
||||||
|
if (!entry || entry.id !== id) {
|
||||||
|
throw new WasiError('Bad file descriptor', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
/* Validate that the fd has the necessary rights. */
|
||||||
|
if ((~entry.rightsBase & base) !== BigInt(0) || (~entry.rightsInheriting & inheriting) !== BigInt(0)) {
|
||||||
|
throw new WasiError('Capabilities insufficient', WasiErrno.ENOTCAPABLE);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
remove(id) {
|
||||||
|
if (id >= this.size) {
|
||||||
|
throw new WasiError('Invalid fd', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const entry = this.fds[id];
|
||||||
|
if (!entry || entry.id !== id) {
|
||||||
|
throw new WasiError('Bad file descriptor', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
this.fds[id] = undefined;
|
||||||
|
this.used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class SyncTable extends FileDescriptorTable {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
this.fs = options.fs;
|
||||||
|
}
|
||||||
|
getFileTypeByFd(fd) {
|
||||||
|
const stats = this.fs.fstatSync(fd, { bigint: true });
|
||||||
|
return toFileType(stats);
|
||||||
|
}
|
||||||
|
insertPreopen(fd, mappedPath, realPath) {
|
||||||
|
const type = this.getFileTypeByFd(fd);
|
||||||
|
if (type !== WasiFileType.DIRECTORY) {
|
||||||
|
throw new WasiError(`Preopen not dir: ["${mappedPath}", "${realPath}"]`, WasiErrno.ENOTDIR);
|
||||||
|
}
|
||||||
|
const result = getRights(this.stdio, fd, 0, type);
|
||||||
|
return this.insert(fd, mappedPath, realPath, type, result.base, result.inheriting, 1);
|
||||||
|
}
|
||||||
|
renumber(dst, src) {
|
||||||
|
if (dst === src)
|
||||||
|
return;
|
||||||
|
if (dst >= this.size || src >= this.size) {
|
||||||
|
throw new WasiError('Invalid fd', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const dstEntry = this.fds[dst];
|
||||||
|
const srcEntry = this.fds[src];
|
||||||
|
if (!dstEntry || !srcEntry || dstEntry.id !== dst || srcEntry.id !== src) {
|
||||||
|
throw new WasiError('Invalid fd', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
this.fs.closeSync(dstEntry.fd);
|
||||||
|
this.fds[dst] = this.fds[src];
|
||||||
|
this.fds[dst].id = dst;
|
||||||
|
this.fds[src] = undefined;
|
||||||
|
this.used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class AsyncTable extends FileDescriptorTable {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
}
|
||||||
|
async getFileTypeByFd(fd) {
|
||||||
|
const stats = await fd.stat({ bigint: true });
|
||||||
|
return toFileType(stats);
|
||||||
|
}
|
||||||
|
async insertPreopen(fd, mappedPath, realPath) {
|
||||||
|
const type = await this.getFileTypeByFd(fd);
|
||||||
|
if (type !== WasiFileType.DIRECTORY) {
|
||||||
|
throw new WasiError(`Preopen not dir: ["${mappedPath}", "${realPath}"]`, WasiErrno.ENOTDIR);
|
||||||
|
}
|
||||||
|
const result = getRights(this.stdio, fd.fd, 0, type);
|
||||||
|
return this.insert(fd, mappedPath, realPath, type, result.base, result.inheriting, 1);
|
||||||
|
}
|
||||||
|
async renumber(dst, src) {
|
||||||
|
if (dst === src)
|
||||||
|
return;
|
||||||
|
if (dst >= this.size || src >= this.size) {
|
||||||
|
throw new WasiError('Invalid fd', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
const dstEntry = this.fds[dst];
|
||||||
|
const srcEntry = this.fds[src];
|
||||||
|
if (!dstEntry || !srcEntry || dstEntry.id !== dst || srcEntry.id !== src) {
|
||||||
|
throw new WasiError('Invalid fd', WasiErrno.EBADF);
|
||||||
|
}
|
||||||
|
await dstEntry.fd.close();
|
||||||
|
this.fds[dst] = this.fds[src];
|
||||||
|
this.fds[dst].id = dst;
|
||||||
|
this.fds[src] = undefined;
|
||||||
|
this.used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
export {};
|
||||||
Generated
Vendored
+186
@@ -0,0 +1,186 @@
|
|||||||
|
import { WASI as WASIPreview1 } from "./preview1.mjs";
|
||||||
|
import { validateObject, validateArray, validateBoolean, validateFunction, validateUndefined, validateString } from "./util.mjs";
|
||||||
|
// eslint-disable-next-line spaced-comment
|
||||||
|
const kEmptyObject = /*#__PURE__*/ Object.freeze(/*#__PURE__*/ Object.create(null));
|
||||||
|
const kExitCode = Symbol('kExitCode');
|
||||||
|
const kSetMemory = Symbol('kSetMemory');
|
||||||
|
const kStarted = Symbol('kStarted');
|
||||||
|
const kInstance = Symbol('kInstance');
|
||||||
|
const kBindingName = Symbol('kBindingName');
|
||||||
|
function validateOptions(options) {
|
||||||
|
var _a;
|
||||||
|
validateObject(options, 'options');
|
||||||
|
let _WASI;
|
||||||
|
if (options.version !== undefined) {
|
||||||
|
validateString(options.version, 'options.version');
|
||||||
|
switch (options.version) {
|
||||||
|
case 'unstable':
|
||||||
|
_WASI = WASIPreview1;
|
||||||
|
this[kBindingName] = 'wasi_unstable';
|
||||||
|
break;
|
||||||
|
case 'preview1':
|
||||||
|
_WASI = WASIPreview1;
|
||||||
|
this[kBindingName] = 'wasi_snapshot_preview1';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new TypeError(`unsupported WASI version "${options.version}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_WASI = WASIPreview1;
|
||||||
|
this[kBindingName] = 'wasi_snapshot_preview1';
|
||||||
|
}
|
||||||
|
if (options.args !== undefined) {
|
||||||
|
validateArray(options.args, 'options.args');
|
||||||
|
}
|
||||||
|
const args = ((_a = options.args) !== null && _a !== void 0 ? _a : []).map(String);
|
||||||
|
const env = [];
|
||||||
|
if (options.env !== undefined) {
|
||||||
|
validateObject(options.env, 'options.env');
|
||||||
|
Object.entries(options.env).forEach(({ 0: key, 1: value }) => {
|
||||||
|
if (value !== undefined) {
|
||||||
|
env.push(`${key}=${value}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const preopens = [];
|
||||||
|
if (options.preopens !== undefined) {
|
||||||
|
validateObject(options.preopens, 'options.preopens');
|
||||||
|
Object.entries(options.preopens).forEach(({ 0: key, 1: value }) => preopens.push({ mappedPath: String(key), realPath: String(value) }));
|
||||||
|
}
|
||||||
|
if (preopens.length > 0) {
|
||||||
|
if (options.fs === undefined) {
|
||||||
|
throw new Error('filesystem is disabled, can not preopen directory');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
validateObject(options.fs, 'options.fs');
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
throw new TypeError('Node.js fs like implementation is not provided');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if (options.filesystem !== undefined) {
|
||||||
|
// validateObject(options.filesystem, 'options.filesystem')
|
||||||
|
// validateString(options.filesystem.type, 'options.filesystem.type')
|
||||||
|
// if (options.filesystem.type !== 'memfs' && options.filesystem.type !== 'file-system-access-api') {
|
||||||
|
// throw new Error(`Filesystem type ${(options.filesystem as any).type as string} is not supported, only "memfs" and "file-system-access-api" is supported currently`)
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// validateObject(options.filesystem.fs, 'options.filesystem.fs')
|
||||||
|
// } catch (_) {
|
||||||
|
// throw new Error('Node.js fs like implementation is not provided')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (options.print !== undefined)
|
||||||
|
validateFunction(options.print, 'options.print');
|
||||||
|
if (options.printErr !== undefined)
|
||||||
|
validateFunction(options.printErr, 'options.printErr');
|
||||||
|
if (options.returnOnExit !== undefined) {
|
||||||
|
validateBoolean(options.returnOnExit, 'options.returnOnExit');
|
||||||
|
}
|
||||||
|
// const { stdin = 0, stdout = 1, stderr = 2 } = options
|
||||||
|
// validateInt32(stdin, 'options.stdin', 0)
|
||||||
|
// validateInt32(stdout, 'options.stdout', 0)
|
||||||
|
// validateInt32(stderr, 'options.stderr', 0)
|
||||||
|
// const stdio = [stdin, stdout, stderr] as const
|
||||||
|
const stdio = [0, 1, 2];
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
env,
|
||||||
|
preopens,
|
||||||
|
stdio,
|
||||||
|
_WASI
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function initWASI(setMemory, wrap) {
|
||||||
|
this[kSetMemory] = setMemory;
|
||||||
|
this.wasiImport = wrap;
|
||||||
|
this[kStarted] = false;
|
||||||
|
this[kExitCode] = 0;
|
||||||
|
this[kInstance] = undefined;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export class WASI {
|
||||||
|
constructor(options = kEmptyObject) {
|
||||||
|
const { args, env, preopens, stdio, _WASI } = validateOptions.call(this, options);
|
||||||
|
const wrap = _WASI.createSync(args, env, preopens, stdio, options.fs, options.print, options.printErr);
|
||||||
|
const setMemory = wrap._setMemory;
|
||||||
|
delete wrap._setMemory;
|
||||||
|
initWASI.call(this, setMemory, wrap);
|
||||||
|
if (options.returnOnExit) {
|
||||||
|
wrap.proc_exit = wasiReturnOnProcExit.bind(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finalizeBindings(instance, _a) {
|
||||||
|
var _b;
|
||||||
|
var { memory = (_b = instance === null || instance === void 0 ? void 0 : instance.exports) === null || _b === void 0 ? void 0 : _b.memory } = _a === void 0 ? {} : _a;
|
||||||
|
if (this[kStarted]) {
|
||||||
|
throw new Error('WASI instance has already started');
|
||||||
|
}
|
||||||
|
validateObject(instance, 'instance');
|
||||||
|
validateObject(instance.exports, 'instance.exports');
|
||||||
|
this[kSetMemory](memory);
|
||||||
|
this[kInstance] = instance;
|
||||||
|
this[kStarted] = true;
|
||||||
|
}
|
||||||
|
// Must not export _initialize, must export _start
|
||||||
|
start(instance) {
|
||||||
|
this.finalizeBindings(instance);
|
||||||
|
const { _start, _initialize } = this[kInstance].exports;
|
||||||
|
validateFunction(_start, 'instance.exports._start');
|
||||||
|
validateUndefined(_initialize, 'instance.exports._initialize');
|
||||||
|
let ret;
|
||||||
|
try {
|
||||||
|
ret = _start();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err !== kExitCode) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret instanceof Promise) {
|
||||||
|
return ret.then(() => this[kExitCode], (err) => {
|
||||||
|
if (err !== kExitCode) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
return this[kExitCode];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this[kExitCode];
|
||||||
|
}
|
||||||
|
// Must not export _start, may optionally export _initialize
|
||||||
|
initialize(instance) {
|
||||||
|
this.finalizeBindings(instance);
|
||||||
|
const { _start, _initialize } = this[kInstance].exports;
|
||||||
|
validateUndefined(_start, 'instance.exports._start');
|
||||||
|
if (_initialize !== undefined) {
|
||||||
|
validateFunction(_initialize, 'instance.exports._initialize');
|
||||||
|
return _initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getImportObject() {
|
||||||
|
return { [this[kBindingName]]: this.wasiImport };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function wasiReturnOnProcExit(rval) {
|
||||||
|
this[kExitCode] = rval;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
||||||
|
throw kExitCode;
|
||||||
|
}
|
||||||
|
/** @public */
|
||||||
|
export async function createAsyncWASI(options = kEmptyObject) {
|
||||||
|
const _this = Object.create(WASI.prototype);
|
||||||
|
const { args, env, preopens, stdio, _WASI } = validateOptions.call(_this, options);
|
||||||
|
if (options.asyncify !== undefined) {
|
||||||
|
validateObject(options.asyncify, 'options.asyncify');
|
||||||
|
validateFunction(options.asyncify.wrapImportFunction, 'options.asyncify.wrapImportFunction');
|
||||||
|
}
|
||||||
|
const wrap = await _WASI.createAsync(args, env, preopens, stdio, options.fs, options.print, options.printErr, options.asyncify);
|
||||||
|
const setMemory = wrap._setMemory;
|
||||||
|
delete wrap._setMemory;
|
||||||
|
initWASI.call(_this, setMemory, wrap);
|
||||||
|
if (options.returnOnExit) {
|
||||||
|
wrap.proc_exit = wasiReturnOnProcExit.bind(_this);
|
||||||
|
}
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
Generated
Vendored
+310
@@ -0,0 +1,310 @@
|
|||||||
|
import { validateString } from "./util.mjs";
|
||||||
|
const CHAR_DOT = 46; /* . */
|
||||||
|
const CHAR_FORWARD_SLASH = 47; /* / */
|
||||||
|
const CHAR_BACKWARD_SLASH = 92; /* \ */
|
||||||
|
const CHAR_COLON = 58; /* : */
|
||||||
|
const CHAR_UPPERCASE_A = 65; /* A */
|
||||||
|
const CHAR_UPPERCASE_Z = 90; /* Z */
|
||||||
|
const CHAR_LOWERCASE_A = 97; /* a */
|
||||||
|
const CHAR_LOWERCASE_Z = 122; /* z */
|
||||||
|
function isPathSeparatorWin(code) {
|
||||||
|
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
||||||
|
}
|
||||||
|
function isWindowsDeviceRoot(code) {
|
||||||
|
return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
|
||||||
|
(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
|
||||||
|
}
|
||||||
|
const _isWin32 = typeof process !== 'undefined' && process.platform === 'win32';
|
||||||
|
/**
|
||||||
|
* Windows variant of `resolve()`. Mirrors Node's `path.win32.resolve`
|
||||||
|
* semantics enough for the WASI shim's needs (drive-letter absolutes
|
||||||
|
* + UNC paths + per-drive cwd lookups via `process.env`/`process.cwd`).
|
||||||
|
*
|
||||||
|
* Why this is needed: on Windows, `FileDescriptor.realPath` is the
|
||||||
|
* host realpath returned by `fs.realpathSync(realPath, 'utf8')` — the
|
||||||
|
* backslash form `D:\…`. The POSIX-only `resolveImpl` below only
|
||||||
|
* treats `/` as a separator, reads `D` as non-`/`, decides realPath
|
||||||
|
* is "relative", and produces a garbage joined path. Downstream
|
||||||
|
* `fs.openSync(garbage)` then returns `EINVAL` and the WASI caller
|
||||||
|
* sees a permanent failure. This function gives us the correct
|
||||||
|
* Windows-style resolution without taking a Node-only `path` import
|
||||||
|
* (which would break browser bundles of this package).
|
||||||
|
*
|
||||||
|
* Cribbed from Node's `lib/path.js` `win32.resolve()` (MIT-licensed),
|
||||||
|
* trimmed to what WASI realpath resolution actually exercises.
|
||||||
|
*/
|
||||||
|
function resolveWin32(args) {
|
||||||
|
let resolvedDevice = '';
|
||||||
|
let resolvedTail = '';
|
||||||
|
let resolvedAbsolute = false;
|
||||||
|
for (let i = args.length - 1; i >= -1; i--) {
|
||||||
|
let path;
|
||||||
|
if (i >= 0) {
|
||||||
|
path = args[i];
|
||||||
|
validateString(path, 'path');
|
||||||
|
if (path.length === 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (resolvedDevice.length === 0) {
|
||||||
|
path = (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
||||||
|
? process.cwd()
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Look up per-drive cwd via the `=X:` env var convention; fall back
|
||||||
|
// to the global cwd if absent.
|
||||||
|
const envKey = `=${resolvedDevice}`;
|
||||||
|
const env = (typeof process !== 'undefined') ? process.env : undefined;
|
||||||
|
path = (env && typeof env[envKey] === 'string')
|
||||||
|
? env[envKey]
|
||||||
|
: (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
||||||
|
? process.cwd()
|
||||||
|
: '';
|
||||||
|
if (path === undefined ||
|
||||||
|
(path.slice(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() &&
|
||||||
|
path.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {
|
||||||
|
path = `${resolvedDevice}\\`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const len = path.length;
|
||||||
|
let rootEnd = 0;
|
||||||
|
let device = '';
|
||||||
|
let isAbsolute = false;
|
||||||
|
const code = path.charCodeAt(0);
|
||||||
|
if (len === 1) {
|
||||||
|
if (isPathSeparatorWin(code)) {
|
||||||
|
rootEnd = 1;
|
||||||
|
isAbsolute = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isPathSeparatorWin(code)) {
|
||||||
|
isAbsolute = true;
|
||||||
|
if (isPathSeparatorWin(path.charCodeAt(1))) {
|
||||||
|
// UNC path: `\\server\share\…`
|
||||||
|
let j = 2;
|
||||||
|
let last = j;
|
||||||
|
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
||||||
|
j++;
|
||||||
|
if (j < len && j !== last) {
|
||||||
|
const firstPart = path.slice(last, j);
|
||||||
|
last = j;
|
||||||
|
while (j < len && isPathSeparatorWin(path.charCodeAt(j)))
|
||||||
|
j++;
|
||||||
|
if (j < len && j !== last) {
|
||||||
|
last = j;
|
||||||
|
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
||||||
|
j++;
|
||||||
|
if (j === len || j !== last) {
|
||||||
|
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
|
||||||
|
rootEnd = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rootEnd = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
|
||||||
|
device = path.slice(0, 2);
|
||||||
|
rootEnd = 2;
|
||||||
|
if (len > 2 && isPathSeparatorWin(path.charCodeAt(2))) {
|
||||||
|
isAbsolute = true;
|
||||||
|
rootEnd = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (device.length > 0) {
|
||||||
|
if (resolvedDevice.length > 0) {
|
||||||
|
if (device.toLowerCase() !== resolvedDevice.toLowerCase())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolvedDevice = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resolvedAbsolute) {
|
||||||
|
if (resolvedDevice.length > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`;
|
||||||
|
resolvedAbsolute = isAbsolute;
|
||||||
|
if (isAbsolute && resolvedDevice.length > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isPathSeparatorWin);
|
||||||
|
return resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail || '.';
|
||||||
|
}
|
||||||
|
function isPosixPathSeparator(code) {
|
||||||
|
return code === CHAR_FORWARD_SLASH;
|
||||||
|
}
|
||||||
|
function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
|
||||||
|
let res = '';
|
||||||
|
let lastSegmentLength = 0;
|
||||||
|
let lastSlash = -1;
|
||||||
|
let dots = 0;
|
||||||
|
let code = 0;
|
||||||
|
for (let i = 0; i <= path.length; ++i) {
|
||||||
|
if (i < path.length) {
|
||||||
|
code = path.charCodeAt(i);
|
||||||
|
}
|
||||||
|
else if (isPathSeparator(code)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
code = CHAR_FORWARD_SLASH;
|
||||||
|
}
|
||||||
|
if (isPathSeparator(code)) {
|
||||||
|
if (lastSlash === i - 1 || dots === 1) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
else if (dots === 2) {
|
||||||
|
if (res.length < 2 || lastSegmentLength !== 2 ||
|
||||||
|
res.charCodeAt(res.length - 1) !== CHAR_DOT ||
|
||||||
|
res.charCodeAt(res.length - 2) !== CHAR_DOT) {
|
||||||
|
if (res.length > 2) {
|
||||||
|
const lastSlashIndex = res.indexOf(separator);
|
||||||
|
if (lastSlashIndex === -1) {
|
||||||
|
res = '';
|
||||||
|
lastSegmentLength = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = res.slice(0, lastSlashIndex);
|
||||||
|
lastSegmentLength =
|
||||||
|
res.length - 1 - res.indexOf(separator);
|
||||||
|
}
|
||||||
|
lastSlash = i;
|
||||||
|
dots = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (res.length !== 0) {
|
||||||
|
res = '';
|
||||||
|
lastSegmentLength = 0;
|
||||||
|
lastSlash = i;
|
||||||
|
dots = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowAboveRoot) {
|
||||||
|
res += res.length > 0 ? `${separator}..` : '..';
|
||||||
|
lastSegmentLength = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (res.length > 0) {
|
||||||
|
res += `${separator}${path.slice(lastSlash + 1, i)}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = path.slice(lastSlash + 1, i);
|
||||||
|
}
|
||||||
|
lastSegmentLength = i - lastSlash - 1;
|
||||||
|
}
|
||||||
|
lastSlash = i;
|
||||||
|
dots = 0;
|
||||||
|
}
|
||||||
|
else if (code === CHAR_DOT && dots !== -1) {
|
||||||
|
++dots;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dots = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
export function resolve(...args) {
|
||||||
|
// On Windows, host paths are `D:\…` style. The POSIX-only resolver
|
||||||
|
// below treats `D` as a non-`/` character and produces garbage; route
|
||||||
|
// to the Windows-aware variant. POSIX hosts (Linux/macOS/browser)
|
||||||
|
// run the original code path unchanged — `_isWin32` is constant-folded
|
||||||
|
// away on those targets.
|
||||||
|
if (_isWin32)
|
||||||
|
return resolveWin32(args);
|
||||||
|
let resolvedPath = '';
|
||||||
|
let resolvedAbsolute = false;
|
||||||
|
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
||||||
|
const path = i >= 0 ? args[i] : '/';
|
||||||
|
validateString(path, 'path');
|
||||||
|
// Skip empty entries
|
||||||
|
if (path.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resolvedPath = `${path}/${resolvedPath}`;
|
||||||
|
resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH;
|
||||||
|
}
|
||||||
|
// At this point the path should be resolved to a full absolute path, but
|
||||||
|
// handle relative paths to be safe (might happen when process.cwd() fails)
|
||||||
|
// Normalize the path
|
||||||
|
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/', isPosixPathSeparator);
|
||||||
|
if (resolvedAbsolute) {
|
||||||
|
return `/${resolvedPath}`;
|
||||||
|
}
|
||||||
|
return resolvedPath.length > 0 ? resolvedPath : '.';
|
||||||
|
}
|
||||||
|
export function relative(from, to) {
|
||||||
|
validateString(from, 'from');
|
||||||
|
validateString(to, 'to');
|
||||||
|
if (from === to)
|
||||||
|
return '';
|
||||||
|
// Trim leading forward slashes.
|
||||||
|
from = resolve(from);
|
||||||
|
to = resolve(to);
|
||||||
|
if (from === to)
|
||||||
|
return '';
|
||||||
|
const fromStart = 1;
|
||||||
|
const fromEnd = from.length;
|
||||||
|
const fromLen = fromEnd - fromStart;
|
||||||
|
const toStart = 1;
|
||||||
|
const toLen = to.length - toStart;
|
||||||
|
// Compare paths to find the longest common path from root
|
||||||
|
const length = (fromLen < toLen ? fromLen : toLen);
|
||||||
|
let lastCommonSep = -1;
|
||||||
|
let i = 0;
|
||||||
|
for (; i < length; i++) {
|
||||||
|
const fromCode = from.charCodeAt(fromStart + i);
|
||||||
|
if (fromCode !== to.charCodeAt(toStart + i)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (fromCode === CHAR_FORWARD_SLASH) {
|
||||||
|
lastCommonSep = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i === length) {
|
||||||
|
if (toLen > length) {
|
||||||
|
if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {
|
||||||
|
// We get here if `from` is the exact base path for `to`.
|
||||||
|
// For example: from='/foo/bar'; to='/foo/bar/baz'
|
||||||
|
return to.slice(toStart + i + 1);
|
||||||
|
}
|
||||||
|
if (i === 0) {
|
||||||
|
// We get here if `from` is the root
|
||||||
|
// For example: from='/'; to='/foo'
|
||||||
|
return to.slice(toStart + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fromLen > length) {
|
||||||
|
if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {
|
||||||
|
// We get here if `to` is the exact base path for `from`.
|
||||||
|
// For example: from='/foo/bar/baz'; to='/foo/bar'
|
||||||
|
lastCommonSep = i;
|
||||||
|
}
|
||||||
|
else if (i === 0) {
|
||||||
|
// We get here if `to` is the root.
|
||||||
|
// For example: from='/foo/bar'; to='/'
|
||||||
|
lastCommonSep = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let out = '';
|
||||||
|
// Generate the relative path based on the path difference between `to`
|
||||||
|
// and `from`.
|
||||||
|
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
|
||||||
|
if (i === fromEnd ||
|
||||||
|
from.charCodeAt(i) === CHAR_FORWARD_SLASH) {
|
||||||
|
out += out.length === 0 ? '..' : '/..';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Lastly, append the rest of the destination (`to`) path that comes after
|
||||||
|
// the common path parts.
|
||||||
|
return `${out}${to.slice(toStart + lastCommonSep)}`;
|
||||||
|
}
|
||||||
Generated
Vendored
+1593
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+135
@@ -0,0 +1,135 @@
|
|||||||
|
import { WasiError } from "./error.mjs";
|
||||||
|
import { WasiErrno, WasiRights, WasiFileType } from "./types.mjs";
|
||||||
|
export const RIGHTS_ALL = WasiRights.FD_DATASYNC |
|
||||||
|
WasiRights.FD_READ |
|
||||||
|
WasiRights.FD_SEEK |
|
||||||
|
WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
WasiRights.FD_SYNC |
|
||||||
|
WasiRights.FD_TELL |
|
||||||
|
WasiRights.FD_WRITE |
|
||||||
|
WasiRights.FD_ADVISE |
|
||||||
|
WasiRights.FD_ALLOCATE |
|
||||||
|
WasiRights.PATH_CREATE_DIRECTORY |
|
||||||
|
WasiRights.PATH_CREATE_FILE |
|
||||||
|
WasiRights.PATH_LINK_SOURCE |
|
||||||
|
WasiRights.PATH_LINK_TARGET |
|
||||||
|
WasiRights.PATH_OPEN |
|
||||||
|
WasiRights.FD_READDIR |
|
||||||
|
WasiRights.PATH_READLINK |
|
||||||
|
WasiRights.PATH_RENAME_SOURCE |
|
||||||
|
WasiRights.PATH_RENAME_TARGET |
|
||||||
|
WasiRights.PATH_FILESTAT_GET |
|
||||||
|
WasiRights.PATH_FILESTAT_SET_SIZE |
|
||||||
|
WasiRights.PATH_FILESTAT_SET_TIMES |
|
||||||
|
WasiRights.FD_FILESTAT_GET |
|
||||||
|
WasiRights.FD_FILESTAT_SET_TIMES |
|
||||||
|
WasiRights.FD_FILESTAT_SET_SIZE |
|
||||||
|
WasiRights.PATH_SYMLINK |
|
||||||
|
WasiRights.PATH_UNLINK_FILE |
|
||||||
|
WasiRights.PATH_REMOVE_DIRECTORY |
|
||||||
|
WasiRights.POLL_FD_READWRITE |
|
||||||
|
WasiRights.SOCK_SHUTDOWN |
|
||||||
|
WasiRights.SOCK_ACCEPT;
|
||||||
|
export const BLOCK_DEVICE_BASE = RIGHTS_ALL;
|
||||||
|
export const BLOCK_DEVICE_INHERITING = RIGHTS_ALL;
|
||||||
|
export const CHARACTER_DEVICE_BASE = RIGHTS_ALL;
|
||||||
|
export const CHARACTER_DEVICE_INHERITING = RIGHTS_ALL;
|
||||||
|
export const REGULAR_FILE_BASE = WasiRights.FD_DATASYNC |
|
||||||
|
WasiRights.FD_READ |
|
||||||
|
WasiRights.FD_SEEK |
|
||||||
|
WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
WasiRights.FD_SYNC |
|
||||||
|
WasiRights.FD_TELL |
|
||||||
|
WasiRights.FD_WRITE |
|
||||||
|
WasiRights.FD_ADVISE |
|
||||||
|
WasiRights.FD_ALLOCATE |
|
||||||
|
WasiRights.FD_FILESTAT_GET |
|
||||||
|
WasiRights.FD_FILESTAT_SET_SIZE |
|
||||||
|
WasiRights.FD_FILESTAT_SET_TIMES |
|
||||||
|
WasiRights.POLL_FD_READWRITE;
|
||||||
|
export const REGULAR_FILE_INHERITING = /*#__PURE__*/ BigInt(0);
|
||||||
|
export const DIRECTORY_BASE = WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
WasiRights.FD_SYNC |
|
||||||
|
WasiRights.FD_ADVISE |
|
||||||
|
WasiRights.PATH_CREATE_DIRECTORY |
|
||||||
|
WasiRights.PATH_CREATE_FILE |
|
||||||
|
WasiRights.PATH_LINK_SOURCE |
|
||||||
|
WasiRights.PATH_LINK_TARGET |
|
||||||
|
WasiRights.PATH_OPEN |
|
||||||
|
WasiRights.FD_READDIR |
|
||||||
|
WasiRights.PATH_READLINK |
|
||||||
|
WasiRights.PATH_RENAME_SOURCE |
|
||||||
|
WasiRights.PATH_RENAME_TARGET |
|
||||||
|
WasiRights.PATH_FILESTAT_GET |
|
||||||
|
WasiRights.PATH_FILESTAT_SET_SIZE |
|
||||||
|
WasiRights.PATH_FILESTAT_SET_TIMES |
|
||||||
|
WasiRights.FD_FILESTAT_GET |
|
||||||
|
WasiRights.FD_FILESTAT_SET_TIMES |
|
||||||
|
WasiRights.PATH_SYMLINK |
|
||||||
|
WasiRights.PATH_UNLINK_FILE |
|
||||||
|
WasiRights.PATH_REMOVE_DIRECTORY |
|
||||||
|
WasiRights.POLL_FD_READWRITE;
|
||||||
|
export const DIRECTORY_INHERITING = DIRECTORY_BASE | REGULAR_FILE_BASE;
|
||||||
|
export const SOCKET_BASE = (WasiRights.FD_READ |
|
||||||
|
WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
WasiRights.FD_WRITE |
|
||||||
|
WasiRights.FD_FILESTAT_GET |
|
||||||
|
WasiRights.POLL_FD_READWRITE |
|
||||||
|
WasiRights.SOCK_SHUTDOWN);
|
||||||
|
export const SOCKET_INHERITING = RIGHTS_ALL;
|
||||||
|
export const TTY_BASE = WasiRights.FD_READ |
|
||||||
|
WasiRights.FD_FDSTAT_SET_FLAGS |
|
||||||
|
WasiRights.FD_WRITE |
|
||||||
|
WasiRights.FD_FILESTAT_GET |
|
||||||
|
WasiRights.POLL_FD_READWRITE;
|
||||||
|
export const TTY_INHERITING = /*#__PURE__*/ BigInt(0);
|
||||||
|
export function getRights(stdio, fd, flags, type) {
|
||||||
|
const ret = {
|
||||||
|
base: BigInt(0),
|
||||||
|
inheriting: BigInt(0)
|
||||||
|
};
|
||||||
|
if (type === WasiFileType.UNKNOWN) {
|
||||||
|
throw new WasiError('Unknown file type', WasiErrno.EINVAL);
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case WasiFileType.REGULAR_FILE:
|
||||||
|
ret.base = REGULAR_FILE_BASE;
|
||||||
|
ret.inheriting = REGULAR_FILE_INHERITING;
|
||||||
|
break;
|
||||||
|
case WasiFileType.DIRECTORY:
|
||||||
|
ret.base = DIRECTORY_BASE;
|
||||||
|
ret.inheriting = DIRECTORY_INHERITING;
|
||||||
|
break;
|
||||||
|
case WasiFileType.SOCKET_STREAM:
|
||||||
|
case WasiFileType.SOCKET_DGRAM:
|
||||||
|
ret.base = SOCKET_BASE;
|
||||||
|
ret.inheriting = SOCKET_INHERITING;
|
||||||
|
break;
|
||||||
|
case WasiFileType.CHARACTER_DEVICE:
|
||||||
|
if (stdio.indexOf(fd) !== -1) {
|
||||||
|
ret.base = TTY_BASE;
|
||||||
|
ret.inheriting = TTY_INHERITING;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret.base = CHARACTER_DEVICE_BASE;
|
||||||
|
ret.inheriting = CHARACTER_DEVICE_INHERITING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WasiFileType.BLOCK_DEVICE:
|
||||||
|
ret.base = BLOCK_DEVICE_BASE;
|
||||||
|
ret.inheriting = BLOCK_DEVICE_INHERITING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret.base = BigInt(0);
|
||||||
|
ret.inheriting = BigInt(0);
|
||||||
|
}
|
||||||
|
/* Disable read/write bits depending on access mode. */
|
||||||
|
const read_or_write_only = flags & (0 | 1 | 2);
|
||||||
|
if (read_or_write_only === 0) {
|
||||||
|
ret.base &= ~WasiRights.FD_WRITE;
|
||||||
|
}
|
||||||
|
else if (read_or_write_only === 1) {
|
||||||
|
ret.base &= ~WasiRights.FD_READ;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
Generated
Vendored
+216
@@ -0,0 +1,216 @@
|
|||||||
|
/* eslint-disable spaced-comment */
|
||||||
|
export var WasiErrno;
|
||||||
|
(function (WasiErrno) {
|
||||||
|
WasiErrno[WasiErrno["ESUCCESS"] = 0] = "ESUCCESS";
|
||||||
|
WasiErrno[WasiErrno["E2BIG"] = 1] = "E2BIG";
|
||||||
|
WasiErrno[WasiErrno["EACCES"] = 2] = "EACCES";
|
||||||
|
WasiErrno[WasiErrno["EADDRINUSE"] = 3] = "EADDRINUSE";
|
||||||
|
WasiErrno[WasiErrno["EADDRNOTAVAIL"] = 4] = "EADDRNOTAVAIL";
|
||||||
|
WasiErrno[WasiErrno["EAFNOSUPPORT"] = 5] = "EAFNOSUPPORT";
|
||||||
|
WasiErrno[WasiErrno["EAGAIN"] = 6] = "EAGAIN";
|
||||||
|
WasiErrno[WasiErrno["EALREADY"] = 7] = "EALREADY";
|
||||||
|
WasiErrno[WasiErrno["EBADF"] = 8] = "EBADF";
|
||||||
|
WasiErrno[WasiErrno["EBADMSG"] = 9] = "EBADMSG";
|
||||||
|
WasiErrno[WasiErrno["EBUSY"] = 10] = "EBUSY";
|
||||||
|
WasiErrno[WasiErrno["ECANCELED"] = 11] = "ECANCELED";
|
||||||
|
WasiErrno[WasiErrno["ECHILD"] = 12] = "ECHILD";
|
||||||
|
WasiErrno[WasiErrno["ECONNABORTED"] = 13] = "ECONNABORTED";
|
||||||
|
WasiErrno[WasiErrno["ECONNREFUSED"] = 14] = "ECONNREFUSED";
|
||||||
|
WasiErrno[WasiErrno["ECONNRESET"] = 15] = "ECONNRESET";
|
||||||
|
WasiErrno[WasiErrno["EDEADLK"] = 16] = "EDEADLK";
|
||||||
|
WasiErrno[WasiErrno["EDESTADDRREQ"] = 17] = "EDESTADDRREQ";
|
||||||
|
WasiErrno[WasiErrno["EDOM"] = 18] = "EDOM";
|
||||||
|
WasiErrno[WasiErrno["EDQUOT"] = 19] = "EDQUOT";
|
||||||
|
WasiErrno[WasiErrno["EEXIST"] = 20] = "EEXIST";
|
||||||
|
WasiErrno[WasiErrno["EFAULT"] = 21] = "EFAULT";
|
||||||
|
WasiErrno[WasiErrno["EFBIG"] = 22] = "EFBIG";
|
||||||
|
WasiErrno[WasiErrno["EHOSTUNREACH"] = 23] = "EHOSTUNREACH";
|
||||||
|
WasiErrno[WasiErrno["EIDRM"] = 24] = "EIDRM";
|
||||||
|
WasiErrno[WasiErrno["EILSEQ"] = 25] = "EILSEQ";
|
||||||
|
WasiErrno[WasiErrno["EINPROGRESS"] = 26] = "EINPROGRESS";
|
||||||
|
WasiErrno[WasiErrno["EINTR"] = 27] = "EINTR";
|
||||||
|
WasiErrno[WasiErrno["EINVAL"] = 28] = "EINVAL";
|
||||||
|
WasiErrno[WasiErrno["EIO"] = 29] = "EIO";
|
||||||
|
WasiErrno[WasiErrno["EISCONN"] = 30] = "EISCONN";
|
||||||
|
WasiErrno[WasiErrno["EISDIR"] = 31] = "EISDIR";
|
||||||
|
WasiErrno[WasiErrno["ELOOP"] = 32] = "ELOOP";
|
||||||
|
WasiErrno[WasiErrno["EMFILE"] = 33] = "EMFILE";
|
||||||
|
WasiErrno[WasiErrno["EMLINK"] = 34] = "EMLINK";
|
||||||
|
WasiErrno[WasiErrno["EMSGSIZE"] = 35] = "EMSGSIZE";
|
||||||
|
WasiErrno[WasiErrno["EMULTIHOP"] = 36] = "EMULTIHOP";
|
||||||
|
WasiErrno[WasiErrno["ENAMETOOLONG"] = 37] = "ENAMETOOLONG";
|
||||||
|
WasiErrno[WasiErrno["ENETDOWN"] = 38] = "ENETDOWN";
|
||||||
|
WasiErrno[WasiErrno["ENETRESET"] = 39] = "ENETRESET";
|
||||||
|
WasiErrno[WasiErrno["ENETUNREACH"] = 40] = "ENETUNREACH";
|
||||||
|
WasiErrno[WasiErrno["ENFILE"] = 41] = "ENFILE";
|
||||||
|
WasiErrno[WasiErrno["ENOBUFS"] = 42] = "ENOBUFS";
|
||||||
|
WasiErrno[WasiErrno["ENODEV"] = 43] = "ENODEV";
|
||||||
|
WasiErrno[WasiErrno["ENOENT"] = 44] = "ENOENT";
|
||||||
|
WasiErrno[WasiErrno["ENOEXEC"] = 45] = "ENOEXEC";
|
||||||
|
WasiErrno[WasiErrno["ENOLCK"] = 46] = "ENOLCK";
|
||||||
|
WasiErrno[WasiErrno["ENOLINK"] = 47] = "ENOLINK";
|
||||||
|
WasiErrno[WasiErrno["ENOMEM"] = 48] = "ENOMEM";
|
||||||
|
WasiErrno[WasiErrno["ENOMSG"] = 49] = "ENOMSG";
|
||||||
|
WasiErrno[WasiErrno["ENOPROTOOPT"] = 50] = "ENOPROTOOPT";
|
||||||
|
WasiErrno[WasiErrno["ENOSPC"] = 51] = "ENOSPC";
|
||||||
|
WasiErrno[WasiErrno["ENOSYS"] = 52] = "ENOSYS";
|
||||||
|
WasiErrno[WasiErrno["ENOTCONN"] = 53] = "ENOTCONN";
|
||||||
|
WasiErrno[WasiErrno["ENOTDIR"] = 54] = "ENOTDIR";
|
||||||
|
WasiErrno[WasiErrno["ENOTEMPTY"] = 55] = "ENOTEMPTY";
|
||||||
|
WasiErrno[WasiErrno["ENOTRECOVERABLE"] = 56] = "ENOTRECOVERABLE";
|
||||||
|
WasiErrno[WasiErrno["ENOTSOCK"] = 57] = "ENOTSOCK";
|
||||||
|
WasiErrno[WasiErrno["ENOTSUP"] = 58] = "ENOTSUP";
|
||||||
|
WasiErrno[WasiErrno["ENOTTY"] = 59] = "ENOTTY";
|
||||||
|
WasiErrno[WasiErrno["ENXIO"] = 60] = "ENXIO";
|
||||||
|
WasiErrno[WasiErrno["EOVERFLOW"] = 61] = "EOVERFLOW";
|
||||||
|
WasiErrno[WasiErrno["EOWNERDEAD"] = 62] = "EOWNERDEAD";
|
||||||
|
WasiErrno[WasiErrno["EPERM"] = 63] = "EPERM";
|
||||||
|
WasiErrno[WasiErrno["EPIPE"] = 64] = "EPIPE";
|
||||||
|
WasiErrno[WasiErrno["EPROTO"] = 65] = "EPROTO";
|
||||||
|
WasiErrno[WasiErrno["EPROTONOSUPPORT"] = 66] = "EPROTONOSUPPORT";
|
||||||
|
WasiErrno[WasiErrno["EPROTOTYPE"] = 67] = "EPROTOTYPE";
|
||||||
|
WasiErrno[WasiErrno["ERANGE"] = 68] = "ERANGE";
|
||||||
|
WasiErrno[WasiErrno["EROFS"] = 69] = "EROFS";
|
||||||
|
WasiErrno[WasiErrno["ESPIPE"] = 70] = "ESPIPE";
|
||||||
|
WasiErrno[WasiErrno["ESRCH"] = 71] = "ESRCH";
|
||||||
|
WasiErrno[WasiErrno["ESTALE"] = 72] = "ESTALE";
|
||||||
|
WasiErrno[WasiErrno["ETIMEDOUT"] = 73] = "ETIMEDOUT";
|
||||||
|
WasiErrno[WasiErrno["ETXTBSY"] = 74] = "ETXTBSY";
|
||||||
|
WasiErrno[WasiErrno["EXDEV"] = 75] = "EXDEV";
|
||||||
|
WasiErrno[WasiErrno["ENOTCAPABLE"] = 76] = "ENOTCAPABLE";
|
||||||
|
})(WasiErrno || (WasiErrno = {}));
|
||||||
|
export var WasiFileType;
|
||||||
|
(function (WasiFileType) {
|
||||||
|
WasiFileType[WasiFileType["UNKNOWN"] = 0] = "UNKNOWN";
|
||||||
|
WasiFileType[WasiFileType["BLOCK_DEVICE"] = 1] = "BLOCK_DEVICE";
|
||||||
|
WasiFileType[WasiFileType["CHARACTER_DEVICE"] = 2] = "CHARACTER_DEVICE";
|
||||||
|
WasiFileType[WasiFileType["DIRECTORY"] = 3] = "DIRECTORY";
|
||||||
|
WasiFileType[WasiFileType["REGULAR_FILE"] = 4] = "REGULAR_FILE";
|
||||||
|
WasiFileType[WasiFileType["SOCKET_DGRAM"] = 5] = "SOCKET_DGRAM";
|
||||||
|
WasiFileType[WasiFileType["SOCKET_STREAM"] = 6] = "SOCKET_STREAM";
|
||||||
|
WasiFileType[WasiFileType["SYMBOLIC_LINK"] = 7] = "SYMBOLIC_LINK";
|
||||||
|
})(WasiFileType || (WasiFileType = {}));
|
||||||
|
const FD_DATASYNC = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(0));
|
||||||
|
const FD_READ = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(1));
|
||||||
|
const FD_SEEK = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(2));
|
||||||
|
const FD_FDSTAT_SET_FLAGS = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(3));
|
||||||
|
const FD_SYNC = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(4));
|
||||||
|
const FD_TELL = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(5));
|
||||||
|
const FD_WRITE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(6));
|
||||||
|
const FD_ADVISE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(7));
|
||||||
|
const FD_ALLOCATE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(8));
|
||||||
|
const PATH_CREATE_DIRECTORY = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(9));
|
||||||
|
const PATH_CREATE_FILE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(10));
|
||||||
|
const PATH_LINK_SOURCE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(11));
|
||||||
|
const PATH_LINK_TARGET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(12));
|
||||||
|
const PATH_OPEN = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(13));
|
||||||
|
const FD_READDIR = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(14));
|
||||||
|
const PATH_READLINK = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(15));
|
||||||
|
const PATH_RENAME_SOURCE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(16));
|
||||||
|
const PATH_RENAME_TARGET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(17));
|
||||||
|
const PATH_FILESTAT_GET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(18));
|
||||||
|
const PATH_FILESTAT_SET_SIZE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(19));
|
||||||
|
const PATH_FILESTAT_SET_TIMES = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(20));
|
||||||
|
const FD_FILESTAT_GET = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(21));
|
||||||
|
const FD_FILESTAT_SET_SIZE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(22));
|
||||||
|
const FD_FILESTAT_SET_TIMES = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(23));
|
||||||
|
const PATH_SYMLINK = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(24));
|
||||||
|
const PATH_REMOVE_DIRECTORY = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(25));
|
||||||
|
const PATH_UNLINK_FILE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(26));
|
||||||
|
const POLL_FD_READWRITE = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(27));
|
||||||
|
const SOCK_SHUTDOWN = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(28));
|
||||||
|
const SOCK_ACCEPT = ( /*#__PURE__*/BigInt(1) << /*#__PURE__*/ BigInt(29));
|
||||||
|
export const WasiRights = {
|
||||||
|
FD_DATASYNC,
|
||||||
|
FD_READ,
|
||||||
|
FD_SEEK,
|
||||||
|
FD_FDSTAT_SET_FLAGS,
|
||||||
|
FD_SYNC,
|
||||||
|
FD_TELL,
|
||||||
|
FD_WRITE,
|
||||||
|
FD_ADVISE,
|
||||||
|
FD_ALLOCATE,
|
||||||
|
PATH_CREATE_DIRECTORY,
|
||||||
|
PATH_CREATE_FILE,
|
||||||
|
PATH_LINK_SOURCE,
|
||||||
|
PATH_LINK_TARGET,
|
||||||
|
PATH_OPEN,
|
||||||
|
FD_READDIR,
|
||||||
|
PATH_READLINK,
|
||||||
|
PATH_RENAME_SOURCE,
|
||||||
|
PATH_RENAME_TARGET,
|
||||||
|
PATH_FILESTAT_GET,
|
||||||
|
PATH_FILESTAT_SET_SIZE,
|
||||||
|
PATH_FILESTAT_SET_TIMES,
|
||||||
|
FD_FILESTAT_GET,
|
||||||
|
FD_FILESTAT_SET_SIZE,
|
||||||
|
FD_FILESTAT_SET_TIMES,
|
||||||
|
PATH_SYMLINK,
|
||||||
|
PATH_REMOVE_DIRECTORY,
|
||||||
|
PATH_UNLINK_FILE,
|
||||||
|
POLL_FD_READWRITE,
|
||||||
|
SOCK_SHUTDOWN,
|
||||||
|
SOCK_ACCEPT
|
||||||
|
};
|
||||||
|
export var WasiWhence;
|
||||||
|
(function (WasiWhence) {
|
||||||
|
WasiWhence[WasiWhence["SET"] = 0] = "SET";
|
||||||
|
WasiWhence[WasiWhence["CUR"] = 1] = "CUR";
|
||||||
|
WasiWhence[WasiWhence["END"] = 2] = "END";
|
||||||
|
})(WasiWhence || (WasiWhence = {}));
|
||||||
|
export var FileControlFlag;
|
||||||
|
(function (FileControlFlag) {
|
||||||
|
FileControlFlag[FileControlFlag["O_RDONLY"] = 0] = "O_RDONLY";
|
||||||
|
FileControlFlag[FileControlFlag["O_WRONLY"] = 1] = "O_WRONLY";
|
||||||
|
FileControlFlag[FileControlFlag["O_RDWR"] = 2] = "O_RDWR";
|
||||||
|
FileControlFlag[FileControlFlag["O_CREAT"] = 64] = "O_CREAT";
|
||||||
|
FileControlFlag[FileControlFlag["O_EXCL"] = 128] = "O_EXCL";
|
||||||
|
FileControlFlag[FileControlFlag["O_NOCTTY"] = 256] = "O_NOCTTY";
|
||||||
|
FileControlFlag[FileControlFlag["O_TRUNC"] = 512] = "O_TRUNC";
|
||||||
|
FileControlFlag[FileControlFlag["O_APPEND"] = 1024] = "O_APPEND";
|
||||||
|
FileControlFlag[FileControlFlag["O_DIRECTORY"] = 65536] = "O_DIRECTORY";
|
||||||
|
FileControlFlag[FileControlFlag["O_NOATIME"] = 262144] = "O_NOATIME";
|
||||||
|
FileControlFlag[FileControlFlag["O_NOFOLLOW"] = 131072] = "O_NOFOLLOW";
|
||||||
|
FileControlFlag[FileControlFlag["O_SYNC"] = 1052672] = "O_SYNC";
|
||||||
|
FileControlFlag[FileControlFlag["O_DIRECT"] = 16384] = "O_DIRECT";
|
||||||
|
FileControlFlag[FileControlFlag["O_NONBLOCK"] = 2048] = "O_NONBLOCK";
|
||||||
|
})(FileControlFlag || (FileControlFlag = {}));
|
||||||
|
export var WasiFileControlFlag;
|
||||||
|
(function (WasiFileControlFlag) {
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_CREAT"] = 1] = "O_CREAT";
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_DIRECTORY"] = 2] = "O_DIRECTORY";
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_EXCL"] = 4] = "O_EXCL";
|
||||||
|
WasiFileControlFlag[WasiFileControlFlag["O_TRUNC"] = 8] = "O_TRUNC";
|
||||||
|
})(WasiFileControlFlag || (WasiFileControlFlag = {}));
|
||||||
|
export var WasiFdFlag;
|
||||||
|
(function (WasiFdFlag) {
|
||||||
|
WasiFdFlag[WasiFdFlag["APPEND"] = 1] = "APPEND";
|
||||||
|
WasiFdFlag[WasiFdFlag["DSYNC"] = 2] = "DSYNC";
|
||||||
|
WasiFdFlag[WasiFdFlag["NONBLOCK"] = 4] = "NONBLOCK";
|
||||||
|
WasiFdFlag[WasiFdFlag["RSYNC"] = 8] = "RSYNC";
|
||||||
|
WasiFdFlag[WasiFdFlag["SYNC"] = 16] = "SYNC";
|
||||||
|
})(WasiFdFlag || (WasiFdFlag = {}));
|
||||||
|
export var WasiClockid;
|
||||||
|
(function (WasiClockid) {
|
||||||
|
WasiClockid[WasiClockid["REALTIME"] = 0] = "REALTIME";
|
||||||
|
WasiClockid[WasiClockid["MONOTONIC"] = 1] = "MONOTONIC";
|
||||||
|
WasiClockid[WasiClockid["PROCESS_CPUTIME_ID"] = 2] = "PROCESS_CPUTIME_ID";
|
||||||
|
WasiClockid[WasiClockid["THREAD_CPUTIME_ID"] = 3] = "THREAD_CPUTIME_ID";
|
||||||
|
})(WasiClockid || (WasiClockid = {}));
|
||||||
|
export var WasiFstFlag;
|
||||||
|
(function (WasiFstFlag) {
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_ATIM"] = 1] = "SET_ATIM";
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_ATIM_NOW"] = 2] = "SET_ATIM_NOW";
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_MTIM"] = 4] = "SET_MTIM";
|
||||||
|
WasiFstFlag[WasiFstFlag["SET_MTIM_NOW"] = 8] = "SET_MTIM_NOW";
|
||||||
|
})(WasiFstFlag || (WasiFstFlag = {}));
|
||||||
|
export var WasiEventType;
|
||||||
|
(function (WasiEventType) {
|
||||||
|
WasiEventType[WasiEventType["CLOCK"] = 0] = "CLOCK";
|
||||||
|
WasiEventType[WasiEventType["FD_READ"] = 1] = "FD_READ";
|
||||||
|
WasiEventType[WasiEventType["FD_WRITE"] = 2] = "FD_WRITE";
|
||||||
|
})(WasiEventType || (WasiEventType = {}));
|
||||||
|
export var WasiSubclockflags;
|
||||||
|
(function (WasiSubclockflags) {
|
||||||
|
WasiSubclockflags[WasiSubclockflags["ABSTIME"] = 1] = "ABSTIME";
|
||||||
|
})(WasiSubclockflags || (WasiSubclockflags = {}));
|
||||||
Generated
Vendored
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/* eslint-disable spaced-comment */
|
||||||
|
export function validateObject(value, name) {
|
||||||
|
if (value === null || typeof value !== 'object') {
|
||||||
|
throw new TypeError(`${name} must be an object. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function validateArray(value, name) {
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
throw new TypeError(`${name} must be an array. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function validateBoolean(value, name) {
|
||||||
|
if (typeof value !== 'boolean') {
|
||||||
|
throw new TypeError(`${name} must be a boolean. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function validateString(value, name) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
throw new TypeError(`${name} must be a string. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function validateFunction(value, name) {
|
||||||
|
if (typeof value !== 'function') {
|
||||||
|
throw new TypeError(`${name} must be a function. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function validateUndefined(value, name) {
|
||||||
|
if (value !== undefined) {
|
||||||
|
throw new TypeError(`${name} must be undefined. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function validateInt32(value, name, min = -2147483648, max = 2147483647) {
|
||||||
|
if (typeof value !== 'number') {
|
||||||
|
throw new TypeError(`${name} must be a number. Received ${value === null ? 'null' : typeof value}`);
|
||||||
|
}
|
||||||
|
if (!Number.isInteger(value)) {
|
||||||
|
throw new RangeError(`${name} must be a integer.`);
|
||||||
|
}
|
||||||
|
if (value < min || value > max) {
|
||||||
|
throw new RangeError(`${name} must be >= ${min} && <= ${max}. Received ${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function isPromiseLike(obj) {
|
||||||
|
return !!(obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function');
|
||||||
|
}
|
||||||
|
export function wrapInstanceExports(exports, mapFn) {
|
||||||
|
const newExports = Object.create(null);
|
||||||
|
Object.keys(exports).forEach(name => {
|
||||||
|
const exportValue = exports[name];
|
||||||
|
Object.defineProperty(newExports, name, {
|
||||||
|
enumerable: true,
|
||||||
|
value: mapFn(exportValue, name)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return newExports;
|
||||||
|
}
|
||||||
|
const _require = /*#__PURE__*/ (function () {
|
||||||
|
let nativeRequire;
|
||||||
|
if (typeof __webpack_public_path__ !== 'undefined') {
|
||||||
|
nativeRequire = (function () {
|
||||||
|
return typeof __non_webpack_require__ !== 'undefined' ? __non_webpack_require__ : undefined;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nativeRequire = (function () {
|
||||||
|
return typeof __webpack_public_path__ !== 'undefined' ? (typeof __non_webpack_require__ !== 'undefined' ? __non_webpack_require__ : undefined) : (typeof require !== 'undefined' ? require : undefined);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
return nativeRequire;
|
||||||
|
})();
|
||||||
|
export const isMainThread = /*#__PURE__*/ (function () {
|
||||||
|
let worker_threads;
|
||||||
|
try {
|
||||||
|
worker_threads = _require('worker_threads');
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
if (!worker_threads) {
|
||||||
|
return typeof importScripts === 'undefined';
|
||||||
|
}
|
||||||
|
return worker_threads.isMainThread;
|
||||||
|
})();
|
||||||
|
export const postMsg = isMainThread
|
||||||
|
? () => { }
|
||||||
|
: /*#__PURE__*/ (function () {
|
||||||
|
let worker_threads;
|
||||||
|
try {
|
||||||
|
worker_threads = _require('worker_threads');
|
||||||
|
}
|
||||||
|
catch (_) { }
|
||||||
|
if (!worker_threads) {
|
||||||
|
return postMessage;
|
||||||
|
}
|
||||||
|
return function postMessage(data) {
|
||||||
|
worker_threads.parentPort.postMessage({ data });
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
export function sleepBreakIf(delay, breakIf) {
|
||||||
|
const start = Date.now();
|
||||||
|
const end = start + delay;
|
||||||
|
let ret = false;
|
||||||
|
while (Date.now() < end) {
|
||||||
|
if (breakIf()) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
export function unsharedSlice(view, start, end) {
|
||||||
|
return ((typeof SharedArrayBuffer === 'function' && view.buffer instanceof SharedArrayBuffer) || (Object.prototype.toString.call(view.buffer.constructor) === '[object SharedArrayBuffer]'))
|
||||||
|
? view.slice(start, end)
|
||||||
|
: view.subarray(start, end);
|
||||||
|
}
|
||||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
const _WebAssembly = typeof WebAssembly !== 'undefined'
|
||||||
|
? WebAssembly
|
||||||
|
: typeof WXWebAssembly !== 'undefined'
|
||||||
|
? WXWebAssembly
|
||||||
|
: undefined;
|
||||||
|
if (!_WebAssembly) {
|
||||||
|
throw new Error('WebAssembly is not supported in this environment');
|
||||||
|
}
|
||||||
|
export { _WebAssembly };
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"name": "@tybys/wasm-util",
|
||||||
|
"version": "0.10.3",
|
||||||
|
"description": "WASI polyfill for browser and some wasm util",
|
||||||
|
"main": "./lib/cjs/index.js",
|
||||||
|
"module": "./dist/wasm-util.esm-bundler.js",
|
||||||
|
"types": "./dist/wasm-util.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"module": "./dist/wasm-util.esm-bundler.js",
|
||||||
|
"import": "./lib/mjs/index.mjs",
|
||||||
|
"require": "./lib/cjs/index.js",
|
||||||
|
"types": "./dist/wasm-util.d.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsgo build",
|
||||||
|
"watch": "tsgo watch",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "eslint ./src/**/*.{ts,js} --fix",
|
||||||
|
"prepare": "npm run build"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"wasm",
|
||||||
|
"webassembly",
|
||||||
|
"wasi",
|
||||||
|
"polyfill"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/toyobayashi/wasm-util.git"
|
||||||
|
},
|
||||||
|
"author": "toyobayashi",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tybys/ts-transform-module-specifier": "^0.0.2",
|
||||||
|
"@tybys/ts-transform-pure-class": "^0.1.1",
|
||||||
|
"@tybys/tsgo": "^1.1.0",
|
||||||
|
"@types/node": "^14.14.31",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||||
|
"@typescript-eslint/parser": "^5.40.1",
|
||||||
|
"eslint": "^8.25.0",
|
||||||
|
"eslint-config-standard-with-typescript": "^23.0.0",
|
||||||
|
"eslint-plugin-import": "^2.26.0",
|
||||||
|
"eslint-plugin-n": "^15.3.0",
|
||||||
|
"eslint-plugin-promise": "^6.1.0",
|
||||||
|
"memfs-browser": "^3.4.13000",
|
||||||
|
"mocha": "^10.1.0",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "~4.8.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
***************************************************************************** */
|
||||||
|
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
# tslib
|
||||||
|
|
||||||
|
This is a runtime library for [TypeScript](https://www.typescriptlang.org/) that contains all of the TypeScript helper functions.
|
||||||
|
|
||||||
|
This library is primarily used by the `--importHelpers` flag in TypeScript.
|
||||||
|
When using `--importHelpers`, a module that uses helper functions like `__extends` and `__assign` in the following emitted file:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||||
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||||
|
s = arguments[i];
|
||||||
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||||
|
t[p] = s[p];
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
exports.x = {};
|
||||||
|
exports.y = __assign({}, exports.x);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
will instead be emitted as something like the following:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
var tslib_1 = require("tslib");
|
||||||
|
exports.x = {};
|
||||||
|
exports.y = tslib_1.__assign({}, exports.x);
|
||||||
|
```
|
||||||
|
|
||||||
|
Because this can avoid duplicate declarations of things like `__extends`, `__assign`, etc., this means delivering users smaller files on average, as well as less runtime overhead.
|
||||||
|
For optimized bundles with TypeScript, you should absolutely consider using `tslib` and `--importHelpers`.
|
||||||
|
|
||||||
|
# Installing
|
||||||
|
|
||||||
|
For the latest stable version, run:
|
||||||
|
|
||||||
|
## npm
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# TypeScript 3.9.2 or later
|
||||||
|
npm install tslib
|
||||||
|
|
||||||
|
# TypeScript 3.8.4 or earlier
|
||||||
|
npm install tslib@^1
|
||||||
|
|
||||||
|
# TypeScript 2.3.2 or earlier
|
||||||
|
npm install tslib@1.6.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## yarn
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# TypeScript 3.9.2 or later
|
||||||
|
yarn add tslib
|
||||||
|
|
||||||
|
# TypeScript 3.8.4 or earlier
|
||||||
|
yarn add tslib@^1
|
||||||
|
|
||||||
|
# TypeScript 2.3.2 or earlier
|
||||||
|
yarn add tslib@1.6.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## bower
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# TypeScript 3.9.2 or later
|
||||||
|
bower install tslib
|
||||||
|
|
||||||
|
# TypeScript 3.8.4 or earlier
|
||||||
|
bower install tslib@^1
|
||||||
|
|
||||||
|
# TypeScript 2.3.2 or earlier
|
||||||
|
bower install tslib@1.6.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSPM
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# TypeScript 3.9.2 or later
|
||||||
|
jspm install tslib
|
||||||
|
|
||||||
|
# TypeScript 3.8.4 or earlier
|
||||||
|
jspm install tslib@^1
|
||||||
|
|
||||||
|
# TypeScript 2.3.2 or earlier
|
||||||
|
jspm install tslib@1.6.1
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
Set the `importHelpers` compiler option on the command line:
|
||||||
|
|
||||||
|
```
|
||||||
|
tsc --importHelpers file.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
or in your tsconfig.json:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"importHelpers": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### For bower and JSPM users
|
||||||
|
|
||||||
|
You will need to add a `paths` mapping for `tslib`, e.g. For Bower users:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "amd",
|
||||||
|
"importHelpers": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"tslib" : ["bower_components/tslib/tslib.d.ts"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For JSPM users:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "system",
|
||||||
|
"importHelpers": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"tslib" : ["jspm_packages/npm/tslib@2.x.y/tslib.d.ts"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
- Choose your new version number
|
||||||
|
- Set it in `package.json` and `bower.json`
|
||||||
|
- Create a tag: `git tag [version]`
|
||||||
|
- Push the tag: `git push --tags`
|
||||||
|
- Create a [release in GitHub](https://github.com/microsoft/tslib/releases)
|
||||||
|
- Run the [publish to npm](https://github.com/microsoft/tslib/actions?query=workflow%3A%22Publish+to+NPM%22) workflow
|
||||||
|
|
||||||
|
Done.
|
||||||
|
|
||||||
|
# Contribute
|
||||||
|
|
||||||
|
There are many ways to [contribute](https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md) to TypeScript.
|
||||||
|
|
||||||
|
* [Submit bugs](https://github.com/Microsoft/TypeScript/issues) and help us verify fixes as they are checked in.
|
||||||
|
* Review the [source code changes](https://github.com/Microsoft/TypeScript/pulls).
|
||||||
|
* Engage with other TypeScript users and developers on [StackOverflow](http://stackoverflow.com/questions/tagged/typescript).
|
||||||
|
* Join the [#typescript](http://twitter.com/#!/search/realtime/%23typescript) discussion on Twitter.
|
||||||
|
* [Contribute bug fixes](https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
* [Quick tutorial](http://www.typescriptlang.org/Tutorial)
|
||||||
|
* [Programming handbook](http://www.typescriptlang.org/Handbook)
|
||||||
|
* [Homepage](http://www.typescriptlang.org/)
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||||
|
|
||||||
|
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||||
|
|
||||||
|
## Reporting Security Issues
|
||||||
|
|
||||||
|
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||||
|
|
||||||
|
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||||
|
|
||||||
|
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||||
|
|
||||||
|
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||||
|
|
||||||
|
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||||
|
|
||||||
|
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||||
|
* Full paths of source file(s) related to the manifestation of the issue
|
||||||
|
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||||
|
* Any special configuration required to reproduce the issue
|
||||||
|
* Step-by-step instructions to reproduce the issue
|
||||||
|
* Proof-of-concept or exploit code (if possible)
|
||||||
|
* Impact of the issue, including how an attacker might exploit the issue
|
||||||
|
|
||||||
|
This information will help us triage your report more quickly.
|
||||||
|
|
||||||
|
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||||
|
|
||||||
|
## Preferred Languages
|
||||||
|
|
||||||
|
We prefer all communications to be in English.
|
||||||
|
|
||||||
|
## Policy
|
||||||
|
|
||||||
|
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||||
|
|
||||||
|
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// Note: named reexports are used instead of `export *` because
|
||||||
|
// TypeScript itself doesn't resolve the `export *` when checking
|
||||||
|
// if a particular helper exists.
|
||||||
|
export {
|
||||||
|
__extends,
|
||||||
|
__assign,
|
||||||
|
__rest,
|
||||||
|
__decorate,
|
||||||
|
__param,
|
||||||
|
__esDecorate,
|
||||||
|
__runInitializers,
|
||||||
|
__propKey,
|
||||||
|
__setFunctionName,
|
||||||
|
__metadata,
|
||||||
|
__awaiter,
|
||||||
|
__generator,
|
||||||
|
__exportStar,
|
||||||
|
__values,
|
||||||
|
__read,
|
||||||
|
__spread,
|
||||||
|
__spreadArrays,
|
||||||
|
__spreadArray,
|
||||||
|
__await,
|
||||||
|
__asyncGenerator,
|
||||||
|
__asyncDelegator,
|
||||||
|
__asyncValues,
|
||||||
|
__makeTemplateObject,
|
||||||
|
__importStar,
|
||||||
|
__importDefault,
|
||||||
|
__classPrivateFieldGet,
|
||||||
|
__classPrivateFieldSet,
|
||||||
|
__classPrivateFieldIn,
|
||||||
|
__createBinding,
|
||||||
|
__addDisposableResource,
|
||||||
|
__disposeResources,
|
||||||
|
__rewriteRelativeImportExtension,
|
||||||
|
} from '../tslib.js';
|
||||||
|
export * as default from '../tslib.js';
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
import tslib from '../tslib.js';
|
||||||
|
const {
|
||||||
|
__extends,
|
||||||
|
__assign,
|
||||||
|
__rest,
|
||||||
|
__decorate,
|
||||||
|
__param,
|
||||||
|
__esDecorate,
|
||||||
|
__runInitializers,
|
||||||
|
__propKey,
|
||||||
|
__setFunctionName,
|
||||||
|
__metadata,
|
||||||
|
__awaiter,
|
||||||
|
__generator,
|
||||||
|
__exportStar,
|
||||||
|
__createBinding,
|
||||||
|
__values,
|
||||||
|
__read,
|
||||||
|
__spread,
|
||||||
|
__spreadArrays,
|
||||||
|
__spreadArray,
|
||||||
|
__await,
|
||||||
|
__asyncGenerator,
|
||||||
|
__asyncDelegator,
|
||||||
|
__asyncValues,
|
||||||
|
__makeTemplateObject,
|
||||||
|
__importStar,
|
||||||
|
__importDefault,
|
||||||
|
__classPrivateFieldGet,
|
||||||
|
__classPrivateFieldSet,
|
||||||
|
__classPrivateFieldIn,
|
||||||
|
__addDisposableResource,
|
||||||
|
__disposeResources,
|
||||||
|
__rewriteRelativeImportExtension,
|
||||||
|
} = tslib;
|
||||||
|
export {
|
||||||
|
__extends,
|
||||||
|
__assign,
|
||||||
|
__rest,
|
||||||
|
__decorate,
|
||||||
|
__param,
|
||||||
|
__esDecorate,
|
||||||
|
__runInitializers,
|
||||||
|
__propKey,
|
||||||
|
__setFunctionName,
|
||||||
|
__metadata,
|
||||||
|
__awaiter,
|
||||||
|
__generator,
|
||||||
|
__exportStar,
|
||||||
|
__createBinding,
|
||||||
|
__values,
|
||||||
|
__read,
|
||||||
|
__spread,
|
||||||
|
__spreadArrays,
|
||||||
|
__spreadArray,
|
||||||
|
__await,
|
||||||
|
__asyncGenerator,
|
||||||
|
__asyncDelegator,
|
||||||
|
__asyncValues,
|
||||||
|
__makeTemplateObject,
|
||||||
|
__importStar,
|
||||||
|
__importDefault,
|
||||||
|
__classPrivateFieldGet,
|
||||||
|
__classPrivateFieldSet,
|
||||||
|
__classPrivateFieldIn,
|
||||||
|
__addDisposableResource,
|
||||||
|
__disposeResources,
|
||||||
|
__rewriteRelativeImportExtension,
|
||||||
|
};
|
||||||
|
export default tslib;
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "tslib",
|
||||||
|
"author": "Microsoft Corp.",
|
||||||
|
"homepage": "https://www.typescriptlang.org/",
|
||||||
|
"version": "2.8.1",
|
||||||
|
"license": "0BSD",
|
||||||
|
"description": "Runtime library for TypeScript helper functions",
|
||||||
|
"keywords": [
|
||||||
|
"TypeScript",
|
||||||
|
"Microsoft",
|
||||||
|
"compiler",
|
||||||
|
"language",
|
||||||
|
"javascript",
|
||||||
|
"tslib",
|
||||||
|
"runtime"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/Microsoft/TypeScript/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Microsoft/tslib.git"
|
||||||
|
},
|
||||||
|
"main": "tslib.js",
|
||||||
|
"module": "tslib.es6.js",
|
||||||
|
"jsnext:main": "tslib.es6.js",
|
||||||
|
"typings": "tslib.d.ts",
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"module": {
|
||||||
|
"types": "./modules/index.d.ts",
|
||||||
|
"default": "./tslib.es6.mjs"
|
||||||
|
},
|
||||||
|
"import": {
|
||||||
|
"node": "./modules/index.js",
|
||||||
|
"default": {
|
||||||
|
"types": "./modules/index.d.ts",
|
||||||
|
"default": "./tslib.es6.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": "./tslib.js"
|
||||||
|
},
|
||||||
|
"./*": "./*",
|
||||||
|
"./": "./"
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user