@agoric/swingset-vat 0.32.3-dev-c14f1bb.0 → 0.32.3-dev-6d9ae67.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 +14 -13
- package/tools/run-utils.ts +156 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/swingset-vat",
|
|
3
|
-
"version": "0.32.3-dev-
|
|
3
|
+
"version": "0.32.3-dev-6d9ae67.0+6d9ae67",
|
|
4
4
|
"description": "Vat/Container Launcher",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
"@types/yargs-parser": "^21.0.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agoric/assert": "0.6.1-dev-
|
|
31
|
-
"@agoric/internal": "0.3.3-dev-
|
|
32
|
-
"@agoric/kmarshal": "0.1.1-dev-
|
|
33
|
-
"@agoric/store": "0.9.3-dev-
|
|
34
|
-
"@agoric/swing-store": "0.9.2-dev-
|
|
35
|
-
"@agoric/swingset-liveslots": "0.10.3-dev-
|
|
36
|
-
"@agoric/swingset-xsnap-supervisor": "0.10.3-dev-
|
|
37
|
-
"@agoric/time": "0.3.3-dev-
|
|
38
|
-
"@agoric/vat-data": "0.5.3-dev-
|
|
39
|
-
"@agoric/xsnap": "0.14.3-dev-
|
|
40
|
-
"@agoric/xsnap-lockdown": "0.14.1-dev-
|
|
30
|
+
"@agoric/assert": "0.6.1-dev-6d9ae67.0+6d9ae67",
|
|
31
|
+
"@agoric/internal": "0.3.3-dev-6d9ae67.0+6d9ae67",
|
|
32
|
+
"@agoric/kmarshal": "0.1.1-dev-6d9ae67.0+6d9ae67",
|
|
33
|
+
"@agoric/store": "0.9.3-dev-6d9ae67.0+6d9ae67",
|
|
34
|
+
"@agoric/swing-store": "0.9.2-dev-6d9ae67.0+6d9ae67",
|
|
35
|
+
"@agoric/swingset-liveslots": "0.10.3-dev-6d9ae67.0+6d9ae67",
|
|
36
|
+
"@agoric/swingset-xsnap-supervisor": "0.10.3-dev-6d9ae67.0+6d9ae67",
|
|
37
|
+
"@agoric/time": "0.3.3-dev-6d9ae67.0+6d9ae67",
|
|
38
|
+
"@agoric/vat-data": "0.5.3-dev-6d9ae67.0+6d9ae67",
|
|
39
|
+
"@agoric/xsnap": "0.14.3-dev-6d9ae67.0+6d9ae67",
|
|
40
|
+
"@agoric/xsnap-lockdown": "0.14.1-dev-6d9ae67.0+6d9ae67",
|
|
41
41
|
"@endo/base64": "^0.2.34",
|
|
42
42
|
"@endo/bundle-source": "^2.7.0",
|
|
43
43
|
"@endo/captp": "^3.1.4",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@endo/patterns": "^0.2.5",
|
|
53
53
|
"@endo/promise-kit": "^0.2.59",
|
|
54
54
|
"@endo/ses-ava": "^0.2.43",
|
|
55
|
+
"@endo/stream": "^0.3.28",
|
|
55
56
|
"@endo/zip": "^0.2.34",
|
|
56
57
|
"ansi-styles": "^6.2.1",
|
|
57
58
|
"anylogger": "^0.21.0",
|
|
@@ -101,5 +102,5 @@
|
|
|
101
102
|
"typeCoverage": {
|
|
102
103
|
"atLeast": 75.26
|
|
103
104
|
},
|
|
104
|
-
"gitHead": "
|
|
105
|
+
"gitHead": "6d9ae67c57499d7139dfce019b8c76f9ecdb825f"
|
|
105
106
|
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/* eslint-disable @jessie.js/safe-await-separator */
|
|
2
|
+
import { Fail, q } from '@agoric/assert';
|
|
3
|
+
import { kunser } from '@agoric/kmarshal';
|
|
4
|
+
import { makeQueue } from '@endo/stream';
|
|
5
|
+
import type { E } from '@endo/eventual-send';
|
|
6
|
+
|
|
7
|
+
import type { SwingsetController } from '../src/controller/controller.js';
|
|
8
|
+
|
|
9
|
+
const sink = () => {};
|
|
10
|
+
|
|
11
|
+
export const makeRunUtils = (
|
|
12
|
+
controller: SwingsetController,
|
|
13
|
+
log = (..._) => {},
|
|
14
|
+
) => {
|
|
15
|
+
let cranksRun = 0;
|
|
16
|
+
|
|
17
|
+
const mutex = makeQueue();
|
|
18
|
+
|
|
19
|
+
mutex.put(controller.run());
|
|
20
|
+
|
|
21
|
+
const runThunk = async <T extends () => any>(
|
|
22
|
+
thunk: T,
|
|
23
|
+
): Promise<ReturnType<T>> => {
|
|
24
|
+
try {
|
|
25
|
+
// this promise for the last lock may fail
|
|
26
|
+
await mutex.get();
|
|
27
|
+
} catch {
|
|
28
|
+
// noop because the result will resolve for the previous runMethod return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const thunkResult = await thunk();
|
|
32
|
+
|
|
33
|
+
const result = controller.run().then(cranks => {
|
|
34
|
+
cranksRun += cranks;
|
|
35
|
+
log(`kernel ran ${cranks} cranks`);
|
|
36
|
+
return thunkResult;
|
|
37
|
+
});
|
|
38
|
+
mutex.put(result.then(sink, sink));
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const queueAndRun = async (deliveryThunk, voidResult = false) => {
|
|
43
|
+
log('queueAndRun at', cranksRun);
|
|
44
|
+
|
|
45
|
+
const kpid = await runThunk(deliveryThunk);
|
|
46
|
+
|
|
47
|
+
if (voidResult) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const status = controller.kpStatus(kpid);
|
|
51
|
+
switch (status) {
|
|
52
|
+
case 'fulfilled':
|
|
53
|
+
return kunser(controller.kpResolution(kpid));
|
|
54
|
+
case 'rejected':
|
|
55
|
+
throw kunser(controller.kpResolution(kpid));
|
|
56
|
+
case 'unresolved':
|
|
57
|
+
throw Fail`unsettled value for ${q(kpid)}`;
|
|
58
|
+
default:
|
|
59
|
+
throw Fail`unknown promise status ${q(kpid)} ${q(status)}`;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
type EVProxy = typeof E & {
|
|
64
|
+
sendOnly: (presence: unknown) => Record<string, (...args: any) => void>;
|
|
65
|
+
vat: (name: string) => Record<string, (...args: any) => Promise<any>>;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// IMPORTANT WARNING TO USERS OF `EV`
|
|
69
|
+
//
|
|
70
|
+
// `EV` presents an abstraction that can be used (within tests only!) to get
|
|
71
|
+
// much of the convenience with respect to messaging that `E` provides in
|
|
72
|
+
// normal code. However, this convenience comes with a huge caveat that all
|
|
73
|
+
// users of this convenience feature MUST keep in mind.
|
|
74
|
+
//
|
|
75
|
+
// A test can drop messages onto the kernel's run queue using the
|
|
76
|
+
// `controller.queueToVatRoot` and `controller.queueToVatObject` methods.
|
|
77
|
+
// These are synchronous operations which merely place messages onto the run
|
|
78
|
+
// queue without causing execution. Execution, on the other hand, is
|
|
79
|
+
// initiated by calling `controller.run`, which will cause the kernel to begin
|
|
80
|
+
// delivering messages to vats from the run queue, continuing until the run
|
|
81
|
+
// queue is exhausted. HOWEVER, exhaustion of the run queue, which resolves
|
|
82
|
+
// the result promise returned by the `run` call, IS NOT coupled in any causal
|
|
83
|
+
// way to the resolution of result promises associated with the individual
|
|
84
|
+
// queued messages themselves. The status and resolution values of these
|
|
85
|
+
// promises can be synchronously queried (by kpid) via the
|
|
86
|
+
// `controller.kpStatus` and `controller.kpResolution` methods once `run` has
|
|
87
|
+
// completed. These queries are only available once the swingset has
|
|
88
|
+
// reqlinquished agency, i.e., when the work initiated by `controller.run` has
|
|
89
|
+
// finished. At that point, nothing is going on inside the kernel, and
|
|
90
|
+
// nothing WILL be going on inside the kernel until a subsequent call to
|
|
91
|
+
// `controller.run`, which in turn will only have an effect if additional
|
|
92
|
+
// messages have been placed on the kernel run queue in the meantime. You MAY
|
|
93
|
+
// NOT call `queueToVatRoot`, `queueToVatObject`, `kpStatus`, or
|
|
94
|
+
// `kpResolution` while run queue execution, triggered by a call to `run`, is
|
|
95
|
+
// in progress
|
|
96
|
+
//
|
|
97
|
+
// The functionality made available by `EV` looks similar to that provided by
|
|
98
|
+
// `E`, but it is very much not. When you send a message using `EV`, it
|
|
99
|
+
// places the message onto the kernel run queue and then immediately invokes
|
|
100
|
+
// `controller.run`. When the result of `run` resolves, the kpid returned by
|
|
101
|
+
// the message enqueueing operation is queried. If at that time the promise
|
|
102
|
+
// it identifies is resolved (or rejected), the value it was resolved (or
|
|
103
|
+
// rejected) to is used as the result from the `EV` invocation. However, if
|
|
104
|
+
// it is still pending at that time, `EV` will throw an exception, which will
|
|
105
|
+
// manifest as a rejection and your test will fail confusingly or abort. This
|
|
106
|
+
// means that if you initiate some operation via an `EV` message send, it must
|
|
107
|
+
// complete within a single `run` cycle for it to be of any use to you. This
|
|
108
|
+
// is quite different from a message sent using `E`, which will return a
|
|
109
|
+
// promise that can remain pending indefinitely, possibly to be settled by a
|
|
110
|
+
// future message delivery.
|
|
111
|
+
|
|
112
|
+
// @ts-expect-error cast, approximate
|
|
113
|
+
const EV: EVProxy = presence =>
|
|
114
|
+
new Proxy(harden({}), {
|
|
115
|
+
get: (_t, method, _rx) => {
|
|
116
|
+
const boundMethod = (...args) =>
|
|
117
|
+
queueAndRun(() =>
|
|
118
|
+
controller.queueToVatObject(presence, method, args),
|
|
119
|
+
);
|
|
120
|
+
return harden(boundMethod);
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
EV.vat = vatName =>
|
|
124
|
+
new Proxy(harden({}), {
|
|
125
|
+
get: (_t, method, _rx) => {
|
|
126
|
+
const boundMethod = (...args) =>
|
|
127
|
+
queueAndRun(() => controller.queueToVatRoot(vatName, method, args));
|
|
128
|
+
return harden(boundMethod);
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
// @ts-expect-error xxx
|
|
132
|
+
EV.sendOnly = presence =>
|
|
133
|
+
new Proxy(harden({}), {
|
|
134
|
+
get: (_t, method, _rx) => {
|
|
135
|
+
const boundMethod = (...args) =>
|
|
136
|
+
queueAndRun(
|
|
137
|
+
() => controller.queueToVatObject(presence, method, args),
|
|
138
|
+
true,
|
|
139
|
+
);
|
|
140
|
+
return harden(boundMethod);
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
// @ts-expect-error xxx
|
|
144
|
+
EV.get = presence =>
|
|
145
|
+
new Proxy(harden({}), {
|
|
146
|
+
get: (_t, pathElement, _rx) =>
|
|
147
|
+
queueAndRun(() =>
|
|
148
|
+
controller.queueToVatRoot('bootstrap', 'awaitVatObject', [
|
|
149
|
+
presence,
|
|
150
|
+
[pathElement],
|
|
151
|
+
]),
|
|
152
|
+
),
|
|
153
|
+
});
|
|
154
|
+
return harden({ runThunk, EV });
|
|
155
|
+
};
|
|
156
|
+
export type RunUtils = ReturnType<typeof makeRunUtils>;
|