@agoric/swingset-liveslots 0.10.3-u17.1 → 0.10.3-u18.1

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-liveslots",
3
- "version": "0.10.3-u17.1",
3
+ "version": "0.10.3-u18.1",
4
4
  "description": "SwingSet ocap support layer",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -17,22 +17,22 @@
17
17
  "lint:eslint": "eslint ."
18
18
  },
19
19
  "dependencies": {
20
- "@agoric/internal": "^0.4.0-u17.1",
21
- "@agoric/store": "^0.9.3-u17.1",
22
- "@endo/env-options": "^1.1.6",
23
- "@endo/errors": "^1.2.5",
24
- "@endo/eventual-send": "^1.2.5",
25
- "@endo/exo": "^1.5.3",
26
- "@endo/far": "^1.1.5",
27
- "@endo/init": "^1.1.4",
28
- "@endo/marshal": "^1.5.3",
29
- "@endo/nat": "^5.0.10",
30
- "@endo/pass-style": "^1.4.3",
31
- "@endo/patterns": "^1.4.3",
32
- "@endo/promise-kit": "^1.1.5"
20
+ "@agoric/internal": "^0.4.0-u18.1",
21
+ "@agoric/store": "^0.9.3-u18.1",
22
+ "@endo/env-options": "^1.1.8",
23
+ "@endo/errors": "^1.2.8",
24
+ "@endo/eventual-send": "^1.2.8",
25
+ "@endo/exo": "^1.5.7",
26
+ "@endo/far": "^1.1.9",
27
+ "@endo/init": "^1.1.7",
28
+ "@endo/marshal": "^1.6.2",
29
+ "@endo/nat": "^5.0.13",
30
+ "@endo/pass-style": "^1.4.7",
31
+ "@endo/patterns": "^1.4.7",
32
+ "@endo/promise-kit": "^1.1.8"
33
33
  },
34
34
  "devDependencies": {
35
- "@agoric/kmarshal": "^0.1.1-u17.1",
35
+ "@agoric/kmarshal": "^0.1.1-u18.1",
36
36
  "ava": "^5.3.0"
37
37
  },
38
38
  "files": [
@@ -66,7 +66,7 @@
66
66
  "access": "public"
67
67
  },
68
68
  "typeCoverage": {
69
- "atLeast": 75.1
69
+ "atLeast": 75.24
70
70
  },
71
- "gitHead": "5259430561693bfcf58516c3ea54123895859708"
71
+ "gitHead": "f8c45b8a2e29a51522a81a6692af25b2d7f6b50f"
72
72
  }
@@ -146,56 +146,48 @@ export function makeCollectionManager(
146
146
  scalarMapStore: {
147
147
  hasWeakKeys: false,
148
148
  kindID: 0,
149
- // eslint-disable-next-line no-use-before-define
150
149
  reanimator: reanimateMapStore,
151
150
  durable: false,
152
151
  },
153
152
  scalarWeakMapStore: {
154
153
  hasWeakKeys: true,
155
154
  kindID: 0,
156
- // eslint-disable-next-line no-use-before-define
157
155
  reanimator: reanimateWeakMapStore,
158
156
  durable: false,
159
157
  },
160
158
  scalarSetStore: {
161
159
  hasWeakKeys: false,
162
160
  kindID: 0,
163
- // eslint-disable-next-line no-use-before-define
164
161
  reanimator: reanimateSetStore,
165
162
  durable: false,
166
163
  },
167
164
  scalarWeakSetStore: {
168
165
  hasWeakKeys: true,
169
166
  kindID: 0,
170
- // eslint-disable-next-line no-use-before-define
171
167
  reanimator: reanimateWeakSetStore,
172
168
  durable: false,
173
169
  },
174
170
  scalarDurableMapStore: {
175
171
  hasWeakKeys: false,
176
172
  kindID: 0,
177
- // eslint-disable-next-line no-use-before-define
178
173
  reanimator: reanimateMapStore,
179
174
  durable: true,
180
175
  },
181
176
  scalarDurableWeakMapStore: {
182
177
  hasWeakKeys: true,
183
178
  kindID: 0,
184
- // eslint-disable-next-line no-use-before-define
185
179
  reanimator: reanimateWeakMapStore,
186
180
  durable: true,
187
181
  },
188
182
  scalarDurableSetStore: {
189
183
  hasWeakKeys: false,
190
184
  kindID: 0,
191
- // eslint-disable-next-line no-use-before-define
192
185
  reanimator: reanimateSetStore,
193
186
  durable: true,
194
187
  },
195
188
  scalarDurableWeakSetStore: {
196
189
  hasWeakKeys: true,
197
190
  kindID: 0,
198
- // eslint-disable-next-line no-use-before-define
199
191
  reanimator: reanimateWeakSetStore,
200
192
  durable: true,
201
193
  },
@@ -218,7 +210,6 @@ export function makeCollectionManager(
218
210
  vrm.registerKind(
219
211
  kindID,
220
212
  storeKindInfo[kind].reanimator,
221
- // eslint-disable-next-line no-use-before-define
222
213
  deleteCollection,
223
214
  storeKindInfo[kind].durable,
224
215
  );
@@ -313,7 +304,6 @@ export function makeCollectionManager(
313
304
  // * vref(o-4) -> "vc.5.r0000000001:o-4"
314
305
 
315
306
  const encodeRemotable = remotable => {
316
- // eslint-disable-next-line no-use-before-define
317
307
  const ordinal = getOrdinal(remotable);
318
308
  ordinal !== undefined || Fail`no ordinal for ${remotable}`;
319
309
  const ordinalTag = zeroPad(ordinal, BIGINT_TAG_LEN);
package/src/index.js CHANGED
@@ -11,5 +11,4 @@ export {
11
11
  insistVatSyscallResult,
12
12
  } from './message.js';
13
13
 
14
- export * from './types.js';
15
- export * from './vatDataTypes.js';
14
+ export * from './types-index.js';
package/src/liveslots.js CHANGED
@@ -155,10 +155,8 @@ function build(
155
155
  const { type, allocatedByVat, virtual, durable } = parseVatSlot(vref);
156
156
  if (type === 'object' && allocatedByVat) {
157
157
  if (virtual || durable) {
158
- // eslint-disable-next-line no-use-before-define
159
158
  vrm.setExportStatus(vref, 'reachable');
160
159
  } else {
161
- // eslint-disable-next-line no-use-before-define
162
160
  const remotable = requiredValForSlot(vref);
163
161
  exportedRemotables.add(remotable);
164
162
  kernelRecognizableRemotables.add(vref);
@@ -183,7 +181,6 @@ function build(
183
181
 
184
182
  if (wr && !wr.deref()) {
185
183
  // we're in the COLLECTED state, or FINALIZED after a re-introduction
186
- // eslint-disable-next-line no-use-before-define
187
184
  addToPossiblyDeadSet(baseRef);
188
185
  slotToVal.delete(baseRef);
189
186
  }
@@ -209,11 +206,9 @@ function build(
209
206
  // Support: o~.[prop](...args) remote method invocation
210
207
  lsdebug(`makeImportedPresence handler.applyMethod (${slot})`);
211
208
  if (disavowedPresences.has(o)) {
212
- // eslint-disable-next-line no-use-before-define
213
209
  exitVatWithFailure(disavowalError);
214
210
  throw disavowalError;
215
211
  }
216
- // eslint-disable-next-line no-use-before-define
217
212
  return queueMessage(slot, prop, args, returnedP);
218
213
  },
219
214
  applyFunction(o, args, returnedP) {
@@ -222,7 +217,6 @@ function build(
222
217
  get(o, prop) {
223
218
  lsdebug(`makeImportedPresence handler.get (${slot})`);
224
219
  if (disavowedPresences.has(o)) {
225
- // eslint-disable-next-line no-use-before-define
226
220
  exitVatWithFailure(disavowalError);
227
221
  throw disavowalError;
228
222
  }
@@ -294,7 +288,6 @@ function build(
294
288
  console.error(`mIPromise handler called after resolution`);
295
289
  Fail`mIPromise handler called after resolution`;
296
290
  }
297
- // eslint-disable-next-line no-use-before-define
298
291
  return queueMessage(vpid, prop, args, returnedP);
299
292
  },
300
293
  get(p, prop) {
@@ -347,17 +340,14 @@ function build(
347
340
  // use a slot from the corresponding allocateX
348
341
 
349
342
  function allocateExportID() {
350
- // eslint-disable-next-line no-use-before-define
351
343
  return vrm.allocateNextID('exportID');
352
344
  }
353
345
 
354
346
  function allocateCollectionID() {
355
- // eslint-disable-next-line no-use-before-define
356
347
  return vrm.allocateNextID('collectionID');
357
348
  }
358
349
 
359
350
  function allocatePromiseID() {
360
- // eslint-disable-next-line no-use-before-define
361
351
  const promiseID = vrm.allocateNextID('promiseID');
362
352
  return makeVatSlot('promise', true, promiseID);
363
353
  }
@@ -385,10 +375,8 @@ function build(
385
375
  // do a syscall.resolve when it fires. The caller must finish
386
376
  // doing their syscall before this turn finishes, to ensure the
387
377
  // kernel isn't surprised by a spurious resolution.
388
- // eslint-disable-next-line no-use-before-define
389
378
  const p = requiredValForSlot(vpid);
390
379
  // if (!knownResolutions.has(p)) { // TODO really?
391
- // eslint-disable-next-line no-use-before-define
392
380
  followForKernel(vpid, p);
393
381
  return true;
394
382
  }
@@ -400,7 +388,6 @@ function build(
400
388
  return makeVatSlot('object', true, exportID);
401
389
  }
402
390
 
403
- // eslint-disable-next-line no-use-before-define
404
391
  const m = makeMarshal(convertValToSlot, convertSlotToVal, {
405
392
  marshalName: `liveSlots:${forVatID}`,
406
393
  serializeBodyFormat: 'smallcaps',
@@ -413,7 +400,6 @@ function build(
413
400
  console.warn('Logging sent error stack', err),
414
401
  });
415
402
  const unmeteredUnserialize = meterControl.unmetered(m.unserialize);
416
- // eslint-disable-next-line no-use-before-define
417
403
  const unmeteredConvertSlotToVal = meterControl.unmetered(convertSlotToVal);
418
404
 
419
405
  function getSlotForVal(val) {
@@ -458,7 +444,6 @@ function build(
458
444
  allocateExportID,
459
445
  getSlotForVal,
460
446
  requiredValForSlot,
461
- // eslint-disable-next-line no-use-before-define
462
447
  registerValue,
463
448
  m.serialize,
464
449
  unmeteredUnserialize,
@@ -471,10 +456,8 @@ function build(
471
456
  vrm,
472
457
  allocateExportID,
473
458
  allocateCollectionID,
474
- // eslint-disable-next-line no-use-before-define
475
459
  convertValToSlot,
476
460
  unmeteredConvertSlotToVal,
477
- // eslint-disable-next-line no-use-before-define
478
461
  registerValue,
479
462
  m.serialize,
480
463
  unmeteredUnserialize,
@@ -486,7 +469,6 @@ function build(
486
469
  vrm,
487
470
  vom,
488
471
  collectionManager,
489
- // eslint-disable-next-line no-use-before-define
490
472
  convertValToSlot,
491
473
  convertSlotToVal: unmeteredConvertSlotToVal,
492
474
  maybeExportPromise,
@@ -516,7 +498,6 @@ function build(
516
498
  slot = allocatePromiseID();
517
499
  } else {
518
500
  if (disavowedPresences.has(val)) {
519
- // eslint-disable-next-line no-use-before-define
520
501
  exitVatWithFailure(disavowalError);
521
502
  throw disavowalError; // cannot reference a disavowed object
522
503
  }
@@ -686,7 +667,6 @@ function build(
686
667
  const priorResolution = knownResolutions.get(p);
687
668
  if (priorResolution && !doneResolutions.has(slot)) {
688
669
  const [priorRejected, priorRes] = priorResolution;
689
- // eslint-disable-next-line no-use-before-define
690
670
  collect(slot, priorRejected, priorRes);
691
671
  }
692
672
  }
@@ -972,7 +952,6 @@ function build(
972
952
  }
973
953
  // in both cases, we are now the decider, so treat it like an
974
954
  // exported promise
975
- // eslint-disable-next-line no-use-before-define
976
955
  followForKernel(resultVPID, p);
977
956
  }
978
957
  }
@@ -1249,7 +1228,6 @@ function build(
1249
1228
  possiblyRetiredSet,
1250
1229
  slotToVal,
1251
1230
  valToSlot,
1252
- // eslint-disable-next-line no-use-before-define
1253
1231
  afterDispatchActions,
1254
1232
  });
1255
1233
 
@@ -1341,7 +1319,7 @@ function build(
1341
1319
 
1342
1320
  /**
1343
1321
  * @param {import('./types.js').VatDeliveryObject} delivery
1344
- * @returns {void | Promise<void>}
1322
+ * @returns {undefined | ReturnType<startVat>}
1345
1323
  */
1346
1324
  function dispatchToUserspace(delivery) {
1347
1325
  let result;
@@ -0,0 +1,4 @@
1
+ // Export all the types this package provides
2
+ // eslint-disable-next-line import/export
3
+ export type * from './types.js';
4
+ export type * from './vatDataTypes.js';
@@ -0,0 +1,2 @@
1
+ // Empty JS file to correspond with its .d.ts twin
2
+ export {};
@@ -1,5 +1,5 @@
1
1
  /* global globalThis */
2
- /* eslint-disable no-use-before-define, jsdoc/require-returns-type */
2
+ /* eslint-disable jsdoc/require-returns-type */
3
3
 
4
4
  import { environmentOptionsListHas } from '@endo/env-options';
5
5
  import { assert, Fail, q, b } from '@endo/errors';
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-use-before-define, jsdoc/require-returns-type */
1
+ /* eslint-disable jsdoc/require-returns-type */
2
2
 
3
3
  import { assert, Fail } from '@endo/errors';
4
4
  import { Nat } from '@endo/nat';
@@ -235,13 +235,23 @@ export function makeWatchedPromiseManager({
235
235
  } else {
236
236
  watchedPromiseTable.init(vpid, harden([[watcher, ...args]]));
237
237
 
238
+ promiseRegistrations.init(vpid, p);
239
+
240
+ // pseudoThen registers a settlement callback that will remove
241
+ // this promise from promiseRegistrations and
242
+ // watchedPromiseTable. To avoid triggering
243
+ // https://github.com/Agoric/agoric-sdk/issues/10757 and
244
+ // preventing slotToVal cleanup, the `pseudoThen()` should
245
+ // precede `maybeExportPromise()`. This isn't foolproof, but
246
+ // does mitigate in advance of a proper fix. See #10756 for
247
+ // details of this particular mitigation, and #10757 for the
248
+ // deeper bug.
249
+ pseudoThen(p, vpid);
250
+
238
251
  // Ensure that this vat's promises are rejected at termination.
239
252
  if (maybeExportPromise(vpid)) {
240
253
  syscall.subscribe(vpid);
241
254
  }
242
-
243
- promiseRegistrations.init(vpid, p);
244
- pseudoThen(p, vpid);
245
255
  }
246
256
  });
247
257
  }
@@ -0,0 +1,70 @@
1
+ import { provideLazy as provide } from '@agoric/store';
2
+
3
+ // Partially duplicates @agoric/vat-data to avoid circular dependencies.
4
+ export const makeExoUtils = VatData => {
5
+ const { defineDurableKind, makeKindHandle, watchPromise } = VatData;
6
+
7
+ const provideKindHandle = (baggage, kindName) =>
8
+ provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName));
9
+
10
+ const emptyRecord = harden({});
11
+ const initEmpty = () => emptyRecord;
12
+
13
+ const defineDurableExoClass = (
14
+ kindHandle,
15
+ interfaceGuard,
16
+ init,
17
+ methods,
18
+ options,
19
+ ) =>
20
+ defineDurableKind(kindHandle, init, methods, {
21
+ ...options,
22
+ thisfulMethods: true,
23
+ interfaceGuard,
24
+ });
25
+
26
+ const prepareExoClass = (
27
+ baggage,
28
+ kindName,
29
+ interfaceGuard,
30
+ init,
31
+ methods,
32
+ options = undefined,
33
+ ) =>
34
+ defineDurableExoClass(
35
+ provideKindHandle(baggage, kindName),
36
+ interfaceGuard,
37
+ init,
38
+ methods,
39
+ options,
40
+ );
41
+
42
+ const prepareExo = (
43
+ baggage,
44
+ kindName,
45
+ interfaceGuard,
46
+ methods,
47
+ options = undefined,
48
+ ) => {
49
+ const makeSingleton = prepareExoClass(
50
+ baggage,
51
+ kindName,
52
+ interfaceGuard,
53
+ initEmpty,
54
+ methods,
55
+ options,
56
+ );
57
+ return provide(baggage, `the_${kindName}`, () => makeSingleton());
58
+ };
59
+
60
+ return {
61
+ defineDurableKind,
62
+ makeKindHandle,
63
+ watchPromise,
64
+
65
+ provideKindHandle,
66
+ defineDurableExoClass,
67
+ prepareExoClass,
68
+ prepareExo,
69
+ };
70
+ };
@@ -2,7 +2,7 @@ import test from 'ava';
2
2
 
3
3
  import { Fail } from '@endo/errors';
4
4
  import { Far } from '@endo/marshal';
5
- import { M, provideLazy as provide } from '@agoric/store';
5
+ import { M } from '@agoric/store';
6
6
  import { makePromiseKit } from '@endo/promise-kit';
7
7
  // Disabled to avoid circular dependencies.
8
8
  // import { makeStoreUtils } from '@agoric/vat-data/src/vat-data-bindings.js';
@@ -10,79 +10,11 @@ import { makePromiseKit } from '@endo/promise-kit';
10
10
  import { kslot, kser } from '@agoric/kmarshal';
11
11
  import { setupTestLiveslots } from './liveslots-helpers.js';
12
12
  import { makeResolve, makeReject } from './util.js';
13
+ import { makeExoUtils } from './exo-utils.js';
13
14
 
14
15
  // eslint-disable-next-line no-unused-vars
15
16
  const compareEntriesByKey = ([ka], [kb]) => (ka < kb ? -1 : 1);
16
17
 
17
- // Paritally duplicates @agoric/vat-data to avoid circular dependencies.
18
- const makeExoUtils = VatData => {
19
- const { defineDurableKind, makeKindHandle, watchPromise } = VatData;
20
-
21
- const provideKindHandle = (baggage, kindName) =>
22
- provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName));
23
-
24
- const emptyRecord = harden({});
25
- const initEmpty = () => emptyRecord;
26
-
27
- const defineDurableExoClass = (
28
- kindHandle,
29
- interfaceGuard,
30
- init,
31
- methods,
32
- options,
33
- ) =>
34
- defineDurableKind(kindHandle, init, methods, {
35
- ...options,
36
- thisfulMethods: true,
37
- interfaceGuard,
38
- });
39
-
40
- const prepareExoClass = (
41
- baggage,
42
- kindName,
43
- interfaceGuard,
44
- init,
45
- methods,
46
- options = undefined,
47
- ) =>
48
- defineDurableExoClass(
49
- provideKindHandle(baggage, kindName),
50
- interfaceGuard,
51
- init,
52
- methods,
53
- options,
54
- );
55
-
56
- const prepareExo = (
57
- baggage,
58
- kindName,
59
- interfaceGuard,
60
- methods,
61
- options = undefined,
62
- ) => {
63
- const makeSingleton = prepareExoClass(
64
- baggage,
65
- kindName,
66
- interfaceGuard,
67
- initEmpty,
68
- methods,
69
- options,
70
- );
71
- return provide(baggage, `the_${kindName}`, () => makeSingleton());
72
- };
73
-
74
- return {
75
- defineDurableKind,
76
- makeKindHandle,
77
- watchPromise,
78
-
79
- provideKindHandle,
80
- defineDurableExoClass,
81
- prepareExoClass,
82
- prepareExo,
83
- };
84
- };
85
-
86
18
  // cf. packages/SwingSet/test/vat-durable-promise-watcher.js
87
19
  const buildPromiseWatcherRootObject = (vatPowers, vatParameters, baggage) => {
88
20
  const { VatData } = vatPowers;
@@ -0,0 +1,94 @@
1
+ /* global globalThis */
2
+ // eslint-disable-next-line import/order
3
+ import { annihilate, startLife } from '../tools/prepare-strict-test-env.js';
4
+
5
+ import test from 'ava';
6
+
7
+ import { makeUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';
8
+ import { makeExoUtils } from './exo-utils.js';
9
+
10
+ test.serial('kind redefinition enforced', async t => {
11
+ annihilate();
12
+
13
+ const { prepareExoClass } = makeExoUtils(globalThis.VatData);
14
+
15
+ await startLife(async baggage => {
16
+ const makeTestExo = prepareExoClass(
17
+ baggage,
18
+ 'TestExo',
19
+ undefined,
20
+ () => ({}),
21
+ {
22
+ foo() {
23
+ return 'bar';
24
+ },
25
+ },
26
+ );
27
+
28
+ baggage.init('testExo', makeTestExo());
29
+ });
30
+
31
+ await t.throwsAsync(
32
+ async () =>
33
+ startLife(async () => {
34
+ // Not redefining the kind here
35
+ }),
36
+ { message: 'defineDurableKind not called for tags: [TestExo]' },
37
+ );
38
+
39
+ await startLife(async baggage => {
40
+ prepareExoClass(baggage, 'TestExo', undefined, () => ({}), {
41
+ foo() {
42
+ return 'baz';
43
+ },
44
+ });
45
+
46
+ t.is(baggage.get('testExo').foo(), 'baz');
47
+ });
48
+ });
49
+
50
+ test.serial('decided promise rejected', async t => {
51
+ annihilate();
52
+
53
+ const { prepareExo } = makeExoUtils(globalThis.VatData);
54
+ const { watchPromise } = globalThis.VatData;
55
+
56
+ t.plan(1);
57
+
58
+ await startLife(async baggage => {
59
+ const watcher = prepareExo(
60
+ baggage,
61
+ 'DurablePromiseTestWatcher',
62
+ undefined,
63
+ {
64
+ onFulfilled(value) {
65
+ t.fail(
66
+ `First incarnation watcher onFulfilled triggered with value ${value}`,
67
+ );
68
+ },
69
+ onRejected(reason) {
70
+ t.fail(
71
+ `First incarnation watcher onRejected triggered with reason ${reason}`,
72
+ );
73
+ },
74
+ },
75
+ );
76
+
77
+ const never = harden(new Promise(() => {}));
78
+
79
+ watchPromise(never, watcher);
80
+ });
81
+
82
+ await startLife(async baggage => {
83
+ prepareExo(baggage, 'DurablePromiseTestWatcher', undefined, {
84
+ onFulfilled(value) {
85
+ t.fail(
86
+ `Second incarnation watcher onFulfilled triggered with value ${value}`,
87
+ );
88
+ },
89
+ onRejected(reason) {
90
+ t.deepEqual(reason, makeUpgradeDisconnection('vat upgraded', 1));
91
+ },
92
+ });
93
+ });
94
+ });
@@ -1,4 +1,4 @@
1
- /* global process */
1
+ /* eslint-env node */
2
2
 
3
3
  // put this in a separate module, so we can make it happen before
4
4
  // importing virtualObjectManager.js
@@ -127,8 +127,8 @@ test('multifaceted virtual objects', t => {
127
127
 
128
128
  flushStateCache();
129
129
  t.deepEqual(log.splice(0), [
130
- `get kindIDID => undefined`,
131
130
  `get idCounters => undefined`,
131
+ `get kindIDID => undefined`,
132
132
  `set kindIDID 1`,
133
133
  `set vom.vkind.2.descriptor {"kindID":"2","tag":"multithing"}`,
134
134
  `set vom.${kid}/1 ${multiThingVal('foo', 1)}`,
@@ -203,8 +203,8 @@ test('virtual object operations', t => {
203
203
  // t3-0: 'thing-3' 200 0
204
204
  const thing4 = makeThing('thing-4', 300); // [t4-0* t3-0* t2-0* t1-0*]
205
205
  // t4-0: 'thing-4' 300 0
206
- t.is(log.shift(), `get kindIDID => undefined`);
207
206
  t.is(log.shift(), `get idCounters => undefined`);
207
+ t.is(log.shift(), `get kindIDID => undefined`);
208
208
  t.is(log.shift(), `set kindIDID 1`);
209
209
  t.is(log.shift(), `set vom.vkind.2.descriptor {"kindID":"2","tag":"thing"}`);
210
210
  t.is(log.shift(), `set vom.vkind.3.descriptor {"kindID":"3","tag":"zot"}`);
@@ -468,8 +468,8 @@ test('symbol named methods', t => {
468
468
  // t1-0: 'thing-1' 0 0
469
469
  const thing2 = makeThing('thing-2', 100); // [t1-0* t2-0*]
470
470
  // t2-0: 'thing-2' 100 0
471
- t.is(log.shift(), `get kindIDID => undefined`);
472
471
  t.is(log.shift(), `get idCounters => undefined`);
472
+ t.is(log.shift(), `get kindIDID => undefined`);
473
473
  t.is(log.shift(), `set kindIDID 1`);
474
474
  t.is(
475
475
  log.shift(),
@@ -649,8 +649,8 @@ test('virtual object gc', t => {
649
649
  },
650
650
  });
651
651
 
652
- t.is(log.shift(), `get kindIDID => undefined`);
653
652
  t.is(log.shift(), `get idCounters => undefined`);
653
+ t.is(log.shift(), `get kindIDID => undefined`);
654
654
  t.is(log.shift(), `set kindIDID 1`);
655
655
  const skit = [
656
656
  'storeKindIDTable',
@@ -0,0 +1,42 @@
1
+ import test from 'ava';
2
+
3
+ import { Far } from '@endo/marshal';
4
+ import { makePromiseKit } from '@endo/promise-kit';
5
+ import { setupTestLiveslots } from './liveslots-helpers.js';
6
+
7
+ const build = vatPowers => {
8
+ const { VatData } = vatPowers;
9
+ const { makeKindHandle, defineDurableKind, watchPromise } = VatData;
10
+
11
+ const kh = makeKindHandle('handler');
12
+ const init = () => ({});
13
+ const behavior = {
14
+ onFulfilled: _value => 0,
15
+ onRejected: _reason => 0,
16
+ };
17
+ const makeHandler = defineDurableKind(kh, init, behavior);
18
+
19
+ return Far('root', {
20
+ async run() {
21
+ const pr = makePromiseKit();
22
+ const handler = makeHandler();
23
+ watchPromise(pr.promise, handler);
24
+ pr.resolve('ignored');
25
+ },
26
+ });
27
+ };
28
+
29
+ test('watched local promises should not leak slotToVal entries', async t => {
30
+ const { dispatchMessage, testHooks } = await setupTestLiveslots(
31
+ t,
32
+ build,
33
+ 'vatA',
34
+ );
35
+ const { slotToVal } = testHooks;
36
+ const initial = slotToVal.size;
37
+
38
+ await dispatchMessage('run');
39
+ t.is(slotToVal.size, initial);
40
+ await dispatchMessage('run');
41
+ t.is(slotToVal.size, initial);
42
+ });
@@ -23,6 +23,7 @@ export function makeFakeVirtualObjectManager(vrm, fakeStuff) {
23
23
  VirtualObjectAwareWeakSet,
24
24
  flushStateCache,
25
25
  canBeDurable,
26
+ insistAllDurableKindsReconnected,
26
27
  } = makeVirtualObjectManager(
27
28
  fakeStuff.syscall,
28
29
  vrm,
@@ -43,6 +44,7 @@ export function makeFakeVirtualObjectManager(vrm, fakeStuff) {
43
44
  defineDurableKindMulti,
44
45
  makeKindHandle,
45
46
  canBeDurable,
47
+ insistAllDurableKindsReconnected,
46
48
  VirtualObjectAwareWeakMap,
47
49
  VirtualObjectAwareWeakSet,
48
50
  };
@@ -28,12 +28,14 @@ class FakeFinalizationRegistry {
28
28
  }
29
29
 
30
30
  class FakeWeakRef {
31
+ #target;
32
+
31
33
  constructor(target) {
32
- this.target = target;
34
+ this.#target = target;
33
35
  }
34
36
 
35
37
  deref() {
36
- return this.target; // strong ref
38
+ return this.#target; // strong ref
37
39
  }
38
40
  }
39
41
 
@@ -41,6 +43,7 @@ export function makeFakeLiveSlotsStuff(options = {}) {
41
43
  let vrm;
42
44
  function setVrm(vrmToUse) {
43
45
  assert(!vrm, 'vrm already configured');
46
+ vrmToUse.initializeIDCounters();
44
47
  vrm = vrmToUse;
45
48
  }
46
49
 
@@ -174,6 +177,7 @@ export function makeFakeLiveSlotsStuff(options = {}) {
174
177
  // and the WeakRef may or may not contain the target value. Use
175
178
  // options={weak:true} to match that behavior, or the default weak:false to
176
179
  // keep strong references.
180
+ const WeakRefForSlot = weak ? RealWeakRef : FakeWeakRef;
177
181
  const valToSlot = new WeakMap();
178
182
  const slotToVal = new Map();
179
183
 
@@ -183,7 +187,7 @@ export function makeFakeLiveSlotsStuff(options = {}) {
183
187
 
184
188
  function getValForSlot(slot) {
185
189
  const d = slotToVal.get(slot);
186
- return d && (weak ? d.deref() : d);
190
+ return d && d.deref();
187
191
  }
188
192
 
189
193
  function requiredValForSlot(slot) {
@@ -193,7 +197,7 @@ export function makeFakeLiveSlotsStuff(options = {}) {
193
197
  }
194
198
 
195
199
  function setValForSlot(slot, val) {
196
- slotToVal.set(slot, weak ? new RealWeakRef(val) : val);
200
+ slotToVal.set(slot, new WeakRefForSlot(val));
197
201
  }
198
202
 
199
203
  function convertValToSlot(val) {
@@ -230,7 +234,6 @@ export function makeFakeLiveSlotsStuff(options = {}) {
230
234
  assert.fail('fake liveSlots stuff configured without vrm');
231
235
  }
232
236
  }
233
- // eslint-disable-next-line no-use-before-define
234
237
  registerEntry(baseRef, val, facet !== undefined);
235
238
  if (!result) {
236
239
  result = val;
@@ -275,6 +278,7 @@ export function makeFakeLiveSlotsStuff(options = {}) {
275
278
  return {
276
279
  syscall,
277
280
  allocateExportID,
281
+ allocatePromiseID,
278
282
  allocateCollectionID,
279
283
  getSlotForVal,
280
284
  requiredValForSlot,
@@ -339,7 +343,7 @@ export function makeFakeWatchedPromiseManager(
339
343
  * @param {object} [options]
340
344
  * @param {number} [options.cacheSize]
341
345
  * @param {boolean} [options.relaxDurabilityRules]
342
- * @param {Map<any, any>} [options.fakeStore]
346
+ * @param {Map<string, string>} [options.fakeStore]
343
347
  * @param {WeakMapConstructor} [options.WeakMap]
344
348
  * @param {WeakSetConstructor} [options.WeakSet]
345
349
  * @param {boolean} [options.weak]
@@ -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();
@@ -12,7 +12,9 @@ import { makeFakeVirtualStuff } from './fakeVirtualSupport.js';
12
12
 
13
13
  const { WeakMap, WeakSet } = globalThis;
14
14
 
15
- /** @type {ReturnType<makeFakeVirtualStuff>} */
15
+ /** @typedef {ReturnType<typeof makeFakeVirtualStuff>} FakeVomKit */
16
+
17
+ /** @type {FakeVomKit} */
16
18
  let fakeVomKit;
17
19
 
18
20
  globalThis.VatData = harden({
@@ -44,18 +46,43 @@ globalThis.VatData = harden({
44
46
 
45
47
  globalThis[PassStyleOfEndowmentSymbol] = passStyleOf;
46
48
 
47
- export const reincarnate = (options = {}) => {
48
- const { fakeStore = new Map(), fakeVomKit: fvk } = options;
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
+ */
49
55
 
50
- if (options.fakeVomKit) {
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) {
51
65
  fvk.vom.flushStateCache();
52
66
  fvk.cm.flushSchemaCache();
53
67
  fvk.vrm.flushIDCounters();
54
68
  }
55
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
+
56
84
  fakeVomKit = makeFakeVirtualStuff({
57
- ...options,
58
- fakeStore,
85
+ ...clonedIncarnation,
59
86
  WeakMap,
60
87
  WeakSet,
61
88
  });
@@ -65,5 +92,5 @@ export const reincarnate = (options = {}) => {
65
92
  // @ts-expect-error ditto
66
93
  globalThis.WeakSet = fakeVomKit.vom.VirtualObjectAwareWeakSet;
67
94
 
68
- return { ...options, fakeStore, fakeVomKit };
95
+ return { ...clonedIncarnation, fakeVomKit };
69
96
  };
@@ -1,276 +0,0 @@
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 { RemotableBrand } from '@endo/eventual-send';
18
- import type { InterfaceGuard, Pattern } from '@endo/patterns';
19
- import type { makeWatchedPromiseManager } from './watchedPromises.js';
20
-
21
- // TODO should be moved into @endo/patterns and eventually imported here
22
- // instead of this local definition.
23
- export type InterfaceGuardKit = Record<string, InterfaceGuard>;
24
- export type { MapStore, Pattern };
25
-
26
- // This needs `any` values. If they were `unknown`, code that uses Baggage
27
- // would need explicit runtime checks or casts for every fetch, which is
28
- // onerous.
29
- export type Baggage = MapStore<string, any>;
30
-
31
- type WatchedPromisesManager = ReturnType<typeof makeWatchedPromiseManager>;
32
-
33
- type Tail<T extends any[]> = T extends [head: any, ...rest: infer Rest]
34
- ? Rest
35
- : [];
36
-
37
- // used to omit the 'context' parameter
38
- type OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R
39
- ? (...args: P) => R
40
- : never;
41
-
42
- // The type of a passable local object with methods.
43
- // An internal helper to avoid having to repeat `O`.
44
- type PrimaryRemotable<O> = O & RemotableObject & RemotableBrand<{}, O>;
45
-
46
- export type KindFacet<O> = PrimaryRemotable<{
47
- [K in keyof O]: OmitFirstArg<O[K]>; // omit the 'context' parameter
48
- }>;
49
-
50
- export type KindFacets<B> = {
51
- [FacetKey in keyof B]: KindFacet<B[FacetKey]>;
52
- };
53
-
54
- export type KindContext<S, F> = { state: S; self: KindFacet<F> };
55
- export type MultiKindContext<S, B> = { state: S; facets: KindFacets<B> };
56
-
57
- export type PlusContext<C, M extends (...args: any[]) => any> = (
58
- c: C,
59
- ...args: Parameters<M>
60
- ) => ReturnType<M>;
61
-
62
- export type FunctionsPlusContext<
63
- C,
64
- O extends Record<string, (...args: any[]) => any>,
65
- > = {
66
- [K in keyof O]: PlusContext<C, O[K]>;
67
- };
68
-
69
- declare class DurableKindHandleClass {
70
- private descriptionTag: string;
71
- }
72
- export type DurableKindHandle = DurableKindHandleClass;
73
-
74
- /**
75
- * Grab bag of options that can be provided to `defineDurableKind` and its
76
- * siblings. Not all options are meaningful in all contexts. See the
77
- * doc-comments on each option.
78
- */
79
- export type DefineKindOptions<C> = {
80
- /**
81
- * If provided, the `finish` function will be called after the instance is
82
- * made and internally registered, but before it is returned. The finish
83
- * function is to do any post-intantiation initialization that should be
84
- * done before exposing the object to its clients.
85
- */
86
- finish?: (context: C) => void;
87
-
88
- /**
89
- * If provided, it describes the shape of all state records of instances
90
- * of this kind.
91
- */
92
- stateShape?: StateShape;
93
-
94
- /**
95
- * If a `receiveAmplifier` function is provided to an exo class kit definition,
96
- * it will be called with an `Amplify` function. If provided to the definition
97
- * of a normal exo or exo class, the definition will throw, since only
98
- * exo kits can be amplified.
99
- * An `Amplify` function is a function that takes a facet instance of
100
- * this class kit as an argument, in which case it will return the facets
101
- * record, giving access to all the facet instances of the same cohort.
102
- */
103
- receiveAmplifier?: ReceivePower<Amplify>;
104
-
105
- /**
106
- * If a `receiveInstanceTester` function is provided, it will be called
107
- * during the definition of the exo class or exo class kit with an
108
- * `IsInstance` function. The first argument of `IsInstance`
109
- * is the value to be tested. When it may be a facet instance of an
110
- * exo class kit, the optional second argument, if provided, is
111
- * a `facetName`. In that case, the function tests only if the first
112
- * argument is an instance of that facet of the associated exo class kit.
113
- */
114
- receiveInstanceTester?: ReceivePower<IsInstance>;
115
-
116
- // TODO properties above are identical to those in FarClassOptions.
117
- // These are the only options that should be exposed by
118
- // vat-data's public virtual/durable exo APIs. This DefineKindOptions
119
- // should explicitly be a subtype, where the methods below are only for
120
- // internal use, i.e., below the exo level.
121
-
122
- /**
123
- * As a kind option, intended for internal use only.
124
- * Meaningful to `makeScalarBigMapStore` and its siblings. These maker
125
- * fuctions will make either virtual or durable stores, depending on
126
- * this flag. Defaults to off, making virtual but not durable collections.
127
- *
128
- * Generally, durable collections are provided with `provideDurableMapStore`
129
- * and its sibling, which use this flag internally. If you do not make
130
- * durable collections by other means, you can consider this as
131
- * intended for internal use only.
132
- */
133
- durable?: boolean;
134
-
135
- /**
136
- * Intended for internal use only.
137
- * Should the raw methods receive their `context` argument as their first
138
- * argument or as their `this` binding? For `defineDurableKind` and its
139
- * siblings (including `prepareSingleton`), this defaults to off, meaning that
140
- * their behavior methods receive `context` as their first argument.
141
- * `prepareExoClass` and its siblings (including `prepareExo`) use
142
- * this flag internally to indicate that their methods receive `context`
143
- * as their `this` binding.
144
- */
145
- thisfulMethods?: boolean;
146
-
147
- /**
148
- * Intended for internal use only.
149
- * Only applicable if this is a class kind. A class kit kind should use
150
- * `interfaceGuardKit` instead.
151
- *
152
- * If an `interfaceGuard` is provided, then the raw methods passed alongside
153
- * it are wrapped by a function that first checks that this method's guard
154
- * pattern is satisfied before calling the raw method.
155
- *
156
- * In `defineDurableKind` and its siblings, this defaults to `undefined`.
157
- * Exo classes use this internally to protect their raw class methods
158
- * using the provided interface.
159
- * In absence, an exo is protected anyway, while a bare kind is
160
- * not (detected by `!thisfulMethods`),
161
- */
162
- interfaceGuard?: InterfaceGuard;
163
-
164
- /**
165
- * Intended for internal use only.
166
- * Only applicable if this is a class kit kind. A class kind should use
167
- * `interfaceGuard` instead.
168
- *
169
- * If an `interfaceGuardKit` is provided, then each member of the
170
- * interfaceGuardKit is used to guard the corresponding facet of the
171
- * class kit.
172
- *
173
- * In `defineDurableKindMulti` and its siblings, this defaults to `undefined`.
174
- * Exo class kits use this internally to protect their facets.
175
- * In absence, an exo is protected anyway, while a bare kind is
176
- * not (detected by `!thisfulMethods`),
177
- */
178
- interfaceGuardKit?: InterfaceGuardKit;
179
- };
180
-
181
- export type VatData = {
182
- // virtual kinds
183
- /** @deprecated Use defineVirtualExoClass instead */
184
- defineKind: <P extends Array<any>, S, F>(
185
- tag: string,
186
- init: (...args: P) => S,
187
- facet: F,
188
- options?: DefineKindOptions<KindContext<S, F>>,
189
- ) => (...args: P) => KindFacet<F>;
190
-
191
- /** @deprecated Use defineVirtualExoClassKit instead */
192
- defineKindMulti: <P extends Array<any>, S, B>(
193
- tag: string,
194
- init: (...args: P) => S,
195
- behavior: B,
196
- options?: DefineKindOptions<MultiKindContext<S, B>>,
197
- ) => (...args: P) => KindFacets<B>;
198
-
199
- // durable kinds
200
- makeKindHandle: (descriptionTag: string) => DurableKindHandle;
201
-
202
- /** @deprecated Use defineDurableExoClass instead */
203
- defineDurableKind: <P extends Array<any>, S, F>(
204
- kindHandle: DurableKindHandle,
205
- init: (...args: P) => S,
206
- facet: F,
207
- options?: DefineKindOptions<KindContext<S, F>>,
208
- ) => (...args: P) => KindFacet<F>;
209
-
210
- /** @deprecated Use defineDurableExoClassKit instead */
211
- defineDurableKindMulti: <P extends Array<any>, S, B>(
212
- kindHandle: DurableKindHandle,
213
- init: (...args: P) => S,
214
- behavior: B,
215
- options?: DefineKindOptions<MultiKindContext<S, B>>,
216
- ) => (...args: P) => KindFacets<B>;
217
-
218
- providePromiseWatcher: WatchedPromisesManager['providePromiseWatcher'];
219
- watchPromise: WatchedPromisesManager['watchPromise'];
220
-
221
- makeScalarBigMapStore: <K, V>(
222
- label: string,
223
- options?: StoreOptions,
224
- ) => MapStore<K, V>;
225
- makeScalarBigWeakMapStore: <K, V>(
226
- label: string,
227
- options?: StoreOptions,
228
- ) => WeakMapStore<K, V>;
229
-
230
- makeScalarBigSetStore: <K>(
231
- label: string,
232
- options?: StoreOptions,
233
- ) => SetStore<K>;
234
- makeScalarBigWeakSetStore: <K>(
235
- label: string,
236
- options?: StoreOptions,
237
- ) => WeakSetStore<K>;
238
- canBeDurable: (specimen: unknown) => boolean;
239
- };
240
-
241
- // The JSDoc is repeated here and at the function definition so it appears
242
- // in IDEs where it's used, regardless of type resolution.
243
- export interface PickFacet {
244
- /**
245
- * When making a multi-facet kind, it's common to pick one facet to
246
- * expose. E.g.,
247
- *
248
- * const makeFoo = (a, b, c, d) => makeFooBase(a, b, c, d).self;
249
- *
250
- * This helper reduces the duplication:
251
- *
252
- * const makeFoo = pickFacet(makeFooBase, 'self');
253
- */
254
- <M extends (...args: any[]) => any, F extends keyof ReturnType<M>>(
255
- maker: M,
256
- facetName: F,
257
- ): (...args: Parameters<M>) => ReturnType<M>[F];
258
- }
259
-
260
- /** @deprecated Use prepareExoClass instead */
261
- export type PrepareKind = <P extends Array<any>, S, F>(
262
- baggage: Baggage,
263
- tag: string,
264
- init: (...args: P) => S,
265
- facet: F,
266
- options?: DefineKindOptions<KindContext<S, F>>,
267
- ) => (...args: P) => KindFacet<F>;
268
-
269
- /** @deprecated Use prepareExoClassKit instead */
270
- export type PrepareKindMulti = <P extends Array<any>, S, B>(
271
- baggage: Baggage,
272
- tag: string,
273
- init: (...args: P) => S,
274
- behavior: B,
275
- options?: DefineKindOptions<MultiKindContext<S, B>>,
276
- ) => (...args: P) => KindFacets<B>;
@@ -1,2 +0,0 @@
1
- // Empty JS file to correspond with vatDataTypes.d.ts
2
- export {};