hakojs
Version:
A secure, embeddable JavaScript engine that runs untrusted code inside WebAssembly sandboxes with fine-grained permissions and resource limits
211 lines • 7.41 kB
TypeScript
import type { HakoRuntime } from "../host/runtime";
import type { VMContext } from "../vm/context";
import type { VMValue } from "../vm/value";
/**
* Represents a Promise in the "pending" state.
*
* This interface is part of the JSPromiseState union type that represents
* all possible states of a JavaScript Promise in the PrimJS engine.
*
* @see {@link JSPromiseState}
*/
export interface JSPromiseStatePending {
/**
* Discriminator property indicating this is a pending promise state.
*/
type: "pending";
/**
* The error property here allows unwrapping a JSPromiseState with {@link VMContext#unwrapResult}.
* Unwrapping a pending promise will throw a {@link PrimJSError}.
*
* This is a getter that creates an error on demand rather than storing one permanently.
*/
get error(): Error;
}
/**
* Represents a Promise in the "fulfilled" state.
*
* This interface is part of the JSPromiseState union type that represents
* all possible states of a JavaScript Promise in the PrimJS engine.
*
* @see {@link JSPromiseState}
*/
export interface JSPromiseStateFulfilled {
/**
* Discriminator property indicating this is a fulfilled promise state.
*/
type: "fulfilled";
/**
* The value with which the Promise was fulfilled.
*/
value: VMValue;
/**
* Error is undefined for fulfilled promises.
*/
error?: undefined;
/**
* Indicates that the original value wasn't actually a Promise.
*
* When attempting to get the promise state of a non-Promise value,
* the system returns a fulfilled state containing the original value,
* with this flag set to true.
*/
notAPromise?: boolean;
}
/**
* Represents a Promise in the "rejected" state.
*
* This interface is part of the JSPromiseState union type that represents
* all possible states of a JavaScript Promise in the PrimJS engine.
*
* @see {@link JSPromiseState}
*/
export interface JSPromiseStateRejected {
/**
* Discriminator property indicating this is a rejected promise state.
*/
type: "rejected";
/**
* The error value with which the Promise was rejected.
*/
error: VMValue;
}
/**
* Deferred Promise implementation for the Hako runtime.
*
* HakoDeferredPromise wraps a PrimJS promise {@link handle} and allows
* {@link resolve}ing or {@link reject}ing that promise. Use it to bridge asynchronous
* code on the host to APIs inside a VMContext.
*
* Managing the lifetime of promises is tricky. There are three
* {@link PrimJSHandle}s inside of each deferred promise object: (1) the promise
* itself, (2) the `resolve` callback, and (3) the `reject` callback.
*
* Proper cleanup depends on the usage scenario:
*
* - If the promise will be fulfilled before the end of it's {@link owner}'s lifetime,
* the only cleanup necessary is `deferred.handle.dispose()`, because
* calling {@link resolve} or {@link reject} will dispose of both callbacks automatically.
*
* - As the return value of a {@link VmFunctionImplementation}, return {@link handle},
* and ensure that either {@link resolve} or {@link reject} will be called. No other
* clean-up is necessary.
*
* - In other cases, call {@link dispose}, which will dispose {@link handle} as well as the
* PrimJS handles that back {@link resolve} and {@link reject}. For this object,
* {@link dispose} is idempotent.
*
* @implements {Disposable} - Implements the Disposable interface for resource cleanup
*/
export declare class HakoDeferredPromise implements Disposable {
/**
* Reference to the runtime that owns this promise.
*/
owner: HakoRuntime;
/**
* Reference to the context in which this promise was created.
*/
context: VMContext;
/**
* A handle of the Promise instance inside the VMContext.
*
* You must dispose {@link handle} or the entire HakoDeferredPromise once you
* are finished with it to prevent memory leaks.
*/
handle: VMValue;
/**
* A native JavaScript Promise that will resolve once this deferred promise is settled.
*
* This can be used to await the settlement of the promise from the host environment.
*/
settled: Promise<void>;
/**
* Handle to the resolve function for the promise.
* @private
*/
private resolveHandle;
/**
* Handle to the reject function for the promise.
* @private
*/
private rejectHandle;
/**
* Callback function to resolve the settled promise.
* @private
*/
private onSettled;
/**
* Creates a new HakoDeferredPromise.
*
* Use {@link VMContext#newPromise} to create a new promise instead of calling
* this constructor directly.
*
* @param args - Configuration object containing the necessary handles
* @param args.context - The VM context in which the promise exists
* @param args.promiseHandle - Handle to the Promise object in the VM
* @param args.resolveHandle - Handle to the resolve function in the VM
* @param args.rejectHandle - Handle to the reject function in the VM
*/
constructor(args: {
context: VMContext;
promiseHandle: VMValue;
resolveHandle: VMValue;
rejectHandle: VMValue;
});
/**
* Resolves the promise with the given value.
*
* This method calls the resolve function in the VM with the provided value.
* If no value is provided, undefined is used.
*
* Calling this method after calling {@link dispose} is a no-op.
*
* Note that after resolving a promise, you may need to call
* {@link PrimJSRuntime#executePendingJobs} to propagate the result to the promise's
* callbacks.
*
* @param value - Optional value to resolve the promise with
*/
resolve: (value?: VMValue) => void;
/**
* Rejects the promise with the given value.
*
* This method calls the reject function in the VM with the provided value.
* If no value is provided, undefined is used.
*
* Calling this method after calling {@link dispose} is a no-op.
*
* Note that after rejecting a promise, you may need to call
* {@link PrimJSRuntime#executePendingJobs} to propagate the result to the promise's
* callbacks.
*
* @param value - Optional value to reject the promise with
*/
reject: (value?: VMValue) => void;
/**
* Checks if any of the handles associated with this promise are still alive.
*
* @returns True if any of the promise, resolve, or reject handles are still alive
*/
get alive(): boolean;
/**
* Disposes of all resources associated with this promise.
*
* This method is idempotent - calling it multiple times has no additional effect.
* It ensures that all handles (promise, resolve, and reject) are properly disposed.
*/
dispose: () => void;
/**
* Helper method to dispose of the resolver and rejecter handles.
* @private
*/
private disposeResolvers;
/**
* Implements the Symbol.dispose method for the Disposable interface.
*
* This allows the deferred promise to be used with the using statement
* in environments that support the Disposable pattern.
*/
[Symbol.dispose](): void;
}
//# sourceMappingURL=deferred-promise.d.ts.map