@agoric/swingset-vat 0.33.0-u17.1 → 0.33.0-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 +31 -31
- package/src/controller/controller.js +10 -10
- package/src/controller/initializeKernel.js +0 -2
- package/src/controller/initializeSwingset.js +72 -63
- package/src/controller/upgradeSwingset.js +179 -36
- package/src/devices/bridge/device-bridge.js +3 -2
- package/src/devices/lib/deviceTools.js +0 -1
- package/src/devices/mailbox/mailbox.js +76 -43
- package/src/index.js +3 -0
- package/src/kernel/deviceTranslator.js +1 -1
- package/src/kernel/gc-actions.js +2 -3
- package/src/kernel/kernel.js +59 -21
- package/src/kernel/state/kernelKeeper.js +230 -128
- package/src/kernel/state/vatKeeper.js +74 -38
- package/src/kernel/vat-warehouse.js +22 -16
- package/src/kernel/vatTranslator.js +7 -3
- package/src/supervisors/subprocess-node/supervisor-subprocess-node.js +1 -0
- package/src/typeGuards.js +3 -2
- package/src/types-external.js +9 -1
- package/src/types-internal.js +11 -0
- package/src/vats/comms/delivery.js +0 -2
- package/src/vats/comms/state.js +0 -4
- package/src/vats/timer/vat-timer.js +0 -2
- package/src/vats/vat-admin/vat-vat-admin.js +0 -4
- package/tools/baggage-check.js +0 -2
- package/tools/bootstrap-dvo-test.js +0 -1
- package/tools/bootstrap-relay.js +9 -0
- package/tools/prepare-strict-test-env-ava.js +19 -0
- package/tools/run-utils.js +11 -4
- package/tools/vat-puppet.js +111 -0
|
@@ -7,6 +7,7 @@ import { isObject } from '@endo/marshal';
|
|
|
7
7
|
import { parseKernelSlot } from '../parseKernelSlots.js';
|
|
8
8
|
import { makeVatSlot, parseVatSlot } from '../../lib/parseVatSlots.js';
|
|
9
9
|
import { insistVatID } from '../../lib/id.js';
|
|
10
|
+
import { insistCapData } from '../../lib/capdata.js';
|
|
10
11
|
import { kdebug } from '../../lib/kdebug.js';
|
|
11
12
|
import {
|
|
12
13
|
parseReachableAndVatSlot,
|
|
@@ -83,49 +84,53 @@ export function initializeVatState(
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
|
-
*
|
|
87
|
+
* @typedef {object} VatKeeperPowers
|
|
88
|
+
* @property {TranscriptStore} transcriptStore Accompanying transcript store, for the transcripts
|
|
89
|
+
* @property {*} kernelSlog
|
|
90
|
+
* @property {*} addKernelObject Kernel function to add a new object to the kernel's mapping tables.
|
|
91
|
+
* @property {*} addKernelPromiseForVat Kernel function to add a new promise to the kernel's mapping tables.
|
|
92
|
+
* @property {(kernelSlot: string) => boolean} kernelObjectExists
|
|
93
|
+
* @property {*} incrementRefCount
|
|
94
|
+
* @property {*} decrementRefCount
|
|
95
|
+
* @property {(kernelSlot: string) => {reachable: number, recognizable: number}} getObjectRefCount
|
|
96
|
+
* @property {(kernelSlot: string, o: { reachable: number, recognizable: number }) => void} setObjectRefCount
|
|
97
|
+
* @property {(vatID: string, kernelSlot: string) => {isReachable: boolean, vatSlot: string}} getReachableAndVatSlot
|
|
98
|
+
* @property {(kernelSlot: string) => void} addMaybeFreeKref
|
|
99
|
+
* @property {*} incStat
|
|
100
|
+
* @property {*} decStat
|
|
101
|
+
* @property {*} getCrankNumber
|
|
102
|
+
* @property {*} scheduleReap
|
|
103
|
+
* @property {SnapStore} snapStore
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Produce a "vat keeper" for the kernel state of a vat.
|
|
87
108
|
*
|
|
88
|
-
* @param {KVStore} kvStore The keyValue store in which the persistent state will be kept
|
|
89
|
-
* @param {TranscriptStore} transcriptStore Accompanying transcript store, for the transcripts
|
|
90
|
-
* @param {*} kernelSlog
|
|
91
109
|
* @param {string} vatID The vat ID string of the vat in question
|
|
92
|
-
* @param {
|
|
93
|
-
*
|
|
94
|
-
* @param {*} addKernelPromiseForVat Kernel function to add a new promise to the
|
|
95
|
-
* kernel's mapping tables.
|
|
96
|
-
* @param {(kernelSlot: string) => boolean} kernelObjectExists
|
|
97
|
-
* @param {*} incrementRefCount
|
|
98
|
-
* @param {*} decrementRefCount
|
|
99
|
-
* @param {(kernelSlot: string) => {reachable: number, recognizable: number}} getObjectRefCount
|
|
100
|
-
* @param {(kernelSlot: string, o: { reachable: number, recognizable: number }) => void} setObjectRefCount
|
|
101
|
-
* @param {(vatID: string, kernelSlot: string) => {isReachable: boolean, vatSlot: string}} getReachableAndVatSlot
|
|
102
|
-
* @param {(kernelSlot: string) => void} addMaybeFreeKref
|
|
103
|
-
* @param {*} incStat
|
|
104
|
-
* @param {*} decStat
|
|
105
|
-
* @param {*} getCrankNumber
|
|
106
|
-
* @param {*} scheduleReap
|
|
107
|
-
* @param {SnapStore} [snapStore]
|
|
108
|
-
* returns an object to hold and access the kernel's state for the given vat
|
|
110
|
+
* @param {KVStore} kvStore The keyValue store in which the persistent state will be kept
|
|
111
|
+
* @param {VatKeeperPowers} powers
|
|
109
112
|
*/
|
|
110
113
|
export function makeVatKeeper(
|
|
111
|
-
kvStore,
|
|
112
|
-
transcriptStore,
|
|
113
|
-
kernelSlog,
|
|
114
114
|
vatID,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
115
|
+
kvStore,
|
|
116
|
+
{
|
|
117
|
+
transcriptStore,
|
|
118
|
+
kernelSlog,
|
|
119
|
+
addKernelObject,
|
|
120
|
+
addKernelPromiseForVat,
|
|
121
|
+
kernelObjectExists,
|
|
122
|
+
incrementRefCount,
|
|
123
|
+
decrementRefCount,
|
|
124
|
+
getObjectRefCount,
|
|
125
|
+
setObjectRefCount,
|
|
126
|
+
getReachableAndVatSlot,
|
|
127
|
+
addMaybeFreeKref,
|
|
128
|
+
incStat,
|
|
129
|
+
decStat,
|
|
130
|
+
getCrankNumber,
|
|
131
|
+
scheduleReap,
|
|
132
|
+
snapStore,
|
|
133
|
+
},
|
|
129
134
|
) {
|
|
130
135
|
insistVatID(vatID);
|
|
131
136
|
|
|
@@ -173,6 +178,35 @@ export function makeVatKeeper(
|
|
|
173
178
|
return harden(options);
|
|
174
179
|
}
|
|
175
180
|
|
|
181
|
+
/**
|
|
182
|
+
* @param {SwingSetCapData} newVPCD
|
|
183
|
+
*/
|
|
184
|
+
function setVatParameters(newVPCD) {
|
|
185
|
+
insistCapData(newVPCD);
|
|
186
|
+
const key = `${vatID}.vatParameters`;
|
|
187
|
+
// increment-before-decrement to minimize spurious rc=0 checks
|
|
188
|
+
for (const kref of newVPCD.slots) {
|
|
189
|
+
incrementRefCount(kref, `${vatID}.vatParameters`);
|
|
190
|
+
}
|
|
191
|
+
const old = kvStore.get(key) || '{"slots":[]}';
|
|
192
|
+
for (const kref of JSON.parse(old).slots) {
|
|
193
|
+
decrementRefCount(kref, `${vatID}.vatParameters`);
|
|
194
|
+
}
|
|
195
|
+
kvStore.set(key, JSON.stringify(newVPCD));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @returns {SwingSetCapData | undefined} vpcd
|
|
200
|
+
*/
|
|
201
|
+
function getVatParameters() {
|
|
202
|
+
const key = `${vatID}.vatParameters`;
|
|
203
|
+
const old = kvStore.get(key);
|
|
204
|
+
if (old) {
|
|
205
|
+
return JSON.parse(old);
|
|
206
|
+
}
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
|
|
176
210
|
// This is named "addDirt" because it should increment all dirt
|
|
177
211
|
// counters (both for reap/BOYD and for heap snapshotting). We don't
|
|
178
212
|
// have `heapSnapshotDirt` yet, but when we do, it should get
|
|
@@ -768,6 +802,8 @@ export function makeVatKeeper(
|
|
|
768
802
|
setSourceAndOptions,
|
|
769
803
|
getSourceAndOptions,
|
|
770
804
|
getOptions,
|
|
805
|
+
setVatParameters,
|
|
806
|
+
getVatParameters,
|
|
771
807
|
addDirt,
|
|
772
808
|
getReapDirt,
|
|
773
809
|
clearReapDirt,
|
|
@@ -97,6 +97,7 @@ export function makeSyscallSimulator(
|
|
|
97
97
|
deliveryNum,
|
|
98
98
|
transcriptEntry,
|
|
99
99
|
) {
|
|
100
|
+
const context = `anachrophobia in ${vatID} delivery d${deliveryNum}`;
|
|
100
101
|
const syscallsExpected = [...transcriptEntry.sc]; // copy
|
|
101
102
|
const syscallsMade = [];
|
|
102
103
|
// syscallStatus's length will be max(syscallsExpected,
|
|
@@ -107,31 +108,36 @@ export function makeSyscallSimulator(
|
|
|
107
108
|
let replayError; // sticky
|
|
108
109
|
|
|
109
110
|
const explain = () => {
|
|
110
|
-
console.log(
|
|
111
|
+
console.log(
|
|
112
|
+
`anachrophobia strikes ${vatID} delivery d${deliveryNum} syscalls`,
|
|
113
|
+
);
|
|
111
114
|
for (const [idx, status] of syscallStatus.entries()) {
|
|
112
115
|
const expected = syscallsExpected[idx];
|
|
113
116
|
const got = syscallsMade[idx];
|
|
114
117
|
switch (status) {
|
|
115
118
|
case 'ok': {
|
|
116
|
-
console.log(`sc
|
|
119
|
+
console.log(`sc${idx}: ok: ${djson.stringify(got)}`);
|
|
117
120
|
break;
|
|
118
121
|
}
|
|
119
122
|
case 'wrong': {
|
|
120
|
-
console.log(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
console.log(
|
|
124
|
+
`
|
|
125
|
+
sc${idx}: WRONG
|
|
126
|
+
expected: ${djson.stringify(expected.s)}
|
|
127
|
+
got : ${djson.stringify(got)}`.trimStart(),
|
|
128
|
+
);
|
|
123
129
|
break;
|
|
124
130
|
}
|
|
125
131
|
case 'extra': {
|
|
126
|
-
console.log(`sc
|
|
132
|
+
console.log(`sc${idx}: EXTRA: ${djson.stringify(got)}`);
|
|
127
133
|
break;
|
|
128
134
|
}
|
|
129
135
|
case 'missing': {
|
|
130
|
-
console.log(`sc
|
|
136
|
+
console.log(`sc${idx}: MISSING: ${djson.stringify(expected.s)}`);
|
|
131
137
|
break;
|
|
132
138
|
}
|
|
133
139
|
default:
|
|
134
|
-
Fail`bad ${status}`;
|
|
140
|
+
Fail`sc${idx}: bad status ${status}`;
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
143
|
};
|
|
@@ -140,16 +146,16 @@ export function makeSyscallSimulator(
|
|
|
140
146
|
// slog entries have no kernel-translated kso/ksr
|
|
141
147
|
const finish = kernelSlog.syscall(vatID, undefined, vso);
|
|
142
148
|
const expected = syscallsExpected[syscallsMade.length];
|
|
143
|
-
syscallsMade.push(vso);
|
|
149
|
+
const idx = syscallsMade.push(vso) - 1;
|
|
144
150
|
if (!expected) {
|
|
145
151
|
syscallStatus.push('extra');
|
|
146
|
-
const error = Error(
|
|
152
|
+
const error = Error(`${context}: extra syscall at index sc${idx}`);
|
|
147
153
|
replayError ||= error;
|
|
148
154
|
throw error;
|
|
149
155
|
}
|
|
150
156
|
if (!syscallsAreIdentical(expected.s, vso)) {
|
|
151
157
|
syscallStatus.push('wrong');
|
|
152
|
-
const error = Error(
|
|
158
|
+
const error = Error(`${context}: wrong syscall at index sc${idx}`);
|
|
153
159
|
replayError ||= error;
|
|
154
160
|
throw error;
|
|
155
161
|
}
|
|
@@ -159,12 +165,14 @@ export function makeSyscallSimulator(
|
|
|
159
165
|
};
|
|
160
166
|
|
|
161
167
|
const finishSimulation = () => {
|
|
162
|
-
|
|
163
|
-
|
|
168
|
+
const missing = syscallsExpected.length - syscallsMade.length;
|
|
169
|
+
if (missing > 0) {
|
|
164
170
|
for (let i = 0; i < missing; i += 1) {
|
|
165
171
|
syscallStatus.push('missing');
|
|
166
172
|
}
|
|
167
|
-
const error = Error(
|
|
173
|
+
const error = Error(
|
|
174
|
+
`${context}: missing ${missing} syscall(s) at index sc${syscallsMade.length}`,
|
|
175
|
+
);
|
|
168
176
|
replayError ||= error;
|
|
169
177
|
}
|
|
170
178
|
|
|
@@ -389,7 +397,6 @@ export function makeVatWarehouse({
|
|
|
389
397
|
// entriesReplayed, // retval of replayTranscript() above
|
|
390
398
|
// );
|
|
391
399
|
ephemeral.vats.set(vatID, result);
|
|
392
|
-
// eslint-disable-next-line no-use-before-define
|
|
393
400
|
await applyAvailabilityPolicy(vatID);
|
|
394
401
|
return result;
|
|
395
402
|
}
|
|
@@ -596,7 +603,6 @@ export function makeVatWarehouse({
|
|
|
596
603
|
//
|
|
597
604
|
/** @type { KernelDeliveryObject } */
|
|
598
605
|
const kd = harden(['bringOutYourDead']);
|
|
599
|
-
// eslint-disable-next-line no-use-before-define
|
|
600
606
|
const vd = kernelDeliveryToVatDelivery(vatID, kd);
|
|
601
607
|
const vs = kernelSlog.provideVatSlogger(vatID).vatSlog;
|
|
602
608
|
await deliverToVat(vatID, kd, vd, vs);
|
|
@@ -50,6 +50,7 @@ function makeTranslateKernelDeliveryToVatDelivery(vatID, kernelKeeper) {
|
|
|
50
50
|
parseVatSlot(targetSlot).allocatedByVat || Fail`deliver() to wrong vat`;
|
|
51
51
|
} else if (type === 'promise') {
|
|
52
52
|
const p = kernelKeeper.getKernelPromise(target);
|
|
53
|
+
assert(p.state === 'unresolved');
|
|
53
54
|
p.decider === vatID || Fail`wrong decider`;
|
|
54
55
|
}
|
|
55
56
|
const inputSlots = msg.methargs.slots.map(slot =>
|
|
@@ -59,7 +60,9 @@ function makeTranslateKernelDeliveryToVatDelivery(vatID, kernelKeeper) {
|
|
|
59
60
|
if (msg.result) {
|
|
60
61
|
insistKernelType('promise', msg.result);
|
|
61
62
|
const p = kernelKeeper.getKernelPromise(msg.result);
|
|
62
|
-
p.state
|
|
63
|
+
if (p.state !== 'unresolved') {
|
|
64
|
+
throw Fail`result ${msg.result} already resolved`;
|
|
65
|
+
}
|
|
63
66
|
!p.decider || Fail`result ${msg.result} already has decider ${p.decider}`;
|
|
64
67
|
resultSlot = vatKeeper.mapKernelSlotToVatSlot(msg.result);
|
|
65
68
|
insistVatType('promise', resultSlot);
|
|
@@ -318,8 +321,9 @@ function makeTranslateVatSyscallToKernelSyscall(vatID, kernelKeeper) {
|
|
|
318
321
|
// In the case of non-pipelining vats these checks are redundant since
|
|
319
322
|
// we're guaranteed to have a promise newly allocated by the vat.
|
|
320
323
|
const p = kernelKeeper.getKernelPromise(result);
|
|
321
|
-
p.state
|
|
322
|
-
Fail`send() result ${result} is already resolved`;
|
|
324
|
+
if (p.state !== 'unresolved') {
|
|
325
|
+
throw Fail`send() result ${result} is already resolved`;
|
|
326
|
+
}
|
|
323
327
|
p.decider === vatID ||
|
|
324
328
|
Fail`send() result ${result} is decided by ${p.decider} not ${vatID}`;
|
|
325
329
|
kernelKeeper.clearDecider(result);
|
package/src/typeGuards.js
CHANGED
|
@@ -10,10 +10,11 @@ export const ManagerType = M.or(
|
|
|
10
10
|
|
|
11
11
|
const Bundle = M.splitRecord({ moduleType: M.string() });
|
|
12
12
|
|
|
13
|
-
const SwingsetConfigOptions =
|
|
13
|
+
const SwingsetConfigOptions = {
|
|
14
14
|
creationOptions: M.splitRecord({}, { critical: M.boolean() }),
|
|
15
15
|
parameters: M.recordOf(M.string(), M.any()),
|
|
16
|
-
}
|
|
16
|
+
};
|
|
17
|
+
harden(SwingsetConfigOptions);
|
|
17
18
|
|
|
18
19
|
const SwingSetConfigProperties = M.or(
|
|
19
20
|
M.splitRecord({ sourceSpec: M.string() }, SwingsetConfigOptions),
|
package/src/types-external.js
CHANGED
|
@@ -124,7 +124,7 @@ export {};
|
|
|
124
124
|
*
|
|
125
125
|
* @typedef { { transcriptCount: number } } VatStats
|
|
126
126
|
* @typedef { ReturnType<typeof import('./kernel/state/vatKeeper.js').makeVatKeeper> } VatKeeper
|
|
127
|
-
* @typedef {
|
|
127
|
+
* @typedef { import('./kernel/state/kernelKeeper.js').KernelKeeper } KernelKeeper
|
|
128
128
|
* @typedef { Awaited<ReturnType<typeof import('@agoric/xsnap').xsnap>> } XSnap
|
|
129
129
|
* @typedef { (dr: VatDeliveryResult) => void } SlogFinishDelivery
|
|
130
130
|
* @typedef { (ksr: KernelSyscallResult, vsr: VatSyscallResult) => void } SlogFinishSyscall
|
|
@@ -227,6 +227,7 @@ export {};
|
|
|
227
227
|
*
|
|
228
228
|
* @typedef { { exports: number,
|
|
229
229
|
* imports: number,
|
|
230
|
+
* promises: number,
|
|
230
231
|
* kv: number,
|
|
231
232
|
* snapshots: number,
|
|
232
233
|
* transcripts: number,
|
|
@@ -283,6 +284,13 @@ export {};
|
|
|
283
284
|
* @property { boolean } [restartWorkerOnSnapshot] Reload worker immediately upon snapshot creation
|
|
284
285
|
*/
|
|
285
286
|
|
|
287
|
+
/**
|
|
288
|
+
* @typedef { import('./devices/mailbox/mailbox.js').Mailbox } Mailbox
|
|
289
|
+
*/
|
|
290
|
+
/**
|
|
291
|
+
* @typedef { import('./devices/mailbox/mailbox.js').MailboxExport } MailboxExport
|
|
292
|
+
*/
|
|
293
|
+
|
|
286
294
|
/**
|
|
287
295
|
* Vat Creation and Management
|
|
288
296
|
*
|
package/src/types-internal.js
CHANGED
|
@@ -92,6 +92,17 @@ export {};
|
|
|
92
92
|
* @property {number} [computrons]
|
|
93
93
|
*/
|
|
94
94
|
|
|
95
|
+
/**
|
|
96
|
+
* @typedef {{ state: 'unresolved', refCount: number,
|
|
97
|
+
* decider: string | undefined, policy: string,
|
|
98
|
+
* subscribers: string[], queue: string[],
|
|
99
|
+
* }} UnresolvedPromiseRecord
|
|
100
|
+
* @typedef {{ state: 'fulfilled' | 'rejected', refCount: number,
|
|
101
|
+
* data: SwingSetCapData,
|
|
102
|
+
* }} SettledPromiseRecord
|
|
103
|
+
* @typedef {UnresolvedPromiseRecord | SettledPromiseRecord} PromiseRecord
|
|
104
|
+
*/
|
|
105
|
+
|
|
95
106
|
/**
|
|
96
107
|
* @typedef {{
|
|
97
108
|
* enablePipelining: boolean,
|
package/src/vats/comms/state.js
CHANGED
|
@@ -150,7 +150,6 @@ export function makeState(syscall) {
|
|
|
150
150
|
store.set('r.nextID', '1');
|
|
151
151
|
store.set('initialized', 'true');
|
|
152
152
|
if (controller) {
|
|
153
|
-
// eslint-disable-next-line no-use-before-define
|
|
154
153
|
addMetaObject(controller);
|
|
155
154
|
cdebug(`comms controller is ${controller}`);
|
|
156
155
|
}
|
|
@@ -393,7 +392,6 @@ export function makeState(syscall) {
|
|
|
393
392
|
// the object is unreachable
|
|
394
393
|
|
|
395
394
|
const { owner, isReachable, isRecognizable } =
|
|
396
|
-
// eslint-disable-next-line no-use-before-define
|
|
397
395
|
getOwnerAndStatus(lref);
|
|
398
396
|
if (isReachable) {
|
|
399
397
|
// but the exporter doesn't realize it yet, so schedule a
|
|
@@ -558,7 +556,6 @@ export function makeState(syscall) {
|
|
|
558
556
|
isReachable = isReachableByKernel(lref);
|
|
559
557
|
isRecognizable = !!mapToKernel(lref);
|
|
560
558
|
} else {
|
|
561
|
-
// eslint-disable-next-line no-use-before-define
|
|
562
559
|
const remote = getRemote(owner);
|
|
563
560
|
isReachable = remote.isReachable(lref);
|
|
564
561
|
isRecognizable = !!remote.mapToRemote(lref);
|
|
@@ -794,7 +791,6 @@ export function makeState(syscall) {
|
|
|
794
791
|
insistPromiseIsUnresolved,
|
|
795
792
|
markPromiseAsResolved,
|
|
796
793
|
|
|
797
|
-
// eslint-disable-next-line no-use-before-define
|
|
798
794
|
getRemote,
|
|
799
795
|
addRemote,
|
|
800
796
|
getRemoteIDForName,
|
|
@@ -100,7 +100,6 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
|
|
|
100
100
|
// getNotifier: ({ state }) => state.notifier, // XXX RESTORE
|
|
101
101
|
getNotifier: ({ _self }) => Fail`not implemented, see #7234`, // XXX TEMP
|
|
102
102
|
},
|
|
103
|
-
// eslint-disable-next-line no-use-before-define
|
|
104
103
|
{ finish: finishMeter },
|
|
105
104
|
);
|
|
106
105
|
|
|
@@ -120,18 +119,15 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
|
|
|
120
119
|
// getNotifier: ({ state }) => state.notifier, // will never fire // XXX RESTORE
|
|
121
120
|
getNotifier: ({ _self }) => Fail`not implemented, see #7234`, // XXX TEMP
|
|
122
121
|
},
|
|
123
|
-
// eslint-disable-next-line no-use-before-define
|
|
124
122
|
{ finish: finishMeter },
|
|
125
123
|
);
|
|
126
124
|
|
|
127
125
|
function finishMeter({ state, self }) {
|
|
128
|
-
// eslint-disable-next-line no-use-before-define
|
|
129
126
|
meterByID.init(
|
|
130
127
|
state.meterID,
|
|
131
128
|
// harden({ meter: self, updater: state.updater }), // XXX RESTORE
|
|
132
129
|
harden({ meter: self }), // XXX TEMP
|
|
133
130
|
);
|
|
134
|
-
// eslint-disable-next-line no-use-before-define
|
|
135
131
|
meterIDByMeter.set(self, state.meterID);
|
|
136
132
|
}
|
|
137
133
|
|
package/tools/baggage-check.js
CHANGED
package/tools/bootstrap-relay.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Source code for a bootstrap vat that runs blockchain behaviors (such as
|
|
3
|
+
* bridge vat integration) and exposes reflective methods for use in testing.
|
|
4
|
+
*
|
|
5
|
+
* TODO: Build from ./vat-puppet.js makeReflectionMethods
|
|
6
|
+
* and share code with packages/vats/tools/vat-reflective-chain-bootstrap.js
|
|
7
|
+
* (which basically extends this for better [mock] blockchain integration).
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
import { Fail, q } from '@endo/errors';
|
|
2
11
|
import { objectMap } from '@agoric/internal';
|
|
3
12
|
import { Far, E } from '@endo/far';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Like prepare-strict-test-env but also sets up ses-ava and provides
|
|
3
|
+
* the ses-ava `test` function to be used as if it is the ava
|
|
4
|
+
* `test` function.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import '@agoric/swingset-liveslots/tools/prepare-strict-test-env.js';
|
|
8
|
+
|
|
9
|
+
import { wrapTest } from '@endo/ses-ava';
|
|
10
|
+
import rawTest from 'ava';
|
|
11
|
+
|
|
12
|
+
export * from '@agoric/swingset-liveslots/tools/prepare-strict-test-env.js';
|
|
13
|
+
|
|
14
|
+
export const test = wrapTest(rawTest);
|
|
15
|
+
|
|
16
|
+
// Does not import from a module because we're testing the global env
|
|
17
|
+
/* global globalThis */
|
|
18
|
+
export const VatData = globalThis.VatData;
|
|
19
|
+
assert(VatData);
|
package/tools/run-utils.js
CHANGED
|
@@ -2,12 +2,18 @@ import { Fail, q } from '@endo/errors';
|
|
|
2
2
|
import { kunser } from '@agoric/kmarshal';
|
|
3
3
|
import { makeQueue } from '@endo/stream';
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* @import { ERef } from '@endo/far'
|
|
7
|
+
* @import { RunPolicy } from '../src/types-external.js'
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** @typedef {{ provideRunPolicy: () => RunPolicy | undefined }} RunHarness */
|
|
6
11
|
|
|
7
12
|
/**
|
|
8
13
|
* @param {import('../src/controller/controller.js').SwingsetController} controller
|
|
14
|
+
* @param {RunHarness} [harness]
|
|
9
15
|
*/
|
|
10
|
-
export const makeRunUtils = controller => {
|
|
16
|
+
export const makeRunUtils = (controller, harness) => {
|
|
11
17
|
const mutex = makeQueue();
|
|
12
18
|
const logRunFailure = reason =>
|
|
13
19
|
console.log('controller.run() failure', reason);
|
|
@@ -17,7 +23,7 @@ export const makeRunUtils = controller => {
|
|
|
17
23
|
* Wait for exclusive access to the controller, then before relinquishing that access,
|
|
18
24
|
* enqueue and process a delivery and return the result.
|
|
19
25
|
*
|
|
20
|
-
* @param {() => ERef<void | ReturnType<controller['queueToVatObject']>>} deliveryThunk
|
|
26
|
+
* @param {() => ERef<void | ReturnType<typeof controller['queueToVatObject']>>} deliveryThunk
|
|
21
27
|
* function for enqueueing a delivery and returning the result kpid (if any)
|
|
22
28
|
* @param {boolean} [voidResult] whether to ignore the result
|
|
23
29
|
* @returns {Promise<any>}
|
|
@@ -25,7 +31,8 @@ export const makeRunUtils = controller => {
|
|
|
25
31
|
const queueAndRun = async (deliveryThunk, voidResult = false) => {
|
|
26
32
|
await mutex.get();
|
|
27
33
|
const kpid = await deliveryThunk();
|
|
28
|
-
const
|
|
34
|
+
const runPolicy = harness && harness.provideRunPolicy();
|
|
35
|
+
const runResultP = controller.run(runPolicy);
|
|
29
36
|
mutex.put(runResultP.catch(logRunFailure));
|
|
30
37
|
await runResultP;
|
|
31
38
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Source code for a vat that exposes reflective methods for use in
|
|
3
|
+
* testing.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Fail, q } from '@endo/errors';
|
|
7
|
+
import { Far, E } from '@endo/far';
|
|
8
|
+
import { makePromiseKit } from '@endo/promise-kit';
|
|
9
|
+
import { objectMap } from '@agoric/internal';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @callback Die
|
|
13
|
+
* @param {unknown} completion
|
|
14
|
+
* @param {[target: unknown, method: string, ...args: unknown[]]} [finalSend]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Array<[name: string, ...args: unknown[]]>} CallLog
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {import('@agoric/swingset-vat').VatPowers} vatPowers
|
|
23
|
+
* @param {import('@agoric/vat-data').Baggage} baggage
|
|
24
|
+
*/
|
|
25
|
+
export const makeReflectionMethods = (vatPowers, baggage) => {
|
|
26
|
+
let baggageHoldCount = 0;
|
|
27
|
+
/** @type {Map<object, CallLog>} */
|
|
28
|
+
const callLogsByRemotable = new Map();
|
|
29
|
+
const heldInHeap = [];
|
|
30
|
+
const send = (target, method, ...args) => E(target)[method](...args);
|
|
31
|
+
const makeSpy = (value, name, callLog) => {
|
|
32
|
+
const spyName = `get ${name}`;
|
|
33
|
+
const spy = {
|
|
34
|
+
[spyName](...args) {
|
|
35
|
+
callLog.push([name, ...args]);
|
|
36
|
+
return value;
|
|
37
|
+
},
|
|
38
|
+
}[spyName];
|
|
39
|
+
return spy;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
/** @type {Die} */
|
|
44
|
+
dieHappy: (completion, finalSend) => {
|
|
45
|
+
vatPowers.exitVat(completion);
|
|
46
|
+
if (finalSend) send(...finalSend);
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
/** @type {Die} */
|
|
50
|
+
dieSad: (reason, finalSend) => {
|
|
51
|
+
vatPowers.exitVatWithFailure(/** @type {Error} */ (reason));
|
|
52
|
+
if (finalSend) send(...finalSend);
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
holdInBaggage: (...values) => {
|
|
56
|
+
for (const value of values) {
|
|
57
|
+
baggage.init(`held-${baggageHoldCount}`, value);
|
|
58
|
+
baggageHoldCount += 1;
|
|
59
|
+
}
|
|
60
|
+
return baggageHoldCount;
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
holdInHeap: (...values) => heldInHeap.push(...values),
|
|
64
|
+
|
|
65
|
+
makePromiseKit: () => {
|
|
66
|
+
const { promise, ...resolverMethods } = makePromiseKit();
|
|
67
|
+
void promise.catch(() => {});
|
|
68
|
+
const resolver = Far('resolver', resolverMethods);
|
|
69
|
+
return harden({ promise, resolver });
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
makeUnsettledPromise() {
|
|
73
|
+
const { promise } = makePromiseKit();
|
|
74
|
+
void promise.catch(() => {});
|
|
75
|
+
return promise;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns a remotable with methods that return provided values. Invocations
|
|
80
|
+
* of those methods and their arguments are captured for later retrieval by
|
|
81
|
+
* `getCallLogForRemotable`.
|
|
82
|
+
*
|
|
83
|
+
* @param {string} [label]
|
|
84
|
+
* @param {Record<string, any>} [fields]
|
|
85
|
+
*/
|
|
86
|
+
makeRemotable: (label = 'Remotable', fields = {}) => {
|
|
87
|
+
/** @type {CallLog} */
|
|
88
|
+
const callLog = [];
|
|
89
|
+
const methods = objectMap(fields, (value, name) =>
|
|
90
|
+
makeSpy(value, name, callLog),
|
|
91
|
+
);
|
|
92
|
+
const remotable = Far(label, { ...methods });
|
|
93
|
+
callLogsByRemotable.set(remotable, callLog);
|
|
94
|
+
return remotable;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {object} remotable
|
|
99
|
+
* @returns {CallLog}
|
|
100
|
+
*/
|
|
101
|
+
getCallLogForRemotable: remotable =>
|
|
102
|
+
callLogsByRemotable.get(remotable) ||
|
|
103
|
+
Fail`unknown remotable ${q(remotable)}`,
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
harden(makeReflectionMethods);
|
|
107
|
+
|
|
108
|
+
export function buildRootObject(vatPowers, _vatParameters, baggage) {
|
|
109
|
+
const methods = makeReflectionMethods(vatPowers, baggage);
|
|
110
|
+
return Far('root', methods);
|
|
111
|
+
}
|