@agoric/swingset-liveslots 0.10.3-other-dev-8f8782b.0 → 0.10.3-other-dev-3eb1a1d.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 (77) hide show
  1. package/README.md +2 -0
  2. package/package.json +27 -19
  3. package/src/boyd-gc.js +598 -0
  4. package/src/cache.js +3 -2
  5. package/src/capdata.js +1 -2
  6. package/src/collectionManager.js +219 -103
  7. package/src/facetiousness.js +1 -1
  8. package/src/index.js +4 -2
  9. package/src/liveslots.js +131 -301
  10. package/src/message.js +5 -5
  11. package/src/parseVatSlots.js +1 -1
  12. package/src/types-index.d.ts +4 -0
  13. package/src/types-index.js +2 -0
  14. package/src/types.js +8 -2
  15. package/src/vatstore-iterators.js +2 -0
  16. package/src/virtualObjectManager.js +185 -71
  17. package/src/virtualReferences.js +135 -26
  18. package/src/watchedPromises.js +67 -17
  19. package/test/{test-baggage.js → baggage.test.js} +1 -2
  20. package/test/{test-cache.js → cache.test.js} +0 -1
  21. package/test/clear-collection.test.js +586 -0
  22. package/test/{test-collection-schema-refcount.js → collection-schema-refcount.test.js} +1 -2
  23. package/test/{test-collection-upgrade.js → collection-upgrade.test.js} +1 -3
  24. package/test/{test-collections.js → collections.test.js} +158 -14
  25. package/test/{test-dropped-collection-weakrefs.js → dropped-collection-weakrefs.test.js} +1 -2
  26. package/test/dropped-weakset-9939.test.js +80 -0
  27. package/test/dummyMeterControl.js +1 -1
  28. package/test/{test-durabilityChecks.js → durabilityChecks.test.js} +4 -4
  29. package/test/exo-utils.js +70 -0
  30. package/test/{test-facetiousness.js → facetiousness.test.js} +1 -2
  31. package/test/gc-and-finalize.js +30 -1
  32. package/test/gc-before-finalizer.test.js +230 -0
  33. package/test/gc-helpers.js +2 -3
  34. package/test/{test-gc-sensitivity.js → gc-sensitivity.test.js} +2 -2
  35. package/test/handled-promises.test.js +506 -0
  36. package/test/{test-initial-vrefs.js → initial-vrefs.test.js} +2 -3
  37. package/test/liveslots-helpers.js +12 -7
  38. package/test/{test-liveslots-mock-gc.js → liveslots-mock-gc.test.js} +101 -2
  39. package/test/{test-liveslots-real-gc.js → liveslots-real-gc.test.js} +62 -37
  40. package/test/{test-liveslots.js → liveslots.test.js} +14 -15
  41. package/test/mock-gc.js +1 -0
  42. package/test/storeGC/{test-lifecycle.js → lifecycle.test.js} +2 -2
  43. package/test/storeGC/{test-refcount-management.js → refcount-management.test.js} +1 -2
  44. package/test/storeGC/{test-scalar-store-kind.js → scalar-store-kind.test.js} +0 -1
  45. package/test/storeGC/{test-weak-key.js → weak-key.test.js} +1 -2
  46. package/test/strict-test-env-upgrade.test.js +94 -0
  47. package/test/util.js +2 -2
  48. package/test/vat-environment.test.js +65 -0
  49. package/test/vat-util.js +2 -2
  50. package/test/virtual-objects/{test-cease-recognition.js → cease-recognition.test.js} +2 -2
  51. package/test/virtual-objects/{test-cross-facet.js → cross-facet.test.js} +5 -4
  52. package/test/virtual-objects/{test-empty-data.js → empty-data.test.js} +1 -2
  53. package/test/virtual-objects/{test-facets.js → facets.test.js} +1 -2
  54. package/test/virtual-objects/{test-kind-changes.js → kind-changes.test.js} +2 -2
  55. package/test/virtual-objects/{test-reachable-vrefs.js → reachable-vrefs.test.js} +2 -2
  56. package/test/virtual-objects/{test-rep-tostring.js → rep-tostring.test.js} +3 -5
  57. package/test/virtual-objects/{test-retain-remotable.js → retain-remotable.test.js} +25 -24
  58. package/test/virtual-objects/set-debug-label-instances.js +1 -1
  59. package/test/virtual-objects/{test-state-shape.js → state-shape.test.js} +2 -2
  60. package/test/virtual-objects/{test-virtualObjectGC.js → virtualObjectGC.test.js} +2 -2
  61. package/test/virtual-objects/{test-virtualObjectManager.js → virtualObjectManager.test.js} +126 -8
  62. package/test/virtual-objects/{test-vo-real-gc.js → vo-real-gc.test.js} +8 -8
  63. package/test/virtual-objects/{test-weakcollections-vref-handling.js → weakcollections-vref-handling.test.js} +1 -2
  64. package/test/{test-vo-test-harness.js → vo-test-harness.test.js} +0 -1
  65. package/test/{test-vpid-liveslots.js → vpid-liveslots.test.js} +105 -5
  66. package/test/waitUntilQuiescent.js +2 -1
  67. package/test/weakset-dropped-remotable.test.js +50 -0
  68. package/tools/fakeCollectionManager.js +44 -0
  69. package/tools/fakeVirtualObjectManager.js +62 -0
  70. package/tools/fakeVirtualSupport.js +389 -0
  71. package/tools/prepare-strict-test-env.js +124 -0
  72. package/tools/prepare-test-env.js +13 -0
  73. package/tools/setup-vat-data.js +96 -0
  74. package/tools/vo-test-harness.js +143 -0
  75. package/CHANGELOG.md +0 -61
  76. package/test/kmarshal.js +0 -79
  77. package/test/test-handled-promises.js +0 -360
@@ -0,0 +1,62 @@
1
+ import { makeVirtualObjectManager } from '../src/virtualObjectManager.js';
2
+
3
+ // Note: `fakeVirtualObjectManager` is something of a misnomer here. The
4
+ // virtual object manager being used to implement this realized by the actual
5
+ // virtual object manager code. What's being faked is everything else the
6
+ // virtual object manager is embedded in, i.e., the kernel and the rest of
7
+ // liveslots. In particular, this module can be (and is, and is intended to be)
8
+ // used for unit tests for the virtual object manager itself. What you get back
9
+ // from `makeFakeVirtualObjectManager` can't be used to program as if you were
10
+ // running in a vat because the rest of the vat environment is not present, but
11
+ // it *will* execute virtual object manager operations in the same way that the
12
+ // real one will because underneath it *is* the real one.
13
+
14
+ export function makeFakeVirtualObjectManager(vrm, fakeStuff) {
15
+ const {
16
+ initializeKindHandleKind,
17
+ defineKind,
18
+ defineKindMulti,
19
+ defineDurableKind,
20
+ defineDurableKindMulti,
21
+ makeKindHandle,
22
+ VirtualObjectAwareWeakMap,
23
+ VirtualObjectAwareWeakSet,
24
+ flushStateCache,
25
+ canBeDurable,
26
+ insistAllDurableKindsReconnected,
27
+ } = makeVirtualObjectManager(
28
+ fakeStuff.syscall,
29
+ vrm,
30
+ fakeStuff.allocateExportID,
31
+ fakeStuff.getSlotForVal,
32
+ fakeStuff.requiredValForSlot,
33
+ fakeStuff.registerEntry,
34
+ fakeStuff.marshal.serialize,
35
+ fakeStuff.marshal.unserialize,
36
+ fakeStuff.assertAcceptableSyscallCapdataSize,
37
+ );
38
+
39
+ const normalVOM = {
40
+ initializeKindHandleKind,
41
+ defineKind,
42
+ defineKindMulti,
43
+ defineDurableKind,
44
+ defineDurableKindMulti,
45
+ makeKindHandle,
46
+ canBeDurable,
47
+ insistAllDurableKindsReconnected,
48
+ VirtualObjectAwareWeakMap,
49
+ VirtualObjectAwareWeakSet,
50
+ };
51
+
52
+ const debugTools = {
53
+ getValForSlot: fakeStuff.getValForSlot,
54
+ setValForSlot: fakeStuff.setValForSlot,
55
+ registerEntry: fakeStuff.registerEntry,
56
+ deleteEntry: fakeStuff.deleteEntry,
57
+ flushStateCache,
58
+ dumpStore: fakeStuff.dumpStore,
59
+ };
60
+
61
+ return harden({ ...normalVOM, ...debugTools });
62
+ }
@@ -0,0 +1,389 @@
1
+ /* global globalThis */
2
+ /* eslint-disable max-classes-per-file */
3
+ import { assert, Fail } from '@endo/errors';
4
+ import { makeMarshal } from '@endo/marshal';
5
+ import { isPromise } from '@endo/promise-kit';
6
+
7
+ import { parseVatSlot } from '../src/parseVatSlots.js';
8
+ import { makeVirtualReferenceManager } from '../src/virtualReferences.js';
9
+ import { makeWatchedPromiseManager } from '../src/watchedPromises.js';
10
+ import { makeFakeVirtualObjectManager } from './fakeVirtualObjectManager.js';
11
+ import { makeFakeCollectionManager } from './fakeCollectionManager.js';
12
+
13
+ const {
14
+ WeakRef: RealWeakRef,
15
+ WeakMap: RealWeakMap,
16
+ WeakSet: RealWeakSet,
17
+ } = globalThis;
18
+
19
+ class FakeFinalizationRegistry {
20
+ // eslint-disable-next-line no-useless-constructor, no-empty-function
21
+ constructor() {}
22
+
23
+ // eslint-disable-next-line class-methods-use-this
24
+ register(_target, _heldValue, _unregisterToken) {}
25
+
26
+ // eslint-disable-next-line class-methods-use-this
27
+ unregister(_unregisterToken) {}
28
+ }
29
+
30
+ class FakeWeakRef {
31
+ #target;
32
+
33
+ constructor(target) {
34
+ this.#target = target;
35
+ }
36
+
37
+ deref() {
38
+ return this.#target; // strong ref
39
+ }
40
+ }
41
+
42
+ export function makeFakeLiveSlotsStuff(options = {}) {
43
+ let vrm;
44
+ function setVrm(vrmToUse) {
45
+ assert(!vrm, 'vrm already configured');
46
+ vrmToUse.initializeIDCounters();
47
+ vrm = vrmToUse;
48
+ }
49
+
50
+ const {
51
+ fakeStore = new Map(),
52
+ weak = false,
53
+ log,
54
+ FinalizationRegistry = FakeFinalizationRegistry,
55
+ WeakRef = FakeWeakRef, // VRM uses this
56
+ WeakMap = RealWeakMap,
57
+ WeakSet = RealWeakSet,
58
+ addToPossiblyDeadSet = () => {},
59
+ addToPossiblyRetiredSet = () => {},
60
+ } = options;
61
+
62
+ let sortedKeys;
63
+ let priorKeyReturned;
64
+ let priorKeyIndex;
65
+
66
+ function s(v) {
67
+ switch (typeof v) {
68
+ case 'symbol':
69
+ return v.toString();
70
+ case 'bigint':
71
+ return `${v}n`;
72
+ default:
73
+ return `${v}`;
74
+ }
75
+ }
76
+
77
+ function ensureSorted() {
78
+ if (!sortedKeys) {
79
+ sortedKeys = [];
80
+ for (const key of fakeStore.keys()) {
81
+ sortedKeys.push(key);
82
+ }
83
+ sortedKeys.sort((k1, k2) => k1.localeCompare(k2));
84
+ }
85
+ }
86
+
87
+ function clearGetNextKeyCache() {
88
+ priorKeyReturned = undefined;
89
+ priorKeyIndex = -1;
90
+ }
91
+ clearGetNextKeyCache();
92
+
93
+ function clearSorted() {
94
+ sortedKeys = undefined;
95
+ clearGetNextKeyCache();
96
+ }
97
+
98
+ function dumpStore() {
99
+ ensureSorted();
100
+ const result = [];
101
+ for (const key of sortedKeys) {
102
+ result.push([key, fakeStore.get(key)]);
103
+ }
104
+ return result;
105
+ }
106
+
107
+ const syscall = {
108
+ vatstoreGet(key) {
109
+ const result = fakeStore.get(key);
110
+ if (log) {
111
+ log.push(`get ${s(key)} => ${s(result)}`);
112
+ }
113
+ return result;
114
+ },
115
+ vatstoreGetNextKey(priorKey) {
116
+ assert.typeof(priorKey, 'string');
117
+ ensureSorted();
118
+ // TODO: binary search for priorKey (maybe missing), then get
119
+ // the one after that. For now we go simple and slow. But cache
120
+ // a starting point, because the main use case is a full
121
+ // iteration. OTOH, the main use case also deletes everything,
122
+ // which will clobber the cache on each deletion, so it might
123
+ // not help.
124
+ const start = priorKeyReturned === priorKey ? priorKeyIndex : 0;
125
+ let result;
126
+ for (let i = start; i < sortedKeys.length; i += 1) {
127
+ const key = sortedKeys[i];
128
+ if (key > priorKey) {
129
+ priorKeyReturned = key;
130
+ priorKeyIndex = i;
131
+ result = key;
132
+ break;
133
+ }
134
+ }
135
+ if (!result) {
136
+ // reached end without finding the key, so clear our cache
137
+ clearGetNextKeyCache();
138
+ }
139
+ if (log) {
140
+ log.push(`getNextKey ${s(priorKey)} => ${s(result)}`);
141
+ }
142
+ return result;
143
+ },
144
+ vatstoreSet(key, value) {
145
+ if (log) {
146
+ log.push(`set ${s(key)} ${s(value)}`);
147
+ }
148
+ if (!fakeStore.has(key)) {
149
+ clearSorted();
150
+ }
151
+ fakeStore.set(key, value);
152
+ },
153
+ vatstoreDelete(key) {
154
+ if (log) {
155
+ log.push(`delete ${s(key)}`);
156
+ }
157
+ if (fakeStore.has(key)) {
158
+ clearSorted();
159
+ }
160
+ fakeStore.delete(key);
161
+ },
162
+ };
163
+
164
+ function allocateExportID() {
165
+ return vrm.allocateNextID('exportID');
166
+ }
167
+
168
+ function allocatePromiseID() {
169
+ return vrm.allocateNextID('promiseID');
170
+ }
171
+
172
+ function allocateCollectionID() {
173
+ return vrm.allocateNextID('collectionID');
174
+ }
175
+
176
+ // note: The real liveslots slotToVal() maps slots (vrefs) to a WeakRef,
177
+ // and the WeakRef may or may not contain the target value. Use
178
+ // options={weak:true} to match that behavior, or the default weak:false to
179
+ // keep strong references.
180
+ const WeakRefForSlot = weak ? RealWeakRef : FakeWeakRef;
181
+ const valToSlot = new WeakMap();
182
+ const slotToVal = new Map();
183
+
184
+ function getSlotForVal(val) {
185
+ return valToSlot.get(val);
186
+ }
187
+
188
+ function getValForSlot(slot) {
189
+ const d = slotToVal.get(slot);
190
+ return d && d.deref();
191
+ }
192
+
193
+ function requiredValForSlot(slot) {
194
+ const val = getValForSlot(slot);
195
+ assert(val, `${slot} must have a value`);
196
+ return val;
197
+ }
198
+
199
+ function setValForSlot(slot, val) {
200
+ slotToVal.set(slot, new WeakRefForSlot(val));
201
+ }
202
+
203
+ function convertValToSlot(val) {
204
+ if (!valToSlot.has(val)) {
205
+ const slot = isPromise(val)
206
+ ? `p+${allocatePromiseID()}`
207
+ : `o+${allocateExportID()}`;
208
+ valToSlot.set(val, slot);
209
+ setValForSlot(slot, val);
210
+ }
211
+ return valToSlot.get(val);
212
+ }
213
+
214
+ function convertSlotToVal(slot) {
215
+ const { type, id, virtual, durable, facet, baseRef } = parseVatSlot(slot);
216
+ assert.equal(type, 'object');
217
+ let val = getValForSlot(baseRef);
218
+ if (val) {
219
+ if (virtual || durable) {
220
+ if (facet !== undefined) {
221
+ return vrm.getFacet(id, val, facet);
222
+ }
223
+ }
224
+ return val;
225
+ }
226
+ let result;
227
+ if (virtual || durable) {
228
+ if (vrm) {
229
+ val = vrm.reanimate(slot);
230
+ if (facet !== undefined) {
231
+ result = vrm.getFacet(id, val, facet);
232
+ }
233
+ } else {
234
+ assert.fail('fake liveSlots stuff configured without vrm');
235
+ }
236
+ }
237
+ registerEntry(baseRef, val, facet !== undefined);
238
+ if (!result) {
239
+ result = val;
240
+ }
241
+ return result;
242
+ }
243
+
244
+ const marshal = makeMarshal(convertValToSlot, convertSlotToVal, {
245
+ serializeBodyFormat: 'smallcaps',
246
+ marshalName: 'fakeLiveSlots',
247
+ errorIdNum: 80_000,
248
+ marshalSaveError: _err => {},
249
+ });
250
+
251
+ function registerEntry(baseRef, val, valIsCohort) {
252
+ const { facet } = parseVatSlot(baseRef);
253
+ !facet ||
254
+ Fail`registerEntry(${baseRef} should not receive individual facets`;
255
+ setValForSlot(baseRef, val);
256
+ if (valIsCohort) {
257
+ const { id } = parseVatSlot(baseRef);
258
+ for (const [index, name] of vrm.getFacetNames(id).entries()) {
259
+ valToSlot.set(val[name], `${baseRef}:${index}`);
260
+ }
261
+ } else {
262
+ valToSlot.set(val, baseRef);
263
+ }
264
+ }
265
+
266
+ function deleteEntry(slot, val) {
267
+ if (!val) {
268
+ val = getValForSlot(slot);
269
+ }
270
+ slotToVal.delete(slot);
271
+ valToSlot.delete(val);
272
+ }
273
+
274
+ function assertAcceptableSyscallCapdataSize(_capdatas) {}
275
+
276
+ const maybeExportPromise = _vref => false;
277
+
278
+ return {
279
+ syscall,
280
+ allocateExportID,
281
+ allocatePromiseID,
282
+ allocateCollectionID,
283
+ getSlotForVal,
284
+ requiredValForSlot,
285
+ getValForSlot,
286
+ setValForSlot,
287
+ registerEntry,
288
+ valToSlot,
289
+ slotToVal,
290
+ convertValToSlot,
291
+ convertSlotToVal,
292
+ marshal,
293
+ deleteEntry,
294
+ FinalizationRegistry,
295
+ WeakRef,
296
+ WeakMap,
297
+ WeakSet,
298
+ addToPossiblyDeadSet,
299
+ addToPossiblyRetiredSet,
300
+ dumpStore,
301
+ setVrm,
302
+ assertAcceptableSyscallCapdataSize,
303
+ maybeExportPromise,
304
+ };
305
+ }
306
+
307
+ export function makeFakeVirtualReferenceManager(
308
+ fakeStuff,
309
+ relaxDurabilityRules = true,
310
+ ) {
311
+ return makeVirtualReferenceManager(
312
+ fakeStuff.syscall,
313
+ fakeStuff.getSlotForVal,
314
+ fakeStuff.getValForSlot,
315
+ fakeStuff.FinalizationRegistry,
316
+ fakeStuff.WeakRef,
317
+ fakeStuff.addToPossiblyDeadSet,
318
+ fakeStuff.addToPossiblyRetiredSet,
319
+ relaxDurabilityRules,
320
+ );
321
+ }
322
+
323
+ export function makeFakeWatchedPromiseManager(
324
+ vrm,
325
+ vom,
326
+ collectionManager,
327
+ fakeStuff,
328
+ ) {
329
+ return makeWatchedPromiseManager({
330
+ syscall: fakeStuff.syscall,
331
+ vrm,
332
+ vom,
333
+ collectionManager,
334
+ convertValToSlot: fakeStuff.convertValToSlot,
335
+ convertSlotToVal: fakeStuff.convertSlotToVal,
336
+ maybeExportPromise: fakeStuff.maybeExportPromise,
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Configure virtual stuff with relaxed durability rules and fake liveslots
342
+ *
343
+ * @param {object} [options]
344
+ * @param {number} [options.cacheSize]
345
+ * @param {boolean} [options.relaxDurabilityRules]
346
+ * @param {Map<string, string>} [options.fakeStore]
347
+ * @param {WeakMapConstructor} [options.WeakMap]
348
+ * @param {WeakSetConstructor} [options.WeakSet]
349
+ * @param {boolean} [options.weak]
350
+ */
351
+ export function makeFakeVirtualStuff(options = {}) {
352
+ const actualOptions = {
353
+ relaxDurabilityRules: true,
354
+ ...options,
355
+ };
356
+ const { relaxDurabilityRules } = actualOptions;
357
+ const fakeStuff = makeFakeLiveSlotsStuff(actualOptions);
358
+ const vrm = makeFakeVirtualReferenceManager(fakeStuff, relaxDurabilityRules);
359
+ fakeStuff.setVrm(vrm);
360
+ const vom = makeFakeVirtualObjectManager(vrm, fakeStuff);
361
+ vom.initializeKindHandleKind();
362
+ const cm = makeFakeCollectionManager(vrm, fakeStuff, actualOptions);
363
+ const wpm = makeFakeWatchedPromiseManager(vrm, vom, cm, fakeStuff);
364
+ wpm.preparePromiseWatcherTables();
365
+ return { fakeStuff, vrm, vom, cm, wpm };
366
+ }
367
+
368
+ export function makeStandaloneFakeVirtualObjectManager(options = {}) {
369
+ const fakeStuff = makeFakeLiveSlotsStuff(options);
370
+ const { relaxDurabilityRules = true } = options;
371
+ const vrm = makeFakeVirtualReferenceManager(fakeStuff, relaxDurabilityRules);
372
+ fakeStuff.setVrm(vrm);
373
+ const vom = makeFakeVirtualObjectManager(vrm, fakeStuff);
374
+ vom.initializeKindHandleKind();
375
+ return vom;
376
+ }
377
+
378
+ export function makeStandaloneFakeCollectionManager(options = {}) {
379
+ const fakeStuff = makeFakeLiveSlotsStuff(options);
380
+ const { relaxDurabilityRules = true } = options;
381
+ const vrm = makeFakeVirtualReferenceManager(fakeStuff, relaxDurabilityRules);
382
+ fakeStuff.setVrm(vrm);
383
+ return makeFakeCollectionManager(vrm, fakeStuff, options);
384
+ }
385
+
386
+ export {
387
+ makeStandaloneFakeVirtualObjectManager as makeFakeVirtualObjectManager,
388
+ makeStandaloneFakeCollectionManager as makeFakeCollectionManager,
389
+ };
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Prepare Agoric SwingSet vat global strict environment for testing.
3
+ *
4
+ * Installs Hardened JS (and does lockdown), plus adds mocks for virtual objects
5
+ * and stores.
6
+ *
7
+ * Exports tools for simulating upgrades.
8
+ */
9
+
10
+ import '@agoric/internal/src/install-ses-debug.js';
11
+
12
+ // eslint-disable-next-line import/order
13
+ import { reincarnate, flushIncarnation } from './setup-vat-data.js';
14
+
15
+ import { makePromiseKit } from '@endo/promise-kit';
16
+ import { Fail } from '@endo/errors';
17
+ import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';
18
+ import { makeUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';
19
+
20
+ export { flushIncarnation };
21
+ export { eventLoopIteration as nextCrank };
22
+
23
+ /**
24
+ * @import { PromiseKit } from '@endo/promise-kit'
25
+ * @import { Baggage } from '@agoric/swingset-liveslots'
26
+ * @import { ReincarnateOptions } from './setup-vat-data.js'
27
+ */
28
+
29
+ /** @type {ReincarnateOptions} */
30
+ let incarnation;
31
+ let incarnationNumber = 0;
32
+
33
+ /** @param {Omit<ReincarnateOptions, 'fakeVomKit' | 'fakeStore'>} [options] */
34
+ export const annihilate = (options = {}) => {
35
+ // @ts-expect-error fakeStore and fakeVomKit don't exist on type, but drop them if they do at runtime
36
+ const { fakeStore: _fs, fakeVomKit: _fvk, ...opts } = options;
37
+ incarnation = reincarnate({ relaxDurabilityRules: false, ...opts });
38
+ incarnationNumber = 0;
39
+ return incarnation;
40
+ };
41
+
42
+ /** @returns {Baggage} */
43
+ export const getBaggage = () => {
44
+ return incarnation.fakeVomKit.cm.provideBaggage();
45
+ };
46
+
47
+ /**
48
+ * @param {ReincarnateOptions} [fromIncarnation]
49
+ */
50
+ export const nextLife = (fromIncarnation = incarnation) => {
51
+ incarnation = reincarnate(fromIncarnation);
52
+ incarnationNumber += 1;
53
+ return incarnation;
54
+ };
55
+
56
+ /**
57
+ * @template {(baggage: Baggage) => Promise<any> | any} B
58
+ * @param {B} build
59
+ * @param {(tools: Awaited<ReturnType<B>>) => Promise<void> | void} [run]
60
+ * @param {object} [options]
61
+ * @param {ReincarnateOptions} [options.fromIncarnation]
62
+ * @param {boolean} [options.cleanStart]
63
+ */
64
+ export const startLife = async (
65
+ build,
66
+ run,
67
+ { fromIncarnation, cleanStart } = {},
68
+ ) => {
69
+ await eventLoopIteration();
70
+ if (cleanStart) annihilate();
71
+ const oldIncarnationNumber = incarnationNumber;
72
+ const oldIncarnation = incarnation;
73
+ const disconnectionObject = makeUpgradeDisconnection(
74
+ 'vat upgraded',
75
+ oldIncarnationNumber,
76
+ );
77
+ const { fakeVomKit } = nextLife(fromIncarnation);
78
+ /** @type {Map<string, PromiseKit<any>>} */
79
+ const previouslyWatchedPromises = new Map();
80
+ let buildTools;
81
+ try {
82
+ buildTools = await build(getBaggage());
83
+ fakeVomKit.wpm.loadWatchedPromiseTable(vref => {
84
+ // See revivePromise in liveslots.js
85
+ const { getValForSlot, valToSlot, setValForSlot } = fakeVomKit.fakeStuff;
86
+ // Assume all promises were decided by the previous incarnation
87
+ !getValForSlot(vref) || Fail`Attempting to revive known promise ${vref}`;
88
+ const pk = makePromiseKit();
89
+ previouslyWatchedPromises.set(vref, pk);
90
+ const val = pk.promise;
91
+ valToSlot.set(val, vref);
92
+ setValForSlot(vref, val);
93
+ return val;
94
+ });
95
+
96
+ fakeVomKit.vom.insistAllDurableKindsReconnected();
97
+
98
+ await eventLoopIteration();
99
+ // End of start crank
100
+ } catch (err) {
101
+ // Rollback upgrade
102
+ incarnation = oldIncarnation;
103
+ incarnationNumber = oldIncarnationNumber;
104
+ throw err;
105
+ }
106
+
107
+ // Simulate a dispatch of previously decided promise rejections
108
+ // In real swingset this could happen after some deliveries
109
+ for (const { reject } of previouslyWatchedPromises.values()) {
110
+ reject(disconnectionObject);
111
+ }
112
+ await eventLoopIteration();
113
+ // End of resolution dispatch crank
114
+
115
+ if (run) {
116
+ await run(buildTools);
117
+ await eventLoopIteration();
118
+ }
119
+
120
+ return incarnation;
121
+ };
122
+
123
+ // Setup the initial incarnation
124
+ annihilate();
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Prepare Agoric SwingSet vat global environment for testing.
3
+ *
4
+ * Installs Hardened JS (and does lockdown), plus adds mocks for virtual objects
5
+ * and stores.
6
+ */
7
+
8
+ import '@agoric/internal/src/install-ses-debug.js';
9
+
10
+ import { reincarnate } from './setup-vat-data.js';
11
+
12
+ // Install the VatData globals.
13
+ reincarnate();
@@ -0,0 +1,96 @@
1
+ // @ts-check
2
+ /* global globalThis */
3
+
4
+ // This file produces the globalThis.VatData property outside of a
5
+ // running SwingSet so that it can be used by '@agoric/vat-data'
6
+ // (which only *consumes* `globalThis.VatData`) in code under test. It
7
+ // also populates the passStyleOf symbol-named property.
8
+
9
+ import { passStyleOf } from '@endo/pass-style';
10
+ import { PassStyleOfEndowmentSymbol } from '@endo/pass-style/endow.js';
11
+ import { makeFakeVirtualStuff } from './fakeVirtualSupport.js';
12
+
13
+ const { WeakMap, WeakSet } = globalThis;
14
+
15
+ /** @typedef {ReturnType<typeof makeFakeVirtualStuff>} FakeVomKit */
16
+
17
+ /** @type {FakeVomKit} */
18
+ let fakeVomKit;
19
+
20
+ globalThis.VatData = harden({
21
+ // @ts-expect-error spread argument for non-rest parameter
22
+ defineKind: (...args) => fakeVomKit.vom.defineKind(...args),
23
+ // @ts-expect-error spread argument for non-rest parameter
24
+ defineKindMulti: (...args) => fakeVomKit.vom.defineKindMulti(...args),
25
+ // @ts-expect-error spread argument for non-rest parameter
26
+ defineDurableKind: (...args) => fakeVomKit.vom.defineDurableKind(...args),
27
+ defineDurableKindMulti: (...args) =>
28
+ // @ts-expect-error spread argument for non-rest parameter
29
+ fakeVomKit.vom.defineDurableKindMulti(...args),
30
+ makeKindHandle: tag => fakeVomKit.vom.makeKindHandle(tag),
31
+ canBeDurable: (...args) => fakeVomKit.vom.canBeDurable(...args),
32
+ providePromiseWatcher: (...args) =>
33
+ // @ts-expect-error spread argument for non-rest parameter
34
+ fakeVomKit.wpm.providePromiseWatcher(...args),
35
+ watchPromise: (p, watcher, ...args) =>
36
+ fakeVomKit.wpm.watchPromise(p, watcher, ...args),
37
+ makeScalarBigMapStore: (...args) =>
38
+ fakeVomKit.cm.makeScalarBigMapStore(...args),
39
+ makeScalarBigWeakMapStore: (...args) =>
40
+ fakeVomKit.cm.makeScalarBigWeakMapStore(...args),
41
+ makeScalarBigSetStore: (...args) =>
42
+ fakeVomKit.cm.makeScalarBigSetStore(...args),
43
+ makeScalarBigWeakSetStore: (...args) =>
44
+ fakeVomKit.cm.makeScalarBigWeakSetStore(...args),
45
+ });
46
+
47
+ globalThis[PassStyleOfEndowmentSymbol] = passStyleOf;
48
+
49
+ /**
50
+ * @typedef {import("@agoric/internal").Simplify<
51
+ * Omit<NonNullable<Parameters<typeof makeFakeVirtualStuff>[0]>, 'WeakMap' | 'WeakSet'> &
52
+ * { fakeVomKit: FakeVomKit; fakeStore: Map<string, string> }
53
+ * >} ReincarnateOptions
54
+ */
55
+
56
+ /**
57
+ *
58
+ * @param {Partial<ReincarnateOptions>} options
59
+ * @returns {Omit<ReincarnateOptions, 'fakeVomKit'>}
60
+ */
61
+ export const flushIncarnation = (options = {}) => {
62
+ const { fakeVomKit: fvk = fakeVomKit, ...fakeStuffOptions } = options;
63
+
64
+ if (fvk) {
65
+ fvk.vom.flushStateCache();
66
+ fvk.cm.flushSchemaCache();
67
+ fvk.vrm.flushIDCounters();
68
+ }
69
+
70
+ // Clone previous fakeStore (if any) to avoid mutations from previous incarnation
71
+ const fakeStore = new Map(options.fakeStore);
72
+
73
+ return { ...fakeStuffOptions, fakeStore };
74
+ };
75
+
76
+ /**
77
+ *
78
+ * @param {Partial<ReincarnateOptions>} options
79
+ * @returns {ReincarnateOptions}
80
+ */
81
+ export const reincarnate = (options = {}) => {
82
+ const clonedIncarnation = flushIncarnation(options);
83
+
84
+ fakeVomKit = makeFakeVirtualStuff({
85
+ ...clonedIncarnation,
86
+ WeakMap,
87
+ WeakSet,
88
+ });
89
+
90
+ // @ts-expect-error toStringTag set imperatively so it doesn't show up in the type
91
+ globalThis.WeakMap = fakeVomKit.vom.VirtualObjectAwareWeakMap;
92
+ // @ts-expect-error ditto
93
+ globalThis.WeakSet = fakeVomKit.vom.VirtualObjectAwareWeakSet;
94
+
95
+ return { ...clonedIncarnation, fakeVomKit };
96
+ };