@agoric/swingset-vat 0.33.0-u19.2 → 0.33.0-u21.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 +38 -36
- package/src/controller/controller.js +424 -330
- package/src/controller/startNodeSubprocess.js +6 -0
- package/src/controller/upgradeSwingset.js +2 -4
- package/src/devices/bridge/device-bridge.js +2 -0
- package/src/devices/timer/device-timer.js +41 -22
- package/src/kernel/kernel.js +79 -17
- package/src/kernel/slogger.js +109 -35
- package/src/kernel/state/deviceKeeper.js +4 -3
- package/src/kernel/state/kernelKeeper.js +39 -31
- package/src/kernel/state/stats.js +12 -9
- package/src/kernel/state/storageHelper.js +7 -2
- package/src/kernel/state/vatKeeper.js +5 -3
- package/src/kernel/vat-warehouse.js +22 -11
- package/src/lib/capdata.js +4 -17
- package/src/lib/message.js +4 -0
- package/src/types-external.js +33 -9
- package/src/vats/plugin-manager.js +3 -9
- package/src/vats/timer/vat-timer.js +12 -5
- package/src/vats/vat-admin/vat-vat-admin.js +2 -2
- package/tools/manual-timer.js +3 -2
- package/tools/run-utils.js +2 -1
- package/src/kernel/metrics.js +0 -152
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Nat, isNat } from '@endo/nat';
|
|
2
2
|
import { assert, Fail } from '@endo/errors';
|
|
3
|
+
import { KERNEL_STATS_METRICS } from '@agoric/internal/src/metrics.js';
|
|
3
4
|
import { naturalCompare } from '@agoric/internal/src/natural-sort.js';
|
|
4
5
|
import { makeDummySlogger, noopConsole } from '../slogger.js';
|
|
5
6
|
import {
|
|
@@ -25,7 +26,6 @@ import {
|
|
|
25
26
|
makeUpgradeID,
|
|
26
27
|
} from '../../lib/id.js';
|
|
27
28
|
import { kdebug } from '../../lib/kdebug.js';
|
|
28
|
-
import { KERNEL_STATS_METRICS } from '../metrics.js';
|
|
29
29
|
import { makeKernelStats } from './stats.js';
|
|
30
30
|
import {
|
|
31
31
|
enumeratePrefixedKeys,
|
|
@@ -212,9 +212,8 @@ function insistMeterID(m) {
|
|
|
212
212
|
export const getAllStaticVats = kvStore => {
|
|
213
213
|
const result = [];
|
|
214
214
|
const prefix = 'vat.name.';
|
|
215
|
-
for (const
|
|
216
|
-
const vatID = kvStore.get(
|
|
217
|
-
const name = k.slice(prefix.length);
|
|
215
|
+
for (const { key, suffix: name } of enumeratePrefixedKeys(kvStore, prefix)) {
|
|
216
|
+
const vatID = kvStore.get(key) || Fail`getNextKey ensures get`;
|
|
218
217
|
result.push([name, vatID]);
|
|
219
218
|
}
|
|
220
219
|
return result;
|
|
@@ -718,17 +717,22 @@ export default function makeKernelKeeper(
|
|
|
718
717
|
// We iterate through all ephemeral and virtual entries so the kernel
|
|
719
718
|
// can ensure that they are abandoned by a vat being upgraded.
|
|
720
719
|
const prefix = `${vatID}.c.`;
|
|
721
|
-
const ephStart =
|
|
722
|
-
const durStart =
|
|
723
|
-
const virStart =
|
|
720
|
+
const ephStart = `o+`;
|
|
721
|
+
const durStart = `o+d`;
|
|
722
|
+
const virStart = `o+v`;
|
|
724
723
|
/** @type {[string, string?][]} */
|
|
725
724
|
const ranges = [[ephStart, durStart], [virStart]];
|
|
726
725
|
for (const range of ranges) {
|
|
727
|
-
|
|
728
|
-
|
|
726
|
+
const rangeSuffix = range[0];
|
|
727
|
+
const args = /** @type {typeof ranges[0]} */ (
|
|
728
|
+
/** @type {unknown} */ (range.map(s => `${prefix}${s}`))
|
|
729
|
+
);
|
|
730
|
+
const prefixedKeys = enumeratePrefixedKeys(kvStore, ...args);
|
|
731
|
+
for (const { key, suffix } of prefixedKeys) {
|
|
732
|
+
const vref = `${rangeSuffix}${suffix}`;
|
|
729
733
|
// exclude the root object, which is replaced by upgrade
|
|
730
734
|
if (vref !== 'o+0') {
|
|
731
|
-
const kref = kvStore.get(
|
|
735
|
+
const kref = kvStore.get(key);
|
|
732
736
|
assert.typeof(kref, 'string');
|
|
733
737
|
yield { kref, vref };
|
|
734
738
|
}
|
|
@@ -1072,7 +1076,7 @@ export default function makeKernelKeeper(
|
|
|
1072
1076
|
|
|
1073
1077
|
// first, scan for exported objects, which must be orphaned
|
|
1074
1078
|
remaining = budget.exports ?? budget.default;
|
|
1075
|
-
for (const
|
|
1079
|
+
for (const { key } of enumeratePrefixedKeys(kvStore, exportPrefix)) {
|
|
1076
1080
|
// The void for an object exported by a vat will always be of the form
|
|
1077
1081
|
// `o+NN`. The '+' means that the vat exported the object (rather than
|
|
1078
1082
|
// importing it) and therefore the object is owned by (i.e., within) the
|
|
@@ -1080,9 +1084,7 @@ export default function makeKernelKeeper(
|
|
|
1080
1084
|
// begin with `vMM.c.o+`. In addition to deleting the c-list entry, we
|
|
1081
1085
|
// must also delete the corresponding kernel owner entry for the object,
|
|
1082
1086
|
// since the object will no longer be accessible.
|
|
1083
|
-
const
|
|
1084
|
-
assert(vref.startsWith('o+'), vref);
|
|
1085
|
-
const kref = kvStore.get(k);
|
|
1087
|
+
const kref = kvStore.get(key);
|
|
1086
1088
|
// note: adds to maybeFreeKrefs, deletes c-list and .owner
|
|
1087
1089
|
orphanKernelObject(kref, vatID);
|
|
1088
1090
|
work.exports += 1;
|
|
@@ -1094,11 +1096,14 @@ export default function makeKernelKeeper(
|
|
|
1094
1096
|
|
|
1095
1097
|
// then scan for imported objects, which must be decrefed
|
|
1096
1098
|
remaining = budget.imports ?? budget.default;
|
|
1097
|
-
for (const
|
|
1099
|
+
for (const { key, suffix } of enumeratePrefixedKeys(
|
|
1100
|
+
kvStore,
|
|
1101
|
+
importPrefix,
|
|
1102
|
+
)) {
|
|
1098
1103
|
// abandoned imports: delete the clist entry as if the vat did a
|
|
1099
1104
|
// drop+retire
|
|
1100
|
-
const kref = kvStore.get(
|
|
1101
|
-
const vref =
|
|
1105
|
+
const kref = kvStore.get(key) || Fail`getNextKey ensures get`;
|
|
1106
|
+
const vref = `o-${suffix}`;
|
|
1102
1107
|
undertaker.deleteCListEntry(kref, vref);
|
|
1103
1108
|
// that will also delete both db keys
|
|
1104
1109
|
work.imports += 1;
|
|
@@ -1113,9 +1118,12 @@ export default function makeKernelKeeper(
|
|
|
1113
1118
|
// kpids are still present in the dead vat's c-list. Clean those
|
|
1114
1119
|
// up now.
|
|
1115
1120
|
remaining = budget.promises ?? budget.default;
|
|
1116
|
-
for (const
|
|
1117
|
-
|
|
1118
|
-
|
|
1121
|
+
for (const { key, suffix } of enumeratePrefixedKeys(
|
|
1122
|
+
kvStore,
|
|
1123
|
+
promisePrefix,
|
|
1124
|
+
)) {
|
|
1125
|
+
const kref = kvStore.get(key) || Fail`getNextKey ensures get`;
|
|
1126
|
+
const vref = `p${suffix}`;
|
|
1119
1127
|
undertaker.deleteCListEntry(kref, vref);
|
|
1120
1128
|
// that will also delete both db keys
|
|
1121
1129
|
work.promises += 1;
|
|
@@ -1127,8 +1135,8 @@ export default function makeKernelKeeper(
|
|
|
1127
1135
|
|
|
1128
1136
|
// now loop back through everything and delete it all
|
|
1129
1137
|
remaining = budget.kv ?? budget.default;
|
|
1130
|
-
for (const
|
|
1131
|
-
kvStore.delete(
|
|
1138
|
+
for (const { key } of enumeratePrefixedKeys(kvStore, `${vatID}.`)) {
|
|
1139
|
+
kvStore.delete(key);
|
|
1132
1140
|
work.kv += 1;
|
|
1133
1141
|
remaining -= 1;
|
|
1134
1142
|
if (remaining <= 0) {
|
|
@@ -1167,11 +1175,11 @@ export default function makeKernelKeeper(
|
|
|
1167
1175
|
kvStore.set(DYNAMIC_IDS_KEY, JSON.stringify(newDynamicVatIDs));
|
|
1168
1176
|
} else {
|
|
1169
1177
|
kdebug(`removing static vat ${vatID}`);
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1178
|
+
const prefixedKeys = enumeratePrefixedKeys(kvStore, 'vat.name.');
|
|
1179
|
+
for (const { key, suffix: name } of prefixedKeys) {
|
|
1180
|
+
if (kvStore.get(key) === vatID) {
|
|
1181
|
+
kvStore.delete(key);
|
|
1173
1182
|
const VAT_NAMES_KEY = 'vat.names';
|
|
1174
|
-
const name = k.slice('vat.name.'.length);
|
|
1175
1183
|
const oldStaticVatNames = JSON.parse(getRequired(VAT_NAMES_KEY));
|
|
1176
1184
|
const newStaticVatNames = oldStaticVatNames.filter(v => v !== name);
|
|
1177
1185
|
kvStore.set(VAT_NAMES_KEY, JSON.stringify(newStaticVatNames));
|
|
@@ -1240,7 +1248,7 @@ export default function makeKernelKeeper(
|
|
|
1240
1248
|
function* enumeratePromisesByDecider(vatID) {
|
|
1241
1249
|
insistVatID(vatID);
|
|
1242
1250
|
const promisePrefix = `${vatID}.c.p`;
|
|
1243
|
-
for (const
|
|
1251
|
+
for (const { key } of enumeratePrefixedKeys(kvStore, promisePrefix)) {
|
|
1244
1252
|
// The vpid for a promise imported or exported by a vat (and thus
|
|
1245
1253
|
// potentially a promise for which the vat *might* be the decider) will
|
|
1246
1254
|
// always be of the form `p+NN` or `p-NN`. The corresponding vpid->kpid
|
|
@@ -1250,7 +1258,7 @@ export default function makeKernelKeeper(
|
|
|
1250
1258
|
// whether the vat is the decider or not. If it is, we add the promise
|
|
1251
1259
|
// to the list of promises that must be rejected because the dead vat
|
|
1252
1260
|
// will never be able to act upon them.
|
|
1253
|
-
const kpid = getRequired(
|
|
1261
|
+
const kpid = getRequired(key);
|
|
1254
1262
|
const p = getKernelPromise(kpid);
|
|
1255
1263
|
if (p.state === 'unresolved' && p.decider === vatID) {
|
|
1256
1264
|
yield [kpid, p];
|
|
@@ -1449,9 +1457,9 @@ export default function makeKernelKeeper(
|
|
|
1449
1457
|
|
|
1450
1458
|
function getDevices() {
|
|
1451
1459
|
const result = [];
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
const deviceID = kvStore.get(
|
|
1460
|
+
const prefixedKeys = enumeratePrefixedKeys(kvStore, 'device.name.');
|
|
1461
|
+
for (const { key, suffix: name } of prefixedKeys) {
|
|
1462
|
+
const deviceID = kvStore.get(key) || Fail`getNextKey ensures get`;
|
|
1455
1463
|
result.push([name, deviceID]);
|
|
1456
1464
|
}
|
|
1457
1465
|
return result;
|
|
@@ -70,10 +70,9 @@ export const makeKernelStats = kernelStatsMetrics => {
|
|
|
70
70
|
Object.freeze(allStatsKeys);
|
|
71
71
|
|
|
72
72
|
const pickStats = (stat, gauge = false) => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
);
|
|
73
|
+
if (!kernelConsensusStats || !kernelLocalStats) {
|
|
74
|
+
throw Fail`Kernel stats not initialized`;
|
|
75
|
+
}
|
|
77
76
|
const metricType = allStatsKeys[stat];
|
|
78
77
|
if (gauge) {
|
|
79
78
|
metricType === 'gauge' || Fail`Invalid kernel gauge stat ${stat}`;
|
|
@@ -116,7 +115,12 @@ export const makeKernelStats = kernelStatsMetrics => {
|
|
|
116
115
|
kernelStats[downStat] += delta;
|
|
117
116
|
};
|
|
118
117
|
|
|
119
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Return a fresh snapshot, with or without local stats.
|
|
120
|
+
*
|
|
121
|
+
* @param {boolean | undefined} [consensusOnly]
|
|
122
|
+
* @returns {Record<string, number>}
|
|
123
|
+
*/
|
|
120
124
|
const getStats = consensusOnly => {
|
|
121
125
|
return {
|
|
122
126
|
...(consensusOnly ? {} : kernelLocalStats),
|
|
@@ -130,10 +134,9 @@ export const makeKernelStats = kernelStatsMetrics => {
|
|
|
130
134
|
};
|
|
131
135
|
|
|
132
136
|
const getSerializedStats = () => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
);
|
|
137
|
+
if (!kernelConsensusStats || !kernelLocalStats) {
|
|
138
|
+
throw Fail`Kernel stats not initialized`;
|
|
139
|
+
}
|
|
137
140
|
|
|
138
141
|
return {
|
|
139
142
|
consensusStats: JSON.stringify(kernelConsensusStats),
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { Fail } from '@endo/errors';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @import {KVStore} from '@agoric/swing-store';
|
|
7
|
+
*/
|
|
8
|
+
|
|
5
9
|
/**
|
|
6
10
|
* Iterate over keys with a given prefix, in lexicographic order,
|
|
7
11
|
* excluding an exact match of the prefix.
|
|
@@ -9,7 +13,8 @@ import { Fail } from '@endo/errors';
|
|
|
9
13
|
* @param {KVStore} kvStore
|
|
10
14
|
* @param {string} prefix
|
|
11
15
|
* @param {string} [exclusiveEnd]
|
|
12
|
-
* @yields {string} the next key with the prefix that is not >= exclusiveEnd
|
|
16
|
+
* @yields {{key: string; suffix: string}} the next `key` with the prefix that is not >= exclusiveEnd
|
|
17
|
+
* and the `suffix` which is obtained by stripping the supplied prefix from the key
|
|
13
18
|
*/
|
|
14
19
|
export function* enumeratePrefixedKeys(kvStore, prefix, exclusiveEnd) {
|
|
15
20
|
/** @type {string | undefined} */
|
|
@@ -22,7 +27,7 @@ export function* enumeratePrefixedKeys(kvStore, prefix, exclusiveEnd) {
|
|
|
22
27
|
if (exclusiveEnd && key >= exclusiveEnd) {
|
|
23
28
|
break;
|
|
24
29
|
}
|
|
25
|
-
yield key;
|
|
30
|
+
yield { key, suffix: key.slice(prefix.length) };
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
harden(enumeratePrefixedKeys);
|
|
@@ -761,11 +761,13 @@ export function makeVatKeeper(
|
|
|
761
761
|
function dumpState() {
|
|
762
762
|
const res = [];
|
|
763
763
|
const prefix = `${vatID}.c.`;
|
|
764
|
-
for (const
|
|
765
|
-
|
|
764
|
+
for (const { key, suffix: slot } of enumeratePrefixedKeys(
|
|
765
|
+
kvStore,
|
|
766
|
+
prefix,
|
|
767
|
+
)) {
|
|
766
768
|
if (!slot.startsWith('k')) {
|
|
767
769
|
const vatSlot = slot;
|
|
768
|
-
const kernelSlot = kvStore.get(
|
|
770
|
+
const kernelSlot = kvStore.get(key) || Fail`getNextKey ensures get`;
|
|
769
771
|
/** @type { [string, string, string] } */
|
|
770
772
|
const item = [kernelSlot, vatID, vatSlot];
|
|
771
773
|
res.push(item);
|
|
@@ -299,7 +299,10 @@ export function makeVatWarehouse({
|
|
|
299
299
|
*/
|
|
300
300
|
async function replayTranscript(vatID, vatKeeper, manager) {
|
|
301
301
|
const total = vatKeeper.transcriptSize();
|
|
302
|
-
kernelSlog.
|
|
302
|
+
const finish = kernelSlog.startDuration(['start-replay', 'finish-replay'], {
|
|
303
|
+
vatID,
|
|
304
|
+
deliveries: total,
|
|
305
|
+
});
|
|
303
306
|
let first = true;
|
|
304
307
|
for await (const [deliveryNum, te] of vatKeeper.getTranscript()) {
|
|
305
308
|
// if (deliveryNum % 100 === 0) {
|
|
@@ -326,7 +329,7 @@ export function makeVatWarehouse({
|
|
|
326
329
|
finishSlog(status);
|
|
327
330
|
sim.finishSimulation(); // will throw if syscalls did not match
|
|
328
331
|
}
|
|
329
|
-
|
|
332
|
+
finish({ deliveries: undefined });
|
|
330
333
|
}
|
|
331
334
|
|
|
332
335
|
/**
|
|
@@ -563,18 +566,20 @@ export function makeVatWarehouse({
|
|
|
563
566
|
|
|
564
567
|
/**
|
|
565
568
|
* Save a heap snapshot for the given vatID, if the snapshotInterval
|
|
566
|
-
* is
|
|
569
|
+
* is satisfied or a lower explicit delivery count has been reached.
|
|
567
570
|
*
|
|
568
571
|
* @param {VatID} vatID
|
|
572
|
+
* @param {number} [minDeliveryCount]
|
|
569
573
|
*/
|
|
570
|
-
async function maybeSaveSnapshot(vatID) {
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
574
|
+
async function maybeSaveSnapshot(vatID, minDeliveryCount = snapshotInterval) {
|
|
575
|
+
kernelKeeper.vatIsAlive(vatID) || Fail`${q(vatID)}: not alive`;
|
|
576
|
+
const vatKeeper = kernelKeeper.provideVatKeeper(vatID);
|
|
577
|
+
const vatOptions = vatKeeper.getOptions();
|
|
578
|
+
|
|
579
|
+
if (!vatOptions.useTranscript) {
|
|
580
|
+
return false;
|
|
575
581
|
}
|
|
576
582
|
|
|
577
|
-
const vatKeeper = kernelKeeper.provideVatKeeper(vatID);
|
|
578
583
|
let reason;
|
|
579
584
|
|
|
580
585
|
const hasSnapshot = !!vatKeeper.getSnapshotInfo();
|
|
@@ -583,15 +588,21 @@ export function makeVatWarehouse({
|
|
|
583
588
|
if (!hasSnapshot && deliveriesInSpan >= snapshotInitial) {
|
|
584
589
|
// begin snapshot after 'snapshotInitial' deliveries in an incarnation
|
|
585
590
|
reason = { snapshotInitial };
|
|
586
|
-
} else if (deliveriesInSpan >=
|
|
591
|
+
} else if (deliveriesInSpan >= minDeliveryCount) {
|
|
587
592
|
// begin snapshot after 'snapshotInterval' deliveries in a span
|
|
588
|
-
reason = { snapshotInterval };
|
|
593
|
+
reason = { snapshotInterval: minDeliveryCount };
|
|
589
594
|
}
|
|
590
595
|
// console.log('maybeSaveSnapshot: reason:', reason);
|
|
591
596
|
if (!reason) {
|
|
592
597
|
return false; // not time to make a snapshot
|
|
593
598
|
}
|
|
594
599
|
|
|
600
|
+
const recreate = true; // PANIC in the failure case
|
|
601
|
+
const { manager } = await ensureVatOnline(vatID, recreate);
|
|
602
|
+
if (!manager.makeSnapshot) {
|
|
603
|
+
return false; // worker cannot make snapshots
|
|
604
|
+
}
|
|
605
|
+
|
|
595
606
|
// always do a bringOutYourDead just before a snapshot, to shake
|
|
596
607
|
// loose as much garbage as we can, and to minimize the GC
|
|
597
608
|
// sensitivity effects of the forced GC that snapshots perform
|
package/src/lib/capdata.js
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { krefOf, kunser } from '@agoric/kmarshal';
|
|
2
2
|
import { passStyleOf } from '@endo/far';
|
|
3
|
-
import { kunser, krefOf } from '@agoric/kmarshal';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
* actually is. A capdata object should have a .body property that's a string
|
|
8
|
-
* and a .slots property that's an array of strings.
|
|
9
|
-
*
|
|
10
|
-
* @param {any} capdata The object to be tested
|
|
11
|
-
* @throws {Error} if, upon inspection, the parameter does not satisfy the above
|
|
12
|
-
* criteria.
|
|
13
|
-
* @returns {asserts capdata is import('@endo/marshal').CapData<string>}
|
|
5
|
+
* @import {CapData} from '@endo/marshal';
|
|
14
6
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Fail`capdata has non-string .body ${capdata.body}`;
|
|
18
|
-
Array.isArray(capdata.slots) ||
|
|
19
|
-
Fail`capdata has non-Array slots ${capdata.slots}`;
|
|
20
|
-
// TODO check that the .slots array elements are actually strings
|
|
21
|
-
}
|
|
7
|
+
|
|
8
|
+
export { insistCapData } from '@agoric/swingset-liveslots/src/capdata.js';
|
|
22
9
|
|
|
23
10
|
/**
|
|
24
11
|
* Returns the slot of a presence if the provided capdata is composed
|
package/src/lib/message.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { assert, Fail } from '@endo/errors';
|
|
2
2
|
import { insistCapData } from './capdata.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @import {VatSyscallObject, VatSyscallResult, VatDeliveryResult} from '@agoric/swingset-liveslots';
|
|
6
|
+
*/
|
|
7
|
+
|
|
4
8
|
/**
|
|
5
9
|
* Assert function to ensure that something expected to be a message object
|
|
6
10
|
* actually is. A message object should have a .method property that's a
|
package/src/types-external.js
CHANGED
|
@@ -5,6 +5,7 @@ export {};
|
|
|
5
5
|
* @import {ERef} from '@endo/far';
|
|
6
6
|
* @import {Passable, RemotableObject} from '@endo/pass-style';
|
|
7
7
|
* @import {LimitedConsole} from '@agoric/internal/src/js-utils.js';
|
|
8
|
+
* @import {SlogProps, SlogDurationProps} from './controller/controller.js';
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
/* This file defines types that part of the external API of swingset. That
|
|
@@ -12,19 +13,36 @@ export {};
|
|
|
12
13
|
* with, like VatAdminService. */
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
|
-
* @
|
|
16
|
+
* @template T
|
|
17
|
+
* @typedef {'Device' & { __deviceType__: T }} Device
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** @typedef {<T>(target: Device<T>) => T} DProxy (approximately) */
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {(extraProps?: SlogDurationProps) => void} FinishSlogDuration
|
|
16
24
|
*/
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
27
|
* @typedef {import('@endo/marshal').CapData<string>} SwingSetCapData
|
|
20
28
|
*/
|
|
21
29
|
|
|
30
|
+
// TODO move Bundle types into Endo
|
|
22
31
|
/**
|
|
32
|
+
* @typedef {'getExport' | 'nestedEvaluate' | 'endoZipBase64'} BundleFormat
|
|
23
33
|
* @typedef { { moduleFormat: 'getExport', source: string, sourceMap?: string } } GetExportBundle
|
|
24
34
|
* @typedef { { moduleFormat: 'nestedEvaluate', source: string, sourceMap?: string } } NestedEvaluateBundle
|
|
25
|
-
* @typedef {
|
|
26
|
-
*
|
|
35
|
+
* @typedef { { moduleFormat: 'test', [x: symbol]: Record<PropertyKey, unknown> } } TestBundle
|
|
36
|
+
* @typedef { EndoZipBase64Bundle | GetExportBundle | NestedEvaluateBundle | TestBundle} Bundle
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
27
40
|
* @typedef { 'local' | 'node-subprocess' | 'xsnap' | 'xs-worker' } ManagerType
|
|
41
|
+
* The type of worker for hosting a vat.
|
|
42
|
+
* - **local**: a Compartment in the SwingSet Node.js process
|
|
43
|
+
* - **node-subprocess**: a child process using the same Node.js executable
|
|
44
|
+
* (`process.execPath`)
|
|
45
|
+
* - **xsnap** or **xs-worker**: an {@link @agoric/xsnap! @agoric/xsnap} worker
|
|
28
46
|
*/
|
|
29
47
|
|
|
30
48
|
/**
|
|
@@ -128,7 +146,9 @@ export {};
|
|
|
128
146
|
* @typedef { Awaited<ReturnType<typeof import('@agoric/xsnap').xsnap>> } XSnap
|
|
129
147
|
* @typedef { (dr: VatDeliveryResult) => void } SlogFinishDelivery
|
|
130
148
|
* @typedef { (ksr: KernelSyscallResult, vsr: VatSyscallResult) => void } SlogFinishSyscall
|
|
131
|
-
* @typedef { { write: (
|
|
149
|
+
* @typedef { { write: (obj: SlogProps) => void,
|
|
150
|
+
* startDuration: (labels: readonly [startLabel: string, endLabel: string],
|
|
151
|
+
* startProps: SlogDurationProps) => FinishSlogDuration,
|
|
132
152
|
* provideVatSlogger: (vatID: string,
|
|
133
153
|
* dynamic?: boolean,
|
|
134
154
|
* description?: string,
|
|
@@ -382,7 +402,9 @@ export {};
|
|
|
382
402
|
*
|
|
383
403
|
* @typedef { { vatParameters?: object, upgradeMessage?: string } } VatUpgradeOptions
|
|
384
404
|
* @typedef { { incarnationNumber: number } } VatUpgradeResults
|
|
385
|
-
|
|
405
|
+
*/
|
|
406
|
+
|
|
407
|
+
/**
|
|
386
408
|
* @callback ShutdownWithFailure
|
|
387
409
|
* Called to shut something down because something went wrong, where the reason
|
|
388
410
|
* is supposed to be an Error that describes what went wrong. Some valid
|
|
@@ -393,7 +415,9 @@ export {};
|
|
|
393
415
|
*
|
|
394
416
|
* @param {Error} reason
|
|
395
417
|
* @returns {void}
|
|
396
|
-
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
/**
|
|
397
421
|
* @typedef {object} VatAdminFacet
|
|
398
422
|
* A powerful object corresponding with a vat
|
|
399
423
|
* that can be used to upgrade it with new code or parameters,
|
|
@@ -411,8 +435,9 @@ export {};
|
|
|
411
435
|
* in which the JS memory space is abandoned. The new image is launched with access to 'baggage'
|
|
412
436
|
* and any durable storage reachable from it, and must fulfill all the obligations of the previous
|
|
413
437
|
* incarnation.
|
|
414
|
-
|
|
415
|
-
|
|
438
|
+
*/
|
|
439
|
+
|
|
440
|
+
/**
|
|
416
441
|
* @typedef {{ adminNode: Guarded<VatAdminFacet>, root: object }} CreateVatResults
|
|
417
442
|
*
|
|
418
443
|
* @typedef {object} VatAdminSvc
|
|
@@ -421,5 +446,4 @@ export {};
|
|
|
421
446
|
* @property {(name: string) => ERef<BundleCap>} getNamedBundleCap
|
|
422
447
|
* @property {(name: string) => ERef<BundleID>} getBundleIDByName
|
|
423
448
|
* @property {(bundleCap: BundleCap, options?: DynamicVatOptions) => ERef<CreateVatResults>} createVat
|
|
424
|
-
*
|
|
425
449
|
*/
|
|
@@ -6,8 +6,9 @@ import { Remotable } from '@endo/marshal';
|
|
|
6
6
|
import { Far, E } from '@endo/far';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* @
|
|
10
|
-
* @
|
|
9
|
+
* @import {ERef} from '@endo/far';
|
|
10
|
+
* @import {MapStore} from '@agoric/store';
|
|
11
|
+
* @import {Device, DProxy} from '@agoric/swingset-vat/src/types-external.js';
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
/** @type {{ onReset: (firstTime: Promise<boolean>) => void}} */
|
|
@@ -16,13 +17,6 @@ const DEFAULT_RESETTER = Far('resetter', { onReset: _ => {} });
|
|
|
16
17
|
/** @type {{ walk: (pluginRootP: any) => any }} */
|
|
17
18
|
const DEFAULT_WALKER = Far('walker', { walk: pluginRootP => pluginRootP });
|
|
18
19
|
|
|
19
|
-
/**
|
|
20
|
-
* @template T
|
|
21
|
-
* @typedef {'Device' & { __deviceType__: T }} Device
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/** @typedef {<T>(target: Device<T>) => T} DProxy (approximately) */
|
|
25
|
-
|
|
26
20
|
/**
|
|
27
21
|
* @callback LoadPlugin
|
|
28
22
|
* @param {string} specifier
|
|
@@ -15,9 +15,11 @@ import { TimeMath } from '@agoric/time';
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @import {LegacyWeakMap, WeakMapStore} from '@agoric/store';
|
|
18
|
-
* @import {MapStore} from '@agoric/swingset-liveslots';
|
|
18
|
+
* @import {Baggage, MapStore} from '@agoric/swingset-liveslots';
|
|
19
19
|
* @import {Passable, RemotableObject} from '@endo/pass-style';
|
|
20
20
|
* @import {Key} from '@endo/patterns';
|
|
21
|
+
* @import {TimerDevice} from '../../devices/timer/device-timer.js';
|
|
22
|
+
* @import {DProxy} from '../../types-external.js';
|
|
21
23
|
*/
|
|
22
24
|
|
|
23
25
|
// This consumes O(N) RAM only for outstanding promises, via wakeAt(),
|
|
@@ -237,9 +239,17 @@ const measureInterval = (start, interval, now) => {
|
|
|
237
239
|
return { latest, next };
|
|
238
240
|
};
|
|
239
241
|
|
|
242
|
+
/**
|
|
243
|
+
* @param {{
|
|
244
|
+
* D: DProxy;
|
|
245
|
+
* }} vatPowers
|
|
246
|
+
* @param {{}} _vatParameters
|
|
247
|
+
* @param {Baggage} baggage
|
|
248
|
+
*/
|
|
240
249
|
export const buildRootObject = (vatPowers, _vatParameters, baggage) => {
|
|
241
250
|
const { D } = vatPowers;
|
|
242
251
|
|
|
252
|
+
/** @type {TimerDevice} */
|
|
243
253
|
let timerDevice;
|
|
244
254
|
const insistDevice = () => {
|
|
245
255
|
assert(timerDevice, 'TimerService used before createTimerService()');
|
|
@@ -455,9 +465,6 @@ export const buildRootObject = (vatPowers, _vatParameters, baggage) => {
|
|
|
455
465
|
},
|
|
456
466
|
};
|
|
457
467
|
|
|
458
|
-
/**
|
|
459
|
-
* @returns { PromiseEvent }
|
|
460
|
-
*/
|
|
461
468
|
const makePromiseEvent = prepareKind(
|
|
462
469
|
baggage,
|
|
463
470
|
'promiseEvent',
|
|
@@ -948,7 +955,7 @@ export const buildRootObject = (vatPowers, _vatParameters, baggage) => {
|
|
|
948
955
|
* device, but we don't prohibit it from being called again (to
|
|
949
956
|
* replace the device), just in case that's useful someday
|
|
950
957
|
*
|
|
951
|
-
* @param {
|
|
958
|
+
* @param {TimerDevice} timerNode
|
|
952
959
|
* @returns {TimerService}
|
|
953
960
|
*/
|
|
954
961
|
const createTimerService = timerNode => {
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @import {VatAdminRootDeviceNode} from '../../devices/vat-admin/device-vat-admin.js';
|
|
23
|
-
* @import {DProxy} from'
|
|
23
|
+
* @import {DProxy} from'../../types-external.js';
|
|
24
24
|
* @import {Baggage} from '@agoric/vat-data';
|
|
25
25
|
*/
|
|
26
26
|
|
|
@@ -49,7 +49,7 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
|
|
|
49
49
|
const pendingBundles = new Map();
|
|
50
50
|
const pendingUpgrades = new Map(); // upgradeID -> Promise<UpgradeResults>
|
|
51
51
|
|
|
52
|
-
/** @type {import('
|
|
52
|
+
/** @type {import('../../types-external.js').Device<VatAdminRootDeviceNode>} */
|
|
53
53
|
let vatAdminDev;
|
|
54
54
|
|
|
55
55
|
const runningVats = new Map(); // vatID -> [doneP, { resolve, reject }]
|
package/tools/manual-timer.js
CHANGED
|
@@ -8,7 +8,7 @@ import { buildRootObject } from '../src/vats/timer/vat-timer.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* @import {Timestamp} from '@agoric/time'
|
|
10
10
|
* @import {TimerService} from '@agoric/time'
|
|
11
|
-
* @import {Waker} from '../src/devices/timer/device-timer.js'
|
|
11
|
+
* @import {TimerDevice, Waker} from '../src/devices/timer/device-timer.js'
|
|
12
12
|
*
|
|
13
13
|
* @typedef {object} ManualTimerCallbacks
|
|
14
14
|
* @property {(newTime: bigint, msg?: string) => void} [advanceTo]
|
|
@@ -34,7 +34,7 @@ const setup = callbacks => {
|
|
|
34
34
|
currentWakeup: undefined,
|
|
35
35
|
currentHandler: undefined,
|
|
36
36
|
};
|
|
37
|
-
const deviceMarker = harden({});
|
|
37
|
+
const deviceMarker = /** @type {TimerDevice} */ (harden({}));
|
|
38
38
|
const timerDeviceFuncs = harden({
|
|
39
39
|
getLastPolled: () => state.now,
|
|
40
40
|
setWakeup: (when, handler) => {
|
|
@@ -54,6 +54,7 @@ const setup = callbacks => {
|
|
|
54
54
|
state.currentHandler = undefined;
|
|
55
55
|
},
|
|
56
56
|
});
|
|
57
|
+
/** @type {any} */
|
|
57
58
|
const D = node => {
|
|
58
59
|
assert.equal(node, deviceMarker, 'fake D only supports devices.timer');
|
|
59
60
|
return timerDeviceFuncs;
|
package/tools/run-utils.js
CHANGED
|
@@ -15,9 +15,10 @@ import { makeQueue } from '@endo/stream';
|
|
|
15
15
|
*/
|
|
16
16
|
export const makeRunUtils = (controller, harness) => {
|
|
17
17
|
const mutex = makeQueue();
|
|
18
|
+
mutex.put('dummy result'); // so the first `await mutex.get()` doesn't hang
|
|
19
|
+
|
|
18
20
|
const logRunFailure = reason =>
|
|
19
21
|
console.log('controller.run() failure', reason);
|
|
20
|
-
mutex.put(controller.run().catch(logRunFailure));
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Wait for exclusive access to the controller, then before relinquishing that access,
|