@agoric/swingset-liveslots 0.10.3-u16.1 → 0.10.3-u17.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 +17 -18
- package/src/boyd-gc.js +598 -0
- package/src/cache.js +1 -1
- package/src/capdata.js +1 -1
- package/src/collectionManager.js +65 -21
- package/src/facetiousness.js +1 -1
- package/src/liveslots.js +83 -202
- package/src/message.js +1 -1
- package/src/parseVatSlots.js +1 -1
- package/src/vatDataTypes.d.ts +7 -2
- package/src/virtualObjectManager.js +1 -6
- package/src/virtualReferences.js +83 -25
- package/src/watchedPromises.js +7 -2
- package/test/clear-collection.test.js +586 -0
- package/test/collections.test.js +41 -0
- package/test/dropped-weakset-9939.test.js +80 -0
- package/test/dummyMeterControl.js +1 -1
- package/test/durabilityChecks.test.js +1 -1
- package/test/gc-before-finalizer.test.js +230 -0
- package/test/handled-promises.test.js +266 -50
- package/test/liveslots-helpers.js +6 -1
- package/test/liveslots-mock-gc.test.js +99 -0
- package/test/liveslots-real-gc.test.js +18 -2
- package/test/liveslots.test.js +1 -1
- package/test/vat-environment.test.js +65 -0
- package/test/vat-util.js +1 -1
- package/test/virtual-objects/rep-tostring.test.js +1 -2
- package/test/vpid-liveslots.test.js +102 -1
- package/test/weakset-dropped-remotable.test.js +50 -0
- package/tools/fakeVirtualSupport.js +1 -3
- package/tools/setup-vat-data.js +10 -3
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import '@endo/init/debug.js';
|
|
3
|
+
import test from 'ava';
|
|
4
|
+
import { Far } from '@endo/marshal';
|
|
5
|
+
import { kser } from '@agoric/kmarshal';
|
|
6
|
+
import { passStyleOf } from '@endo/pass-style';
|
|
7
|
+
import { PassStyleOfEndowmentSymbol } from '@endo/pass-style/endow.js';
|
|
8
|
+
import { makeLiveSlots } from '../src/index.js';
|
|
9
|
+
import { makeStartVat } from './util.js';
|
|
10
|
+
import { buildSyscall } from './liveslots-helpers.js';
|
|
11
|
+
import { makeMockGC } from './mock-gc.js';
|
|
12
|
+
|
|
13
|
+
test('vat globals', async t => {
|
|
14
|
+
const { syscall } = buildSyscall();
|
|
15
|
+
const gcTools = makeMockGC();
|
|
16
|
+
const buildRootObject = () => Far('root', {});
|
|
17
|
+
let called = 0;
|
|
18
|
+
let vatGlobals;
|
|
19
|
+
let inescapableGlobalProperties;
|
|
20
|
+
const vatNS = harden({ buildRootObject });
|
|
21
|
+
// buildVatNamespace
|
|
22
|
+
const bVN = async (vG, iGP) => {
|
|
23
|
+
called += 1;
|
|
24
|
+
vatGlobals = vG;
|
|
25
|
+
inescapableGlobalProperties = iGP;
|
|
26
|
+
return vatNS;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const ls = makeLiveSlots(syscall, 'vatA', {}, {}, gcTools, undefined, bVN);
|
|
30
|
+
t.is(called, 0); // not called yet
|
|
31
|
+
await ls.dispatch(makeStartVat(kser()));
|
|
32
|
+
t.is(called, 1);
|
|
33
|
+
t.truthy(vatGlobals);
|
|
34
|
+
|
|
35
|
+
// 'harden' is provided by SES (installed by the lockdown bundle),
|
|
36
|
+
// not liveslots
|
|
37
|
+
t.is(typeof vatGlobals.harden, 'undefined');
|
|
38
|
+
|
|
39
|
+
// but liveslots provides VatData
|
|
40
|
+
t.is(typeof vatGlobals.VatData, 'object');
|
|
41
|
+
t.is(typeof vatGlobals.VatData, 'object');
|
|
42
|
+
t.is(typeof vatGlobals.VatData.defineKind, 'function');
|
|
43
|
+
t.is(typeof vatGlobals.VatData.defineKindMulti, 'function');
|
|
44
|
+
t.is(typeof vatGlobals.VatData.defineDurableKind, 'function');
|
|
45
|
+
t.is(typeof vatGlobals.VatData.defineDurableKindMulti, 'function');
|
|
46
|
+
t.is(typeof vatGlobals.VatData.makeKindHandle, 'function');
|
|
47
|
+
t.is(typeof vatGlobals.VatData.canBeDurable, 'function');
|
|
48
|
+
t.is(typeof vatGlobals.VatData.providePromiseWatcher, 'function');
|
|
49
|
+
t.is(typeof vatGlobals.VatData.watchPromise, 'function');
|
|
50
|
+
t.is(typeof vatGlobals.VatData.makeScalarBigMapStore, 'function');
|
|
51
|
+
t.is(typeof vatGlobals.VatData.makeScalarBigWeakMapStore, 'function');
|
|
52
|
+
t.is(typeof vatGlobals.VatData.makeScalarBigSetStore, 'function');
|
|
53
|
+
t.is(typeof vatGlobals.VatData.makeScalarBigWeakSetStore, 'function');
|
|
54
|
+
|
|
55
|
+
t.is(typeof inescapableGlobalProperties.WeakMap, 'function');
|
|
56
|
+
t.not(inescapableGlobalProperties.WeakMap, WeakMap);
|
|
57
|
+
t.is(typeof inescapableGlobalProperties.WeakSet, 'function');
|
|
58
|
+
t.not(inescapableGlobalProperties.WeakSet, WeakSet);
|
|
59
|
+
t.is(
|
|
60
|
+
typeof inescapableGlobalProperties[PassStyleOfEndowmentSymbol],
|
|
61
|
+
'function',
|
|
62
|
+
);
|
|
63
|
+
// this is the passStyleOf created by liveslots, with a real WeakMap
|
|
64
|
+
t.is(inescapableGlobalProperties[PassStyleOfEndowmentSymbol], passStyleOf);
|
|
65
|
+
});
|
package/test/vat-util.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// this file is imported by some test vats, so don't import any non-pure
|
|
2
2
|
// modules
|
|
3
3
|
|
|
4
|
-
import { Fail } from '@
|
|
4
|
+
import { Fail } from '@endo/errors';
|
|
5
5
|
import { kser, kunser } from '@agoric/kmarshal';
|
|
6
6
|
|
|
7
7
|
export function extractMessage(vatDeliverObject) {
|
|
@@ -5,12 +5,11 @@ import './set-debug-label-instances.js';
|
|
|
5
5
|
import { passStyleOf } from '@endo/far';
|
|
6
6
|
|
|
7
7
|
// this samples it
|
|
8
|
+
import { q } from '@endo/errors';
|
|
8
9
|
import { makeFakeVirtualStuff } from '../../tools/fakeVirtualSupport.js';
|
|
9
10
|
// all tests in this file will be run with DEBUG='label-instances'
|
|
10
11
|
import { parseVatSlot } from '../../src/parseVatSlots.js';
|
|
11
12
|
|
|
12
|
-
const { quote: q } = assert;
|
|
13
|
-
|
|
14
13
|
const init = () => ({});
|
|
15
14
|
const behavior = {};
|
|
16
15
|
const facets = { foo: {}, bar: {} };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import test from 'ava';
|
|
3
3
|
|
|
4
|
+
import { Fail } from '@endo/errors';
|
|
4
5
|
import { E } from '@endo/eventual-send';
|
|
5
6
|
import { makePromiseKit } from '@endo/promise-kit';
|
|
6
7
|
import { Far } from '@endo/marshal';
|
|
7
|
-
import { Fail } from '@agoric/assert';
|
|
8
8
|
import { kser, kslot } from '@agoric/kmarshal';
|
|
9
9
|
import { buildSyscall, makeDispatch } from './liveslots-helpers.js';
|
|
10
10
|
import { makeMessage, makeResolve, makeReject } from './util.js';
|
|
@@ -898,3 +898,104 @@ test('inter-vat circular promise references', async t => {
|
|
|
898
898
|
// });
|
|
899
899
|
// t.deepEqual(log, []);
|
|
900
900
|
});
|
|
901
|
+
|
|
902
|
+
test('accept previously allocated promise', async t => {
|
|
903
|
+
function build(vatPowers, vatParameters) {
|
|
904
|
+
const { target } = vatParameters;
|
|
905
|
+
return Far('root', {
|
|
906
|
+
call() {
|
|
907
|
+
const promise = E(target).foo();
|
|
908
|
+
// wrap to avoid adoption
|
|
909
|
+
return { promise };
|
|
910
|
+
},
|
|
911
|
+
async waitFor(promise2) {
|
|
912
|
+
// if we're in the same incarnation as the `E(target).foo()`, this
|
|
913
|
+
// `promise2` will be the same JS Promise as the `promise` above
|
|
914
|
+
const v = await promise2;
|
|
915
|
+
return v;
|
|
916
|
+
},
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
let log;
|
|
921
|
+
let syscall;
|
|
922
|
+
let dispatch;
|
|
923
|
+
|
|
924
|
+
const kvStore = new Map();
|
|
925
|
+
({ log, syscall } = buildSyscall({ kvStore }));
|
|
926
|
+
|
|
927
|
+
const target = 'o-1';
|
|
928
|
+
({ dispatch } = await makeDispatch(
|
|
929
|
+
syscall,
|
|
930
|
+
build,
|
|
931
|
+
'reimport-promise',
|
|
932
|
+
{},
|
|
933
|
+
{ target: kslot(target) },
|
|
934
|
+
));
|
|
935
|
+
log.length = 0; // assume pre-build vatstore operations are correct
|
|
936
|
+
|
|
937
|
+
const root = 'o+0';
|
|
938
|
+
const callResultP = 'p-1';
|
|
939
|
+
const waitForResultP = 'p-2';
|
|
940
|
+
const expectedP1 = 'p+5';
|
|
941
|
+
|
|
942
|
+
await dispatch(makeMessage(root, 'call', [], callResultP));
|
|
943
|
+
|
|
944
|
+
// The vat should send 'foo', subscribe to the result promise, and resolve with that promise
|
|
945
|
+
t.deepEqual(log.splice(0, 3), [
|
|
946
|
+
{
|
|
947
|
+
type: 'send',
|
|
948
|
+
targetSlot: target,
|
|
949
|
+
methargs: kser(['foo', []]),
|
|
950
|
+
resultSlot: expectedP1,
|
|
951
|
+
},
|
|
952
|
+
{ type: 'subscribe', target: expectedP1 },
|
|
953
|
+
{
|
|
954
|
+
type: 'resolve',
|
|
955
|
+
resolutions: [[callResultP, false, kser({ promise: kslot(expectedP1) })]],
|
|
956
|
+
},
|
|
957
|
+
]);
|
|
958
|
+
matchIDCounterSet(t, log);
|
|
959
|
+
t.deepEqual(log, []);
|
|
960
|
+
|
|
961
|
+
// snapshot the store at this point
|
|
962
|
+
const clonedStore = new Map(kvStore);
|
|
963
|
+
|
|
964
|
+
const verifyPromiseReImport = async shouldSubscribe => {
|
|
965
|
+
await dispatch(
|
|
966
|
+
makeMessage(root, 'waitFor', [kslot(expectedP1)], waitForResultP),
|
|
967
|
+
);
|
|
968
|
+
|
|
969
|
+
// The vat will only subscribe if it was upgraded; if the vat still
|
|
970
|
+
// remembers it, receiving the vref will merely look it up in slotToVal and
|
|
971
|
+
// not create a new Promise (and trigger a subscribe)
|
|
972
|
+
if (shouldSubscribe) {
|
|
973
|
+
t.deepEqual(log.shift(), { type: 'subscribe', target: expectedP1 });
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// waitFor will suspend until promise is resolved
|
|
977
|
+
t.deepEqual(log, []);
|
|
978
|
+
|
|
979
|
+
// Resolution propagates the value to the waitFor result
|
|
980
|
+
await dispatch(makeResolve(expectedP1, kser('success')));
|
|
981
|
+
t.deepEqual(log.shift(), {
|
|
982
|
+
type: 'resolve',
|
|
983
|
+
resolutions: [[waitForResultP, false, kser('success')]],
|
|
984
|
+
});
|
|
985
|
+
t.deepEqual(log, []);
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
await verifyPromiseReImport(false);
|
|
989
|
+
({ log, syscall } = buildSyscall({ kvStore: clonedStore }));
|
|
990
|
+
({ dispatch } = await makeDispatch(
|
|
991
|
+
syscall,
|
|
992
|
+
build,
|
|
993
|
+
'reimport-promise-v2',
|
|
994
|
+
{},
|
|
995
|
+
{},
|
|
996
|
+
));
|
|
997
|
+
log.length = 0;
|
|
998
|
+
|
|
999
|
+
// verify this works the same in the restarted vat
|
|
1000
|
+
await verifyPromiseReImport(true);
|
|
1001
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { Far } from '@endo/marshal';
|
|
3
|
+
import { kser, kslot } from '@agoric/kmarshal';
|
|
4
|
+
import { makeLiveSlots } from '../src/liveslots.js';
|
|
5
|
+
import { buildSyscall } from './liveslots-helpers.js';
|
|
6
|
+
import { makeStartVat, makeMessage, makeBringOutYourDead } from './util.js';
|
|
7
|
+
import { makeMockGC } from './mock-gc.js';
|
|
8
|
+
|
|
9
|
+
// Test for https://github.com/Agoric/agoric-sdk/issues/9956
|
|
10
|
+
|
|
11
|
+
test('delete remotable key from weakset', async t => {
|
|
12
|
+
const { syscall, log } = buildSyscall();
|
|
13
|
+
const gcTools = makeMockGC();
|
|
14
|
+
const rem = Far('remotable', {});
|
|
15
|
+
|
|
16
|
+
function buildRootObject(vatPowers) {
|
|
17
|
+
const { VatData } = vatPowers;
|
|
18
|
+
const { makeScalarBigWeakMapStore } = VatData;
|
|
19
|
+
const wms = makeScalarBigWeakMapStore();
|
|
20
|
+
return Far('root', {
|
|
21
|
+
store: p => {
|
|
22
|
+
wms.init(rem, p);
|
|
23
|
+
gcTools.kill(p);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const makeNS = () => ({ buildRootObject });
|
|
29
|
+
const ls = makeLiveSlots(syscall, 'vatA', {}, {}, gcTools, undefined, makeNS);
|
|
30
|
+
const { dispatch } = ls;
|
|
31
|
+
await dispatch(makeStartVat(kser()));
|
|
32
|
+
|
|
33
|
+
await dispatch(makeMessage('o+0', 'store', [kslot('o-1')]));
|
|
34
|
+
|
|
35
|
+
// pretend the Remotable was dropped from RAM
|
|
36
|
+
log.length = 0;
|
|
37
|
+
gcTools.kill(rem);
|
|
38
|
+
gcTools.flushAllFRs();
|
|
39
|
+
await dispatch(makeBringOutYourDead());
|
|
40
|
+
|
|
41
|
+
// that ought to emit a drop and retire for the presence
|
|
42
|
+
const gcCalls = log.filter(
|
|
43
|
+
l => l.type === 'dropImports' || l.type === 'retireImports',
|
|
44
|
+
);
|
|
45
|
+
t.deepEqual(gcCalls, [
|
|
46
|
+
{ type: 'dropImports', slots: ['o-1'] },
|
|
47
|
+
{ type: 'retireImports', slots: ['o-1'] },
|
|
48
|
+
]);
|
|
49
|
+
log.length = 0;
|
|
50
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* global globalThis */
|
|
2
2
|
/* eslint-disable max-classes-per-file */
|
|
3
|
+
import { assert, Fail } from '@endo/errors';
|
|
3
4
|
import { makeMarshal } from '@endo/marshal';
|
|
4
|
-
import { assert } from '@agoric/assert';
|
|
5
5
|
import { isPromise } from '@endo/promise-kit';
|
|
6
6
|
|
|
7
7
|
import { parseVatSlot } from '../src/parseVatSlots.js';
|
|
@@ -10,8 +10,6 @@ import { makeWatchedPromiseManager } from '../src/watchedPromises.js';
|
|
|
10
10
|
import { makeFakeVirtualObjectManager } from './fakeVirtualObjectManager.js';
|
|
11
11
|
import { makeFakeCollectionManager } from './fakeCollectionManager.js';
|
|
12
12
|
|
|
13
|
-
const { Fail } = assert;
|
|
14
|
-
|
|
15
13
|
const {
|
|
16
14
|
WeakRef: RealWeakRef,
|
|
17
15
|
WeakMap: RealWeakMap,
|
package/tools/setup-vat-data.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/* global globalThis */
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
//
|
|
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';
|
|
6
11
|
import { makeFakeVirtualStuff } from './fakeVirtualSupport.js';
|
|
7
12
|
|
|
8
13
|
const { WeakMap, WeakSet } = globalThis;
|
|
@@ -37,6 +42,8 @@ globalThis.VatData = harden({
|
|
|
37
42
|
fakeVomKit.cm.makeScalarBigWeakSetStore(...args),
|
|
38
43
|
});
|
|
39
44
|
|
|
45
|
+
globalThis[PassStyleOfEndowmentSymbol] = passStyleOf;
|
|
46
|
+
|
|
40
47
|
export const reincarnate = (options = {}) => {
|
|
41
48
|
const { fakeStore = new Map(), fakeVomKit: fvk } = options;
|
|
42
49
|
|