UNPKG

@metamask/ocap-kernel

Version:
1 lines 15.7 kB
{"version":3,"file":"promise.mjs","sourceRoot":"","sources":["../../../src/store/methods/promise.ts"],"names":[],"mappings":"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","sourcesContent":["import { Fail } from '@endo/errors';\nimport type { CapData } from '@endo/marshal';\n\nimport { getBaseMethods } from './base.ts';\nimport { getQueueMethods } from './queue.ts';\nimport type {\n KRef,\n KernelPromise,\n Message,\n PromiseState,\n RunQueueItemSend,\n VatId,\n} from '../../types.ts';\nimport { insistVatId } from '../../types.ts';\nimport type { StoreContext } from '../types.ts';\nimport { getRefCountMethods } from './refcount.ts';\nimport { makeKernelSlot } from '../utils/kernel-slots.ts';\nimport { parseRef } from '../utils/parse-ref.ts';\nimport { isPromiseRef } from '../utils/promise-ref.ts';\n\n/**\n * Create a promise store object that provides functionality for managing kernel promises.\n *\n * @param ctx - The store context.\n * @returns A promise 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 getPromiseMethods(ctx: StoreContext) {\n const { incCounter, provideStoredQueue, getPrefixedKeys, refCountKey } =\n getBaseMethods(ctx.kv);\n const { enqueueRun } = getQueueMethods(ctx);\n const { decrementRefCount } = getRefCountMethods(ctx);\n\n /**\n * Create a new, unresolved kernel promise. The new promise will be born with\n * a reference count of 1 on the assumption that the promise has just been\n * imported from somewhere.\n *\n * @returns A tuple of the new promise's KRef and an object describing the\n * new promise itself.\n */\n function initKernelPromise(): [KRef, KernelPromise] {\n const kpr: KernelPromise = {\n state: 'unresolved',\n subscribers: [],\n };\n const kpid = getNextPromiseId();\n provideStoredQueue(kpid, false);\n ctx.kv.set(`${kpid}.state`, 'unresolved');\n ctx.kv.set(`${kpid}.subscribers`, '[]');\n ctx.kv.set(refCountKey(kpid), '1');\n // TODO(#562): Use logger instead.\n // eslint-disable-next-line no-console\n console.debug(\n 'initKernelPromise',\n kpid,\n ctx.kv.get(refCountKey(kpid)),\n kpr,\n );\n return [kpid, kpr];\n }\n\n /**\n * Fetch the descriptive record for a kernel promise.\n *\n * @param kpid - The KRef of the kernel promise of interest.\n * @returns An object describing the requested kernel promise.\n */\n function getKernelPromise(kpid: KRef): KernelPromise {\n const { context, isPromise } = parseRef(kpid);\n assert(context === 'kernel' && isPromise);\n const state = ctx.kv.get(`${kpid}.state`) as PromiseState;\n if (state === undefined) {\n throw Error(`unknown kernel promise ${kpid}`);\n }\n const result: KernelPromise = { state };\n switch (state as string) {\n case 'unresolved': {\n const decider = ctx.kv.get(`${kpid}.decider`);\n if (decider !== '' && decider !== undefined) {\n result.decider = decider;\n }\n const subscribers = ctx.kv.getRequired(`${kpid}.subscribers`);\n result.subscribers = JSON.parse(subscribers);\n break;\n }\n case 'fulfilled':\n case 'rejected': {\n result.value = JSON.parse(ctx.kv.getRequired(`${kpid}.value`));\n break;\n }\n default:\n throw Error(`unknown state for ${kpid}: ${state}`);\n }\n return result;\n }\n\n /**\n * Expunge a kernel promise from the kernel's persistent state.\n *\n * @param kpid - The KRef of the kernel promise to delete.\n */\n function deleteKernelPromise(kpid: KRef): void {\n ctx.kv.delete(`${kpid}.state`);\n ctx.kv.delete(`${kpid}.decider`);\n ctx.kv.delete(`${kpid}.subscribers`);\n ctx.kv.delete(`${kpid}.value`);\n ctx.kv.delete(refCountKey(kpid));\n provideStoredQueue(kpid).delete();\n }\n\n /**\n * Obtain a KRef for the next unallocated kernel promise.\n *\n * @returns The next kpid use.\n */\n function getNextPromiseId(): KRef {\n return makeKernelSlot('promise', incCounter(ctx.nextPromiseId));\n }\n\n /**\n * Add a new subscriber to a kernel promise's collection of subscribers.\n *\n * @param vatId - The vat that is subscribing.\n * @param kpid - The KRef of the promise being subscribed to.\n */\n function addPromiseSubscriber(vatId: VatId, kpid: KRef): void {\n insistVatId(vatId);\n const kp = getKernelPromise(kpid);\n kp.state === 'unresolved' ||\n Fail`attempt to add subscriber to resolved promise ${kpid}`;\n const tempSet = new Set(kp.subscribers);\n tempSet.add(vatId);\n const newSubscribers = Array.from(tempSet).sort();\n const key = `${kpid}.subscribers`;\n ctx.kv.set(key, JSON.stringify(newSubscribers));\n }\n\n /**\n * Assign a kernel promise's decider.\n *\n * @param kpid - The KRef of promise whose decider is being set.\n * @param vatId - The vat which will become the decider.\n */\n function setPromiseDecider(kpid: KRef, vatId: VatId): void {\n if (vatId !== 'kernel') {\n insistVatId(vatId);\n }\n if (kpid) {\n ctx.kv.set(`${kpid}.decider`, vatId);\n }\n }\n\n /**\n * Record the resolution of a kernel promise.\n *\n * @param kpid - The ref of the promise being resolved.\n * @param rejected - True if the promise is being rejected, false if fulfilled.\n * @param value - The value the promise is being fulfilled to or rejected with.\n */\n function resolveKernelPromise(\n kpid: KRef,\n rejected: boolean,\n value: CapData<KRef>,\n ): void {\n const queue = provideStoredQueue(kpid, false);\n for (const message of getKernelPromiseMessageQueue(kpid)) {\n const messageItem: RunQueueItemSend = {\n type: 'send',\n target: kpid,\n message,\n };\n enqueueRun(messageItem);\n }\n ctx.kv.set(`${kpid}.state`, rejected ? 'rejected' : 'fulfilled');\n ctx.kv.set(`${kpid}.value`, JSON.stringify(value));\n ctx.kv.delete(`${kpid}.decider`);\n ctx.kv.delete(`${kpid}.subscribers`);\n // Drop the baseline “decider” refcount now that the promise is settled.\n decrementRefCount(kpid, 'resolve|decider');\n queue.delete();\n }\n\n /**\n * Append a message to a promise's message queue.\n *\n * @param kpid - The KRef of the promise to enqueue on.\n * @param message - The message to enqueue.\n */\n function enqueuePromiseMessage(kpid: KRef, message: Message): void {\n provideStoredQueue(kpid, false).enqueue(message);\n }\n\n /**\n * Fetch the messages in a kernel promise's message queue.\n *\n * @param kpid - The KRef of the kernel promise of interest.\n * @returns An array of all the messages in the given promise's message queue.\n */\n function getKernelPromiseMessageQueue(kpid: KRef): Message[] {\n const result: Message[] = [];\n const queue = provideStoredQueue(kpid, false);\n for (;;) {\n const message = queue.dequeue() as Message;\n if (message) {\n result.push(message);\n } else {\n return result;\n }\n }\n }\n /**\n * Generator that yield the promises decided by a given vat.\n *\n * @param decider - The vat ID of the vat of interest.\n *\n * @yields the kpids of all the promises decided by `decider`.\n */\n function* getPromisesByDecider(decider: VatId): Generator<string> {\n const basePrefix = `cle.${decider}.`;\n for (const key of getPrefixedKeys(`${basePrefix}p`)) {\n const kpid = ctx.kv.getRequired(key);\n const kp = getKernelPromise(kpid);\n if (kp.state === 'unresolved' && kp.decider === decider) {\n yield kpid;\n }\n }\n }\n\n /**\n * Given a promise that has just been resolved and the value it resolved to,\n * find all promises reachable (recursively) from the new resolution value\n * which are themselves already resolved. This will determine the set of\n * resolutions that subscribers to the original promise will need to be\n * notified of.\n *\n * This is needed because subscription to a promise carries with it an implied\n * subscription to any promises that appear in its resolution value -- these\n * subscriptions must be implied rather than explicit because they are\n * necessarily unknown at the time of the original promise was subscribed to.\n *\n * @param origKpid - The original promise to start from.\n * @param origValue - The value the original promise is resolved to.\n * @returns An array of the kpids of the promises whose values become visible\n * as a consequence of the resolution of `origKpid`.\n */\n function getKpidsToRetire(origKpid: KRef, origValue: CapData<KRef>): KRef[] {\n const seen = new Set<KRef>();\n const scanPromise = (kpid: KRef, value: CapData<KRef>): void => {\n seen.add(kpid);\n if (value) {\n for (const slot of value.slots) {\n if (isPromiseRef(slot)) {\n if (!seen.has(slot)) {\n const promise = getKernelPromise(slot);\n if (promise.state !== 'unresolved') {\n if (promise.value) {\n scanPromise(slot, promise.value);\n }\n }\n }\n }\n }\n }\n };\n scanPromise(origKpid, origValue);\n return Array.from(seen);\n }\n\n return {\n initKernelPromise,\n getKernelPromise,\n deleteKernelPromise,\n getNextPromiseId,\n addPromiseSubscriber,\n setPromiseDecider,\n resolveKernelPromise,\n enqueuePromiseMessage,\n getKernelPromiseMessageQueue,\n getPromisesByDecider,\n getKpidsToRetire,\n };\n}\n"]}