/** * @file The runtime of an OCapN vat: SES, an OCapN peer, and the vat's own * module (`vat.js`), which exports `buildRootObject(vatPowers, params)`. * * Bundled (see build.js) and loaded as the facet's main module beside the * vat's code. The vat's designator is its id; it reaches other peers, and * they reach it, through the vatAdmin's router (`env.router`). */ import "@endo/init"; import { DurableObject } from "cloudflare:workers"; import { E, Far } from "@endo/far"; import { makeClient } from "@endo/ocapn"; import { makeRpcNetLayer } from "./netlayer.js"; import * as vat from "./vat.js"; /** * The swissnum of a vat's bootstrap: the vatAdmin starts the vat through it. * Not exported: workerd takes every export of a main module for an entrypoint. */ const VAT_SWISSNUM = "vat"; export class App extends DurableObject { #gateway; constructor(ctx, env) { super(ctx, env); this.#gateway = this.#boot(); } async #boot() { const { vatId, router } = this.env; let root; const vatPowers = Object.freeze({ E, Far, storage: this.ctx.storage.kv }); const bootstrap = Far("vatBootstrap", { start: (params) => { root ??= vat.buildRootObject(vatPowers, params); return root; }, }); // workerd runs FinalizationRegistry callbacks outside any request, where // sending the resulting GC message is forbidden I/O. So imports are // never collected here; they go when their session does. const ocapn = makeClient({ debugLabel: vatId.slice(0, 8), swissnumTable: new Map([[VAT_SWISSNUM, bootstrap]]), enableImportCollection: false, }); const netlayer = await ocapn.registerNetlayer( makeRpcNetLayer({ designator: vatId, openGateway: (designator) => router.gateway(designator) }), ); return netlayer.gateway; } /** This vat's OCapN gateway, for the router. */ gateway() { return this.#gateway; } }