@agoric/swingset-liveslots 0.10.3-u13.0 → 0.10.3-u16.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.
Files changed (60) hide show
  1. package/README.md +2 -0
  2. package/package.json +27 -19
  3. package/src/cache.js +2 -1
  4. package/src/capdata.js +0 -1
  5. package/src/collectionManager.js +154 -72
  6. package/src/index.js +4 -1
  7. package/src/liveslots.js +52 -81
  8. package/src/message.js +4 -4
  9. package/src/types.js +8 -2
  10. package/src/vatDataTypes.d.ts +271 -0
  11. package/src/vatDataTypes.js +2 -0
  12. package/src/vatstore-iterators.js +2 -0
  13. package/src/virtualObjectManager.js +189 -70
  14. package/src/virtualReferences.js +51 -0
  15. package/src/watchedPromises.js +61 -16
  16. package/test/{test-baggage.js → baggage.test.js} +1 -2
  17. package/test/{test-cache.js → cache.test.js} +0 -1
  18. package/test/{test-collection-schema-refcount.js → collection-schema-refcount.test.js} +1 -2
  19. package/test/{test-collection-upgrade.js → collection-upgrade.test.js} +1 -3
  20. package/test/{test-collections.js → collections.test.js} +117 -14
  21. package/test/{test-dropped-collection-weakrefs.js → dropped-collection-weakrefs.test.js} +1 -2
  22. package/test/{test-durabilityChecks.js → durabilityChecks.test.js} +3 -3
  23. package/test/{test-facetiousness.js → facetiousness.test.js} +1 -2
  24. package/test/gc-and-finalize.js +30 -1
  25. package/test/gc-helpers.js +2 -3
  26. package/test/{test-gc-sensitivity.js → gc-sensitivity.test.js} +2 -2
  27. package/test/{test-handled-promises.js → handled-promises.test.js} +5 -7
  28. package/test/{test-initial-vrefs.js → initial-vrefs.test.js} +2 -3
  29. package/test/liveslots-helpers.js +6 -6
  30. package/test/{test-liveslots-mock-gc.js → liveslots-mock-gc.test.js} +2 -2
  31. package/test/{test-liveslots-real-gc.js → liveslots-real-gc.test.js} +44 -35
  32. package/test/{test-liveslots.js → liveslots.test.js} +13 -14
  33. package/test/mock-gc.js +1 -0
  34. package/test/storeGC/{test-lifecycle.js → lifecycle.test.js} +2 -2
  35. package/test/storeGC/{test-refcount-management.js → refcount-management.test.js} +1 -2
  36. package/test/storeGC/{test-scalar-store-kind.js → scalar-store-kind.test.js} +0 -1
  37. package/test/storeGC/{test-weak-key.js → weak-key.test.js} +1 -2
  38. package/test/util.js +2 -2
  39. package/test/vat-util.js +1 -1
  40. package/test/virtual-objects/{test-cease-recognition.js → cease-recognition.test.js} +2 -2
  41. package/test/virtual-objects/{test-cross-facet.js → cross-facet.test.js} +5 -4
  42. package/test/virtual-objects/{test-empty-data.js → empty-data.test.js} +1 -2
  43. package/test/virtual-objects/{test-facets.js → facets.test.js} +1 -2
  44. package/test/virtual-objects/{test-kind-changes.js → kind-changes.test.js} +2 -2
  45. package/test/virtual-objects/{test-reachable-vrefs.js → reachable-vrefs.test.js} +2 -2
  46. package/test/virtual-objects/{test-rep-tostring.js → rep-tostring.test.js} +2 -3
  47. package/test/virtual-objects/{test-retain-remotable.js → retain-remotable.test.js} +25 -24
  48. package/test/virtual-objects/{test-state-shape.js → state-shape.test.js} +2 -2
  49. package/test/virtual-objects/{test-virtualObjectGC.js → virtualObjectGC.test.js} +2 -2
  50. package/test/virtual-objects/{test-virtualObjectManager.js → virtualObjectManager.test.js} +126 -8
  51. package/test/virtual-objects/{test-vo-real-gc.js → vo-real-gc.test.js} +8 -8
  52. package/test/virtual-objects/{test-weakcollections-vref-handling.js → weakcollections-vref-handling.test.js} +1 -2
  53. package/test/{test-vo-test-harness.js → vo-test-harness.test.js} +0 -1
  54. package/test/{test-vpid-liveslots.js → vpid-liveslots.test.js} +4 -5
  55. package/test/waitUntilQuiescent.js +2 -1
  56. package/tools/fakeVirtualSupport.js +51 -21
  57. package/tools/prepare-test-env.js +13 -0
  58. package/tools/setup-vat-data.js +62 -0
  59. package/CHANGELOG.md +0 -85
  60. package/test/kmarshal.js +0 -79
package/src/liveslots.js CHANGED
@@ -33,7 +33,7 @@ const { details: X } = assert;
33
33
  * @param {*} syscall Kernel syscall interface that the vat will have access to
34
34
  * @param {*} forVatID Vat ID label, for use in debug diagnostics
35
35
  * @param {*} vatPowers
36
- * @param {import('./types').LiveSlotsOptions} liveSlotsOptions
36
+ * @param {import('./types.js').LiveSlotsOptions} liveSlotsOptions
37
37
  * @param {*} gcTools { WeakRef, FinalizationRegistry, waitUntilQuiescent, gcAndFinalize,
38
38
  * meterControl }
39
39
  * @param {Pick<Console, 'debug' | 'log' | 'info' | 'warn' | 'error'>} console
@@ -251,13 +251,10 @@ function build(
251
251
  const importsToRetire = new Set();
252
252
  const exportsToRetire = new Set();
253
253
  let doMore;
254
+ await null;
254
255
  do {
255
256
  doMore = false;
256
257
 
257
- // Yes, we know this is an await inside a loop. Too bad. (Also, it's a
258
- // `do {} while` loop, which means there's no conditional bypass of the
259
- // await.)
260
- // eslint-disable-next-line no-await-in-loop, @jessie.js/no-nested-await
261
258
  await gcTools.gcAndFinalize();
262
259
 
263
260
  // possiblyDeadSet contains a baseref for everything (Presences,
@@ -270,7 +267,6 @@ function build(
270
267
  const deadSet = new Set();
271
268
 
272
269
  for (const baseRef of possiblyDeadSet) {
273
- // eslint-disable-next-line no-use-before-define
274
270
  if (slotToVal.has(baseRef)) {
275
271
  continue; // RAM pillar remains
276
272
  }
@@ -500,54 +496,6 @@ function build(
500
496
  return Remotable(iface);
501
497
  }
502
498
 
503
- /**
504
- * Counters to track the next number for various categories of allocation.
505
- * `exportID` starts at 1 because 'o+0' is always automatically
506
- * pre-assigned to the root object.
507
- * `promiseID` starts at 5 as a very minor aid to debugging: when puzzling
508
- * over trace logs and the like, it helps for the numbers in various species
509
- * of IDs that are jumbled together to be a little out of sync and thus a
510
- * little less similar to each other.
511
- */
512
- const initialIDCounters = { exportID: 1, collectionID: 1, promiseID: 5 };
513
- /** @type {Record<string, number>} */
514
- let idCounters;
515
- let idCountersAreDirty = false;
516
-
517
- function initializeIDCounters() {
518
- if (!idCounters) {
519
- // the saved value might be missing, or from an older liveslots
520
- // (with fewer counters), so merge it with our initial values
521
- const saved = JSON.parse(syscall.vatstoreGet('idCounters') || '{}');
522
- idCounters = { ...initialIDCounters, ...saved };
523
- idCountersAreDirty = true;
524
- }
525
- }
526
-
527
- function allocateNextID(name) {
528
- if (!idCounters) {
529
- // Normally `initializeIDCounters` would be called from startVat, but some
530
- // tests bypass that so this is a backstop. Note that the invocation from
531
- // startVat is there to make vatStore access patterns a bit more
532
- // consistent from one vat to another, principally as a confusion
533
- // reduction measure in service of debugging; it is not a correctness
534
- // issue.
535
- initializeIDCounters();
536
- }
537
- const result = idCounters[name];
538
- result !== undefined || Fail`unknown idCounters[${name}]`;
539
- idCounters[name] += 1;
540
- idCountersAreDirty = true;
541
- return result;
542
- }
543
-
544
- function flushIDCounters() {
545
- if (idCountersAreDirty) {
546
- syscall.vatstoreSet('idCounters', JSON.stringify(idCounters));
547
- idCountersAreDirty = false;
548
- }
549
- }
550
-
551
499
  // TODO: fix awkward non-orthogonality: allocateExportID() returns a number,
552
500
  // allocatePromiseID() returns a slot, registerPromise() uses the slot from
553
501
  // allocatePromiseID(), exportPassByPresence() generates a slot itself using
@@ -556,15 +504,18 @@ function build(
556
504
  // use a slot from the corresponding allocateX
557
505
 
558
506
  function allocateExportID() {
559
- return allocateNextID('exportID');
507
+ // eslint-disable-next-line no-use-before-define
508
+ return vrm.allocateNextID('exportID');
560
509
  }
561
510
 
562
511
  function allocateCollectionID() {
563
- return allocateNextID('collectionID');
512
+ // eslint-disable-next-line no-use-before-define
513
+ return vrm.allocateNextID('collectionID');
564
514
  }
565
515
 
566
516
  function allocatePromiseID() {
567
- const promiseID = allocateNextID('promiseID');
517
+ // eslint-disable-next-line no-use-before-define
518
+ const promiseID = vrm.allocateNextID('promiseID');
568
519
  return makeVatSlot('promise', true, promiseID);
569
520
  }
570
521
 
@@ -612,7 +563,7 @@ function build(
612
563
  serializeBodyFormat: 'smallcaps',
613
564
  // TODO Temporary hack.
614
565
  // See https://github.com/Agoric/agoric-sdk/issues/2780
615
- errorIdNum: 70000,
566
+ errorIdNum: 70_000,
616
567
  marshalSaveError: err =>
617
568
  // By sending this to `console.warn`, under cosmic-swingset this is
618
569
  // controlled by the `console` option given to makeLiveSlots.
@@ -759,9 +710,9 @@ function build(
759
710
  Fail`registerValue(${baseRef} should not receive individual facets`;
760
711
  slotToVal.set(baseRef, new WeakRef(val));
761
712
  if (valIsCohort) {
762
- vrm.getFacetNames(id).forEach((name, index) => {
713
+ for (const [index, name] of vrm.getFacetNames(id).entries()) {
763
714
  valToSlot.set(val[name], `${baseRef}:${index}`);
764
- });
715
+ }
765
716
  } else {
766
717
  valToSlot.set(val, baseRef);
767
718
  }
@@ -983,12 +934,20 @@ function build(
983
934
  return null;
984
935
  }
985
936
  syscall.resolve(resolutions);
986
- resolutions.forEach(([_xvpid, _isReject, resolutionCD]) => {
987
- resolutionCD.slots.forEach(vref => maybeNewVPIDs.add(vref));
988
- });
989
- resolutions.forEach(([xvpid]) => maybeNewVPIDs.delete(xvpid));
937
+ for (const resolution of resolutions) {
938
+ const [_xvpid, _isReject, resolutionCD] = resolution;
939
+ for (const vref of resolutionCD.slots) {
940
+ maybeNewVPIDs.add(vref);
941
+ }
942
+ }
943
+ for (const resolution of resolutions) {
944
+ const [xvpid] = resolution;
945
+ maybeNewVPIDs.delete(xvpid);
946
+ }
947
+ }
948
+ for (const newVPID of Array.from(maybeNewVPIDs).sort()) {
949
+ maybeExportPromise(newVPID);
990
950
  }
991
- Array.from(maybeNewVPIDs).sort().forEach(maybeExportPromise);
992
951
 
993
952
  // ideally we'd wait until .then is called on p before subscribing, but
994
953
  // the current Promise API doesn't give us a way to discover this, so we
@@ -1190,13 +1149,21 @@ function build(
1190
1149
 
1191
1150
  const maybeNewVPIDs = new Set();
1192
1151
  // if we mention a vpid, we might need to track it
1193
- resolutions.forEach(([_xvpid, _isReject, resolutionCD]) => {
1194
- resolutionCD.slots.forEach(vref => maybeNewVPIDs.add(vref));
1195
- });
1152
+ for (const resolution of resolutions) {
1153
+ const [_xvpid, _isReject, resolutionCD] = resolution;
1154
+ for (const vref of resolutionCD.slots) {
1155
+ maybeNewVPIDs.add(vref);
1156
+ }
1157
+ }
1196
1158
  // but not if we just resolved it (including the primary)
1197
- resolutions.forEach(([xvpid]) => maybeNewVPIDs.delete(xvpid));
1159
+ for (const resolution of resolutions) {
1160
+ const [xvpid] = resolution;
1161
+ maybeNewVPIDs.delete(xvpid);
1162
+ }
1198
1163
  // track everything that's left
1199
- Array.from(maybeNewVPIDs).sort().forEach(maybeExportPromise);
1164
+ for (const newVPID of Array.from(maybeNewVPIDs).sort()) {
1165
+ maybeExportPromise(newVPID);
1166
+ }
1200
1167
 
1201
1168
  // only the primary can possibly be newly resolved
1202
1169
  unregisterUnreferencedVPID(vpid);
@@ -1254,11 +1221,11 @@ function build(
1254
1221
  // 'imports' is an exclusively-owned Set that holds all new
1255
1222
  // promise vpids, both resolved and unresolved
1256
1223
  const imports = finishCollectingPromiseImports();
1257
- retiredVPIDs.forEach(vpid => {
1224
+ for (const vpid of retiredVPIDs) {
1258
1225
  unregisterUnreferencedVPID(vpid); // unregisters if not in vdata
1259
1226
  importedVPIDs.delete(vpid);
1260
1227
  imports.delete(vpid); // resolved, so don't subscribe()
1261
- });
1228
+ }
1262
1229
  for (const vpid of Array.from(imports).sort()) {
1263
1230
  syscall.subscribe(vpid);
1264
1231
  }
@@ -1298,14 +1265,18 @@ function build(
1298
1265
 
1299
1266
  function retireExports(vrefs) {
1300
1267
  assert(Array.isArray(vrefs));
1301
- vrefs.forEach(retireOneExport);
1268
+ for (const vref of vrefs) {
1269
+ retireOneExport(vref);
1270
+ }
1302
1271
  }
1303
1272
 
1304
1273
  function retireImports(vrefs) {
1305
1274
  assert(Array.isArray(vrefs));
1306
1275
  vrefs.map(vref => insistVatType('object', vref));
1307
1276
  vrefs.map(vref => assert(!parseVatSlot(vref).allocatedByVat));
1308
- vrefs.forEach(vrm.ceaseRecognition);
1277
+ for (const vref of vrefs) {
1278
+ vrm.ceaseRecognition(vref);
1279
+ }
1309
1280
  }
1310
1281
 
1311
1282
  // TODO: when we add notifyForward, guard against cycles
@@ -1450,7 +1421,7 @@ function build(
1450
1421
  }
1451
1422
  harden(vpow);
1452
1423
 
1453
- initializeIDCounters();
1424
+ vrm.initializeIDCounters();
1454
1425
  vom.initializeKindHandleKind();
1455
1426
  collectionManager.initializeStoreKindInfo();
1456
1427
 
@@ -1496,7 +1467,7 @@ function build(
1496
1467
  }
1497
1468
 
1498
1469
  /**
1499
- * @param {import('./types').VatDeliveryObject} delivery
1470
+ * @param {import('./types.js').VatDeliveryObject} delivery
1500
1471
  * @returns {void | Promise<void>}
1501
1472
  */
1502
1473
  function dispatchToUserspace(delivery) {
@@ -1561,7 +1532,7 @@ function build(
1561
1532
  }
1562
1533
 
1563
1534
  /**
1564
- * @param { import('./types').SwingSetCapData } _disconnectObjectCapData
1535
+ * @param { import('./types.js').SwingSetCapData } _disconnectObjectCapData
1565
1536
  * @returns {Promise<void>}
1566
1537
  */
1567
1538
  async function stopVat(_disconnectObjectCapData) {
@@ -1573,7 +1544,7 @@ function build(
1573
1544
  * dispatch has completed and user code has relinquished agency.
1574
1545
  */
1575
1546
  function afterDispatchActions() {
1576
- flushIDCounters();
1547
+ vrm.flushIDCounters();
1577
1548
  collectionManager.flushSchemaCache();
1578
1549
  vom.flushStateCache();
1579
1550
  }
@@ -1613,7 +1584,7 @@ function build(
1613
1584
  * terminate the vat). Userspace should not be able to cause the delivery
1614
1585
  * to fail: only a bug in liveslots should trigger a failure.
1615
1586
  *
1616
- * @param {import('./types').VatDeliveryObject} delivery
1587
+ * @param {import('./types.js').VatDeliveryObject} delivery
1617
1588
  * @returns {Promise<void>}
1618
1589
  */
1619
1590
  async function dispatch(delivery) {
@@ -1629,7 +1600,7 @@ function build(
1629
1600
  // *not* directly wait for the userspace function to complete, nor for
1630
1601
  // any promise it returns to fire.
1631
1602
  const p = Promise.resolve(delivery).then(unmeteredDispatch);
1632
- p.finally(() => (complete = true));
1603
+ void p.finally(() => (complete = true));
1633
1604
 
1634
1605
  // Instead, we wait for userspace to become idle by draining the
1635
1606
  // promise queue. We clean up and then examine/return 'p' so any
@@ -1664,7 +1635,7 @@ function build(
1664
1635
  * @param {*} syscall Kernel syscall interface that the vat will have access to
1665
1636
  * @param {*} forVatID Vat ID label, for use in debug diagostics
1666
1637
  * @param {*} vatPowers
1667
- * @param {import('./types').LiveSlotsOptions} liveSlotsOptions
1638
+ * @param {import('./types.js').LiveSlotsOptions} liveSlotsOptions
1668
1639
  * @param {*} gcTools { WeakRef, FinalizationRegistry, waitUntilQuiescent }
1669
1640
  * @param {Pick<Console, 'debug' | 'log' | 'info' | 'warn' | 'error'>} [liveSlotsConsole]
1670
1641
  * @param {*} [buildVatNamespace]
package/src/message.js CHANGED
@@ -3,7 +3,7 @@ import { insistCapData } from './capdata.js';
3
3
 
4
4
  /**
5
5
  * @typedef {{
6
- * methargs: import('./types').SwingSetCapData, // of [method, args]
6
+ * methargs: import('./types.js').SwingSetCapData, // of [method, args]
7
7
  * result: string | undefined | null,
8
8
  * }} Message
9
9
  */
@@ -32,7 +32,7 @@ export function insistMessage(message) {
32
32
 
33
33
  /**
34
34
  * @param {unknown} vdo
35
- * @returns {asserts vdo is VatDeliveryObject}
35
+ * @returns {asserts vdo is import('./types').VatDeliveryObject}
36
36
  */
37
37
 
38
38
  export function insistVatDeliveryObject(vdo) {
@@ -114,7 +114,7 @@ export function insistVatDeliveryResult(vdr) {
114
114
 
115
115
  /**
116
116
  * @param {unknown} vso
117
- * @returns {asserts vso is VatSyscallObject}
117
+ * @returns {asserts vso is import('./types').VatSyscallObject}
118
118
  */
119
119
 
120
120
  export function insistVatSyscallObject(vso) {
@@ -194,7 +194,7 @@ export function insistVatSyscallObject(vso) {
194
194
 
195
195
  /**
196
196
  * @param {unknown} vsr
197
- * @returns {asserts vsr is VatSyscallResult}
197
+ * @returns {asserts vsr is import('./types').VatSyscallResult}
198
198
  */
199
199
 
200
200
  export function insistVatSyscallResult(vsr) {
package/src/types.js CHANGED
@@ -1,3 +1,6 @@
1
+ // Ensure this is a module.
2
+ export {};
3
+
1
4
  /**
2
5
  * @callback makeLiveSlots
3
6
  */
@@ -79,5 +82,8 @@
79
82
  *
80
83
  */
81
84
 
82
- // Ensure this is a module.
83
- export {};
85
+ /**
86
+ * @template V fulfilled value
87
+ * @template {any[]} [A=unknown[]] arguments
88
+ * @typedef { {onFulfilled?: (value: V, ...args: A) => void, onRejected?: (reason: unknown, ...args: A) => void} } PromiseWatcher
89
+ */
@@ -0,0 +1,271 @@
1
+ /**
2
+ * @file Types for vat-data
3
+ *
4
+ * Facet is a single object with methods.
5
+ * Behavior is a description when defining a kind of what facets it will have.
6
+ * For the non-multi defineKind, there is just one facet so it doesn't have a key.
7
+ */
8
+ import type {
9
+ MapStore,
10
+ SetStore,
11
+ StoreOptions,
12
+ WeakMapStore,
13
+ WeakSetStore,
14
+ } from '@agoric/store';
15
+ import type { Amplify, IsInstance, ReceivePower, StateShape } from '@endo/exo';
16
+ import type { RemotableObject } from '@endo/pass-style';
17
+ import type { InterfaceGuard, Pattern } from '@endo/patterns';
18
+ import type { makeWatchedPromiseManager } from './watchedPromises.js';
19
+
20
+ // TODO should be moved into @endo/patterns and eventually imported here
21
+ // instead of this local definition.
22
+ export type InterfaceGuardKit = Record<string, InterfaceGuard>;
23
+ export type { MapStore, Pattern };
24
+
25
+ // This needs `any` values. If they were `unknown`, code that uses Baggage
26
+ // would need explicit runtime checks or casts for every fetch, which is
27
+ // onerous.
28
+ export type Baggage = MapStore<string, any>;
29
+
30
+ type WatchedPromisesManager = ReturnType<typeof makeWatchedPromiseManager>;
31
+
32
+ type Tail<T extends any[]> = T extends [head: any, ...rest: infer Rest]
33
+ ? Rest
34
+ : [];
35
+
36
+ // used to omit the 'context' parameter
37
+ type OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R
38
+ ? (...args: P) => R
39
+ : never;
40
+
41
+ export type KindFacet<O> = RemotableObject & {
42
+ [K in keyof O]: OmitFirstArg<O[K]>; // omit the 'context' parameter
43
+ };
44
+
45
+ export type KindFacets<B> = {
46
+ [FacetKey in keyof B]: KindFacet<B[FacetKey]>;
47
+ };
48
+
49
+ export type KindContext<S, F> = { state: S; self: KindFacet<F> };
50
+ export type MultiKindContext<S, B> = { state: S; facets: KindFacets<B> };
51
+
52
+ export type PlusContext<C, M extends (...args: any[]) => any> = (
53
+ c: C,
54
+ ...args: Parameters<M>
55
+ ) => ReturnType<M>;
56
+
57
+ export type FunctionsPlusContext<
58
+ C,
59
+ O extends Record<string, (...args: any[]) => any>,
60
+ > = {
61
+ [K in keyof O]: PlusContext<C, O[K]>;
62
+ };
63
+
64
+ declare class DurableKindHandleClass {
65
+ private descriptionTag: string;
66
+ }
67
+ export type DurableKindHandle = DurableKindHandleClass;
68
+
69
+ /**
70
+ * Grab bag of options that can be provided to `defineDurableKind` and its
71
+ * siblings. Not all options are meaningful in all contexts. See the
72
+ * doc-comments on each option.
73
+ */
74
+ export type DefineKindOptions<C> = {
75
+ /**
76
+ * If provided, the `finish` function will be called after the instance is
77
+ * made and internally registered, but before it is returned. The finish
78
+ * function is to do any post-intantiation initialization that should be
79
+ * done before exposing the object to its clients.
80
+ */
81
+ finish?: (context: C) => void;
82
+
83
+ /**
84
+ * If provided, it describes the shape of all state records of instances
85
+ * of this kind.
86
+ */
87
+ stateShape?: StateShape;
88
+
89
+ /**
90
+ * If a `receiveAmplifier` function is provided to an exo class kit definition,
91
+ * it will be called with an `Amplify` function. If provided to the definition
92
+ * of a normal exo or exo class, the definition will throw, since only
93
+ * exo kits can be amplified.
94
+ * An `Amplify` function is a function that takes a facet instance of
95
+ * this class kit as an argument, in which case it will return the facets
96
+ * record, giving access to all the facet instances of the same cohort.
97
+ */
98
+ receiveAmplifier?: ReceivePower<Amplify>;
99
+
100
+ /**
101
+ * If a `receiveInstanceTester` function is provided, it will be called
102
+ * during the definition of the exo class or exo class kit with an
103
+ * `IsInstance` function. The first argument of `IsInstance`
104
+ * is the value to be tested. When it may be a facet instance of an
105
+ * exo class kit, the optional second argument, if provided, is
106
+ * a `facetName`. In that case, the function tests only if the first
107
+ * argument is an instance of that facet of the associated exo class kit.
108
+ */
109
+ receiveInstanceTester?: ReceivePower<IsInstance>;
110
+
111
+ // TODO properties above are identical to those in FarClassOptions.
112
+ // These are the only options that should be exposed by
113
+ // vat-data's public virtual/durable exo APIs. This DefineKindOptions
114
+ // should explicitly be a subtype, where the methods below are only for
115
+ // internal use, i.e., below the exo level.
116
+
117
+ /**
118
+ * As a kind option, intended for internal use only.
119
+ * Meaningful to `makeScalarBigMapStore` and its siblings. These maker
120
+ * fuctions will make either virtual or durable stores, depending on
121
+ * this flag. Defaults to off, making virtual but not durable collections.
122
+ *
123
+ * Generally, durable collections are provided with `provideDurableMapStore`
124
+ * and its sibling, which use this flag internally. If you do not make
125
+ * durable collections by other means, you can consider this as
126
+ * intended for internal use only.
127
+ */
128
+ durable?: boolean;
129
+
130
+ /**
131
+ * Intended for internal use only.
132
+ * Should the raw methods receive their `context` argument as their first
133
+ * argument or as their `this` binding? For `defineDurableKind` and its
134
+ * siblings (including `prepareSingleton`), this defaults to off, meaning that
135
+ * their behavior methods receive `context` as their first argument.
136
+ * `prepareExoClass` and its siblings (including `prepareExo`) use
137
+ * this flag internally to indicate that their methods receive `context`
138
+ * as their `this` binding.
139
+ */
140
+ thisfulMethods?: boolean;
141
+
142
+ /**
143
+ * Intended for internal use only.
144
+ * Only applicable if this is a class kind. A class kit kind should use
145
+ * `interfaceGuardKit` instead.
146
+ *
147
+ * If an `interfaceGuard` is provided, then the raw methods passed alongside
148
+ * it are wrapped by a function that first checks that this method's guard
149
+ * pattern is satisfied before calling the raw method.
150
+ *
151
+ * In `defineDurableKind` and its siblings, this defaults to `undefined`.
152
+ * Exo classes use this internally to protect their raw class methods
153
+ * using the provided interface.
154
+ * In absence, an exo is protected anyway, while a bare kind is
155
+ * not (detected by `!thisfulMethods`),
156
+ */
157
+ interfaceGuard?: InterfaceGuard;
158
+
159
+ /**
160
+ * Intended for internal use only.
161
+ * Only applicable if this is a class kit kind. A class kind should use
162
+ * `interfaceGuard` instead.
163
+ *
164
+ * If an `interfaceGuardKit` is provided, then each member of the
165
+ * interfaceGuardKit is used to guard the corresponding facet of the
166
+ * class kit.
167
+ *
168
+ * In `defineDurableKindMulti` and its siblings, this defaults to `undefined`.
169
+ * Exo class kits use this internally to protect their facets.
170
+ * In absence, an exo is protected anyway, while a bare kind is
171
+ * not (detected by `!thisfulMethods`),
172
+ */
173
+ interfaceGuardKit?: InterfaceGuardKit;
174
+ };
175
+
176
+ export type VatData = {
177
+ // virtual kinds
178
+ /** @deprecated Use defineVirtualExoClass instead */
179
+ defineKind: <P extends Array<any>, S, F>(
180
+ tag: string,
181
+ init: (...args: P) => S,
182
+ facet: F,
183
+ options?: DefineKindOptions<KindContext<S, F>>,
184
+ ) => (...args: P) => KindFacet<F>;
185
+
186
+ /** @deprecated Use defineVirtualExoClassKit instead */
187
+ defineKindMulti: <P extends Array<any>, S, B>(
188
+ tag: string,
189
+ init: (...args: P) => S,
190
+ behavior: B,
191
+ options?: DefineKindOptions<MultiKindContext<S, B>>,
192
+ ) => (...args: P) => KindFacets<B>;
193
+
194
+ // durable kinds
195
+ makeKindHandle: (descriptionTag: string) => DurableKindHandle;
196
+
197
+ /** @deprecated Use defineDurableExoClass instead */
198
+ defineDurableKind: <P extends Array<any>, S, F>(
199
+ kindHandle: DurableKindHandle,
200
+ init: (...args: P) => S,
201
+ facet: F,
202
+ options?: DefineKindOptions<KindContext<S, F>>,
203
+ ) => (...args: P) => KindFacet<F>;
204
+
205
+ /** @deprecated Use defineDurableExoClassKit instead */
206
+ defineDurableKindMulti: <P extends Array<any>, S, B>(
207
+ kindHandle: DurableKindHandle,
208
+ init: (...args: P) => S,
209
+ behavior: B,
210
+ options?: DefineKindOptions<MultiKindContext<S, B>>,
211
+ ) => (...args: P) => KindFacets<B>;
212
+
213
+ providePromiseWatcher: WatchedPromisesManager['providePromiseWatcher'];
214
+ watchPromise: WatchedPromisesManager['watchPromise'];
215
+
216
+ makeScalarBigMapStore: <K, V>(
217
+ label: string,
218
+ options?: StoreOptions,
219
+ ) => MapStore<K, V>;
220
+ makeScalarBigWeakMapStore: <K, V>(
221
+ label: string,
222
+ options?: StoreOptions,
223
+ ) => WeakMapStore<K, V>;
224
+
225
+ makeScalarBigSetStore: <K>(
226
+ label: string,
227
+ options?: StoreOptions,
228
+ ) => SetStore<K>;
229
+ makeScalarBigWeakSetStore: <K>(
230
+ label: string,
231
+ options?: StoreOptions,
232
+ ) => WeakSetStore<K>;
233
+ canBeDurable: (specimen: unknown) => boolean;
234
+ };
235
+
236
+ // The JSDoc is repeated here and at the function definition so it appears
237
+ // in IDEs where it's used, regardless of type resolution.
238
+ export interface PickFacet {
239
+ /**
240
+ * When making a multi-facet kind, it's common to pick one facet to
241
+ * expose. E.g.,
242
+ *
243
+ * const makeFoo = (a, b, c, d) => makeFooBase(a, b, c, d).self;
244
+ *
245
+ * This helper reduces the duplication:
246
+ *
247
+ * const makeFoo = pickFacet(makeFooBase, 'self');
248
+ */
249
+ <M extends (...args: any[]) => any, F extends keyof ReturnType<M>>(
250
+ maker: M,
251
+ facetName: F,
252
+ ): (...args: Parameters<M>) => ReturnType<M>[F];
253
+ }
254
+
255
+ /** @deprecated Use prepareExoClass instead */
256
+ export type PrepareKind = <P extends Array<any>, S, F>(
257
+ baggage: Baggage,
258
+ tag: string,
259
+ init: (...args: P) => S,
260
+ facet: F,
261
+ options?: DefineKindOptions<KindContext<S, F>>,
262
+ ) => (...args: P) => KindFacet<F>;
263
+
264
+ /** @deprecated Use prepareExoClassKit instead */
265
+ export type PrepareKindMulti = <P extends Array<any>, S, B>(
266
+ baggage: Baggage,
267
+ tag: string,
268
+ init: (...args: P) => S,
269
+ behavior: B,
270
+ options?: DefineKindOptions<MultiKindContext<S, B>>,
271
+ ) => (...args: P) => KindFacets<B>;
@@ -0,0 +1,2 @@
1
+ // Empty JS file to correspond with vatDataTypes.d.ts
2
+ export {};
@@ -18,6 +18,7 @@ export function* enumerateKeysStartEnd(syscall, start, end, checkF) {
18
18
  dbKey = syscall.vatstoreGetNextKey(dbKey);
19
19
  }
20
20
  }
21
+ harden(enumerateKeysStartEnd);
21
22
 
22
23
  // return an iterator of all existing keys that start with 'prefix'
23
24
  // (excluding the prefix itself)
@@ -32,6 +33,7 @@ export function* enumerateKeysWithPrefix(syscall, prefix) {
32
33
  yield key;
33
34
  }
34
35
  }
36
+ harden(enumerateKeysWithPrefix);
35
37
 
36
38
  export function prefixedKeysExist(syscall, prefix) {
37
39
  const nextKey = syscall.vatstoreGetNextKey(prefix);