hakojs
Version:
A secure, embeddable JavaScript engine that runs untrusted code inside WebAssembly sandboxes with fine-grained permissions and resource limits
710 lines • 24.8 kB
TypeScript
import type { HakoRuntime } from "../host/runtime";
import type { DisposableResult } from "../mem/lifetime";
import type { CModuleInitializer } from "../vm/cmodule";
import type { VMContext } from "../vm/context";
import type { VMValue } from "../vm/value";
import type { VmCallResult } from "../vm/vm-interface";
/**
* Opaque type helper that wraps a basic type with a specific string tag
* for type safety while maintaining the underlying type's functionality.
*
* @template T - The underlying type (e.g., string, number)
* @template K - A string literal used as a type tag
*/
type Opaque<T, K extends string> = T & {
__typename: K;
};
/**
* Base64-encoded string type. Uses the Opaque type pattern to differentiate
* from regular strings at the type level while maintaining string compatibility.
*/
export type Base64 = Opaque<string, "base64">;
/**
* Pointer to a JavaScript runtime instance in WebAssembly memory.
* Maps to LEPUSRuntime* in C code.
*/
export type JSRuntimePointer = number;
/**
* Pointer to a JavaScript execution context in WebAssembly memory.
* Maps to LEPUSContext* in C code.
*/
export type JSContextPointer = number;
/**
* Pointer to a mutable JavaScript value in WebAssembly memory.
* Maps to LEPUSValue* in C code.
*/
export type JSValuePointer = number;
/**
* Pointer to a constant JavaScript value in WebAssembly memory.
* Maps to LEPUSValueConst* in C code.
*/
export type JSValueConstPointer = number;
/**
* A numerical value representing the JavaScript type of a value.
*/
export type HAKOTypeOf = number;
/**
* JavaScript property atom identifier. Represents a property name
* that has been interned for faster property lookups.
* Maps to LEPUSAtom in C code.
*/
export type JSAtom = number;
/**
* Pointer to a null-terminated C string in WebAssembly memory.
* Maps to CString in C code.
*/
export type CString = number;
/**
* Pointer to heap-allocated character data that must be freed.
* Maps to OwnedHeapChar in C code.
*/
export type OwnedHeapChar = number;
/**
* Pointer to opaque data in WebAssembly memory.
*/
export type JSVoid = number;
/**
* Boolean type used in the LEPUS/QuickJS C API.
* -1: Exception occurred
* 0: False
* 1: True
*/
export type LEPUS_BOOL = -1 | 0 | 1;
/**
* LEPUS_BOOL constant representing an exception state.
*/
export declare const LEPUS_EXCEPTION: LEPUS_BOOL;
/**
* LEPUS_BOOL constant representing false.
*/
export declare const LEPUS_FALSE: LEPUS_BOOL;
/**
* LEPUS_BOOL constant representing true.
*/
export declare const LEPUS_TRUE: LEPUS_BOOL;
export type LEPUSModuleDef = number;
/**
* Converts a LEPUS_BOOL value to a JavaScript boolean.
*
* @param value - The LEPUS_BOOL value to convert
* @returns The corresponding JavaScript boolean
* @throws {PrimJSError} If the value is not a valid LEPUS_BOOL
*/
export declare function LEPUS_BOOLToBoolean(value: LEPUS_BOOL): boolean;
/**
* Host function type that can be called from the JavaScript environment.
*
* @template VmHandle - Type representing a VM value handle
* @param this - The 'this' value for the function call
* @param args - Arguments passed to the function from JavaScript
* @returns A VM value handle, VM call result, or void
*/
export type HostCallbackFunction<VmHandle> = (this: VmHandle, ...args: VmHandle[]) => VmHandle | VmCallResult<VmHandle> | void;
export type ModuleLoaderResult = {
type: "source";
data: string;
} | {
type: "precompiled";
data: number;
} | {
type: "error";
} | null;
/**
* Function used to load JavaScript module source code.
*
* @param moduleName - The name of the module to load
* @param attributes - Import attributes object (e.g., { type: "json" })
* @returns The module source code as a string, null if not found, or a Promise resolving to either
*/
export type ModuleLoaderFunction = (moduleName: string, attributes?: Record<string, string>) => ModuleLoaderResult | Promise<ModuleLoaderResult>;
/**
* Function used to normalize module specifiers to absolute module names.
*
* @param baseName - The base module name (typically the importing module's name)
* @param moduleName - The module specifier to normalize
* @returns The normalized module name or a Promise resolving to the normalized name
*/
export type ModuleNormalizerFunction = (baseName: string, moduleName: string) => string | Promise<string>;
/**
* Function used to resolve module names (import.meta.resolve).
*
* @param moduleName - The module name to resolve
* @param currentModule - The current module context
* @returns The fully qualified path to the module, or undefined if not found
*/
export type ModuleResolverFunction = (moduleName: string, currentModule?: string) => string | undefined;
/**
* Function used to initialize a C module.
* This is called when the module is loaded into the runtime.
*
* @param module - The CModuleInitializer instance representing the module
* @returns A status code indicating success (0) or failure (non-zero)
*/
export type ModuleInitFunction = (module: CModuleInitializer) => number;
/**
* Function used to finalize a C classes
*/
export type ClassConstructorHandler = (context: VMContext, newTarget: VMValue, args: VMValue[], classId: number) => VMValue;
export type ClassFinalizerHandler = (runtime: HakoRuntime, opaque: number, classId: number) => void;
export interface ClassOptions {
finalizer?: ClassFinalizerHandler;
methods?: Record<string, HostCallbackFunction<VMValue>>;
staticMethods?: Record<string, HostCallbackFunction<VMValue>>;
}
/**
* Basic interrupt handler function signature for C callbacks.
* This is the low-level function called by the C side.
*
* @returns `true` to interrupt JavaScript execution, `false` to continue
*/
export type InterruptHandlerFunction = () => boolean;
/**
* Enhanced interrupt handler that receives the runtime object.
* Determines if JavaScript execution inside the VM should be interrupted.
*
* @param runtime - The Hako runtime instance that is executing JavaScript
* @param context - The VM context in which the JavaScript is executing
* @param opaque - Opaque pointer data passed through from the enableInterruptHandler call
* @returns `true` to interrupt JS execution, `false` or `undefined` to continue
*/
export type InterruptHandler = (runtime: HakoRuntime, context: VMContext, opaque: JSVoid) => boolean | undefined;
/**
* Phase type for the trace events we're tracking
*/
export type TraceEventPhase = "B" | "E";
/**
* Structure of a trace event for function profiling
*/
export type TraceEvent = {
/** Function name */
name: string;
/** Category - always "js" for our events */
cat: "js";
/** Phase - 'B' for begin or 'E' for end */
ph: TraceEventPhase;
/** Timestamp in microseconds */
ts: number;
/** Process ID - always 1 for our events */
pid: 1;
/** Thread ID - always 1 for our events */
tid: 1;
};
/**
* Handler for function profiling events
*/
export type ProfilerEventHandler = {
/**
* Handler for function start event
* @param context - The VM context in which the function is executing
* @param event - The trace event for the function start
* @param opaque - Opaque pointer data passed through from the caller
*/
onFunctionStart: (context: VMContext, event: TraceEvent, opaque: JSVoid) => void;
/**
* Handler for function end event
* @param context - The VM context in which the function is executing
* @param event - The trace event for the function end
* @param opaque - Opaque pointer data passed through from the caller
*/
onFunctionEnd: (context: VMContext, event: TraceEvent, opaque: JSVoid) => void;
};
/**
* Result type for executing pending Promise jobs (microtasks).
* On success, contains the number of jobs executed.
* On failure, contains the error value and associated context.
*/
export type ExecutePendingJobsResult = DisposableResult<
/** Number of jobs successfully executed. */
number,
/** The error that occurred. */
VMValue & {
/** The context where the error occurred. */
context: VMContext;
}>;
/**
* Bitfield enum representing built-in JavaScript features that can be enabled in a context.
* Each bit represents a specific feature group.
*/
export declare enum Intrinsic {
/** Basic object functionality (Object, Function, Array, etc.) */
BaseObjects = 1,
/** Date object and related functionality */
Date = 2,
/** eval() function and related functionality */
Eval = 4,
/** String.prototype.normalize() functionality */
StringNormalize = 8,
/** RegExp object and related functionality */
RegExp = 16,
/** RegExp compiler functionality */
RegExpCompiler = 32,
/** JSON object and related functionality */
JSON = 64,
/** Proxy object and related functionality */
Proxy = 128,
/** Map and Set objects and related functionality */
MapSet = 256,
/** TypedArray objects (Uint8Array, etc.) */
TypedArrays = 512,
/** Promise object and related functionality */
Promise = 1024,
/** BigInt functionality */
BigInt = 2048,
/** BigFloat functionality (non-standard) */
BigFloat = 4096,
/** BigDecimal functionality (non-standard) */
BigDecimal = 8192,
/** Operator overloading functionality (non-standard) */
OperatorOverloading = 16384,
/** Extended bignum functionality (non-standard) */
BignumExt = 32768,
/** Performance measurement API */
Performance = 65536,
/** Default set of features for most contexts */
Default = 3935,
/** Minimal functionality (only BaseObjects) */
Basic = 1,
/** All available features */
All = 1048575
}
/**
* Configuration interface for enabling or disabling specific JavaScript language features.
* Each property corresponds to a feature group represented in the Intrinsic enum.
*/
export type Intrinsics = {
/** Basic object functionality (Object, Function, Array, etc.) */
BaseObjects?: boolean;
/** Date object and related functionality */
Date?: boolean;
/** eval() function and related functionality */
Eval?: boolean;
/** String.prototype.normalize() functionality */
StringNormalize?: boolean;
/** RegExp object and related functionality */
RegExp?: boolean;
/** RegExp compiler functionality */
RegExpCompiler?: boolean;
/** JSON object and related functionality */
JSON?: boolean;
/** Proxy object and related functionality */
Proxy?: boolean;
/** Map and Set objects and related functionality */
MapSet?: boolean;
/** TypedArray objects (Uint8Array, etc.) */
TypedArrays?: boolean;
/** Promise object and related functionality */
Promise?: boolean;
/** BigInt functionality */
BigInt?: boolean;
/** BigFloat functionality (non-standard) */
BigFloat?: boolean;
/** BigDecimal functionality (non-standard) */
BigDecimal?: boolean;
/** Operator overloading functionality (non-standard) */
OperatorOverloading?: boolean;
/** Extended bignum functionality (non-standard) */
BignumExt?: boolean;
/** Whether to enable the 'performance' object */
Performance?: boolean;
};
/**
* The default set of JavaScript language features enabled in a new context.
* @see {@link ContextOptions}
*/
export declare const DefaultIntrinsics: Readonly<{
readonly BaseObjects: true;
readonly Date: true;
readonly Eval: true;
readonly StringNormalize: true;
readonly RegExp: true;
readonly JSON: true;
readonly Proxy: true;
readonly MapSet: true;
readonly TypedArrays: true;
readonly Promise: true;
}>;
/**
* Converts an Intrinsics object into the corresponding Intrinsic enum bitfield value.
*
* @param intrinsics - The Intrinsics configuration object
* @returns A combined Intrinsic enum value representing all enabled features
*/
export declare function intrinsicsToFlags(intrinsics: Intrinsics): Intrinsic;
/**
* Configuration options for creating a JavaScript execution context.
* Pass to {@link HakoRuntime#newContext}.
*/
export interface ContextOptions {
/**
* What built-in objects and language features to enable?
* If unset, the default intrinsics will be used.
* To omit all intrinsics, pass an empty array.
*
* To remove a specific intrinsic, but retain the other defaults,
* override it from {@link DefaultIntrinsics}
* ```ts
* const contextWithoutDateOrEval = runtime.newContext({
* intrinsics: {
* ...DefaultIntrinsics,
* Date: false,
* }
* })
* ```
*/
intrinsics?: Intrinsics;
/**
* Wrap the provided context instead of constructing a new one.
* @private Used internally, not intended for direct use
*/
contextPointer?: JSContextPointer;
/**
* Maximum stack size for JavaScript execution in this context, in bytes.
* Helps prevent stack overflow attacks in untrusted code.
*/
maxStackSizeBytes?: number;
}
/**
* Flags controlling JavaScript code evaluation behavior.
* Corresponds to the C API's eval flags.
*/
export declare enum EvalFlag {
/** Evaluate as global code (default) */
Global = 0,// LEPUS_EVAL_TYPE_GLOBAL (0 << 0)
/** Evaluate as ES module code */
Module = 1,// LEPUS_EVAL_TYPE_MODULE (1 << 0)
/** Direct call (internal use) */
Direct = 2,// LEPUS_EVAL_TYPE_DIRECT (2 << 0)
/** Indirect call (internal use) */
Indirect = 3,// LEPUS_EVAL_TYPE_INDIRECT (3 << 0)
/** Mask for extracting type flags */
TypeMask = 3,// LEPUS_EVAL_TYPE_MASK (3 << 0)
/** Force 'strict' mode */
Strict = 8,// LEPUS_EVAL_FLAG_STRICT (1 << 3)
/** reserved */
Reserved = 16,// LEPUS_EVAL_FLAG_STRIP (1 << 4)
/** Compile only (don't execute) */
CompileOnly = 32,// LEPUS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
/** Don't persist the script for debugger (internal use) */
DebuggerNoPersistScript = 64
}
/**
* Bit flag for stripping source code
* @internal
*/
export declare const JS_STRIP_SOURCE: number;
/**
* Bit flag for stripping all debug information including source code
* @internal
*/
export declare const JS_STRIP_DEBUG: number;
/**
* Options for configuring code stripping behavior
*/
export interface StripOptions {
/**
* When true, source code will be stripped from the compiled output
*/
stripSource?: boolean;
/**
* When true, all debug information including source code will be stripped
* Setting this to true automatically enables stripSource as well
*/
stripDebug?: boolean;
}
/**
* Options for evaluating JavaScript code in a context.
*/
export interface ContextEvalOptions {
/**
* Global code (default), or "module" code?
*
* - When type is `"global"`, the code is evaluated in the global scope of the context,
* and the return value is the result of the last expression.
* - When type is `"module"`, the code is evaluated as a module scope, may use `import`,
* `export`, and top-level `await`. The return value is the module's exports,
* or a promise for the module's exports.
*/
type?: "global" | "module";
/** Force "strict" mode */
strict?: boolean;
/**
* Compile but do not run the code. The result is an object with a
* JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
* with JS_EvalFunction().
*/
compileOnly?: boolean;
/** Don't persist script in debugger */
noPersist?: boolean;
/** Filename for error reporting */
fileName?: string;
/** Automatically detect if code should be treated as a module */
detectModule?: boolean;
}
/**
* Converts evaluation options to the corresponding bitfield flags.
*
* @param evalOptions - Options object, number (raw flags), or undefined
* @returns The combined EvalFlag bitfield
*/
export declare function evalOptionsToFlags(evalOptions: ContextEvalOptions | number | undefined): EvalFlag;
/**
* JavaScript Promise states.
*/
export type PromiseState =
/** Promise has not been resolved or rejected yet */
"pending"
/** Promise has been resolved with a value */
| "fulfilled"
/** Promise has been rejected with a reason */
| "rejected";
/**
* Different modes for comparing JavaScript values for equality.
*/
export declare enum EqualOp {
/** Uses strict equality operator (===) */
StrictEquals = 0,
/** Uses Object.is() semantics */
SameValue = 1,
/** Similar to Object.is() but treats +0 and -0 as equal */
SameValueZero = 2
}
/**
* Flags for controlling property enumeration.
*/
export declare enum PropertyEnumFlags {
/** Include string property names */
String = 1,
/** Include symbol property names */
Symbol = 2,
/** Include private properties */
Private = 4,
/** Include enumerable properties */
Enumerable = 16,
/** Include non-enumerable properties */
NonEnumerable = 32,
/** Include configurable properties */
Configurable = 64,
/** Include non-configurable properties */
NonConfigurable = 128,
/** Include numeric properties */
Number = 16384,
/** Use standards-compliant property enumeration */
Compliant = 32768
}
/**
* ABI-level JavaScript type tags as understood by the underlying engine.
*/
export declare enum ABIJSType {
Null = 0,
Undefined = 1,
Boolean = 2,
Number = 3,
String = 4,
Object = 5,
Function = 6,
Symbol = 7,
BigInt = 8,
Module = 9,
Unknown = -1
}
/**
* String representation of JavaScript types, aligned with typeof operator results.
*/
export type JSType = "undefined" | "object" | "string" | "symbol" | "boolean" | "number" | "bigint" | "function";
/**
* Lifecycle modes for JavaScript values.
*/
export declare enum ValueLifecycle {
/** Value is owned by us and must be explicitly freed */
Owned = 0,
/** Value is borrowed and should not be freed */
Borrowed = 1,
/** Value is temporary and will be automatically freed */
Temporary = 2
}
/**
* Memory usage statistics returned by HAKO_RuntimeComputeMemoryUsage.
* Provides detailed information about memory consumption by different components.
*/
export interface MemoryUsage {
/** Maximum memory limit in bytes, or -1 if no limit */
malloc_limit: number;
/** Current memory usage in bytes */
memory_used_size: number;
/** Number of active malloc allocations */
malloc_count: number;
/** Total count of memory allocations */
memory_used_count: number;
/** Number of interned property names (atoms) */
atom_count: number;
/** Memory used by atoms in bytes */
atom_size: number;
/** Number of string objects */
str_count: number;
/** Memory used by strings in bytes */
str_size: number;
/** Number of JavaScript objects */
obj_count: number;
/** Memory used by objects in bytes */
obj_size: number;
/** Number of object properties */
prop_count: number;
/** Memory used by properties in bytes */
prop_size: number;
/** Number of object shapes */
shape_count: number;
/** Memory used by shapes in bytes */
shape_size: number;
/** Number of JavaScript functions */
lepus_func_count: number;
/** Memory used by functions in bytes */
lepus_func_size: number;
/** Memory used by function bytecode in bytes */
lepus_func_code_size: number;
/** Number of PC to line mappings for debugging */
lepus_func_pc2line_count: number;
/** Memory used by PC to line mappings in bytes */
lepus_func_pc2line_size: number;
/** Number of C functions exposed to JavaScript */
c_func_count: number;
/** Number of arrays */
array_count: number;
/** Number of fast arrays (optimized for numeric indices) */
fast_array_count: number;
/** Number of elements in fast arrays */
fast_array_elements: number;
/** Number of binary objects (ArrayBuffer, TypedArray) */
binary_object_count: number;
/** Memory used by binary objects in bytes */
binary_object_size: number;
}
/**
* Property descriptor for defining object properties.
* Similar to the standard JavaScript Object.defineProperty descriptor.
*/
export interface PropertyDescriptor {
/** Property value */
value?: VMValue;
/** Whether the property can be changed and deleted */
configurable?: boolean;
/** Whether the property shows up during enumeration */
enumerable?: boolean;
/** Getter function */
get?: (this: VMValue) => VMValue;
/** Setter function */
set?: (this: VMValue, value: VMValue) => void;
}
/**
* Configuration options for resource-limited interrupt handlers.
*/
export interface ResourceLimitOptions {
/** Maximum execution time in milliseconds */
maxTimeMs?: number;
/** Maximum memory usage in bytes */
maxMemoryBytes?: number;
/** Maximum number of steps to execute */
maxSteps?: number;
/** How often to check memory usage (every N steps) */
memoryCheckInterval?: number;
}
/**
* Equality operation modes for isEqual.
*/
export declare enum IsEqualOp {
/** Uses === operator semantics */
IsStrictlyEqual = 0,
/** Uses Object.is() semantics */
IsSameValue = 1,
/** Uses Array.prototype.includes() semantics (treats +0 and -0 as equal) */
IsSameValueZero = 2
}
/**
* Promise executor function type, compatible with standard JavaScript Promise.
*/
export type PromiseExecutor<ResolveT, RejectT> = (resolve: (value: ResolveT | PromiseLike<ResolveT>) => void, reject: (reason: RejectT) => void) => void;
/**
* Result type for VMContext operations.
*/
export type VMContextResult<S> = DisposableResult<S, VMValue>;
/**
* Interface for Error objects with an options property containing a cause.
*/
interface ErrorWithOptions extends Error {
options?: {
cause?: unknown;
};
}
/**
* Type guard to check if an Error has options with a cause property.
*
* @param error - The error to check
* @returns True if the error has options with a cause
*/
export declare function hasOptionsWithCause(error: Error): error is ErrorWithOptions;
/**
* Detects circular references within an object and throws a TypeError when found.
*
* @param obj - The object to check for circular references
* @param path - Optional path string for error messaging (used internally)
* @throws TypeError when circular reference is detected
*/
export declare function detectCircularReferences(obj: unknown, path?: string): void;
/**
* Information about the build configuration of the Hako WebAssembly module.
*/
export type HakoBuildInfo = {
/** Version string of the Hako library */
version: string;
/** Raw flags value representing build configuration */
flags: number;
/** Date and time the module was built */
buildDate: string;
/** Version of the WASI SDK used */
wasiSdkVersion: string;
/** Version of WASI libc used */
wasiLibc: string;
/** LLVM compiler used */
llvm: string;
/** Version of LLVM used */
llvmVersion: string;
/** Build configuration string */
config: string;
/** Whether this is a debug build */
isDebug: boolean;
/** Whether sanitizers are enabled */
hasSanitizer: boolean;
/** Whether BigNum support is enabled */
hasBignum: boolean;
/** Whether LepusNG (next-gen engine) is enabled */
hasLepusNG: boolean;
/** Whether debugger support is enabled */
hasDebugger: boolean;
/** Whether snapshot support is enabled */
hasSnapshot: boolean;
/** Whether compatible memory management is enabled */
hasCompatibleMM: boolean;
/** Whether NaN boxing is enabled */
hasNanbox: boolean;
/** Whether code cache is enabled */
hasCodeCache: boolean;
/** Whether cache profiling is enabled */
hasCacheProfile: boolean;
/** Whether memory detection is enabled */
hasMemDetection: boolean;
/** Whether atomics support is enabled */
hasAtomics: boolean;
/** Whether force garbage collection is enabled */
hasForceGC: boolean;
/** Whether Lynx simplification is enabled */
hasLynxSimplify: boolean;
/** Whether builtin serialization is enabled */
hasBuiltinSerialize: boolean;
/** Whether hako was compiled with profiling enabled */
hasHakoProfiler: boolean;
};
/**
* Type of JavaScript TypedArray.
*/
export type TypedArrayType = "Unknown" | "Uint8Array" | "Uint8ClampedArray" | "Int8Array" | "Uint16Array" | "Int16Array" | "Uint32Array" | "Int32Array" | "BigUint64Array" | "BigInt64Array" | "Float16Array" | "Float32Array" | "Float64Array";
export {};
//# sourceMappingURL=types.d.ts.map