@agoric/async-flow 0.1.1-dev-96c19f5.0 → 0.1.1-dev-e193e66.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/async-flow",
|
|
3
|
-
"version": "0.1.1-dev-
|
|
3
|
+
"version": "0.1.1-dev-e193e66.0+e193e66",
|
|
4
4
|
"description": "Upgrade async functions at await points by replay",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/Agoric/agoric-sdk",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"author": "Agoric",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@agoric/base-zone": "0.1.1-dev-
|
|
28
|
-
"@agoric/store": "0.9.3-dev-
|
|
29
|
-
"@agoric/vow": "0.1.1-dev-
|
|
27
|
+
"@agoric/base-zone": "0.1.1-dev-e193e66.0+e193e66",
|
|
28
|
+
"@agoric/store": "0.9.3-dev-e193e66.0+e193e66",
|
|
29
|
+
"@agoric/vow": "0.1.1-dev-e193e66.0+e193e66",
|
|
30
30
|
"@endo/common": "^1.2.2",
|
|
31
31
|
"@endo/errors": "^1.2.2",
|
|
32
32
|
"@endo/eventual-send": "^1.2.2",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"@endo/promise-kit": "^1.1.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@agoric/internal": "0.3.3-dev-
|
|
40
|
-
"@agoric/swingset-liveslots": "0.10.3-dev-
|
|
41
|
-
"@agoric/zone": "0.2.3-dev-
|
|
39
|
+
"@agoric/internal": "0.3.3-dev-e193e66.0+e193e66",
|
|
40
|
+
"@agoric/swingset-liveslots": "0.10.3-dev-e193e66.0+e193e66",
|
|
41
|
+
"@agoric/zone": "0.2.3-dev-e193e66.0+e193e66",
|
|
42
42
|
"@endo/env-options": "^1.1.4",
|
|
43
43
|
"@endo/ses-ava": "^1.2.2",
|
|
44
44
|
"ava": "^5.3.0"
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"typeCoverage": {
|
|
63
63
|
"atLeast": 77.83
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "e193e66fc578b1c00eda5f5ab6599f1cfbdc542f"
|
|
66
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-membrane.d.ts","sourceRoot":"","sources":["replay-membrane.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replay-membrane.d.ts","sourceRoot":"","sources":["replay-membrane.js"],"names":[],"mappings":"AAqBO;;;;;;;;;;;;;;;;;;;;uFAZuC,CAAC;;;oBAqBtC,SAAS;8CAZoB,IAAI,SAC/B,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;;;;;;;;;;GAqdnC;6BAGa,UAAU;;;;;;;;;;;;;;;;;;;;uFAlesB,CAAC;;;oBAqBtC,SAAS;2DAXP,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;;;;;;;;;;GAwdQ"}
|
package/src/replay-membrane.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/* eslint-disable no-use-before-define */
|
|
2
|
-
import { Fail, b, q } from '@endo/errors';
|
|
2
|
+
import { Fail, X, b, makeError, q } from '@endo/errors';
|
|
3
3
|
import { Far, Remotable, getInterfaceOf } from '@endo/pass-style';
|
|
4
4
|
import { E } from '@endo/eventual-send';
|
|
5
5
|
import { getMethodNames } from '@endo/eventual-send/utils.js';
|
|
6
|
-
import { makePromiseKit } from '@endo/promise-kit';
|
|
7
6
|
import { makeEquate } from './equate.js';
|
|
8
7
|
import { makeConvertKit } from './convert.js';
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* @import {PromiseKit} from '@endo/promise-kit'
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { fromEntries, defineProperties, assign } = Object;
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* @param {LogStore} log
|
|
@@ -31,6 +34,8 @@ export const makeReplayMembrane = (
|
|
|
31
34
|
|
|
32
35
|
let stopped = false;
|
|
33
36
|
|
|
37
|
+
const Panic = (template, ...args) => panic(makeError(X(template, ...args)));
|
|
38
|
+
|
|
34
39
|
// ////////////// Host or Interpreter to Guest ///////////////////////////////
|
|
35
40
|
|
|
36
41
|
/**
|
|
@@ -196,9 +201,61 @@ export const makeReplayMembrane = (
|
|
|
196
201
|
default: {
|
|
197
202
|
// @ts-expect-error TS correctly knows this case would be outside
|
|
198
203
|
// the type. But that's what we want to check.
|
|
199
|
-
throw
|
|
204
|
+
throw Panic`unexpected outcome kind ${q(outcome.kind)}`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// //////////////// Eventual Send ////////////////////////////////////////////
|
|
210
|
+
|
|
211
|
+
const guestHandler = harden({
|
|
212
|
+
applyMethod(guestTarget, optVerb, guestArgs, guestReturnedP) {
|
|
213
|
+
if (optVerb === undefined) {
|
|
214
|
+
throw Panic`guest eventual call not yet supported: ${guestTarget}(${b(guestArgs)}) -> ${b(guestReturnedP)}`;
|
|
215
|
+
} else {
|
|
216
|
+
throw Panic`guest eventual send not yet supported: ${guestTarget}.${b(optVerb)}(${b(guestArgs)}) -> ${b(guestReturnedP)}`;
|
|
200
217
|
}
|
|
218
|
+
},
|
|
219
|
+
applyFunction(guestTarget, guestArgs, guestReturnedP) {
|
|
220
|
+
return guestHandler.applyMethod(
|
|
221
|
+
guestTarget,
|
|
222
|
+
undefined,
|
|
223
|
+
guestArgs,
|
|
224
|
+
guestReturnedP,
|
|
225
|
+
);
|
|
226
|
+
},
|
|
227
|
+
get(guestTarget, prop, guestReturnedP) {
|
|
228
|
+
throw Panic`guest eventual get not yet supported: ${guestTarget}.${b(prop)} -> ${b(guestReturnedP)}`;
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const makeGuestPresence = (iface, methodEntries) => {
|
|
233
|
+
let guestPresence;
|
|
234
|
+
void new HandledPromise((_res, _rej, resolveWithPresence) => {
|
|
235
|
+
guestPresence = resolveWithPresence(guestHandler);
|
|
236
|
+
}); // no unfulfilledHandler
|
|
237
|
+
if (typeof guestPresence !== 'object') {
|
|
238
|
+
throw Fail`presence expected to be object ${guestPresence}`;
|
|
201
239
|
}
|
|
240
|
+
assign(guestPresence, fromEntries(methodEntries));
|
|
241
|
+
const result = Remotable(iface, undefined, guestPresence);
|
|
242
|
+
result === guestPresence ||
|
|
243
|
+
Fail`Remotable expected to make presence in place: ${guestPresence} vs ${result}`;
|
|
244
|
+
return result;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @returns {PromiseKit<any>}
|
|
249
|
+
*/
|
|
250
|
+
const makeGuestPromiseKit = () => {
|
|
251
|
+
let resolve;
|
|
252
|
+
let reject;
|
|
253
|
+
const promise = new HandledPromise((res, rej, _resPres) => {
|
|
254
|
+
resolve = res;
|
|
255
|
+
reject = rej;
|
|
256
|
+
}, guestHandler);
|
|
257
|
+
// @ts-expect-error TS cannot infer that it is a PromiseKit
|
|
258
|
+
return harden({ promise, resolve, reject });
|
|
202
259
|
};
|
|
203
260
|
|
|
204
261
|
// //////////////// Converters ///////////////////////////////////////////////
|
|
@@ -246,9 +303,7 @@ export const makeReplayMembrane = (
|
|
|
246
303
|
name,
|
|
247
304
|
makeGuestMethod(name),
|
|
248
305
|
]);
|
|
249
|
-
|
|
250
|
-
// use HandledPromise to make gRem a remote presence for hRem
|
|
251
|
-
gRem = Remotable(guestIface, undefined, fromEntries(guestMethods));
|
|
306
|
+
gRem = makeGuestPresence(guestIface, guestMethods);
|
|
252
307
|
}
|
|
253
308
|
// See note at the top of the function to see why clearing the `hRem`
|
|
254
309
|
// variable is safe, and what invariant the above code needs to maintain so
|
|
@@ -258,10 +313,12 @@ export const makeReplayMembrane = (
|
|
|
258
313
|
};
|
|
259
314
|
harden(makeGuestForHostRemotable);
|
|
260
315
|
|
|
316
|
+
/**
|
|
317
|
+
* @param {Vow} hVow
|
|
318
|
+
* @returns {Promise}
|
|
319
|
+
*/
|
|
261
320
|
const makeGuestForHostVow = hVow => {
|
|
262
|
-
|
|
263
|
-
// use HandledPromise to make `promise` a handled promise for hVow
|
|
264
|
-
const { promise, resolve, reject } = makePromiseKit();
|
|
321
|
+
const { promise, resolve, reject } = makeGuestPromiseKit();
|
|
265
322
|
guestPromiseMap.set(promise, harden({ resolve, reject }));
|
|
266
323
|
|
|
267
324
|
watchWake(hVow);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// eslint-disable-next-line import/order
|
|
2
|
+
import {
|
|
3
|
+
test,
|
|
4
|
+
getBaggage,
|
|
5
|
+
annihilate,
|
|
6
|
+
nextLife,
|
|
7
|
+
} from './prepare-test-env-ava.js';
|
|
8
|
+
|
|
9
|
+
import { Fail } from '@endo/errors';
|
|
10
|
+
import { prepareVowTools } from '@agoric/vow';
|
|
11
|
+
import { E } from '@endo/eventual-send';
|
|
12
|
+
// import E from '@agoric/vow/src/E.js';
|
|
13
|
+
import { makeHeapZone } from '@agoric/zone/heap.js';
|
|
14
|
+
import { makeVirtualZone } from '@agoric/zone/virtual.js';
|
|
15
|
+
import { makeDurableZone } from '@agoric/zone/durable.js';
|
|
16
|
+
|
|
17
|
+
import { prepareLogStore } from '../src/log-store.js';
|
|
18
|
+
import { prepareBijection } from '../src/bijection.js';
|
|
19
|
+
import { makeReplayMembrane } from '../src/replay-membrane.js';
|
|
20
|
+
|
|
21
|
+
const watchWake = _vowish => {};
|
|
22
|
+
const panic = problem => Fail`panic over ${problem}`;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Zone} zone
|
|
26
|
+
*/
|
|
27
|
+
const preparePingee = zone =>
|
|
28
|
+
zone.exoClass('Pingee', undefined, () => ({}), {
|
|
29
|
+
ping(_str) {},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {ReturnType<ReturnType<preparePingee>>} Pingee
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {any} t
|
|
38
|
+
* @param {Zone} zone
|
|
39
|
+
*/
|
|
40
|
+
const testFirstPlay = async (t, zone) => {
|
|
41
|
+
const vowTools = prepareVowTools(zone);
|
|
42
|
+
const makeLogStore = prepareLogStore(zone);
|
|
43
|
+
const makeBijection = prepareBijection(zone);
|
|
44
|
+
const makePingee = preparePingee(zone);
|
|
45
|
+
|
|
46
|
+
const log = zone.makeOnce('log', () => makeLogStore());
|
|
47
|
+
const bij = zone.makeOnce('bij', makeBijection);
|
|
48
|
+
|
|
49
|
+
const mem = makeReplayMembrane(log, bij, vowTools, watchWake, panic);
|
|
50
|
+
|
|
51
|
+
t.deepEqual(log.dump(), []);
|
|
52
|
+
|
|
53
|
+
/** @type {Pingee} */
|
|
54
|
+
const pingee = zone.makeOnce('pingee', () => makePingee());
|
|
55
|
+
/** @type {Pingee} */
|
|
56
|
+
const guestPingee = mem.hostToGuest(pingee);
|
|
57
|
+
t.deepEqual(log.dump(), []);
|
|
58
|
+
|
|
59
|
+
const pingTestSendResult = t.throwsAsync(() => E(guestPingee).ping('send'), {
|
|
60
|
+
message:
|
|
61
|
+
'panic over "[Error: guest eventual send not yet supported: \\"[Alleged: Pingee guest wrapper]\\".ping([\\"send\\"]) -> \\"[Promise]\\"]"',
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
guestPingee.ping('call');
|
|
65
|
+
|
|
66
|
+
await pingTestSendResult;
|
|
67
|
+
|
|
68
|
+
t.deepEqual(log.dump(), [
|
|
69
|
+
['checkCall', pingee, 'ping', ['call'], 0],
|
|
70
|
+
['doReturn', 0, undefined],
|
|
71
|
+
]);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
test.serial('test heap replay-membrane settlement', async t => {
|
|
75
|
+
const zone = makeHeapZone('heapRoot');
|
|
76
|
+
return testFirstPlay(t, zone);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test.serial('test virtual replay-membrane settlement', async t => {
|
|
80
|
+
annihilate();
|
|
81
|
+
const zone = makeVirtualZone('virtualRoot');
|
|
82
|
+
return testFirstPlay(t, zone);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test.serial('test durable replay-membrane settlement', async t => {
|
|
86
|
+
annihilate();
|
|
87
|
+
|
|
88
|
+
nextLife();
|
|
89
|
+
const zone1 = makeDurableZone(getBaggage(), 'durableRoot');
|
|
90
|
+
return testFirstPlay(t, zone1);
|
|
91
|
+
});
|