UNPKG

hakojs

Version:

A secure, embeddable JavaScript engine that runs untrusted code inside WebAssembly sandboxes with fine-grained permissions and resource limits

294 lines 12.7 kB
import { type ContextOptions, type ExecutePendingJobsResult, type InterruptHandler, type JSRuntimePointer, type JSVoid, type MemoryUsage, type ModuleLoaderFunction, type ModuleNormalizerFunction, type ModuleResolverFunction, type ProfilerEventHandler, type StripOptions } from "../etc/types"; import { CModuleBuilder, type CModuleInitializer } from "../vm/cmodule"; import { VMContext } from "../vm/context"; import type { Container } from "./container"; /** * The HakoRuntime class represents a JavaScript execution environment. * * It manages the lifecycle of JS execution contexts, handles memory allocation * and deallocation, provides module loading capabilities, and offers utilities * for performance monitoring and control. * * @implements {Disposable} - Implements the Disposable interface for resource cleanup */ export declare class HakoRuntime implements Disposable { /** * The dependency injection container that provides access to core services and WebAssembly exports. */ private container; /** * An optional default context for this runtime. * * If this runtime was created as part of a context, points to the context * associated with the runtime. If this runtime was created stand-alone, this may * be lazily initialized when needed (e.g., for {@link computeMemoryUsage}). */ private context; /** * The pointer to the native runtime instance in WebAssembly memory. */ private rtPtr; /** * Flag indicating whether this runtime has been released. */ private isReleased; /** * Map of all contexts created within this runtime, keyed by their pointer values. * Used for management and cleanup. */ private contextMap; /** * Reference to the current interrupt handler function. * Stored to allow for proper cleanup when the runtime is disposed. */ private currentInterruptHandler; /** * Creates a new HakoRuntime instance. * * @param container - The dependency injection container that provides access to core services * @param rtPtr - The pointer to the native runtime instance in WebAssembly memory */ constructor(container: Container, rtPtr: JSRuntimePointer); /** * Gets the native runtime pointer. * * @returns The pointer to the native runtime instance in WebAssembly memory */ get pointer(): JSRuntimePointer; /** * Creates a C module with inline handler registration */ createCModule(name: string, handler: (initializer: CModuleInitializer) => number | undefined, ctx?: VMContext | undefined): CModuleBuilder; /** * Creates a new JavaScript execution context within this runtime. * * Contexts isolate JavaScript execution environments, each with their own global object * and set of available APIs based on the specified intrinsics. * * @param options - Configuration options for the new context * @param options.contextPointer - Optional existing context pointer to wrap * @param options.intrinsics - Optional set of intrinsics to include in the context * @param options.maxStackSizeBytes - Optional maximum stack size for the context * * @returns A new VMContext instance * @throws {Error} When context creation fails */ createContext(options?: ContextOptions): VMContext; /** * Sets the stripping options for the runtime * * @param options - Configuration options for code stripping * @param options.stripSource - When true, source code will be stripped * @param options.stripDebug - When true, all debug info will be stripped (including source) * * @example * // Strip only source code * runtime.setStripInfo({ stripSource: true }); * * // Strip all debug info (including source) * runtime.setStripInfo({ stripDebug: true }); */ setStripInfo(options?: StripOptions): void; /** * Gets the current stripping configuration * * @returns The current stripping options * * @remarks * Note that stripSource will be true if either source stripping or debug stripping * is enabled, matching the behavior of the underlying C implementation. * * @example * const options = runtime.getStripInfo(); * console.log(`Source stripping: ${options.stripSource}`); * console.log(`Debug stripping: ${options.stripDebug}`); */ getStripInfo(): StripOptions; /** * Sets the memory usage limit for this runtime. * * This controls the maximum amount of memory the JavaScript engine can allocate. * When the limit is reached, allocation attempts will fail with out-of-memory errors. * * @param limit - The memory limit in bytes, or -1 for no limit (default) */ setMemoryLimit(limit?: number): void; /** * Computes detailed memory usage statistics for this runtime. * * This method provides insights into how memory is being used by different * components of the JavaScript engine. * * @param ctx - Optional context to use for creating the result object. * If not provided, the system context will be used. * * @returns An object containing memory usage information * @throws {Error} When memory usage computation fails */ computeMemoryUsage(ctx?: VMContext | undefined): MemoryUsage; /** * Generates a human-readable string representation of memory usage. * * This is useful for debugging memory issues or monitoring runtime memory consumption. * * @returns A formatted string containing memory usage information */ dumpMemoryUsage(): string; /** * Enables the module loader for this runtime to support ES modules. * * The module loader allows JavaScript code executed in this runtime to import * modules using the standard ES module syntax (import/export). * * @param loader - Function to load module source code given a module specifier * @param normalizer - Optional function to normalize module names (resolve relative paths, etc.) * @param resolver - Optional function to handle import.meta.resolve calls */ enableModuleLoader(loader: ModuleLoaderFunction, normalizer?: ModuleNormalizerFunction, resolver?: ModuleResolverFunction): void; /** * Disables the module loader for this runtime. * * After calling this method, attempts to import modules will fail. */ disableModuleLoader(): void; /** * Enables the interrupt handler for this runtime. * * The interrupt handler allows controlled termination of long-running JavaScript * operations to prevent infinite loops or excessive execution time. * * @param handler - Function called periodically during JavaScript execution to check * if execution should be interrupted. Return true to interrupt. * @param opaque - Optional user data passed to the handler */ enableInterruptHandler(handler: InterruptHandler, opaque?: number): void; /** * Enables profiling of JavaScript function calls. * @param handler - The handlers for trace events * @param sampling - Controls profiling frequency: only 1/sampling function calls are instrumented. * Must be ≥ 1. Example: if sampling=4, only 25% of function calls will trigger the handlers. * @param opaque - Optional user data passed to both handlers. */ enableProfileCalls(handler: ProfilerEventHandler, sampling?: number, opaque?: JSVoid): void; /** * Disables the interrupt handler for this runtime. * * After calling this method, JavaScript code can run without being interruptible, * which may lead to infinite loops or excessive execution time. */ disableInterruptHandler(): void; /** * Gets or lazily creates the system context for this runtime. * * The system context is used for operations that need a context but don't * specifically require a user-created one. * * @returns The system context instance */ getSystemContext(): VMContext; /** * Creates a time-based interrupt handler that terminates execution * after a specified time has elapsed. * * This is useful for imposing time limits on JavaScript execution to prevent * excessive CPU usage or hanging processes. * * @param deadlineMs - The time limit in milliseconds from now * @returns An interrupt handler function that can be passed to enableInterruptHandler() * * @example * ```typescript * // Limit execution to 1 second * const handler = runtime.createDeadlineInterruptHandler(1000); * runtime.enableInterruptHandler(handler); * context.evaluateScript("while(true) {}"); // Will be interrupted after ~1 second * ``` */ createDeadlineInterruptHandler(deadlineMs: number): InterruptHandler; /** * Creates a gas-based interrupt handler that terminates script execution * after a specified number of JavaScript operations (gas units) have been performed. * * This handler provides a deterministic method for limiting the computational * complexity of scripts by counting operations rather than relying on time-based limits. * * @param maxGas - The maximum number of operations (gas units) allowed before interruption. * @returns An interrupt handler function that returns `true` when the gas limit is reached, * which can be passed to `enableInterruptHandler()`. * * @example * ```typescript * // Limit execution to 1 million gas units (operations) * const handler = runtime.createGasInterruptHandler(1_000_000); * runtime.enableInterruptHandler(handler); * context.evaluateScript("let i = 0; while(true) { i++; }"); // This script will be interrupted. * ``` */ createGasInterruptHandler(maxGas: number): InterruptHandler; /** * Checks if there are pending asynchronous jobs (Promises) in this runtime. * * @returns True if there are pending jobs, false otherwise */ isJobPending(): boolean; /** * Executes pending Promise jobs (microtasks) in the runtime. * * In JavaScript engines, promises and async functions create "jobs" that * are executed after the current execution context completes. This method * manually triggers the execution of these pending jobs. * * @param maxJobsToExecute - When negative (default), run all pending jobs. * Otherwise, execute at most `maxJobsToExecute` jobs before returning. * * @returns On success, returns the number of executed jobs. On error, returns * the exception that stopped execution and the context it occurred in. * * @remarks * This method does not normally return errors thrown inside async functions or * rejected promises. Those errors are available by calling * {@link VMContext#resolvePromise} on the promise handle returned by the async function. */ executePendingJobs(maxJobsToExecute?: number): ExecutePendingJobsResult; /** * Performs a memory leak check if compiled with leak sanitizer. * * This is a development/debugging utility to detect memory leaks. * * @returns Leak check result code (non-zero indicates potential leaks) */ recoverableLeakCheck(): number; dropContext(context: VMContext): void; /** * Releases all resources associated with this runtime. * * This includes all contexts, handlers, and the native runtime itself. * After calling this method, the runtime instance should not be used. */ release(): void; /** * Allocates shared runtime memory. * @param size - The size in bytes to allocate * @returns The pointer to the allocated memory */ allocateMemory(size: number): number; /** * Frees previously allocated shared runtime memory. * @param ptr - The pointer to the memory to free */ freeMemory(ptr: number): void; /** * Gets build information about the WebAssembly module. * * @returns Build metadata including version, build date, and configuration */ get build(): import("../etc/types").HakoBuildInfo; /** * Implements the Symbol.dispose method for the Disposable interface. * * This allows the runtime to be used with the using/with statements in * environments that support the Disposable pattern. */ [Symbol.dispose](): void; } //# sourceMappingURL=runtime.d.ts.map