/** * @typedef {Object} ModuleInfo * @property {string} name - Module name * @property {string} path - Path to .beam or .avm file * @property {string} signature - Module signature hash * @property {number} loadedAt - Timestamp when loaded * @property {number} version - Module version (increments on reload) * @property {'loaded' | 'reloading' | 'error'} status - Current status */ /** * @typedef {Object} HotSwapCallback * @property {string} moduleName - Target module name * @property {Function} beforeSwap - Called before module swap * @property {Function} afterSwap - Called after successful swap * @property {Function} [onError] - Called if swap fails */ /** * @typedef {Object} LoadResult * @property {boolean} success - Whether load succeeded * @property {string} moduleName - Loaded module name * @property {string} [signature] - Module signature if successful * @property {string} [error] - Error message if failed */ /** * @typedef {Object} ReloadResult * @property {boolean} success - Whether reload succeeded * @property {string} moduleName - Reloaded module name * @property {number} version - New version number * @property {number} duration - Reload duration in ms * @property {string} [error] - Error message if failed */ /** * @typedef {Object} SignatureValidationResult * @property {boolean} valid - Whether signature is valid * @property {string} signature - Computed signature * @property {string} [previousSignature] - Previous signature if available * @property {string} [error] - Error message if validation failed */ /** * HotCodeLoader manages dynamic loading and hot-swapping of BEAM modules. * * Features: * - Load new .beam or .avm modules at runtime * - Reload modules from updated files * - Register callbacks for before/after reload events * - Validate module signatures before swapping * - Queue concurrent reloads to ensure atomicity * - Notify supervisor tree of module changes * * @class */ export class HotCodeLoader { /** * Creates a new HotCodeLoader instance. * * @param {import('./atomvm-runtime.mjs').AtomVMRuntime} runtime - AtomVM runtime instance * @param {Object} [options] - Configuration options * @param {import('./supervisor-tree.mjs').SupervisorTree} [options.supervisor] - Supervisor tree for notifications * @param {number} [options.maxQueueSize=100] - Maximum reload queue size * @param {number} [options.reloadTimeout=30000] - Reload timeout in ms */ constructor(runtime: import("./atomvm-runtime.mjs").AtomVMRuntime, options?: { supervisor?: import("./supervisor-tree.mjs").SupervisorTree; maxQueueSize?: number; reloadTimeout?: number; }); /** @type {import('./atomvm-runtime.mjs').AtomVMRuntime} */ runtime: import("./atomvm-runtime.mjs").AtomVMRuntime; /** @type {import('./supervisor-tree.mjs').SupervisorTree | null} */ supervisor: import("./supervisor-tree.mjs").SupervisorTree | null; /** @type {Map} */ activeModules: Map; /** @type {Map} */ hotSwapCallbacks: Map; /** @type {Array<{moduleName: string, resolve: Function, reject: Function}>} */ reloadQueue: Array<{ moduleName: string; resolve: Function; reject: Function; }>; /** @type {boolean} */ isProcessingQueue: boolean; /** @type {number} */ maxQueueSize: number; /** @type {number} */ reloadTimeout: number; /** @type {Map} */ moduleCache: Map; /** * Load a new BEAM module (.beam or .avm file). * * **Poka-Yoke**: Validates file existence and signature before adding to active modules. * * @param {string} modulePath - Path to .beam or .avm file * @returns {Promise} Load result */ loadModule(modulePath: string): Promise; /** * Reload a module from its updated file. * * **Poka-Yoke**: Validates signature, executes callbacks, and queues concurrent reloads. * * @param {string} moduleName - Name of module to reload * @returns {Promise} Reload result */ reloadModule(moduleName: string): Promise; /** * Register a hot swap callback for a module. * * @param {string} moduleName - Target module name * @param {Function} callback - Callback function or object with beforeSwap/afterSwap * @returns {Function} Unregister function */ registerHotSwap(moduleName: string, callback: Function): Function; /** * Get list of all active modules. * * @returns {ModuleInfo[]} Array of active module info objects */ getActiveModules(): ModuleInfo[]; /** * Validate a module's signature before swap. * * **Poka-Yoke**: Ensures module integrity before allowing swap. * * @param {string} moduleName - Module name to validate * @returns {Promise} Validation result */ validateModuleSignature(moduleName: string): Promise; /** * Unload a module from the active modules. * * @param {string} moduleName - Module name to unload * @returns {boolean} True if module was unloaded */ unloadModule(moduleName: string): boolean; /** * Set supervisor tree for notifications. * * @param {import('./supervisor-tree.mjs').SupervisorTree} supervisor - Supervisor tree */ setSupervisor(supervisor: import("./supervisor-tree.mjs").SupervisorTree): void; /** * Get pending reload queue size. * * @returns {number} Number of pending reloads */ getPendingReloadCount(): number; /** * Execute module reload with OTEL tracing. * * @private * @param {string} moduleName - Module to reload * @returns {Promise} Reload result */ private _executeReload; /** * Queue a reload request. * * @private * @param {string} moduleName - Module to reload * @returns {Promise} Reload result */ private _queueReload; /** * Process next item in reload queue. * * @private */ private _processNextInQueue; /** * Execute before-swap callbacks for a module. * * @private * @param {string} moduleName - Module name */ private _executeBeforeSwapCallbacks; /** * Execute after-swap callbacks for a module. * * @private * @param {string} moduleName - Module name */ private _executeAfterSwapCallbacks; /** * Execute error callbacks for a module. * * @private * @param {string} moduleName - Module name * @param {Error} error - Error that occurred */ private _executeErrorCallbacks; /** * Notify supervisor tree of module reload. * * @private * @param {string} moduleName - Reloaded module name */ private _notifySupervisor; /** * Extract module name from path. * * @private * @param {string} modulePath - Module path * @returns {string} Module name */ private _extractModuleName; /** * Load module content from path. * * @private * @param {string} modulePath - Module path * @returns {Promise} Module content or null */ private _loadModuleContent; /** * Compute signature hash for module content. * * @private * @param {ArrayBuffer} content - Module content * @returns {Promise} Signature hash */ private _computeSignature; } export type ModuleInfo = { /** * - Module name */ name: string; /** * - Path to .beam or .avm file */ path: string; /** * - Module signature hash */ signature: string; /** * - Timestamp when loaded */ loadedAt: number; /** * - Module version (increments on reload) */ version: number; /** * - Current status */ status: "loaded" | "reloading" | "error"; }; export type HotSwapCallback = { /** * - Target module name */ moduleName: string; /** * - Called before module swap */ beforeSwap: Function; /** * - Called after successful swap */ afterSwap: Function; /** * - Called if swap fails */ onError?: Function; }; export type LoadResult = { /** * - Whether load succeeded */ success: boolean; /** * - Loaded module name */ moduleName: string; /** * - Module signature if successful */ signature?: string; /** * - Error message if failed */ error?: string; }; export type ReloadResult = { /** * - Whether reload succeeded */ success: boolean; /** * - Reloaded module name */ moduleName: string; /** * - New version number */ version: number; /** * - Reload duration in ms */ duration: number; /** * - Error message if failed */ error?: string; }; export type SignatureValidationResult = { /** * - Whether signature is valid */ valid: boolean; /** * - Computed signature */ signature: string; /** * - Previous signature if available */ previousSignature?: string; /** * - Error message if validation failed */ error?: string; };