@metamask/ocap-kernel
Version:
OCap kernel core components
1 lines • 9.61 kB
Source Map (JSON)
{"version":3,"file":"refcount.cjs","sourceRoot":"","sources":["../../../src/store/methods/refcount.ts"],"names":[],"mappings":"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","sourcesContent":["import { Fail } from '@endo/errors';\n\nimport { getObjectMethods } from './object.ts';\nimport type { KRef } from '../../types.ts';\nimport type { StoreContext } from '../types.ts';\nimport { getBaseMethods } from './base.ts';\nimport { parseRef } from '../utils/parse-ref.ts';\n\n/**\n * Create a refcount store object that provides functionality for managing reference counts.\n *\n * @param ctx - The store context.\n * @returns A refcount store object that maps various persistent kernel data\n * structures onto `kv`.\n */\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nexport function getRefCountMethods(ctx: StoreContext) {\n const { refCountKey } = getBaseMethods(ctx.kv);\n const { getObjectRefCount, setObjectRefCount } = getObjectMethods(ctx);\n\n /**\n * Get a promise's reference count.\n *\n * @param kref - The KRef of the promise of interest.\n * @returns the reference count of the indicated promise.\n */\n function getRefCount(kref: KRef): number {\n return Number(ctx.kv.get(refCountKey(kref)));\n }\n\n /**\n * Check if a kernel object exists in the kernel's persistent state.\n *\n * @param kref - The KRef of the kernel object in question.\n * @returns True if the kernel object exists, false otherwise.\n */\n function kernelRefExists(kref: KRef): boolean {\n return Boolean(ctx.kv.get(refCountKey(kref)));\n }\n\n /**\n * Increment a promise's reference count.\n *\n * @param kref - The KRef of the promise to increment the ref count of.\n * @returns the new reference count after incrementing.\n */\n function incRefCount(kref: KRef): number {\n const key = refCountKey(kref);\n const newCount = Number(ctx.kv.get(key)) + 1;\n ctx.kv.set(key, `${newCount}`);\n return newCount;\n }\n\n /**\n * Decrement a promise's reference count.\n *\n * @param kref - The KRef of the promise to decrement the ref count of.\n * @returns the new reference count after decrementing.\n */\n function decRefCount(kref: KRef): number {\n const key = refCountKey(kref);\n const newCount = Number(ctx.kv.get(key)) - 1;\n ctx.kv.set(key, `${newCount}`);\n return newCount;\n }\n\n /**\n * Increment the reference count associated with some kernel object.\n *\n * We track references to promises and objects, but not devices. Promises\n * have only a \"reachable\" count, whereas objects track both \"reachable\"\n * and \"recognizable\" counts.\n *\n * @param kref - The kernel slot whose refcount is to be incremented.\n * @param tag - The tag of the kernel slot.\n * @param options - Options for the increment.\n * @param options.isExport - True if the reference comes from a clist export, which counts for promises but not objects.\n * @param options.onlyRecognizable - True if the reference provides only recognition, not reachability.\n */\n function incrementRefCount(\n kref: KRef,\n tag: string,\n {\n isExport = false,\n onlyRecognizable = false,\n }: { isExport?: boolean; onlyRecognizable?: boolean } = {},\n ): void {\n kref || Fail`incrementRefCount called with empty kref`;\n\n const { isPromise } = parseRef(kref);\n if (isPromise) {\n const refCount = Number(ctx.kv.get(refCountKey(kref))) + 1;\n ctx.logger?.debug('++', refCountKey(kref), refCount, tag);\n ctx.kv.set(refCountKey(kref), `${refCount}`);\n return;\n }\n\n // If `isExport` the reference comes from a clist export, which counts for promises but not objects\n if (isExport) {\n return;\n }\n\n const counts = getObjectRefCount(kref);\n if (!onlyRecognizable) {\n counts.reachable += 1;\n }\n counts.recognizable += 1;\n ctx.logger?.debug('++', refCountKey(kref), JSON.stringify(counts), tag);\n setObjectRefCount(kref, counts);\n }\n\n /**\n * Decrement the reference count associated with some kernel object.\n *\n * @param kref - The kernel slot whose refcount is to be decremented.\n * @param tag - The tag of the kernel slot.\n * @param options - Options for the decrement.\n * @param options.isExport - True if the reference comes from a clist export, which counts for promises but not objects.\n * @param options.onlyRecognizable - True if the reference provides only recognition, not reachability.\n * @returns True if the reference count has been decremented to zero, false if it is still non-zero.\n * @throws if this tries to decrement the reference count below zero.\n */\n function decrementRefCount(\n kref: KRef,\n tag: string,\n {\n isExport = false,\n onlyRecognizable = false,\n }: { isExport?: boolean; onlyRecognizable?: boolean } = {},\n ): boolean {\n kref || Fail`decrementRefCount called with empty kref`;\n\n const { isPromise } = parseRef(kref);\n if (isPromise) {\n let refCount = Number(ctx.kv.get(refCountKey(kref)));\n ctx.logger?.debug('--', refCountKey(kref), refCount - 1, tag);\n refCount > 0 || Fail`refCount underflow ${kref}`;\n refCount -= 1;\n ctx.kv.set(refCountKey(kref), `${refCount}`);\n if (refCount === 0) {\n ctx.maybeFreeKrefs.add(kref);\n return true;\n }\n return false;\n }\n\n if (isExport || !kernelRefExists(kref)) {\n return false;\n }\n\n const counts = getObjectRefCount(kref);\n if (!onlyRecognizable) {\n counts.reachable -= 1;\n }\n counts.recognizable -= 1;\n if (!counts.reachable || !counts.recognizable) {\n ctx.maybeFreeKrefs.add(kref);\n }\n ctx.logger?.debug('--', refCountKey(kref), JSON.stringify(counts), tag);\n setObjectRefCount(kref, counts);\n ctx.kv.set('initialized', 'true');\n return false;\n }\n\n return {\n getRefCount,\n kernelRefExists,\n incRefCount,\n decRefCount,\n incrementRefCount,\n decrementRefCount,\n };\n}\n"]}