@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-96c19f5.0+96c19f5",
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-96c19f5.0+96c19f5",
28
- "@agoric/store": "0.9.3-dev-96c19f5.0+96c19f5",
29
- "@agoric/vow": "0.1.1-dev-96c19f5.0+96c19f5",
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-96c19f5.0+96c19f5",
40
- "@agoric/swingset-liveslots": "0.10.3-dev-96c19f5.0+96c19f5",
41
- "@agoric/zone": "0.2.3-dev-96c19f5.0+96c19f5",
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": "96c19f54bd17fd616883713d372a9dc8ca0140f9"
65
+ "gitHead": "e193e66fc578b1c00eda5f5ab6599f1cfbdc542f"
66
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"replay-membrane.d.ts","sourceRoot":"","sources":["replay-membrane.js"],"names":[],"mappings":"AAkBO;;;;;;;;;;;;;;;;;;;;uFATK,CAAC;;;oBAkBwB,SAEhC;8CAdiC,IAAI,SAC/B,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;;;;;;;;;;GA+ZnC;6BAGa,UAAU;;;;;;;;;;;;;;;;;;;;uFAzaZ,CAAC;;;oBAkBwB,SAEhC;2DAbM,CAAC,OAAO,EAAE,KAAK,KAAK,KAAK;;;;;;;;;;GAkaQ"}
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"}
@@ -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
- const { fromEntries, defineProperties } = Object;
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 Fail`unexpected outcome kind ${q(outcome.kind)}`;
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
- // TODO in order to support E *well*,
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
- // TODO in order to support E *well*,
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
+ });