@agoric/swingset-liveslots 0.10.3-u14.0 → 0.10.3-u16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/package.json +27 -19
- package/src/cache.js +2 -1
- package/src/capdata.js +0 -1
- package/src/collectionManager.js +154 -72
- package/src/index.js +4 -1
- package/src/liveslots.js +52 -81
- package/src/message.js +4 -4
- package/src/types.js +8 -2
- package/src/vatDataTypes.d.ts +271 -0
- package/src/vatDataTypes.js +2 -0
- package/src/vatstore-iterators.js +2 -0
- package/src/virtualObjectManager.js +189 -70
- package/src/virtualReferences.js +51 -0
- package/src/watchedPromises.js +61 -16
- package/test/{test-baggage.js → baggage.test.js} +1 -2
- package/test/{test-cache.js → cache.test.js} +0 -1
- package/test/{test-collection-schema-refcount.js → collection-schema-refcount.test.js} +1 -2
- package/test/{test-collection-upgrade.js → collection-upgrade.test.js} +1 -3
- package/test/{test-collections.js → collections.test.js} +117 -14
- package/test/{test-dropped-collection-weakrefs.js → dropped-collection-weakrefs.test.js} +1 -2
- package/test/{test-durabilityChecks.js → durabilityChecks.test.js} +3 -3
- package/test/{test-facetiousness.js → facetiousness.test.js} +1 -2
- package/test/gc-and-finalize.js +30 -1
- package/test/gc-helpers.js +2 -3
- package/test/{test-gc-sensitivity.js → gc-sensitivity.test.js} +2 -2
- package/test/{test-handled-promises.js → handled-promises.test.js} +5 -7
- package/test/{test-initial-vrefs.js → initial-vrefs.test.js} +2 -3
- package/test/liveslots-helpers.js +6 -6
- package/test/{test-liveslots-mock-gc.js → liveslots-mock-gc.test.js} +2 -2
- package/test/{test-liveslots-real-gc.js → liveslots-real-gc.test.js} +44 -35
- package/test/{test-liveslots.js → liveslots.test.js} +13 -14
- package/test/mock-gc.js +1 -0
- package/test/storeGC/{test-lifecycle.js → lifecycle.test.js} +2 -2
- package/test/storeGC/{test-refcount-management.js → refcount-management.test.js} +1 -2
- package/test/storeGC/{test-scalar-store-kind.js → scalar-store-kind.test.js} +0 -1
- package/test/storeGC/{test-weak-key.js → weak-key.test.js} +1 -2
- package/test/util.js +2 -2
- package/test/vat-util.js +1 -1
- package/test/virtual-objects/{test-cease-recognition.js → cease-recognition.test.js} +2 -2
- package/test/virtual-objects/{test-cross-facet.js → cross-facet.test.js} +5 -4
- package/test/virtual-objects/{test-empty-data.js → empty-data.test.js} +1 -2
- package/test/virtual-objects/{test-facets.js → facets.test.js} +1 -2
- package/test/virtual-objects/{test-kind-changes.js → kind-changes.test.js} +2 -2
- package/test/virtual-objects/{test-reachable-vrefs.js → reachable-vrefs.test.js} +2 -2
- package/test/virtual-objects/{test-rep-tostring.js → rep-tostring.test.js} +2 -3
- package/test/virtual-objects/{test-retain-remotable.js → retain-remotable.test.js} +25 -24
- package/test/virtual-objects/{test-state-shape.js → state-shape.test.js} +2 -2
- package/test/virtual-objects/{test-virtualObjectGC.js → virtualObjectGC.test.js} +2 -2
- package/test/virtual-objects/{test-virtualObjectManager.js → virtualObjectManager.test.js} +6 -2
- package/test/virtual-objects/{test-vo-real-gc.js → vo-real-gc.test.js} +8 -8
- package/test/virtual-objects/{test-weakcollections-vref-handling.js → weakcollections-vref-handling.test.js} +1 -2
- package/test/{test-vo-test-harness.js → vo-test-harness.test.js} +0 -1
- package/test/{test-vpid-liveslots.js → vpid-liveslots.test.js} +4 -5
- package/test/waitUntilQuiescent.js +2 -1
- package/tools/fakeVirtualSupport.js +41 -24
- package/tools/prepare-test-env.js +13 -0
- package/tools/setup-vat-data.js +62 -0
- package/CHANGELOG.md +0 -93
- package/test/kmarshal.js +0 -79
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/* global process */
|
|
2
3
|
import test from 'ava';
|
|
3
|
-
import '@endo/init/debug.js';
|
|
4
4
|
|
|
5
5
|
import { Far } from '@endo/marshal';
|
|
6
6
|
import { makePromiseKit } from '@endo/promise-kit';
|
|
7
|
+
import { kslot, kser } from '@agoric/kmarshal';
|
|
7
8
|
import engineGC from './engine-gc.js';
|
|
8
|
-
import { makeGcAndFinalize } from './gc-and-finalize.js';
|
|
9
|
-
import { kslot, kser } from './kmarshal.js';
|
|
9
|
+
import { watchCollected, makeGcAndFinalize } from './gc-and-finalize.js';
|
|
10
10
|
import { buildSyscall, makeDispatch } from './liveslots-helpers.js';
|
|
11
11
|
import {
|
|
12
12
|
makeMessage,
|
|
@@ -28,13 +28,13 @@ const gcAndFinalize = makeGcAndFinalize(engineGC);
|
|
|
28
28
|
|
|
29
29
|
test.serial('liveslots retains pending exported promise', async t => {
|
|
30
30
|
const { log, syscall } = buildSyscall();
|
|
31
|
-
let
|
|
31
|
+
let collected;
|
|
32
32
|
const success = [];
|
|
33
33
|
function build(_vatPowers) {
|
|
34
34
|
const root = Far('root', {
|
|
35
35
|
make() {
|
|
36
36
|
const pk = makePromiseKit();
|
|
37
|
-
|
|
37
|
+
collected = watchCollected(pk.promise);
|
|
38
38
|
// we export the Promise, but do not retain resolve/reject
|
|
39
39
|
return [pk.promise];
|
|
40
40
|
},
|
|
@@ -55,7 +55,7 @@ test.serial('liveslots retains pending exported promise', async t => {
|
|
|
55
55
|
const resultP = 'p-1';
|
|
56
56
|
await dispatch(makeMessage(rootA, 'make', [], resultP));
|
|
57
57
|
await gcAndFinalize();
|
|
58
|
-
t.
|
|
58
|
+
t.false(collected.result, 'Promise retained');
|
|
59
59
|
t.is(log[0].type, 'resolve');
|
|
60
60
|
const res0 = log[0].resolutions[0];
|
|
61
61
|
t.is(res0[0], resultP);
|
|
@@ -66,13 +66,13 @@ test.serial('liveslots retains pending exported promise', async t => {
|
|
|
66
66
|
|
|
67
67
|
test.serial('liveslots retains device nodes', async t => {
|
|
68
68
|
const { syscall } = buildSyscall();
|
|
69
|
-
let
|
|
69
|
+
let collected;
|
|
70
70
|
const recognize = new WeakSet(); // real WeakSet
|
|
71
71
|
const success = [];
|
|
72
72
|
function build(_vatPowers) {
|
|
73
73
|
const root = Far('root', {
|
|
74
74
|
first(dn) {
|
|
75
|
-
|
|
75
|
+
collected = watchCollected(dn);
|
|
76
76
|
recognize.add(dn);
|
|
77
77
|
},
|
|
78
78
|
second(dn) {
|
|
@@ -87,25 +87,24 @@ test.serial('liveslots retains device nodes', async t => {
|
|
|
87
87
|
const device = 'd-1';
|
|
88
88
|
await dispatch(makeMessage(rootA, 'first', [kslot(device)]));
|
|
89
89
|
await gcAndFinalize();
|
|
90
|
-
t.
|
|
90
|
+
t.false(collected.result, 'Device node retained');
|
|
91
91
|
await dispatch(makeMessage(rootA, 'second', [kslot(device)]));
|
|
92
92
|
t.deepEqual(success, [true]);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
test.serial('GC syscall.dropImports', async t => {
|
|
96
96
|
const { log, syscall } = buildSyscall();
|
|
97
|
-
let
|
|
97
|
+
let collected;
|
|
98
98
|
function build(_vatPowers) {
|
|
99
|
-
|
|
100
|
-
let presence1;
|
|
99
|
+
const holder = new Set();
|
|
101
100
|
const root = Far('root', {
|
|
102
101
|
one(arg) {
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
holder.add(arg);
|
|
103
|
+
collected = watchCollected(arg);
|
|
105
104
|
},
|
|
106
105
|
two() {},
|
|
107
106
|
three() {
|
|
108
|
-
|
|
107
|
+
holder.clear(); // drops the import
|
|
109
108
|
},
|
|
110
109
|
});
|
|
111
110
|
return root;
|
|
@@ -121,19 +120,29 @@ test.serial('GC syscall.dropImports', async t => {
|
|
|
121
120
|
// rp1 = root~.one(arg)
|
|
122
121
|
await dispatch(makeMessage(rootA, 'one', [kslot(arg)]));
|
|
123
122
|
await dispatch(makeBringOutYourDead());
|
|
124
|
-
t.
|
|
123
|
+
t.false(collected.result);
|
|
125
124
|
|
|
126
125
|
// an intermediate message will trigger GC, but the presence is still held
|
|
127
126
|
await dispatch(makeMessage(rootA, 'two', []));
|
|
128
127
|
await dispatch(makeBringOutYourDead());
|
|
129
|
-
t.
|
|
128
|
+
t.false(collected.result);
|
|
130
129
|
|
|
131
130
|
// now tell the vat to drop the 'arg' presence we gave them earlier
|
|
132
131
|
await dispatch(makeMessage(rootA, 'three', []));
|
|
133
132
|
await dispatch(makeBringOutYourDead());
|
|
134
133
|
|
|
134
|
+
const isV8 =
|
|
135
|
+
typeof process !== 'undefined' && 'v8' in (process.versions || {});
|
|
136
|
+
|
|
135
137
|
// the presence itself should be gone
|
|
136
|
-
|
|
138
|
+
if (!collected.result) {
|
|
139
|
+
if (isV8) {
|
|
140
|
+
// Flake in v8/node: https://github.com/Agoric/agoric-sdk/issues/8883
|
|
141
|
+
t.log('skipping flake in v8');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
t.fail('import not collected');
|
|
145
|
+
}
|
|
137
146
|
|
|
138
147
|
// first it will check that there are no VO's holding onto it
|
|
139
148
|
const l2 = log.shift();
|
|
@@ -246,12 +255,12 @@ test.serial('GC dispatch.retireExports', async t => {
|
|
|
246
255
|
|
|
247
256
|
test.serial('GC dispatch.dropExports', async t => {
|
|
248
257
|
const { log, syscall } = buildSyscall();
|
|
249
|
-
let
|
|
258
|
+
let collected;
|
|
250
259
|
function build(_vatPowers) {
|
|
251
260
|
const root = Far('root', {
|
|
252
261
|
one() {
|
|
253
262
|
const ex1 = Far('export', {});
|
|
254
|
-
|
|
263
|
+
collected = watchCollected(ex1);
|
|
255
264
|
return ex1;
|
|
256
265
|
// ex1 goes out of scope, dropping last userspace strongref
|
|
257
266
|
},
|
|
@@ -285,19 +294,19 @@ test.serial('GC dispatch.dropExports', async t => {
|
|
|
285
294
|
|
|
286
295
|
// the exported Remotable should be held in place by exportedRemotables
|
|
287
296
|
// until we tell the vat we don't need it any more
|
|
288
|
-
t.
|
|
297
|
+
t.false(collected.result);
|
|
289
298
|
|
|
290
299
|
// an intermediate message will trigger GC, but the presence is still held
|
|
291
300
|
await dispatch(makeMessage(rootA, 'two', []));
|
|
292
301
|
await dispatch(makeBringOutYourDead());
|
|
293
|
-
t.
|
|
302
|
+
t.false(collected.result);
|
|
294
303
|
|
|
295
304
|
// now tell the vat we don't need a strong reference to that export.
|
|
296
305
|
await dispatch(makeDropExports(ex1));
|
|
297
306
|
await dispatch(makeBringOutYourDead());
|
|
298
307
|
|
|
299
308
|
// that should allow ex1 to be collected
|
|
300
|
-
t.
|
|
309
|
+
t.true(collected.result);
|
|
301
310
|
|
|
302
311
|
// and once it's collected, the vat should emit `syscall.retireExport`
|
|
303
312
|
// because nobody else will be able to recognize it again
|
|
@@ -313,19 +322,19 @@ test.serial(
|
|
|
313
322
|
'GC dispatch.retireExports inhibits syscall.retireExports',
|
|
314
323
|
async t => {
|
|
315
324
|
const { log, syscall } = buildSyscall();
|
|
316
|
-
let
|
|
325
|
+
let collected;
|
|
317
326
|
function build(_vatPowers) {
|
|
318
|
-
|
|
327
|
+
const holder = new Set();
|
|
319
328
|
const root = Far('root', {
|
|
320
329
|
hold() {
|
|
321
|
-
ex1 = Far('export', {});
|
|
322
|
-
|
|
330
|
+
const ex1 = Far('export', {});
|
|
331
|
+
holder.add(ex1);
|
|
332
|
+
collected = watchCollected(ex1);
|
|
323
333
|
return ex1;
|
|
324
334
|
},
|
|
325
335
|
two() {},
|
|
326
336
|
drop() {
|
|
327
|
-
//
|
|
328
|
-
ex1 = undefined; // drop the last userspace strongref
|
|
337
|
+
holder.clear(); // drop the last userspace strongref
|
|
329
338
|
},
|
|
330
339
|
});
|
|
331
340
|
return root;
|
|
@@ -356,19 +365,19 @@ test.serial(
|
|
|
356
365
|
|
|
357
366
|
// the exported Remotable should be held in place by exportedRemotables
|
|
358
367
|
// until we tell the vat we don't need it any more
|
|
359
|
-
t.
|
|
368
|
+
t.false(collected.result);
|
|
360
369
|
|
|
361
370
|
// an intermediate message will trigger GC, but the presence is still held
|
|
362
371
|
await dispatch(makeMessage(rootA, 'two', []));
|
|
363
372
|
await dispatch(makeBringOutYourDead());
|
|
364
|
-
t.
|
|
373
|
+
t.false(collected.result);
|
|
365
374
|
|
|
366
375
|
// now tell the vat we don't need a strong reference to that export.
|
|
367
376
|
await dispatch(makeDropExports(ex1));
|
|
368
377
|
await dispatch(makeBringOutYourDead());
|
|
369
378
|
|
|
370
379
|
// that removes the liveslots strongref, but the vat's remains in place
|
|
371
|
-
t.
|
|
380
|
+
t.false(collected.result);
|
|
372
381
|
|
|
373
382
|
// now the kernel tells the vat we can't even recognize the export
|
|
374
383
|
await dispatch(makeRetireExports(ex1));
|
|
@@ -376,14 +385,14 @@ test.serial(
|
|
|
376
385
|
|
|
377
386
|
// that ought to delete the table entry, but doesn't affect the vat
|
|
378
387
|
// strongref
|
|
379
|
-
t.
|
|
388
|
+
t.false(collected.result);
|
|
380
389
|
|
|
381
390
|
// now tell the vat to drop its strongref
|
|
382
391
|
await dispatch(makeMessage(rootA, 'drop', []));
|
|
383
392
|
await dispatch(makeBringOutYourDead());
|
|
384
393
|
|
|
385
394
|
// which should let the export be collected
|
|
386
|
-
t.
|
|
395
|
+
t.true(collected.result);
|
|
387
396
|
|
|
388
397
|
// the vat should *not* emit `syscall.retireExport`, because it already
|
|
389
398
|
// received a dispatch.retireExport
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
3
|
|
|
4
4
|
import { E } from '@endo/eventual-send';
|
|
5
5
|
import { Far } from '@endo/marshal';
|
|
6
6
|
import { makePromiseKit } from '@endo/promise-kit';
|
|
7
7
|
import { Fail } from '@agoric/assert';
|
|
8
|
+
import { kslot, kser, kunser } from '@agoric/kmarshal';
|
|
8
9
|
import { M } from '@agoric/store';
|
|
9
10
|
import { makeLiveSlots, makeMarshaller } from '../src/liveslots.js';
|
|
10
|
-
import { kslot, kser, kunser } from './kmarshal.js';
|
|
11
11
|
import { buildSyscall, makeDispatch } from './liveslots-helpers.js';
|
|
12
12
|
import { makeMessage, makeStartVat, makeResolve, makeReject } from './util.js';
|
|
13
13
|
import { makeMockGC } from './mock-gc.js';
|
|
@@ -45,14 +45,14 @@ test('calls', async t => {
|
|
|
45
45
|
|
|
46
46
|
// root!one() // sendOnly
|
|
47
47
|
await dispatch(makeMessage(rootA, 'one', ['args']));
|
|
48
|
-
t.
|
|
48
|
+
t.is(log.shift(), 'one');
|
|
49
49
|
|
|
50
50
|
// pr = makePromise()
|
|
51
51
|
// root!two(pr.promise)
|
|
52
52
|
// pr.resolve('result')
|
|
53
53
|
await dispatch(makeMessage(rootA, 'two', [kslot('p-1')]));
|
|
54
54
|
t.deepEqual(log.shift(), { type: 'subscribe', target: 'p-1' });
|
|
55
|
-
t.
|
|
55
|
+
t.is(log.shift(), 'two true');
|
|
56
56
|
|
|
57
57
|
await dispatch(makeResolve('p-1', kser('result')));
|
|
58
58
|
t.deepEqual(log.shift(), ['res', 'result']);
|
|
@@ -63,7 +63,7 @@ test('calls', async t => {
|
|
|
63
63
|
|
|
64
64
|
await dispatch(makeMessage(rootA, 'two', [kslot('p-2')]));
|
|
65
65
|
t.deepEqual(log.shift(), { type: 'subscribe', target: 'p-2' });
|
|
66
|
-
t.
|
|
66
|
+
t.is(log.shift(), 'two true');
|
|
67
67
|
|
|
68
68
|
await dispatch(makeReject('p-2', kser('rejection')));
|
|
69
69
|
t.deepEqual(log.shift(), ['rej', 'rejection']);
|
|
@@ -99,7 +99,7 @@ test('liveslots pipelines to syscall.send', async t => {
|
|
|
99
99
|
// for x!pipe1(), a second pipelined to the result promise of it, and a
|
|
100
100
|
// third pipelined to the result of the second.
|
|
101
101
|
|
|
102
|
-
t.
|
|
102
|
+
t.is(log.shift(), 'sent p1p2p3');
|
|
103
103
|
t.deepEqual(log.shift(), {
|
|
104
104
|
type: 'send',
|
|
105
105
|
targetSlot: x,
|
|
@@ -656,8 +656,7 @@ test('capdata size limit on syscalls', async t => {
|
|
|
656
656
|
};
|
|
657
657
|
|
|
658
658
|
const send = op => dispatch(makeMessage(rootA, op, [kslot(target)], rp));
|
|
659
|
-
const expectFail = () =>
|
|
660
|
-
t.deepEqual(log.shift(), 'fail: syscall capdata too large');
|
|
659
|
+
const expectFail = () => t.is(log.shift(), 'fail: syscall capdata too large');
|
|
661
660
|
const expectVoidReturn = () =>
|
|
662
661
|
t.deepEqual(log.shift(), {
|
|
663
662
|
type: 'resolve',
|
|
@@ -906,7 +905,7 @@ test('disable disavow', async t => {
|
|
|
906
905
|
|
|
907
906
|
// root~.one() // sendOnly
|
|
908
907
|
await dispatch(makeMessage(rootA, 'one', []));
|
|
909
|
-
t.
|
|
908
|
+
t.is(log.shift(), false);
|
|
910
909
|
t.deepEqual(log, []);
|
|
911
910
|
});
|
|
912
911
|
|
|
@@ -967,7 +966,7 @@ test('disavow', async t => {
|
|
|
967
966
|
// root~.one(import1) // sendOnly
|
|
968
967
|
await dispatch(makeMessage(rootA, 'one', [kslot(import1)]));
|
|
969
968
|
t.deepEqual(log.shift(), { type: 'dropImports', slots: [import1] });
|
|
970
|
-
t.
|
|
969
|
+
t.is(log.shift(), 'disavowed pres1');
|
|
971
970
|
|
|
972
971
|
function loggedError(re) {
|
|
973
972
|
const l = log.shift();
|
|
@@ -975,11 +974,11 @@ test('disavow', async t => {
|
|
|
975
974
|
t.truthy(re.test(l.message));
|
|
976
975
|
}
|
|
977
976
|
loggedError(/attempt to disavow unknown/);
|
|
978
|
-
t.
|
|
977
|
+
t.is(log.shift(), 'tried duplicate disavow');
|
|
979
978
|
loggedError(/attempt to disavow unknown/);
|
|
980
|
-
t.
|
|
979
|
+
t.is(log.shift(), 'tried to disavow Promise');
|
|
981
980
|
loggedError(/attempt to disavow an export/);
|
|
982
|
-
t.
|
|
981
|
+
t.is(log.shift(), 'tried to disavow export');
|
|
983
982
|
const msg = log.shift();
|
|
984
983
|
t.like(msg, {
|
|
985
984
|
type: 'exit',
|
|
@@ -987,7 +986,7 @@ test('disavow', async t => {
|
|
|
987
986
|
});
|
|
988
987
|
expectError(t, msg.info, /this Presence has been disavowed/);
|
|
989
988
|
t.deepEqual(log.shift(), Error('this Presence has been disavowed'));
|
|
990
|
-
t.
|
|
989
|
+
t.is(log.shift(), 'tried to send to disavowed');
|
|
991
990
|
t.deepEqual(log, []);
|
|
992
991
|
});
|
|
993
992
|
|
package/test/mock-gc.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
3
|
|
|
4
|
+
import { kslot, kunser } from '@agoric/kmarshal';
|
|
4
5
|
import {
|
|
5
6
|
setupTestLiveslots,
|
|
6
7
|
findSyscallsByType,
|
|
7
8
|
} from '../liveslots-helpers.js';
|
|
8
9
|
import { buildRootObject, mainHeldIdx, mapRef } from '../gc-helpers.js';
|
|
9
|
-
import { kslot, kunser } from '../kmarshal.js';
|
|
10
10
|
import { parseVatSlot } from '../../src/parseVatSlots.js';
|
|
11
11
|
|
|
12
12
|
// These tests follow the model described in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
2
|
|
|
3
|
+
import { kslot } from '@agoric/kmarshal';
|
|
4
4
|
import {
|
|
5
5
|
findSyscallsByType,
|
|
6
6
|
setupTestLiveslots,
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
refValString,
|
|
13
13
|
assertCollectionDeleted,
|
|
14
14
|
} from '../gc-helpers.js';
|
|
15
|
-
import { kslot } from '../kmarshal.js';
|
|
16
15
|
import { vstr } from '../util.js';
|
|
17
16
|
|
|
18
17
|
// These tests follow the model described in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
2
|
|
|
3
|
+
import { kslot } from '@agoric/kmarshal';
|
|
4
4
|
import { setupTestLiveslots } from '../liveslots-helpers.js';
|
|
5
5
|
import {
|
|
6
6
|
buildRootObject,
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
assertCollectionDeleted,
|
|
9
9
|
deduceCollectionID,
|
|
10
10
|
} from '../gc-helpers.js';
|
|
11
|
-
import { kslot } from '../kmarshal.js';
|
|
12
11
|
import { vstr } from '../util.js';
|
|
13
12
|
|
|
14
13
|
// These tests follow the model described in test-virtualObjectGC.js
|
package/test/util.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { kser } from '@agoric/kmarshal';
|
|
1
2
|
import { vstr } from './vat-util.js';
|
|
2
|
-
import { kser } from './kmarshal.js';
|
|
3
3
|
|
|
4
4
|
export { vstr };
|
|
5
5
|
|
|
@@ -48,7 +48,7 @@ export function buildDispatch(onDispatchCallback) {
|
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* @param {unknown} target
|
|
51
|
-
* @param {string} method
|
|
51
|
+
* @param {string | symbol} method
|
|
52
52
|
* @param {any[]} args
|
|
53
53
|
* @param {unknown} result
|
|
54
54
|
*/
|
package/test/vat-util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
/* global FinalizationRegistry WeakRef */
|
|
2
3
|
import test from 'ava';
|
|
3
|
-
import '@endo/init/debug.js';
|
|
4
4
|
|
|
5
5
|
import { buildSyscall } from '../liveslots-helpers.js';
|
|
6
6
|
import { makeVirtualReferenceManager } from '../../src/virtualReferences.js';
|
|
@@ -38,7 +38,7 @@ function weakKeyCheck(t, log, vref) {
|
|
|
38
38
|
t.true(result === undefined || !result.startsWith(prefix), `ew:${result}`);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
test('only enumerate virtual objects',
|
|
41
|
+
test('only enumerate virtual objects', t => {
|
|
42
42
|
const { log, vrm } = makeVRM();
|
|
43
43
|
|
|
44
44
|
// retiring a plain Remotable does a is-it-a-weak-key chck
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
2
|
|
|
4
3
|
import { makeFakeVirtualObjectManager } from '../../tools/fakeVirtualSupport.js';
|
|
5
4
|
|
|
@@ -15,7 +14,7 @@ function attack2(mut1, immut2) {
|
|
|
15
14
|
Reflect.apply(mutableProto.set, immut2, [6]);
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
test('forbid cross-facet prototype attack',
|
|
17
|
+
test('forbid cross-facet prototype attack', t => {
|
|
19
18
|
const vom = makeFakeVirtualObjectManager();
|
|
20
19
|
const init = () => ({ value: 0 });
|
|
21
20
|
const behavior = {
|
|
@@ -34,10 +33,12 @@ test('forbid cross-facet prototype attack', async t => {
|
|
|
34
33
|
thing2.mutable.set(2);
|
|
35
34
|
|
|
36
35
|
t.throws(() => attack1(thing1.mutable, thing2.immutable), {
|
|
37
|
-
message:
|
|
36
|
+
message:
|
|
37
|
+
'"In \\"set\\" method of (thing mutable)" may only be applied to a valid instance: "[Alleged: thing immutable]"',
|
|
38
38
|
});
|
|
39
39
|
t.throws(() => attack2(thing1.mutable, thing2.immutable), {
|
|
40
|
-
message:
|
|
40
|
+
message:
|
|
41
|
+
'"In \\"set\\" method of (thing mutable)" may only be applied to a valid instance: "[Alleged: thing immutable]"',
|
|
41
42
|
});
|
|
42
43
|
t.is(thing1.immutable.get(), 1);
|
|
43
44
|
t.is(thing2.immutable.get(), 2);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
2
|
|
|
4
3
|
import { makeFakeVirtualObjectManager } from '../../tools/fakeVirtualSupport.js';
|
|
5
4
|
|
|
6
|
-
test('non-object initial data message',
|
|
5
|
+
test('non-object initial data message', t => {
|
|
7
6
|
const vom = makeFakeVirtualObjectManager();
|
|
8
7
|
const goodInit = () => ({ value: 0 });
|
|
9
8
|
// 'badInit' is () => { value: 0 }
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
2
|
|
|
4
3
|
import { makeFakeVirtualObjectManager } from '../../tools/fakeVirtualSupport.js';
|
|
5
4
|
|
|
6
|
-
test('facets',
|
|
5
|
+
test('facets', t => {
|
|
7
6
|
const vom = makeFakeVirtualObjectManager();
|
|
8
7
|
const init = () => ({ value: 0 });
|
|
9
8
|
const behavior = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
3
|
import { Far } from '@endo/marshal';
|
|
4
|
+
import { kser } from '@agoric/kmarshal';
|
|
4
5
|
import { makeFakeVirtualStuff } from '../../tools/fakeVirtualSupport.js';
|
|
5
6
|
import { makeLiveSlots } from '../../src/liveslots.js';
|
|
6
7
|
import { parseVatSlot } from '../../src/parseVatSlots.js';
|
|
7
|
-
import { kser } from '../kmarshal.js';
|
|
8
8
|
import { buildSyscall } from '../liveslots-helpers.js';
|
|
9
9
|
import { makeStartVat, makeMessage } from '../util.js';
|
|
10
10
|
import { makeMockGC } from '../mock-gc.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
3
|
|
|
4
4
|
import { Remotable } from '@endo/marshal';
|
|
5
5
|
import { initEmpty } from '@agoric/store';
|
|
@@ -7,7 +7,7 @@ import { initEmpty } from '@agoric/store';
|
|
|
7
7
|
import { makeVatSlot } from '../../src/parseVatSlots.js';
|
|
8
8
|
import { makeFakeVirtualStuff } from '../../tools/fakeVirtualSupport.js';
|
|
9
9
|
|
|
10
|
-
test('VOM tracks reachable vrefs',
|
|
10
|
+
test('VOM tracks reachable vrefs', t => {
|
|
11
11
|
const { vom, vrm, cm } = makeFakeVirtualStuff();
|
|
12
12
|
const { defineKind } = vom;
|
|
13
13
|
const { makeScalarBigWeakMapStore } = cm;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
import '@endo/init/debug.js';
|
|
3
2
|
// this sets process.env.DEBUG = 'label-instances'
|
|
4
3
|
import './set-debug-label-instances.js';
|
|
5
4
|
|
|
@@ -16,7 +15,7 @@ const init = () => ({});
|
|
|
16
15
|
const behavior = {};
|
|
17
16
|
const facets = { foo: {}, bar: {} };
|
|
18
17
|
|
|
19
|
-
test('representatives with label-instances',
|
|
18
|
+
test('representatives with label-instances', t => {
|
|
20
19
|
const { fakeStuff, vom } = makeFakeVirtualStuff();
|
|
21
20
|
const { getSlotForVal } = fakeStuff;
|
|
22
21
|
const makeThing = vom.defineKind('thing', init, behavior);
|
|
@@ -33,7 +32,7 @@ test('representatives with label-instances', async t => {
|
|
|
33
32
|
t.is(`${q(thing2)}`, `"[Alleged: thing#${thing2vref}]"`);
|
|
34
33
|
});
|
|
35
34
|
|
|
36
|
-
test('facets with label-instances',
|
|
35
|
+
test('facets with label-instances', t => {
|
|
37
36
|
const { fakeStuff, vom } = makeFakeVirtualStuff();
|
|
38
37
|
const { getSlotForVal } = fakeStuff;
|
|
39
38
|
const makeThings = vom.defineKindMulti('thing', init, facets);
|
|
@@ -1,56 +1,57 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-nocheck
|
|
2
2
|
import test from 'ava';
|
|
3
|
-
import '@endo/init/debug.js';
|
|
4
3
|
|
|
5
4
|
import { Far } from '@endo/marshal';
|
|
6
5
|
import { initEmpty } from '@agoric/store';
|
|
7
6
|
|
|
8
7
|
import engineGC from '../engine-gc.js';
|
|
9
|
-
import { makeGcAndFinalize } from '../gc-and-finalize.js';
|
|
8
|
+
import { makeGcAndFinalize, watchCollected } from '../gc-and-finalize.js';
|
|
10
9
|
import { makeFakeVirtualStuff } from '../../tools/fakeVirtualSupport.js';
|
|
11
10
|
|
|
12
|
-
function
|
|
13
|
-
const held = Far(
|
|
14
|
-
const
|
|
11
|
+
function makeStashKit(name = 'held') {
|
|
12
|
+
const held = Far(name);
|
|
13
|
+
const collected = watchCollected(held);
|
|
15
14
|
const ws = new WeakSet(); // note: real WeakSet, not vref-aware
|
|
16
15
|
ws.add(held);
|
|
17
16
|
function isHeld(obj) {
|
|
18
17
|
return ws.has(obj);
|
|
19
18
|
}
|
|
20
|
-
|
|
19
|
+
function isCollected() {
|
|
20
|
+
return collected.result;
|
|
21
|
+
}
|
|
22
|
+
return { held, isCollected, isHeld };
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
function prepareEphemeral(vom) {
|
|
24
|
-
const
|
|
25
|
-
vom.registerEntry('o+12345',
|
|
26
|
-
|
|
27
|
-
return { wr };
|
|
26
|
+
const { held, isCollected } = makeStashKit('ephemeral');
|
|
27
|
+
vom.registerEntry('o+12345', held);
|
|
28
|
+
return { isCollected };
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
function stashRemotableOne(weakStore, key1) {
|
|
31
|
-
const { held,
|
|
32
|
+
const { held, isCollected, isHeld } = makeStashKit();
|
|
32
33
|
weakStore.init(key1, held);
|
|
33
|
-
return {
|
|
34
|
+
return { isCollected, isHeld };
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
function stashRemotableTwo(weakStore, key1) {
|
|
37
|
-
const { held,
|
|
38
|
+
const { held, isCollected, isHeld } = makeStashKit();
|
|
38
39
|
weakStore.init(key1, 'initial');
|
|
39
40
|
weakStore.set(key1, held);
|
|
40
|
-
return {
|
|
41
|
+
return { isCollected, isHeld };
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
function stashRemotableThree(holderMaker) {
|
|
44
|
-
const { held,
|
|
45
|
+
const { held, isCollected, isHeld } = makeStashKit();
|
|
45
46
|
const holder = holderMaker(held);
|
|
46
|
-
return {
|
|
47
|
+
return { isCollected, isHeld, holder };
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
function stashRemotableFour(holderMaker) {
|
|
50
|
-
const { held,
|
|
51
|
+
const { held, isCollected, isHeld } = makeStashKit();
|
|
51
52
|
const holder = holderMaker('initial');
|
|
52
53
|
holder.setHeld(held);
|
|
53
|
-
return {
|
|
54
|
+
return { isCollected, isHeld, holder };
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
test('remotables retained by virtualized data', async t => {
|
|
@@ -74,7 +75,7 @@ test('remotables retained by virtualized data', async t => {
|
|
|
74
75
|
// false positive in the subsequent test
|
|
75
76
|
const stash0 = prepareEphemeral(vom);
|
|
76
77
|
await gcAndFinalize();
|
|
77
|
-
t.
|
|
78
|
+
t.true(stash0.isCollected(), `caution: fake VOM didn't release Remotable`);
|
|
78
79
|
|
|
79
80
|
// stash a Remotable in the value of a weakStore
|
|
80
81
|
const key1 = makeKey();
|
|
@@ -84,14 +85,14 @@ test('remotables retained by virtualized data', async t => {
|
|
|
84
85
|
// Representatives or Presences, so the value is not holding a strong
|
|
85
86
|
// reference to the Remotable. The VOM is supposed to keep it alive, via
|
|
86
87
|
// reachableRemotables.
|
|
87
|
-
t.
|
|
88
|
+
t.false(stash1.isCollected());
|
|
88
89
|
t.truthy(stash1.isHeld(weakStore.get(key1)));
|
|
89
90
|
|
|
90
91
|
// do the same, but exercise weakStore.set instead of .init
|
|
91
92
|
const key2 = makeKey();
|
|
92
93
|
const stash2 = stashRemotableTwo(weakStore, key2);
|
|
93
94
|
await gcAndFinalize();
|
|
94
|
-
t.
|
|
95
|
+
t.false(stash2.isCollected());
|
|
95
96
|
t.truthy(stash2.isHeld(weakStore.get(key2)));
|
|
96
97
|
|
|
97
98
|
// now stash a Remotable in the state of a virtual object during init()
|
|
@@ -100,12 +101,12 @@ test('remotables retained by virtualized data', async t => {
|
|
|
100
101
|
// Each state property is virtualized upon write (via the generated
|
|
101
102
|
// setters). So again we rely on the VOM to keep the Remotable alive in
|
|
102
103
|
// case someone retrieves it again.
|
|
103
|
-
t.
|
|
104
|
+
t.false(stash3.isCollected());
|
|
104
105
|
t.truthy(stash3.isHeld(stash3.holder.getHeld()));
|
|
105
106
|
|
|
106
107
|
// same, but stash after init()
|
|
107
108
|
const stash4 = stashRemotableFour(makeHolder);
|
|
108
109
|
await gcAndFinalize();
|
|
109
|
-
t.
|
|
110
|
+
t.false(stash4.isCollected());
|
|
110
111
|
t.truthy(stash4.isHeld(stash4.holder.getHeld()));
|
|
111
112
|
});
|