UNPKG

@metamask/ocap-kernel

Version:
613 lines 28.5 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Kernel_instances, _Kernel_commandStream, _Kernel_rpcService, _Kernel_vats, _Kernel_vatWorkerService, _Kernel_kernelStore, _Kernel_logger, _Kernel_kernelQueue, _Kernel_kernelRouter, _Kernel_kernelServicesByName, _Kernel_kernelServicesByObject, _Kernel_init, _Kernel_handleCommandMessage, _Kernel_launchVat, _Kernel_runVat, _Kernel_launchVatsForSubcluster, _Kernel_stopVat, _Kernel_getVat, _Kernel_resetKernelState, _Kernel_invokeKernelService; import { StreamReadError, VatAlreadyExistsError, VatDeletedError, VatNotFoundError, SubclusterNotFoundError } from "@metamask/kernel-errors"; import { RpcService } from "@metamask/kernel-rpc-methods"; import { stringify } from "@metamask/kernel-utils"; import { Logger, splitLoggerStream } from "@metamask/logger"; import { serializeError } from "@metamask/rpc-errors"; import { hasProperty } from "@metamask/utils"; import { KernelQueue } from "./KernelQueue.mjs"; import { KernelRouter } from "./KernelRouter.mjs"; import { kernelHandlers } from "./rpc/index.mjs"; import { kslot, kser, kunser } from "./services/kernel-marshal.mjs"; import { makeKernelStore } from "./store/index.mjs"; import { ROOT_OBJECT_VREF, isClusterConfig } from "./types.mjs"; import { Fail, assert } from "./utils/assert.mjs"; import { VatHandle } from "./VatHandle.mjs"; export class Kernel { /** * Construct a new kernel instance. * * @param commandStream - Command channel from whatever external software is driving the kernel. * @param vatWorkerService - Service to create a worker in which a new vat can run. * @param kernelDatabase - Database holding the kernel's persistent state. * @param options - Options for the kernel constructor. * @param options.resetStorage - If true, the storage will be cleared. * @param options.logger - Optional logger for error and diagnostic output. */ // eslint-disable-next-line no-restricted-syntax constructor(commandStream, vatWorkerService, kernelDatabase, options = {}) { _Kernel_instances.add(this); /** Command channel from the controlling console/browser extension/test driver */ _Kernel_commandStream.set(this, void 0); _Kernel_rpcService.set(this, void 0); /** Currently running vats, by ID */ _Kernel_vats.set(this, void 0); /** Service to spawn workers (in iframes) for vats to run in */ _Kernel_vatWorkerService.set(this, void 0); /** Storage holding the kernel's own persistent state */ _Kernel_kernelStore.set(this, void 0); /** Logger for outputting messages (such as errors) to the console */ _Kernel_logger.set(this, void 0); /** The kernel's run queue */ _Kernel_kernelQueue.set(this, void 0); /** The kernel's router */ _Kernel_kernelRouter.set(this, void 0); /** Objects providing custom or kernel-privileged services to vats. */ _Kernel_kernelServicesByName.set(this, new Map()); _Kernel_kernelServicesByObject.set(this, new Map()); __classPrivateFieldSet(this, _Kernel_commandStream, commandStream, "f"); __classPrivateFieldSet(this, _Kernel_rpcService, new RpcService(kernelHandlers, {}), "f"); __classPrivateFieldSet(this, _Kernel_vats, new Map(), "f"); __classPrivateFieldSet(this, _Kernel_vatWorkerService, vatWorkerService, "f"); __classPrivateFieldSet(this, _Kernel_logger, options.logger ?? new Logger('ocap-kernel'), "f"); __classPrivateFieldSet(this, _Kernel_kernelStore, makeKernelStore(kernelDatabase), "f"); if (options.resetStorage) { __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_resetKernelState).call(this); } __classPrivateFieldSet(this, _Kernel_kernelQueue, new KernelQueue(__classPrivateFieldGet(this, _Kernel_kernelStore, "f"), this.terminateVat.bind(this)), "f"); __classPrivateFieldSet(this, _Kernel_kernelRouter, new KernelRouter(__classPrivateFieldGet(this, _Kernel_kernelStore, "f"), __classPrivateFieldGet(this, _Kernel_kernelQueue, "f"), __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_getVat).bind(this), __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_invokeKernelService).bind(this)), "f"); harden(this); } /** * Create a new kernel instance. * * @param commandStream - Command channel from whatever external software is driving the kernel. * @param vatWorkerService - Service to create a worker in which a new vat can run. * @param kernelDatabase - Database holding the kernel's persistent state. * @param options - Options for the kernel constructor. * @param options.resetStorage - If true, the storage will be cleared. * @param options.logger - Optional logger for error and diagnostic output. * @returns A promise for the new kernel instance. */ static async make(commandStream, vatWorkerService, kernelDatabase, options = {}) { const kernel = new Kernel(commandStream, vatWorkerService, kernelDatabase, options); await __classPrivateFieldGet(kernel, _Kernel_instances, "m", _Kernel_init).call(kernel); return kernel; } /** * Send a message from the kernel to an object in a vat. * * @param target - The object to which the message is directed. * @param method - The method to be invoked. * @param args - Message arguments. * * @returns a promise for the (CapData encoded) result of the message invocation. */ async queueMessage(target, method, args) { return __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").enqueueMessage(target, method, args); } /** * Launches a sub-cluster of vats. * * @param config - Configuration object for sub-cluster. * @returns a promise for the (CapData encoded) result of the bootstrap message. */ async launchSubcluster(config) { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); isClusterConfig(config) || Fail `invalid cluster config`; if (!config.vats[config.bootstrap]) { Fail `invalid bootstrap vat name ${config.bootstrap}`; } const subclusterId = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").addSubcluster(config); return __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_launchVatsForSubcluster).call(this, subclusterId, config); } /** * Terminates a named sub-cluster of vats. * * @param subclusterId - The id of the subcluster to terminate. * @returns A promise that resolves when termination is complete. */ async terminateSubcluster(subclusterId) { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); if (!__classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubcluster(subclusterId)) { throw new SubclusterNotFoundError(subclusterId); } const vatIdsToTerminate = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubclusterVats(subclusterId); for (const vatId of vatIdsToTerminate.reverse()) { await this.terminateVat(vatId); this.collectGarbage(); } __classPrivateFieldGet(this, _Kernel_kernelStore, "f").deleteSubcluster(subclusterId); } /** * Reloads a named subcluster by restarting all its vats. * This terminates and restarts all vats in the subcluster. * * @param subclusterId - The id of the subcluster to reload. * @returns A promise for an object containing the subcluster. * @throws If the subcluster is not found. */ async reloadSubcluster(subclusterId) { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); const subcluster = this.getSubcluster(subclusterId); if (!subcluster) { throw new SubclusterNotFoundError(subclusterId); } for (const vatId of subcluster.vats.reverse()) { await this.terminateVat(vatId); this.collectGarbage(); } const newId = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").addSubcluster(subcluster.config); await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_launchVatsForSubcluster).call(this, newId, subcluster.config); const newSubcluster = this.getSubcluster(newId); if (!newSubcluster) { throw new SubclusterNotFoundError(newId); } return newSubcluster; } /** * Retrieves a subcluster by its ID. * * @param subclusterId - The id of the subcluster. * @returns The subcluster, or undefined if not found. */ getSubcluster(subclusterId) { return __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubcluster(subclusterId); } /** * Gets all subclusters. * * @returns An array of subcluster information records. */ getSubclusters() { return __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubclusters(); } /** * Checks if a vat belongs to a specific subcluster. * * @param vatId - The ID of the vat to check. * @param subclusterId - The ID of the subcluster to check against. * @returns True if the vat belongs to the specified subcluster, false otherwise. */ isVatInSubcluster(vatId, subclusterId) { return __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getVatSubcluster(vatId) === subclusterId; } /** * Gets all vat IDs that belong to a specific subcluster. * * @param subclusterId - The ID of the subcluster to get vats for. * @returns An array of vat IDs that belong to the specified subcluster. */ getSubclusterVats(subclusterId) { return __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubclusterVats(subclusterId); } /** * Restarts a vat. * * @param vatId - The ID of the vat. * @returns A promise for the restarted vat. */ async restartVat(vatId) { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); const vat = __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_getVat).call(this, vatId); if (!vat) { throw new VatNotFoundError(vatId); } const { config } = vat; await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_stopVat).call(this, vatId, false); await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_runVat).call(this, vatId, config); return vat; } /** * Terminate a vat with extreme prejudice. * * @param vatId - The ID of the vat. * @param reason - If the vat is being terminated, the reason for the termination. */ async terminateVat(vatId, reason) { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_stopVat).call(this, vatId, true, reason); // Mark for deletion (which will happen later, in vat-cleanup events) __classPrivateFieldGet(this, _Kernel_kernelStore, "f").markVatAsTerminated(vatId); } /** * Clear the database. */ async clearStorage() { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); __classPrivateFieldGet(this, _Kernel_kernelStore, "f").clear(); } /** * Gets a list of the IDs of all running vats. * * @returns An array of vat IDs. */ getVatIds() { return Array.from(__classPrivateFieldGet(this, _Kernel_vats, "f").keys()); } /** * Gets a list of information about all running vats. * * @returns An array of vat information records. */ getVats() { return Array.from(__classPrivateFieldGet(this, _Kernel_vats, "f").values()).map((vat) => { const subclusterId = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getVatSubcluster(vat.vatId); return { id: vat.vatId, config: vat.config, subclusterId, }; }); } /** * Revoke an exported object. Idempotent. Revoking promises is not supported. * * @param kref - The KRef of the object to revoke. * @throws If the object is a promise. */ revoke(kref) { __classPrivateFieldGet(this, _Kernel_kernelStore, "f").revoke(kref); } /** * Check if an object is revoked. * * @param kref - The KRef of the object to check. * @returns True if the object is revoked, false otherwise. */ isRevoked(kref) { return __classPrivateFieldGet(this, _Kernel_kernelStore, "f").isRevoked(kref); } /** * Get the current kernel status, defined as the current cluster configuration * and a list of all running vats. * * @returns The current kernel status containing vats and subclusters information. */ async getStatus() { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); return { vats: this.getVats(), subclusters: __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubclusters(), }; } /** * Reap vats that match the filter. * * @param filter - A function that returns true if the vat should be reaped. */ reapVats(filter = () => true) { for (const vatID of this.getVatIds()) { if (filter(vatID)) { __classPrivateFieldGet(this, _Kernel_kernelStore, "f").scheduleReap(vatID); } } } /** * Pin a vat root. * * @param vatId - The ID of the vat. * @returns The KRef of the vat root. */ pinVatRoot(vatId) { const kref = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getRootObject(vatId); if (!kref) { throw new VatNotFoundError(vatId); } __classPrivateFieldGet(this, _Kernel_kernelStore, "f").pinObject(kref); return kref; } /** * Unpin a vat root. * * @param vatId - The ID of the vat. */ unpinVatRoot(vatId) { const kref = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getRootObject(vatId); if (!kref) { throw new VatNotFoundError(vatId); } __classPrivateFieldGet(this, _Kernel_kernelStore, "f").unpinObject(kref); } /** * Ping a vat. * * @param vatId - The ID of the vat. * @returns A promise that resolves to the result of the ping. */ async pingVat(vatId) { const vat = __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_getVat).call(this, vatId); return vat.ping(); } /** * Stop all running vats and reset the kernel state. * This is for debugging purposes only. */ async reset() { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); try { await this.terminateAllVats(); __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_resetKernelState).call(this); } catch (error) { __classPrivateFieldGet(this, _Kernel_logger, "f").error('Error resetting kernel:', error); throw error; } } /** * Terminate all vats and collect garbage. * This is for debugging purposes only. */ async terminateAllVats() { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); for (const id of this.getVatIds().reverse()) { await this.terminateVat(id); this.collectGarbage(); } } /** * Terminate all running vats and reload them. * This is for debugging purposes only. */ async reload() { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); const subclusters = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getSubclusters(); await this.terminateAllVats(); for (const subcluster of subclusters) { await __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").waitForCrank(); const newId = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").addSubcluster(subcluster.config); await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_launchVatsForSubcluster).call(this, newId, subcluster.config); } } /** * Collect garbage. * This is for debugging purposes only. */ collectGarbage() { while (__classPrivateFieldGet(this, _Kernel_kernelStore, "f").nextTerminatedVatCleanup()) { // wait for all vats to be cleaned up } __classPrivateFieldGet(this, _Kernel_kernelStore, "f").collectGarbage(); } registerKernelServiceObject(name, service) { const kref = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").initKernelObject('kernel'); const kernelService = { name, kref, service }; __classPrivateFieldGet(this, _Kernel_kernelServicesByName, "f").set(name, kernelService); __classPrivateFieldGet(this, _Kernel_kernelServicesByObject, "f").set(kref, kernelService); } } _Kernel_commandStream = new WeakMap(), _Kernel_rpcService = new WeakMap(), _Kernel_vats = new WeakMap(), _Kernel_vatWorkerService = new WeakMap(), _Kernel_kernelStore = new WeakMap(), _Kernel_logger = new WeakMap(), _Kernel_kernelQueue = new WeakMap(), _Kernel_kernelRouter = new WeakMap(), _Kernel_kernelServicesByName = new WeakMap(), _Kernel_kernelServicesByObject = new WeakMap(), _Kernel_instances = new WeakSet(), _Kernel_init = /** * Start the kernel running. Sets it up to actually receive command messages * and then begin processing the run queue. */ async function _Kernel_init() { __classPrivateFieldGet(this, _Kernel_commandStream, "f") .drain(__classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_handleCommandMessage).bind(this)) .catch((error) => { __classPrivateFieldGet(this, _Kernel_logger, "f").error('Stream read error:', error); throw new StreamReadError({ kernelId: 'kernel' }, error); }); const starts = []; for (const { vatID, vatConfig } of __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getAllVatRecords()) { starts.push(__classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_runVat).call(this, vatID, vatConfig)); } await Promise.all(starts); __classPrivateFieldGet(this, _Kernel_kernelQueue, "f") .run(__classPrivateFieldGet(this, _Kernel_kernelRouter, "f").deliver.bind(__classPrivateFieldGet(this, _Kernel_kernelRouter, "f"))) .catch((error) => { __classPrivateFieldGet(this, _Kernel_logger, "f").error('Run loop error:', error); throw error; }); }, _Kernel_handleCommandMessage = /** * Handle messages received over the command channel. * * @param message - The message to handle. */ async function _Kernel_handleCommandMessage(message) { try { __classPrivateFieldGet(this, _Kernel_rpcService, "f").assertHasMethod(message.method); const result = await __classPrivateFieldGet(this, _Kernel_rpcService, "f").execute(message.method, message.params); if (hasProperty(message, 'id') && typeof message.id === 'string') { await __classPrivateFieldGet(this, _Kernel_commandStream, "f").write({ id: message.id, jsonrpc: '2.0', result, }); } } catch (error) { __classPrivateFieldGet(this, _Kernel_logger, "f").error('Error executing command', error); if (hasProperty(message, 'id') && typeof message.id === 'string') { await __classPrivateFieldGet(this, _Kernel_commandStream, "f").write({ id: message.id, jsonrpc: '2.0', error: serializeError(error), }); } } }, _Kernel_launchVat = /** * Launches a new vat. * * @param vatConfig - Configuration for the new vat. * @param subclusterId - The ID of the subcluster to launch the vat in. Optional. * @returns a promise for the KRef of the new vat's root object. */ async function _Kernel_launchVat(vatConfig, subclusterId) { const vatId = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").getNextVatId(); await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_runVat).call(this, vatId, vatConfig); __classPrivateFieldGet(this, _Kernel_kernelStore, "f").initEndpoint(vatId); const rootRef = __classPrivateFieldGet(this, _Kernel_kernelStore, "f").exportFromVat(vatId, ROOT_OBJECT_VREF); __classPrivateFieldGet(this, _Kernel_kernelStore, "f").setVatConfig(vatId, vatConfig); if (subclusterId) { __classPrivateFieldGet(this, _Kernel_kernelStore, "f").addSubclusterVat(subclusterId, vatId); } return rootRef; }, _Kernel_runVat = /** * Start a new or resurrected vat running. * * @param vatId - The ID of the vat to start. * @param vatConfig - Its configuration. */ async function _Kernel_runVat(vatId, vatConfig) { if (__classPrivateFieldGet(this, _Kernel_vats, "f").has(vatId)) { throw new VatAlreadyExistsError(vatId); } const stream = await __classPrivateFieldGet(this, _Kernel_vatWorkerService, "f").launch(vatId, vatConfig); const { kernelStream: vatStream, loggerStream } = splitLoggerStream(stream); const vatLogger = __classPrivateFieldGet(this, _Kernel_logger, "f").subLogger({ tags: [vatId] }); vatLogger.injectStream(loggerStream, (error) => __classPrivateFieldGet(this, _Kernel_logger, "f").error(`Vat ${vatId} error: ${stringify(error)}`)); const vat = await VatHandle.make({ vatId, vatConfig, vatStream, kernelStore: __classPrivateFieldGet(this, _Kernel_kernelStore, "f"), kernelQueue: __classPrivateFieldGet(this, _Kernel_kernelQueue, "f"), logger: vatLogger, }); __classPrivateFieldGet(this, _Kernel_vats, "f").set(vatId, vat); }, _Kernel_launchVatsForSubcluster = /** * Launches all vats for a subcluster and sets up their bootstrap connections. * * @param subclusterId - The ID of the subcluster to launch vats for. * @param config - The configuration for the subcluster. * @returns A promise for the (CapData encoded) result of the bootstrap message, if any. */ async function _Kernel_launchVatsForSubcluster(subclusterId, config) { const rootIds = {}; const roots = {}; for (const [vatName, vatConfig] of Object.entries(config.vats)) { const rootRef = await __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_launchVat).call(this, vatConfig, subclusterId); rootIds[vatName] = rootRef; roots[vatName] = kslot(rootRef, 'vatRoot'); } const services = {}; if (config.services) { for (const name of config.services) { const possibleService = __classPrivateFieldGet(this, _Kernel_kernelServicesByName, "f").get(name); if (possibleService) { const { kref } = possibleService; services[name] = kslot(kref); } else { throw Error(`no registered kernel service '${name}'`); } } } const bootstrapRoot = rootIds[config.bootstrap]; if (bootstrapRoot) { const result = await this.queueMessage(bootstrapRoot, 'bootstrap', [ roots, services, ]); const unserialized = kunser(result); if (unserialized instanceof Error) { throw unserialized; } return result; } return undefined; }, _Kernel_stopVat = /** * Stop a vat from running. * * Note that after this operation, the vat will be in a weird twilight zone * between existence and nonexistence, so this operation should only be used * as a component of vat restart (which will push it back into existence) or * vat termination (which will push it all the way into nonexistence). * * @param vatId - The ID of the vat. * @param terminating - If true, the vat is being killed, if false, it's being * restarted. * @param reason - If the vat is being terminated, the reason for the termination. */ async function _Kernel_stopVat(vatId, terminating, reason) { const vat = __classPrivateFieldGet(this, _Kernel_instances, "m", _Kernel_getVat).call(this, vatId); if (!vat) { throw new VatNotFoundError(vatId); } let terminationError; if (reason) { terminationError = new Error(`Vat termination: ${reason.body}`); } else if (terminating) { terminationError = new VatDeletedError(vatId); } await __classPrivateFieldGet(this, _Kernel_vatWorkerService, "f") .terminate(vatId, terminationError) .catch(__classPrivateFieldGet(this, _Kernel_logger, "f").error); await vat.terminate(terminating, terminationError); __classPrivateFieldGet(this, _Kernel_vats, "f").delete(vatId); }, _Kernel_getVat = function _Kernel_getVat(vatId) { const vat = __classPrivateFieldGet(this, _Kernel_vats, "f").get(vatId); if (vat === undefined) { throw new VatNotFoundError(vatId); } return vat; }, _Kernel_resetKernelState = function _Kernel_resetKernelState() { __classPrivateFieldGet(this, _Kernel_kernelStore, "f").clear(); __classPrivateFieldGet(this, _Kernel_kernelStore, "f").reset(); }, _Kernel_invokeKernelService = async function _Kernel_invokeKernelService(target, message) { const kernelService = __classPrivateFieldGet(this, _Kernel_kernelServicesByObject, "f").get(target); if (!kernelService) { throw Error(`no registered service for ${target}`); } const { methargs, result } = message; const [method, args] = kunser(methargs); assert.typeof(method, 'string'); if (result) { assert.typeof(result, 'string'); } // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type const service = kernelService.service; const methodFunction = service[method]; if (methodFunction === undefined) { if (result) { __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").resolvePromises('kernel', [ [result, true, kser(Error(`unknown service method '${method}'`))], ]); } else { __classPrivateFieldGet(this, _Kernel_logger, "f").error(`unknown service method '${method}'`); } return; } assert.typeof(methodFunction, 'function'); assert(Array.isArray(args)); try { // eslint-disable-next-line prefer-spread const resultValue = await methodFunction.apply(null, args); if (result) { __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").resolvePromises('kernel', [ [result, false, kser(resultValue)], ]); } } catch (problem) { if (result) { __classPrivateFieldGet(this, _Kernel_kernelQueue, "f").resolvePromises('kernel', [ [result, true, kser(problem)], ]); } else { __classPrivateFieldGet(this, _Kernel_logger, "f").error('error in kernel service method:', problem); } } }; harden(Kernel); //# sourceMappingURL=Kernel.mjs.map