@agoric/swingset-liveslots 0.10.3-mainnet1B-dev-26244e8.0 → 0.10.3-orchestration-dev-096c4e8.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 (58) hide show
  1. package/README.md +2 -0
  2. package/package.json +25 -17
  3. package/src/cache.js +5 -3
  4. package/src/collectionManager.js +147 -69
  5. package/src/index.js +2 -1
  6. package/src/liveslots.js +52 -79
  7. package/src/message.js +4 -4
  8. package/src/types.js +8 -2
  9. package/src/vatDataTypes.d.ts +234 -0
  10. package/src/vatDataTypes.js +2 -0
  11. package/src/vatstore-iterators.js +2 -0
  12. package/src/virtualObjectManager.js +107 -63
  13. package/src/virtualReferences.js +51 -0
  14. package/src/watchedPromises.js +50 -15
  15. package/test/gc-and-finalize.js +30 -1
  16. package/test/gc-helpers.js +2 -1
  17. package/test/liveslots-helpers.js +6 -6
  18. package/test/mock-gc.js +1 -0
  19. package/test/storeGC/test-lifecycle.js +2 -2
  20. package/test/storeGC/test-refcount-management.js +1 -2
  21. package/test/storeGC/test-scalar-store-kind.js +0 -1
  22. package/test/storeGC/test-weak-key.js +1 -2
  23. package/test/test-baggage.js +1 -2
  24. package/test/test-cache.js +0 -1
  25. package/test/test-collection-schema-refcount.js +1 -2
  26. package/test/test-collection-upgrade.js +1 -3
  27. package/test/test-collections.js +117 -14
  28. package/test/test-dropped-collection-weakrefs.js +1 -2
  29. package/test/test-durabilityChecks.js +3 -3
  30. package/test/test-facetiousness.js +1 -2
  31. package/test/test-gc-sensitivity.js +2 -2
  32. package/test/test-handled-promises.js +5 -7
  33. package/test/test-initial-vrefs.js +2 -3
  34. package/test/test-liveslots-mock-gc.js +2 -2
  35. package/test/test-liveslots-real-gc.js +44 -35
  36. package/test/test-liveslots.js +13 -14
  37. package/test/test-vo-test-harness.js +0 -1
  38. package/test/test-vpid-liveslots.js +4 -5
  39. package/test/util.js +2 -2
  40. package/test/vat-util.js +1 -1
  41. package/test/virtual-objects/test-cease-recognition.js +2 -2
  42. package/test/virtual-objects/test-cross-facet.js +1 -2
  43. package/test/virtual-objects/test-empty-data.js +1 -2
  44. package/test/virtual-objects/test-facets.js +1 -2
  45. package/test/virtual-objects/test-kind-changes.js +2 -2
  46. package/test/virtual-objects/test-reachable-vrefs.js +2 -2
  47. package/test/virtual-objects/test-rep-tostring.js +2 -3
  48. package/test/virtual-objects/test-retain-remotable.js +25 -24
  49. package/test/virtual-objects/test-state-shape.js +2 -2
  50. package/test/virtual-objects/test-virtualObjectGC.js +2 -2
  51. package/test/virtual-objects/test-virtualObjectManager.js +126 -8
  52. package/test/virtual-objects/test-vo-real-gc.js +8 -8
  53. package/test/virtual-objects/test-weakcollections-vref-handling.js +1 -2
  54. package/tools/fakeVirtualSupport.js +48 -21
  55. package/tools/prepare-test-env.js +13 -0
  56. package/tools/setup-vat-data.js +62 -0
  57. package/CHANGELOG.md +0 -77
  58. package/test/kmarshal.js +0 -79
package/src/liveslots.js CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint @typescript-eslint/no-floating-promises: "warn" */
1
2
  import {
2
3
  Remotable,
3
4
  passStyleOf,
@@ -33,7 +34,7 @@ const { details: X } = assert;
33
34
  * @param {*} syscall Kernel syscall interface that the vat will have access to
34
35
  * @param {*} forVatID Vat ID label, for use in debug diagnostics
35
36
  * @param {*} vatPowers
36
- * @param {import('./types').LiveSlotsOptions} liveSlotsOptions
37
+ * @param {import('./types.js').LiveSlotsOptions} liveSlotsOptions
37
38
  * @param {*} gcTools { WeakRef, FinalizationRegistry, waitUntilQuiescent, gcAndFinalize,
38
39
  * meterControl }
39
40
  * @param {Pick<Console, 'debug' | 'log' | 'info' | 'warn' | 'error'>} console
@@ -251,13 +252,10 @@ function build(
251
252
  const importsToRetire = new Set();
252
253
  const exportsToRetire = new Set();
253
254
  let doMore;
255
+ await null;
254
256
  do {
255
257
  doMore = false;
256
258
 
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
259
  await gcTools.gcAndFinalize();
262
260
 
263
261
  // possiblyDeadSet contains a baseref for everything (Presences,
@@ -500,54 +498,6 @@ function build(
500
498
  return Remotable(iface);
501
499
  }
502
500
 
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
501
  // TODO: fix awkward non-orthogonality: allocateExportID() returns a number,
552
502
  // allocatePromiseID() returns a slot, registerPromise() uses the slot from
553
503
  // allocatePromiseID(), exportPassByPresence() generates a slot itself using
@@ -556,15 +506,18 @@ function build(
556
506
  // use a slot from the corresponding allocateX
557
507
 
558
508
  function allocateExportID() {
559
- return allocateNextID('exportID');
509
+ // eslint-disable-next-line no-use-before-define
510
+ return vrm.allocateNextID('exportID');
560
511
  }
561
512
 
562
513
  function allocateCollectionID() {
563
- return allocateNextID('collectionID');
514
+ // eslint-disable-next-line no-use-before-define
515
+ return vrm.allocateNextID('collectionID');
564
516
  }
565
517
 
566
518
  function allocatePromiseID() {
567
- const promiseID = allocateNextID('promiseID');
519
+ // eslint-disable-next-line no-use-before-define
520
+ const promiseID = vrm.allocateNextID('promiseID');
568
521
  return makeVatSlot('promise', true, promiseID);
569
522
  }
570
523
 
@@ -759,9 +712,9 @@ function build(
759
712
  Fail`registerValue(${baseRef} should not receive individual facets`;
760
713
  slotToVal.set(baseRef, new WeakRef(val));
761
714
  if (valIsCohort) {
762
- vrm.getFacetNames(id).forEach((name, index) => {
715
+ for (const [index, name] of vrm.getFacetNames(id).entries()) {
763
716
  valToSlot.set(val[name], `${baseRef}:${index}`);
764
- });
717
+ }
765
718
  } else {
766
719
  valToSlot.set(val, baseRef);
767
720
  }
@@ -983,12 +936,20 @@ function build(
983
936
  return null;
984
937
  }
985
938
  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));
939
+ for (const resolution of resolutions) {
940
+ const [_xvpid, _isReject, resolutionCD] = resolution;
941
+ for (const vref of resolutionCD.slots) {
942
+ maybeNewVPIDs.add(vref);
943
+ }
944
+ }
945
+ for (const resolution of resolutions) {
946
+ const [xvpid] = resolution;
947
+ maybeNewVPIDs.delete(xvpid);
948
+ }
949
+ }
950
+ for (const newVPID of Array.from(maybeNewVPIDs).sort()) {
951
+ maybeExportPromise(newVPID);
990
952
  }
991
- Array.from(maybeNewVPIDs).sort().forEach(maybeExportPromise);
992
953
 
993
954
  // ideally we'd wait until .then is called on p before subscribing, but
994
955
  // the current Promise API doesn't give us a way to discover this, so we
@@ -1190,13 +1151,21 @@ function build(
1190
1151
 
1191
1152
  const maybeNewVPIDs = new Set();
1192
1153
  // 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
- });
1154
+ for (const resolution of resolutions) {
1155
+ const [_xvpid, _isReject, resolutionCD] = resolution;
1156
+ for (const vref of resolutionCD.slots) {
1157
+ maybeNewVPIDs.add(vref);
1158
+ }
1159
+ }
1196
1160
  // but not if we just resolved it (including the primary)
1197
- resolutions.forEach(([xvpid]) => maybeNewVPIDs.delete(xvpid));
1161
+ for (const resolution of resolutions) {
1162
+ const [xvpid] = resolution;
1163
+ maybeNewVPIDs.delete(xvpid);
1164
+ }
1198
1165
  // track everything that's left
1199
- Array.from(maybeNewVPIDs).sort().forEach(maybeExportPromise);
1166
+ for (const newVPID of Array.from(maybeNewVPIDs).sort()) {
1167
+ maybeExportPromise(newVPID);
1168
+ }
1200
1169
 
1201
1170
  // only the primary can possibly be newly resolved
1202
1171
  unregisterUnreferencedVPID(vpid);
@@ -1254,11 +1223,11 @@ function build(
1254
1223
  // 'imports' is an exclusively-owned Set that holds all new
1255
1224
  // promise vpids, both resolved and unresolved
1256
1225
  const imports = finishCollectingPromiseImports();
1257
- retiredVPIDs.forEach(vpid => {
1226
+ for (const vpid of retiredVPIDs) {
1258
1227
  unregisterUnreferencedVPID(vpid); // unregisters if not in vdata
1259
1228
  importedVPIDs.delete(vpid);
1260
1229
  imports.delete(vpid); // resolved, so don't subscribe()
1261
- });
1230
+ }
1262
1231
  for (const vpid of Array.from(imports).sort()) {
1263
1232
  syscall.subscribe(vpid);
1264
1233
  }
@@ -1298,14 +1267,18 @@ function build(
1298
1267
 
1299
1268
  function retireExports(vrefs) {
1300
1269
  assert(Array.isArray(vrefs));
1301
- vrefs.forEach(retireOneExport);
1270
+ for (const vref of vrefs) {
1271
+ retireOneExport(vref);
1272
+ }
1302
1273
  }
1303
1274
 
1304
1275
  function retireImports(vrefs) {
1305
1276
  assert(Array.isArray(vrefs));
1306
1277
  vrefs.map(vref => insistVatType('object', vref));
1307
1278
  vrefs.map(vref => assert(!parseVatSlot(vref).allocatedByVat));
1308
- vrefs.forEach(vrm.ceaseRecognition);
1279
+ for (const vref of vrefs) {
1280
+ vrm.ceaseRecognition(vref);
1281
+ }
1309
1282
  }
1310
1283
 
1311
1284
  // TODO: when we add notifyForward, guard against cycles
@@ -1450,7 +1423,7 @@ function build(
1450
1423
  }
1451
1424
  harden(vpow);
1452
1425
 
1453
- initializeIDCounters();
1426
+ vrm.initializeIDCounters();
1454
1427
  vom.initializeKindHandleKind();
1455
1428
  collectionManager.initializeStoreKindInfo();
1456
1429
 
@@ -1496,7 +1469,7 @@ function build(
1496
1469
  }
1497
1470
 
1498
1471
  /**
1499
- * @param {import('./types').VatDeliveryObject} delivery
1472
+ * @param {import('./types.js').VatDeliveryObject} delivery
1500
1473
  * @returns {void | Promise<void>}
1501
1474
  */
1502
1475
  function dispatchToUserspace(delivery) {
@@ -1561,7 +1534,7 @@ function build(
1561
1534
  }
1562
1535
 
1563
1536
  /**
1564
- * @param { import('./types').SwingSetCapData } _disconnectObjectCapData
1537
+ * @param { import('./types.js').SwingSetCapData } _disconnectObjectCapData
1565
1538
  * @returns {Promise<void>}
1566
1539
  */
1567
1540
  async function stopVat(_disconnectObjectCapData) {
@@ -1573,7 +1546,7 @@ function build(
1573
1546
  * dispatch has completed and user code has relinquished agency.
1574
1547
  */
1575
1548
  function afterDispatchActions() {
1576
- flushIDCounters();
1549
+ vrm.flushIDCounters();
1577
1550
  collectionManager.flushSchemaCache();
1578
1551
  vom.flushStateCache();
1579
1552
  }
@@ -1613,7 +1586,7 @@ function build(
1613
1586
  * terminate the vat). Userspace should not be able to cause the delivery
1614
1587
  * to fail: only a bug in liveslots should trigger a failure.
1615
1588
  *
1616
- * @param {import('./types').VatDeliveryObject} delivery
1589
+ * @param {import('./types.js').VatDeliveryObject} delivery
1617
1590
  * @returns {Promise<void>}
1618
1591
  */
1619
1592
  async function dispatch(delivery) {
@@ -1629,7 +1602,7 @@ function build(
1629
1602
  // *not* directly wait for the userspace function to complete, nor for
1630
1603
  // any promise it returns to fire.
1631
1604
  const p = Promise.resolve(delivery).then(unmeteredDispatch);
1632
- p.finally(() => (complete = true));
1605
+ void p.finally(() => (complete = true));
1633
1606
 
1634
1607
  // Instead, we wait for userspace to become idle by draining the
1635
1608
  // promise queue. We clean up and then examine/return 'p' so any
@@ -1664,7 +1637,7 @@ function build(
1664
1637
  * @param {*} syscall Kernel syscall interface that the vat will have access to
1665
1638
  * @param {*} forVatID Vat ID label, for use in debug diagostics
1666
1639
  * @param {*} vatPowers
1667
- * @param {import('./types').LiveSlotsOptions} liveSlotsOptions
1640
+ * @param {import('./types.js').LiveSlotsOptions} liveSlotsOptions
1668
1641
  * @param {*} gcTools { WeakRef, FinalizationRegistry, waitUntilQuiescent }
1669
1642
  * @param {Pick<Console, 'debug' | 'log' | 'info' | 'warn' | 'error'>} [liveSlotsConsole]
1670
1643
  * @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,234 @@
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 { InterfaceGuard, Pattern } from '@endo/patterns';
9
+ import type {
10
+ MapStore,
11
+ SetStore,
12
+ StoreOptions,
13
+ WeakMapStore,
14
+ WeakSetStore,
15
+ } from '@agoric/store';
16
+ import type { StateShape } from '@endo/exo';
17
+ import type { makeWatchedPromiseManager } from './watchedPromises.js';
18
+
19
+ // TODO should be moved into @endo/patterns and eventually imported here
20
+ // instead of this local definition.
21
+ export type InterfaceGuardKit = Record<string, InterfaceGuard>;
22
+ export type { MapStore, Pattern };
23
+
24
+ // This needs `any` values. If they were `unknown`, code that uses Baggage
25
+ // would need explicit runtime checks or casts for every fetch, which is
26
+ // onerous.
27
+ export type Baggage = MapStore<string, any>;
28
+
29
+ type WatchedPromisesManager = ReturnType<typeof makeWatchedPromiseManager>;
30
+
31
+ type Tail<T extends any[]> = T extends [head: any, ...rest: infer Rest]
32
+ ? Rest
33
+ : [];
34
+
35
+ // used to omit the 'context' parameter
36
+ type OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R
37
+ ? (...args: P) => R
38
+ : never;
39
+
40
+ export type KindFacet<O> = {
41
+ [K in keyof O]: OmitFirstArg<O[K]>; // omit the 'context' parameter
42
+ };
43
+
44
+ export type KindFacets<B> = {
45
+ [FacetKey in keyof B]: KindFacet<B[FacetKey]>;
46
+ };
47
+
48
+ export type KindContext<S, F> = { state: S; self: KindFacet<F> };
49
+ export type MultiKindContext<S, B> = { state: S; facets: KindFacets<B> };
50
+
51
+ export type PlusContext<C, M> = (c: C, ...args: Parameters<M>) => ReturnType<M>;
52
+ export type FunctionsPlusContext<C, O> = {
53
+ [K in keyof O]: PlusContext<C, O[K]>;
54
+ };
55
+
56
+ declare class DurableKindHandleClass {
57
+ private descriptionTag: string;
58
+ }
59
+ export type DurableKindHandle = DurableKindHandleClass;
60
+
61
+ /**
62
+ * Grab bag of options that can be provided to `defineDurableKind` and its
63
+ * siblings. Not all options are meaningful in all contexts. See the
64
+ * doc-comments on each option.
65
+ */
66
+ export type DefineKindOptions<C> = {
67
+ /**
68
+ * If provided, the `finish` function will be called after the instance is
69
+ * made and internally registered, but before it is returned. The finish
70
+ * function is to do any post-intantiation initialization that should be
71
+ * done before exposing the object to its clients.
72
+ */
73
+ finish?: (context: C) => void;
74
+
75
+ /**
76
+ * Meaningful to `makeScalarBigMapStore` and its siblings. These maker
77
+ * fuctions will make either virtual or durable stores, depending on
78
+ * this flag. Defaults to off, making virtual but not durable collections.
79
+ *
80
+ * Generally, durable collections are provided with `provideDurableMapStore`
81
+ * and its sibling, which use this flag internally. If you do not make
82
+ * durable collections by other means, you can consider this as
83
+ * intended for internal use only.
84
+ */
85
+ durable?: boolean;
86
+
87
+ /**
88
+ * If provided, it describes the shape of all state records of instances
89
+ * of this kind.
90
+ */
91
+ stateShape?: StateShape;
92
+
93
+ /**
94
+ * Intended for internal use only.
95
+ * Should the raw methods receive their `context` argument as their first
96
+ * argument or as their `this` binding? For `defineDurableKind` and its
97
+ * siblings (including `prepareSingleton`), this defaults to off, meaning that
98
+ * their behavior methods receive `context` as their first argument.
99
+ * `prepareExoClass` and its siblings (including `prepareExo`) use
100
+ * this flag internally to indicate that their methods receive `context`
101
+ * as their `this` binding.
102
+ */
103
+ thisfulMethods?: boolean;
104
+
105
+ /**
106
+ * Intended for internal use only.
107
+ * Only applicable if this is a class kind. A class kit kind should use
108
+ * `interfaceGuardKit` instead.
109
+ *
110
+ * If an `interfaceGuard` is provided, then the raw methods passed alongside
111
+ * it are wrapped by a function that first checks that this method's guard
112
+ * pattern is satisfied before calling the raw method.
113
+ *
114
+ * In `defineDurableKind` and its siblings, this defaults to `undefined`.
115
+ * Exo classes use this internally to protect their raw class methods
116
+ * using the provided interface.
117
+ * In absence, an exo is protected anyway, while a bare kind is
118
+ * not (detected by `!thisfulMethods`),
119
+ */
120
+ interfaceGuard?: InterfaceGuard;
121
+
122
+ /**
123
+ * Intended for internal use only.
124
+ * Only applicable if this is a class kit kind. A class kind should use
125
+ * `interfaceGuard` instead.
126
+ *
127
+ * If an `interfaceGuardKit` is provided, then each member of the
128
+ * interfaceGuardKit is used to guard the corresponding facet of the
129
+ * class kit.
130
+ *
131
+ * In `defineDurableKindMulti` and its siblings, this defaults to `undefined`.
132
+ * Exo class kits use this internally to protect their facets.
133
+ * In absence, an exo is protected anyway, while a bare kind is
134
+ * not (detected by `!thisfulMethods`),
135
+ */
136
+ interfaceGuardKit?: InterfaceGuardKit;
137
+ };
138
+
139
+ export type VatData = {
140
+ // virtual kinds
141
+ /** @deprecated Use defineVirtualExoClass instead */
142
+ defineKind: <P, S, F>(
143
+ tag: string,
144
+ init: (...args: P) => S,
145
+ facet: F,
146
+ options?: DefineKindOptions<KindContext<S, F>>,
147
+ ) => (...args: P) => KindFacet<F>;
148
+
149
+ /** @deprecated Use defineVirtualExoClassKit instead */
150
+ defineKindMulti: <P, S, B>(
151
+ tag: string,
152
+ init: (...args: P) => S,
153
+ behavior: B,
154
+ options?: DefineKindOptions<MultiKindContext<S, B>>,
155
+ ) => (...args: P) => KindFacets<B>;
156
+
157
+ // durable kinds
158
+ makeKindHandle: (descriptionTag: string) => DurableKindHandle;
159
+
160
+ /** @deprecated Use defineDurableExoClass instead */
161
+ defineDurableKind: <P, S, F>(
162
+ kindHandle: DurableKindHandle,
163
+ init: (...args: P) => S,
164
+ facet: F,
165
+ options?: DefineKindOptions<KindContext<S, F>>,
166
+ ) => (...args: P) => KindFacet<F>;
167
+
168
+ /** @deprecated Use defineDurableExoClassKit instead */
169
+ defineDurableKindMulti: <P, S, B>(
170
+ kindHandle: DurableKindHandle,
171
+ init: (...args: P) => S,
172
+ behavior: B,
173
+ options?: DefineKindOptions<MultiKindContext<S, B>>,
174
+ ) => (...args: P) => KindFacets<B>;
175
+
176
+ providePromiseWatcher: WatchedPromisesManager['providePromiseWatcher'];
177
+ watchPromise: WatchedPromisesManager['watchPromise'];
178
+
179
+ makeScalarBigMapStore: <K, V>(
180
+ label: string,
181
+ options?: StoreOptions,
182
+ ) => MapStore<K, V>;
183
+ makeScalarBigWeakMapStore: <K, V>(
184
+ label: string,
185
+ options?: StoreOptions,
186
+ ) => WeakMapStore<K, V>;
187
+
188
+ makeScalarBigSetStore: <K>(
189
+ label: string,
190
+ options?: StoreOptions,
191
+ ) => SetStore<K>;
192
+ makeScalarBigWeakSetStore: <K>(
193
+ label: string,
194
+ options?: StoreOptions,
195
+ ) => WeakSetStore<K>;
196
+ canBeDurable: (specimen: unknown) => boolean;
197
+ };
198
+
199
+ // The JSDoc is repeated here and at the function definition so it appears
200
+ // in IDEs where it's used, regardless of type resolution.
201
+ export interface PickFacet {
202
+ /**
203
+ * When making a multi-facet kind, it's common to pick one facet to
204
+ * expose. E.g.,
205
+ *
206
+ * const makeFoo = (a, b, c, d) => makeFooBase(a, b, c, d).self;
207
+ *
208
+ * This helper reduces the duplication:
209
+ *
210
+ * const makeFoo = pickFacet(makeFooBase, 'self');
211
+ */
212
+ <M extends (...args: any[]) => any, F extends keyof ReturnType<M>>(
213
+ maker: M,
214
+ facetName: F,
215
+ ): (...args: Parameters<M>) => ReturnType<M>[F];
216
+ }
217
+
218
+ /** @deprecated Use prepareExoClass instead */
219
+ export type PrepareKind = <P, S, F>(
220
+ baggage: Baggage,
221
+ tag: string,
222
+ init: (...args: P) => S,
223
+ facet: F,
224
+ options?: DefineKindOptions<KindContext<S, F>>,
225
+ ) => (...args: P) => KindFacet<F>;
226
+
227
+ /** @deprecated Use prepareExoClassKit instead */
228
+ export type PrepareKindMulti = <P, S, B>(
229
+ baggage: Baggage,
230
+ tag: string,
231
+ init: (...args: P) => S,
232
+ behavior: B,
233
+ options?: DefineKindOptions<MultiKindContext<S, B>>,
234
+ ) => (...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);