@agoric/swingset-liveslots 0.10.3-dev-b282e92.0 → 0.10.3-dev-0cd32a5.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/package.json +5 -5
- package/test/exo-utils.js +70 -0
- package/test/handled-promises.test.js +2 -70
- package/test/strict-test-env-upgrade.test.js +94 -0
- package/test/virtual-objects/virtualObjectManager.test.js +4 -4
- package/tools/fakeVirtualObjectManager.js +2 -0
- package/tools/fakeVirtualSupport.js +10 -5
- package/tools/prepare-strict-test-env.js +121 -0
- package/tools/setup-vat-data.js +34 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/swingset-liveslots",
|
|
3
|
-
"version": "0.10.3-dev-
|
|
3
|
+
"version": "0.10.3-dev-0cd32a5.0+0cd32a5",
|
|
4
4
|
"description": "SwingSet ocap support layer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"lint:eslint": "eslint ."
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@agoric/internal": "0.3.3-dev-
|
|
21
|
-
"@agoric/store": "0.9.3-dev-
|
|
20
|
+
"@agoric/internal": "0.3.3-dev-0cd32a5.0+0cd32a5",
|
|
21
|
+
"@agoric/store": "0.9.3-dev-0cd32a5.0+0cd32a5",
|
|
22
22
|
"@endo/env-options": "^1.1.6",
|
|
23
23
|
"@endo/errors": "^1.2.5",
|
|
24
24
|
"@endo/eventual-send": "^1.2.5",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@endo/promise-kit": "^1.1.5"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@agoric/kmarshal": "0.1.1-dev-
|
|
35
|
+
"@agoric/kmarshal": "0.1.1-dev-0cd32a5.0+0cd32a5",
|
|
36
36
|
"ava": "^5.3.0"
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"typeCoverage": {
|
|
69
69
|
"atLeast": 75.1
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "0cd32a59f24dbea365f80be5ac3880db9234e4d1"
|
|
72
72
|
}
|
|
@@ -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
|
|
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
|
+
});
|
|
@@ -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',
|
|
@@ -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
|
|
34
|
+
this.#target = target;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
deref() {
|
|
36
|
-
return this
|
|
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 &&
|
|
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,
|
|
200
|
+
slotToVal.set(slot, new WeakRefForSlot(val));
|
|
197
201
|
}
|
|
198
202
|
|
|
199
203
|
function convertValToSlot(val) {
|
|
@@ -275,6 +279,7 @@ export function makeFakeLiveSlotsStuff(options = {}) {
|
|
|
275
279
|
return {
|
|
276
280
|
syscall,
|
|
277
281
|
allocateExportID,
|
|
282
|
+
allocatePromiseID,
|
|
278
283
|
allocateCollectionID,
|
|
279
284
|
getSlotForVal,
|
|
280
285
|
requiredValForSlot,
|
|
@@ -339,7 +344,7 @@ export function makeFakeWatchedPromiseManager(
|
|
|
339
344
|
* @param {object} [options]
|
|
340
345
|
* @param {number} [options.cacheSize]
|
|
341
346
|
* @param {boolean} [options.relaxDurabilityRules]
|
|
342
|
-
* @param {Map<
|
|
347
|
+
* @param {Map<string, string>} [options.fakeStore]
|
|
343
348
|
* @param {WeakMapConstructor} [options.WeakMap]
|
|
344
349
|
* @param {WeakSetConstructor} [options.WeakSet]
|
|
345
350
|
* @param {boolean} [options.weak]
|
|
@@ -0,0 +1,121 @@
|
|
|
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 { ReincarnateOptions } from './setup-vat-data.js'
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** @type {ReincarnateOptions} */
|
|
28
|
+
let incarnation;
|
|
29
|
+
let incarnationNumber = 0;
|
|
30
|
+
|
|
31
|
+
/** @param {Omit<ReincarnateOptions, 'fakeVomKit' | 'fakeStore'>} [options] */
|
|
32
|
+
export const annihilate = (options = {}) => {
|
|
33
|
+
// @ts-expect-error fakeStore and fakeVomKit don't exist on type, but drop them if they do at runtime
|
|
34
|
+
const { fakeStore: _fs, fakeVomKit: _fvk, ...opts } = options;
|
|
35
|
+
incarnation = reincarnate({ relaxDurabilityRules: false, ...opts });
|
|
36
|
+
incarnationNumber = 0;
|
|
37
|
+
return incarnation;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const getBaggage = () => {
|
|
41
|
+
return incarnation.fakeVomKit.cm.provideBaggage();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {ReincarnateOptions} [fromIncarnation]
|
|
46
|
+
*/
|
|
47
|
+
export const nextLife = (fromIncarnation = incarnation) => {
|
|
48
|
+
incarnation = reincarnate(fromIncarnation);
|
|
49
|
+
incarnationNumber += 1;
|
|
50
|
+
return incarnation;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @template {(baggage: import('@agoric/swingset-liveslots').Baggage) => Promise<any> | any} B
|
|
55
|
+
* @param {B} build
|
|
56
|
+
* @param {(tools: Awaited<ReturnType<B>>) => Promise<void> | void} [run]
|
|
57
|
+
* @param {object} [options]
|
|
58
|
+
* @param {ReincarnateOptions} [options.fromIncarnation]
|
|
59
|
+
* @param {boolean} [options.cleanStart]
|
|
60
|
+
*/
|
|
61
|
+
export const startLife = async (
|
|
62
|
+
build,
|
|
63
|
+
run,
|
|
64
|
+
{ fromIncarnation, cleanStart } = {},
|
|
65
|
+
) => {
|
|
66
|
+
await eventLoopIteration();
|
|
67
|
+
if (cleanStart) annihilate();
|
|
68
|
+
const oldIncarnationNumber = incarnationNumber;
|
|
69
|
+
const oldIncarnation = incarnation;
|
|
70
|
+
const disconnectionObject = makeUpgradeDisconnection(
|
|
71
|
+
'vat upgraded',
|
|
72
|
+
oldIncarnationNumber,
|
|
73
|
+
);
|
|
74
|
+
const { fakeVomKit } = nextLife(fromIncarnation);
|
|
75
|
+
/** @type {Map<string, import('@endo/promise-kit').PromiseKit<any>>} */
|
|
76
|
+
const previouslyWatchedPromises = new Map();
|
|
77
|
+
let buildTools;
|
|
78
|
+
try {
|
|
79
|
+
buildTools = await build(getBaggage());
|
|
80
|
+
fakeVomKit.wpm.loadWatchedPromiseTable(vref => {
|
|
81
|
+
// See revivePromise in liveslots.js
|
|
82
|
+
const { getValForSlot, valToSlot, setValForSlot } = fakeVomKit.fakeStuff;
|
|
83
|
+
// Assume all promises were decided by the previous incarnation
|
|
84
|
+
!getValForSlot(vref) || Fail`Attempting to revive known promise ${vref}`;
|
|
85
|
+
const pk = makePromiseKit();
|
|
86
|
+
previouslyWatchedPromises.set(vref, pk);
|
|
87
|
+
const val = pk.promise;
|
|
88
|
+
valToSlot.set(val, vref);
|
|
89
|
+
setValForSlot(vref, val);
|
|
90
|
+
return val;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
fakeVomKit.vom.insistAllDurableKindsReconnected();
|
|
94
|
+
|
|
95
|
+
await eventLoopIteration();
|
|
96
|
+
// End of start crank
|
|
97
|
+
} catch (err) {
|
|
98
|
+
// Rollback upgrade
|
|
99
|
+
incarnation = oldIncarnation;
|
|
100
|
+
incarnationNumber = oldIncarnationNumber;
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Simulate a dispatch of previously decided promise rejections
|
|
105
|
+
// In real swingset this could happen after some deliveries
|
|
106
|
+
for (const { reject } of previouslyWatchedPromises.values()) {
|
|
107
|
+
reject(disconnectionObject);
|
|
108
|
+
}
|
|
109
|
+
await eventLoopIteration();
|
|
110
|
+
// End of resolution dispatch crank
|
|
111
|
+
|
|
112
|
+
if (run) {
|
|
113
|
+
await run(buildTools);
|
|
114
|
+
await eventLoopIteration();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return incarnation;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Setup the initial incarnation
|
|
121
|
+
annihilate();
|
package/tools/setup-vat-data.js
CHANGED
|
@@ -12,7 +12,9 @@ import { makeFakeVirtualStuff } from './fakeVirtualSupport.js';
|
|
|
12
12
|
|
|
13
13
|
const { WeakMap, WeakSet } = globalThis;
|
|
14
14
|
|
|
15
|
-
/** @
|
|
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
|
-
|
|
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
|
+
*/
|
|
49
55
|
|
|
50
|
-
|
|
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
|
-
...
|
|
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 { ...
|
|
95
|
+
return { ...clonedIncarnation, fakeVomKit };
|
|
69
96
|
};
|