@metamask/ocap-kernel
Version:
OCap kernel core components
72 lines • 3.03 kB
JavaScript
import { insistVatSyscallObject, insistVatSyscallResult } from "@agoric/swingset-liveslots";
/**
* This returns a function that is provided to liveslots as the 'syscall'
* argument: an object with one method per syscall type. These methods return
* data, or nothing. If the kernel experiences a problem executing the syscall,
* the method will throw, or the kernel will kill the vat, or both.
*
* I should be given a `syscallToManager` function that accepts a
* VatSyscallObject and (synchronously) returns a VatSyscallResult.
*
* @param supervisor - The VatSupervisor for which we're providing syscall services.
* @param kv - A key/value store for holding the vat's persistent state.
*
* @returns a syscall object suitable for use by liveslots.
*/
function makeSupervisorSyscall(supervisor, kv) {
/**
* Actually perform the syscall operation.
*
* @param vso - A descriptor for the syscall to be performed.
* @returns the result from performing the syscall.
*/
function doSyscall(vso) {
insistVatSyscallObject(vso);
let syscallResult;
try {
syscallResult = supervisor.executeSyscall(vso);
}
catch (problem) {
console.warn(`supervisor got error during syscall:`, problem);
throw problem;
}
const vsr = syscallResult;
insistVatSyscallResult(vsr);
const [type, ...rest] = vsr;
switch (type) {
case 'ok': {
const [data] = rest;
return data;
}
case 'error': {
const [problem] = rest;
throw Error(`syscall.${vso[0]} failed: ${problem}`);
}
default:
throw Error(`unknown result type ${type}`);
}
}
// this will be given to liveslots, it should have distinct methods that
// return immediate results or throw errors
const syscallForVat = {
send: (target, methargs, result) => doSyscall(['send', target, { methargs, result }]),
subscribe: (vpid) => doSyscall(['subscribe', vpid]),
resolve: (resolutions) => doSyscall(['resolve', resolutions]),
exit: (isFailure, info) => doSyscall(['exit', isFailure, info]),
dropImports: (vrefs) => doSyscall(['dropImports', vrefs]),
retireImports: (vrefs) => doSyscall(['retireImports', vrefs]),
retireExports: (vrefs) => doSyscall(['retireExports', vrefs]),
abandonExports: (vrefs) => doSyscall(['abandonExports', vrefs]),
callNow: (_target, _method, _args) => {
throw Error(`callNow not supported (we have no devices)`);
},
vatstoreGet: (key) => kv.get(key),
vatstoreGetNextKey: (priorKey) => kv.getNextKey(priorKey),
vatstoreSet: (key, value) => kv.set(key, value),
vatstoreDelete: (key) => kv.delete(key),
};
return harden(syscallForVat);
}
harden(makeSupervisorSyscall);
export { makeSupervisorSyscall };
//# sourceMappingURL=syscall.mjs.map