UNPKG

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
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