@agoric/swingset-vat 0.32.3-dev-9dfa568.0 → 0.32.3-dev-b8d96c7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/swingset-vat",
3
- "version": "0.32.3-dev-9dfa568.0+9dfa568",
3
+ "version": "0.32.3-dev-b8d96c7.0+b8d96c7",
4
4
  "description": "Vat/Container Launcher",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -27,15 +27,15 @@
27
27
  "@types/yargs-parser": "^21.0.0"
28
28
  },
29
29
  "dependencies": {
30
- "@agoric/internal": "0.3.3-dev-9dfa568.0+9dfa568",
31
- "@agoric/kmarshal": "0.1.1-dev-9dfa568.0+9dfa568",
32
- "@agoric/store": "0.9.3-dev-9dfa568.0+9dfa568",
33
- "@agoric/swing-store": "0.9.2-dev-9dfa568.0+9dfa568",
34
- "@agoric/swingset-liveslots": "0.10.3-dev-9dfa568.0+9dfa568",
35
- "@agoric/swingset-xsnap-supervisor": "0.10.3-dev-9dfa568.0+9dfa568",
36
- "@agoric/time": "0.3.3-dev-9dfa568.0+9dfa568",
37
- "@agoric/vat-data": "0.5.3-dev-9dfa568.0+9dfa568",
38
- "@agoric/xsnap-lockdown": "0.14.1-dev-9dfa568.0+9dfa568",
30
+ "@agoric/internal": "0.3.3-dev-b8d96c7.0+b8d96c7",
31
+ "@agoric/kmarshal": "0.1.1-dev-b8d96c7.0+b8d96c7",
32
+ "@agoric/store": "0.9.3-dev-b8d96c7.0+b8d96c7",
33
+ "@agoric/swing-store": "0.9.2-dev-b8d96c7.0+b8d96c7",
34
+ "@agoric/swingset-liveslots": "0.10.3-dev-b8d96c7.0+b8d96c7",
35
+ "@agoric/swingset-xsnap-supervisor": "0.10.3-dev-b8d96c7.0+b8d96c7",
36
+ "@agoric/time": "0.3.3-dev-b8d96c7.0+b8d96c7",
37
+ "@agoric/vat-data": "0.5.3-dev-b8d96c7.0+b8d96c7",
38
+ "@agoric/xsnap-lockdown": "0.14.1-dev-b8d96c7.0+b8d96c7",
39
39
  "@endo/base64": "^1.0.9",
40
40
  "@endo/bundle-source": "^3.5.1",
41
41
  "@endo/captp": "^4.4.4",
@@ -102,5 +102,5 @@
102
102
  "typeCoverage": {
103
103
  "atLeast": 76.28
104
104
  },
105
- "gitHead": "9dfa5685ac8f60d31802589777b0dbadc8efb8c9"
105
+ "gitHead": "b8d96c7314cc9edd47b960876f23a88c18f70070"
106
106
  }
@@ -100,7 +100,6 @@ export async function initializeKernel(config, kernelStorage, options = {}) {
100
100
  // the VatManager, since it isn't available until the bundle is evaluated
101
101
  assertKnownOptions(creationOptions, [
102
102
  'enablePipelining',
103
- 'metered',
104
103
  'managerType',
105
104
  'enableDisavow',
106
105
  'enableSetup',
@@ -442,26 +442,24 @@ export async function initializeSwingset(
442
442
  * The host application gives us
443
443
  * config.[vats|devices].NAME.[bundle|bundleSpec|sourceSpec|bundleName] .
444
444
  * The 'bundleName' option points into
445
- * config.bundles.BUNDLENAME.[bundle|bundleSpec|sourceSpec] , which can
445
+ * config.bundles.BUNDLENAME.[bundle|bundleSpec|sourceSpec], which can
446
446
  * also include arbitrary named bundles that will be made available to
447
- * E(vatAdminService).getNamedBundleCap(bundleName) ,and temporarily as
447
+ * E(vatAdminService).getNamedBundleCap(bundleName), and temporarily as
448
448
  * E(vatAdminService).createVatByName(bundleName)
449
449
  *
450
450
  * The 'kconfig' we pass through to initializeKernel has
451
451
  * kconfig.[vats|devices].NAME.bundleID and
452
- * kconfig.namedBundleIDs.BUNDLENAME=bundleID , which both point into
452
+ * kconfig.namedBundleIDs.BUNDLENAME=bundleID, which both point into
453
453
  * kconfig.idToBundle.BUNDLEID=bundle
454
454
  *
455
- * @param {SwingSetConfigProperties | { bundleName: string }} desc
455
+ * @param {SwingSetConfigProperties} desc
456
456
  * @param {Record<string, *>} [nameToBundle]
457
457
  */
458
458
  async function getBundle(desc, nameToBundle) {
459
459
  trace(
460
460
  'getBundle',
461
461
  Object.keys(desc),
462
- // @ts-expect-error optional
463
462
  desc.moduleFormat,
464
- // @ts-expect-error optional
465
463
  desc.endoZipBase64Sha512 || desc.sourceSpec,
466
464
  );
467
465
 
@@ -489,8 +487,9 @@ export async function initializeSwingset(
489
487
  throw Error(`unknown mode in desc`, desc);
490
488
  }
491
489
 
492
- // fires with BundleWithID: { ...bundle, id }
493
490
  /**
491
+ * Returns a bundle record with an "id" property from an input that might be missing it.
492
+ *
494
493
  * @param {EndoZipBase64Bundle & {id?: string}} bundle
495
494
  * @returns {Promise<EndoZipBase64Bundle & {id: string}>} bundle
496
495
  */
@@ -508,11 +507,9 @@ export async function initializeSwingset(
508
507
  };
509
508
  }
510
509
 
511
- // fires with BundleWithID: { ...bundle, id }
512
-
513
510
  /**
514
511
  *
515
- * @param {(SwingSetConfigProperties | { bundleName: string }) & {bundleID?: string }} desc
512
+ * @param {SwingSetConfigProperties & {bundleID?: string}} desc
516
513
  * @param {Record<string, EndoZipBase64Bundle>} [nameToBundle]
517
514
  */
518
515
  async function processDesc(desc, nameToBundle) {
@@ -526,14 +523,14 @@ export async function initializeSwingset(
526
523
  modes.length === 1 ||
527
524
  Fail`need =1 of bundle/bundleSpec/sourceSpec/bundleName, got ${modes}`;
528
525
  const mode = modes[0];
529
- return getBundle(desc, nameToBundle)
530
- .then(addBundleID)
531
- .then(bundleWithID => {
532
- // replace original .sourceSpec/etc with a uniform .bundleID
533
- delete desc[mode];
534
- desc.bundleID = bundleWithID.id;
535
- return bundleWithID;
536
- });
526
+
527
+ // Remove the original mode in favor of a uniform "bundleID" property.
528
+ const bundle = await getBundle(desc, nameToBundle);
529
+ const bundleWithID = await addBundleID(bundle);
530
+ delete desc[mode];
531
+ desc.bundleID = bundleWithID.id;
532
+
533
+ return bundleWithID;
537
534
  }
538
535
 
539
536
  /**
@@ -32,16 +32,15 @@ function makeSupervisorDispatch(dispatch) {
32
32
  async function dispatchToVat(delivery) {
33
33
  // the (low-level) vat is responsible for giving up agency, but we still
34
34
  // protect against exceptions
35
- return Promise.resolve(delivery)
36
- .then(dispatch)
37
- .then(
38
- res => harden(['ok', res, null]),
39
- err => {
40
- // TODO react more thoughtfully, maybe terminate the vat
41
- console.warn(`error during vat dispatch() of ${delivery}`, err);
42
- return harden(['error', `${err}`, null]);
43
- },
44
- );
35
+ await null;
36
+ try {
37
+ const res = await dispatch(delivery);
38
+ return harden(['ok', res, null]);
39
+ } catch (err) {
40
+ // TODO react more thoughtfully, maybe terminate the vat
41
+ console.warn(`error during vat dispatch() of ${delivery}`, err);
42
+ return harden(['error', `${err}`, null]);
43
+ }
45
44
  }
46
45
 
47
46
  return harden(dispatchToVat);
package/src/typeGuards.js CHANGED
@@ -10,38 +10,40 @@ export const ManagerType = M.or(
10
10
 
11
11
  const Bundle = M.splitRecord({ moduleType: M.string() });
12
12
 
13
- const SwingsetConfigOptions = {
13
+ const VatConfigOptions = harden({
14
14
  creationOptions: M.splitRecord({}, { critical: M.boolean() }),
15
15
  parameters: M.recordOf(M.string(), M.any()),
16
- };
17
- harden(SwingsetConfigOptions);
16
+ });
18
17
 
19
- const SwingSetConfigProperties = M.or(
20
- M.splitRecord({ sourceSpec: M.string() }, SwingsetConfigOptions),
21
- M.splitRecord({ bundleSpec: M.string() }, SwingsetConfigOptions),
22
- M.splitRecord({ bundle: Bundle }, SwingsetConfigOptions),
23
- );
24
- const SwingSetConfigDescriptor = M.recordOf(
25
- M.string(),
26
- SwingSetConfigProperties,
27
- );
18
+ const makeSwingSetConfigProperties = (required = {}, optional = {}, rest) =>
19
+ M.or(
20
+ M.splitRecord({ sourceSpec: M.string(), ...required }, optional, rest),
21
+ M.splitRecord({ bundleSpec: M.string(), ...required }, optional, rest),
22
+ M.splitRecord({ bundle: Bundle, ...required }, optional, rest),
23
+ );
24
+ const makeSwingSetConfigDescriptor = (required, optional, rest) =>
25
+ M.recordOf(
26
+ M.string(),
27
+ makeSwingSetConfigProperties(required, optional, rest),
28
+ );
28
29
 
29
30
  /**
30
31
  * NOTE: this pattern suffices for PSM bootstrap,
31
32
  * but does not cover the whole SwingSet config syntax.
32
33
  *
33
34
  * {@link ./docs/configuration.md}
34
- * TODO: move this to swingset?
35
35
  *
36
36
  * @see SwingSetConfig
37
37
  * in ./types-external.js
38
38
  */
39
- export const SwingSetConfig = M.and(
40
- M.splitRecord({}, { defaultManagerType: ManagerType }),
41
- M.splitRecord({}, { includeDevDependencies: M.boolean() }),
42
- M.splitRecord({}, { defaultReapInterval: M.number() }), // not in type decl
43
- M.splitRecord({}, { snapshotInterval: M.number() }),
44
- M.splitRecord({}, { vats: SwingSetConfigDescriptor }),
45
- M.splitRecord({}, { bootstrap: M.string() }),
46
- M.splitRecord({}, { bundles: SwingSetConfigDescriptor }),
39
+ export const SwingSetConfig = M.splitRecord(
40
+ { vats: makeSwingSetConfigDescriptor(undefined, VatConfigOptions) },
41
+ {
42
+ defaultManagerType: ManagerType,
43
+ includeDevDependencies: M.boolean(),
44
+ defaultReapInterval: M.number(),
45
+ snapshotInterval: M.number(),
46
+ bootstrap: M.string(),
47
+ bundles: makeSwingSetConfigDescriptor(undefined, undefined, {}),
48
+ },
47
49
  );
@@ -154,27 +154,25 @@ export {};
154
154
  */
155
155
 
156
156
  /**
157
+ * @typedef {{ bundle: Bundle }} BundleRef a bundle object
158
+ * @typedef {{ bundleName: string }} BundleName a name identifying a property in the `bundles` of a SwingSetOptions object
159
+ * @typedef {{ bundleSpec: string }} BundleSpec a path to a bundle file
160
+ * @typedef {{ sourceSpec: string }} SourceSpec a package specifier such as "@agoric/swingset-vat/tools/vat-puppet.js"
161
+ *
157
162
  * @typedef {{
158
- * sourceSpec: string // path to pre-bundled root
159
- * }} SourceSpec
160
- * @typedef {{
161
- * bundleSpec: string // path to bundled code
162
- * }} BundleSpec
163
- * @typedef {{
164
- * bundle: Bundle
165
- * }} BundleRef
166
- * @typedef {{
167
- * bundleName: string
168
- * }} BundleName
169
- * @typedef {(SourceSpec | BundleSpec | BundleRef | BundleName ) & {
170
163
  * bundleID?: BundleID,
171
- * creationOptions?: Record<string, any>,
164
+ * creationOptions?: StaticVatOptions,
172
165
  * parameters?: Record<string, any>,
173
- * }} SwingSetConfigProperties
166
+ * }} VatConfigOptions
167
+ */
168
+ /**
169
+ * @template [Fields=object]
170
+ * @typedef {(SourceSpec | BundleSpec | BundleName | BundleRef) & Fields} SwingSetConfigProperties
174
171
  */
175
172
 
176
173
  /**
177
- * @typedef {Record<string, SwingSetConfigProperties>} SwingSetConfigDescriptor
174
+ * @template [Fields=object]
175
+ * @typedef {Record<string, SwingSetConfigProperties<Fields>>} SwingSetConfigDescriptor
178
176
  * Where the property name is the name of the vat. Note that
179
177
  * the `bootstrap` property names the vat that should be used as the bootstrap vat. Although a swingset
180
178
  * configuration can designate any vat as its bootstrap vat, `loadBasedir` will always look for a file named
@@ -188,7 +186,7 @@ export {};
188
186
  * `devDependencies` of the surrounding `package.json` should be accessible to
189
187
  * bundles.
190
188
  * @property {string} [bundleCachePath] if present, SwingSet will use a bundle cache at this path
191
- * @property {SwingSetConfigDescriptor} vats
189
+ * @property {SwingSetConfigDescriptor<VatConfigOptions>} vats
192
190
  * @property {SwingSetConfigDescriptor} [bundles]
193
191
  * @property {BundleFormat} [bundleFormat] the bundle source / import bundle
194
192
  * format.
@@ -206,7 +204,7 @@ export {};
206
204
  */
207
205
 
208
206
  /**
209
- * @typedef {{ bundleName: string} | { bundle: Bundle } | { bundleID: BundleID } } SourceOfBundle
207
+ * @typedef {BundleName | BundleRef | {bundleID: BundleID}} SourceOfBundle
210
208
  */
211
209
  /**
212
210
  * @typedef { import('@agoric/swing-store').KVStore } KVStore
@@ -295,12 +293,8 @@ export {};
295
293
  * Vat Creation and Management
296
294
  *
297
295
  * @typedef { string } BundleID
298
- * @typedef {any} BundleCap
296
+ * @typedef { any } BundleCap
299
297
  * @typedef { { moduleFormat: 'endoZipBase64', endoZipBase64: string, endoZipBase64Sha512: string } } EndoZipBase64Bundle
300
- *
301
- * @typedef { unknown } Meter
302
- *
303
- * E(vatAdminService).createVat(bundle, options: DynamicVatOptions)
304
298
  */
305
299
 
306
300
  /**
@@ -326,8 +320,6 @@ export {};
326
320
  * types are then defined as amendments to this base type.
327
321
  *
328
322
  * @typedef { object } BaseVatOptions
329
- * @property { string } name
330
- * @property { * } [vatParameters]
331
323
  * @property { boolean } [enableSetup]
332
324
  * If true, permits the vat to construct itself using the
333
325
  * `setup()` API, which bypasses the imposition of LiveSlots but
@@ -346,6 +338,10 @@ export {};
346
338
  * outbound syscalls so that the vat's internal state can be
347
339
  * reconstructed via replay. If false, no such record is kept.
348
340
  * Defaults to true.
341
+ * @property { ManagerType } [managerType]
342
+ * @property { boolean } [neverReap]
343
+ * If true, disables automatic bringOutYourDead deliveries to a vat.
344
+ * Defaults to false.
349
345
  * @property { number | 'never' } [reapInterval]
350
346
  * Trigger a bringOutYourDead after the vat has received
351
347
  * this many deliveries. If the value is 'never',
@@ -360,7 +356,7 @@ export {};
360
356
  */
361
357
 
362
358
  /**
363
- * @typedef { { meter?: Meter } } OptMeter
359
+ * @typedef { { meter?: unknown } } OptMeter
364
360
  * If a meter is provided, the new dynamic vat is limited to a fixed
365
361
  * amount of computation and allocation that can occur during any
366
362
  * given crank. Peak stack frames are limited as well. In addition,
@@ -370,14 +366,13 @@ export {};
370
366
  * terminated. If undefined, the vat is unmetered. Static vats
371
367
  * cannot be metered.
372
368
  *
373
- * @typedef { { managerType?: ManagerType } } OptManagerType
374
- * @typedef { BaseVatOptions & OptMeter & OptManagerType } DynamicVatOptions
369
+ * @typedef { BaseVatOptions & { name: string, vatParameters?: object } & OptMeter } DynamicVatOptions
375
370
  *
376
371
  * config.vats[name].creationOptions: StaticVatOptions
377
372
  *
378
373
  * @typedef { { enableDisavow?: boolean } } OptEnableDisavow
379
374
  * @typedef { { nodeOptions?: string[] } } OptNodeOptions
380
- * @typedef { BaseVatOptions & OptManagerType & OptEnableDisavow & OptNodeOptions } StaticVatOptions
375
+ * @typedef { BaseVatOptions & OptEnableDisavow & OptNodeOptions } StaticVatOptions
381
376
  *
382
377
  * @typedef { { vatParameters?: object, upgradeMessage?: string } } VatUpgradeOptions
383
378
  * @typedef { { incarnationNumber: number } } VatUpgradeResults
@@ -29,7 +29,6 @@ export {};
29
29
  * @typedef { string } MeterID
30
30
  * @typedef { { meterID?: MeterID } } OptMeterID
31
31
  * @typedef { import('./types-external.js').BaseVatOptions } BaseVatOptions
32
- * @typedef { import('./types-external.js').OptManagerType } OptManagerType
33
32
  * @typedef { import('@agoric/swingset-liveslots').VatDeliveryObject } VatDeliveryObject
34
33
  * @typedef { import('@agoric/swingset-liveslots').VatDeliveryResult } VatDeliveryResult
35
34
  * @typedef { import('@agoric/swingset-liveslots').VatSyscallObject } VatSyscallObject
@@ -38,7 +37,7 @@ export {};
38
37
  *
39
38
  * // used by vatKeeper.setSourceAndOptions(source, RecordedVatOptions)
40
39
  *
41
- * @typedef { BaseVatOptions & OptMeterID & OptManagerType } InternalDynamicVatOptions
40
+ * @typedef { BaseVatOptions & OptMeterID } InternalDynamicVatOptions
42
41
  *
43
42
  * RecordedVatOptions is fully-specified, no optional fields
44
43
  *
@@ -53,10 +53,25 @@ export const makeRunUtils = (controller, harness) => {
53
53
  };
54
54
 
55
55
  /**
56
- * @typedef {import('@endo/eventual-send').EProxy & {
57
- * sendOnly: (presence: unknown) => Record<string, (...args: any) => void>;
58
- * vat: (name: string) => Record<string, (...args: any) => Promise<any>>;
59
- * }} EVProxy
56
+ * @typedef {import('@endo/eventual-send').EProxy | object} EVProxyMethods
57
+ * @property {(presence: unknown) => Record<string, (...args: any) => Promise<void>>} sendOnly
58
+ * Returns a "methods proxy" for the presence that ignores the results of
59
+ * each method invocation.
60
+ * @property {(name: string) => Record<string, (...args: any) => Promise<any>>} vat
61
+ * Returns a "methods proxy" for the root object of the specified vat.
62
+ * So e.g. `EV.vat('foo').m(0)` becomes
63
+ * `controller.queueToVatRoot('foo', 'm', [0])`.
64
+ * @property {(presence: unknown) => Record<string, Promise<any>>} get
65
+ * Returns a "values proxy" for the presence for which each requested
66
+ * property manifests as a promise.
67
+ */
68
+ /**
69
+ * @typedef {import('@endo/eventual-send').EProxy & EVProxyMethods} EVProxy
70
+ * Given a presence, return a "methods proxy" for which each requested
71
+ * property manifests as a method that forwards its invocation through the
72
+ * controller to the presence as an invocation of an identically-named method
73
+ * with identical arguments (modulo passable translation).
74
+ * So e.g. `EV(x).m(0)` becomes `controller.queueToVatObject(x, 'm', [0])`.
60
75
  */
61
76
 
62
77
  // IMPORTANT WARNING TO USERS OF `EV`
@@ -103,50 +118,26 @@ export const makeRunUtils = (controller, harness) => {
103
118
  // promise that can remain pending indefinitely, possibly to be settled by a
104
119
  // future message delivery.
105
120
 
121
+ const makeMethodsProxy = (invoker, target, voidResult = false) =>
122
+ new Proxy(harden({}), {
123
+ get: (_t, method, _rx) => {
124
+ const boundMethod = (...args) =>
125
+ queueAndRun(() => invoker(target, method, args), voidResult);
126
+ return harden(boundMethod);
127
+ },
128
+ });
129
+
106
130
  /** @type {EVProxy} */
107
- // @ts-expect-error cast, approximate
108
131
  const EV = Object.assign(
109
- presence =>
110
- new Proxy(harden({}), {
111
- get: (_t, method, _rx) => {
112
- const boundMethod = (...args) =>
113
- queueAndRun(() =>
114
- controller.queueToVatObject(presence, method, args),
115
- );
116
- return harden(boundMethod);
117
- },
118
- }),
132
+ presence => makeMethodsProxy(controller.queueToVatObject, presence),
119
133
  {
120
- vat: vatName =>
121
- new Proxy(harden({}), {
122
- get: (_t, method, _rx) => {
123
- const boundMethod = (...args) =>
124
- queueAndRun(() =>
125
- controller.queueToVatRoot(vatName, method, args),
126
- );
127
- return harden(boundMethod);
128
- },
129
- }),
134
+ vat: vatName => makeMethodsProxy(controller.queueToVatRoot, vatName),
130
135
  sendOnly: presence =>
131
- new Proxy(harden({}), {
132
- get: (_t, method, _rx) => {
133
- const boundMethod = (...args) =>
134
- queueAndRun(
135
- () => controller.queueToVatObject(presence, method, args),
136
- true,
137
- );
138
- return harden(boundMethod);
139
- },
140
- }),
136
+ makeMethodsProxy(controller.queueToVatObject, presence, true),
141
137
  get: presence =>
142
138
  new Proxy(harden({}), {
143
- get: (_t, pathElement, _rx) =>
144
- queueAndRun(() =>
145
- controller.queueToVatRoot('bootstrap', 'awaitVatObject', [
146
- presence,
147
- [pathElement],
148
- ]),
149
- ),
139
+ get: (_t, key, _rx) =>
140
+ EV.vat('bootstrap').awaitVatObject(presence, [key]),
150
141
  }),
151
142
  },
152
143
  );