@agoric/async-flow 0.1.1-upgrade-16-dev-d492653.0 → 0.1.1-upgrade-17-dev-3b97a9f.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/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +20 -19
- package/src/async-flow.d.ts +19 -12
- package/src/async-flow.d.ts.map +1 -1
- package/src/async-flow.js +31 -16
- package/src/bijection.d.ts +7 -4
- package/src/bijection.d.ts.map +1 -1
- package/src/bijection.js +90 -15
- package/src/convert.d.ts +1 -0
- package/src/convert.d.ts.map +1 -1
- package/src/convert.js +7 -5
- package/src/endowments.d.ts +16 -0
- package/src/endowments.d.ts.map +1 -0
- package/src/endowments.js +294 -0
- package/src/ephemera.d.ts +1 -0
- package/src/ephemera.d.ts.map +1 -1
- package/src/ephemera.js +4 -0
- package/src/equate.js +4 -4
- package/src/log-store.d.ts +4 -2
- package/src/log-store.d.ts.map +1 -1
- package/src/log-store.js +5 -1
- package/src/replay-membrane.d.ts +19 -50
- package/src/replay-membrane.d.ts.map +1 -1
- package/src/replay-membrane.js +218 -18
- package/src/type-guards.d.ts.map +1 -1
- package/src/type-guards.js +21 -7
- package/src/types.d.ts +211 -60
- package/src/types.js +1 -164
- package/test/async-flow-crank.test.js +6 -0
- package/test/async-flow-early-completion.test.js +2 -0
- package/test/async-flow-no-this.js +6 -0
- package/test/async-flow.test.js +5 -2
- package/test/bad-host.test.js +5 -0
- package/test/bijection.test.js +12 -6
- package/test/convert.test.js +5 -0
- package/test/endowments.test.js +157 -0
- package/test/equate.test.js +6 -2
- package/test/log-store.test.js +9 -1
- package/test/replay-membrane-eventual.test.js +134 -8
- package/test/replay-membrane-settlement.test.js +24 -5
- package/test/replay-membrane-zombie.test.js +43 -14
- package/test/replay-membrane.test.js +39 -13
- package/test/types.test-d.ts +73 -0
- package/tsconfig.json +2 -0
- package/src/types.d.ts.map +0 -1
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/async-flow",
|
|
3
|
-
"version": "0.1.1-upgrade-
|
|
3
|
+
"version": "0.1.1-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
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,24 +24,25 @@
|
|
|
24
24
|
"author": "Agoric",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@agoric/base-zone": "0.1.1-upgrade-
|
|
28
|
-
"@agoric/
|
|
29
|
-
"@agoric/
|
|
30
|
-
"@
|
|
31
|
-
"@endo/
|
|
32
|
-
"@endo/
|
|
33
|
-
"@endo/
|
|
34
|
-
"@endo/
|
|
35
|
-
"@endo/
|
|
36
|
-
"@endo/
|
|
27
|
+
"@agoric/base-zone": "0.1.1-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
28
|
+
"@agoric/internal": "0.3.3-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
29
|
+
"@agoric/store": "0.9.3-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
30
|
+
"@agoric/vow": "0.1.1-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
31
|
+
"@endo/common": "^1.2.5",
|
|
32
|
+
"@endo/errors": "^1.2.5",
|
|
33
|
+
"@endo/eventual-send": "^1.2.5",
|
|
34
|
+
"@endo/marshal": "^1.5.3",
|
|
35
|
+
"@endo/pass-style": "^1.4.3",
|
|
36
|
+
"@endo/patterns": "^1.4.3",
|
|
37
|
+
"@endo/promise-kit": "^1.1.5"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@agoric/
|
|
40
|
-
"@agoric/
|
|
41
|
-
"@
|
|
42
|
-
"@endo/
|
|
43
|
-
"
|
|
44
|
-
"
|
|
40
|
+
"@agoric/swingset-liveslots": "0.10.3-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
41
|
+
"@agoric/zone": "0.2.3-upgrade-17-dev-3b97a9f.0+3b97a9f",
|
|
42
|
+
"@endo/env-options": "^1.1.6",
|
|
43
|
+
"@endo/ses-ava": "^1.2.5",
|
|
44
|
+
"ava": "^5.3.0",
|
|
45
|
+
"tsd": "^0.31.1"
|
|
45
46
|
},
|
|
46
47
|
"publishConfig": {
|
|
47
48
|
"access": "public"
|
|
@@ -60,7 +61,7 @@
|
|
|
60
61
|
"workerThreads": false
|
|
61
62
|
},
|
|
62
63
|
"typeCoverage": {
|
|
63
|
-
"atLeast": 77.
|
|
64
|
+
"atLeast": 77.1
|
|
64
65
|
},
|
|
65
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "3b97a9f0bc7d5dcd24d20dd81ca2af5d59d6e43d"
|
|
66
67
|
}
|
package/src/async-flow.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export function prepareAsyncFlowTools(outerZone: Zone, outerOptions?: Preparatio
|
|
|
15
15
|
*/
|
|
16
16
|
restart(eager?: boolean | undefined): void;
|
|
17
17
|
wake(): void;
|
|
18
|
-
getOutcome(): Vow<any>;
|
|
19
|
-
dump(): ([op: "doFulfill", vow: Vow<Passable>, fulfillment: Passable] | [op: "doReject", vow: Vow<Passable>, reason: Passable] | [op: "doReturn", callIndex: number, result: Passable] | [op: "doThrow", callIndex: number, problem: Passable] | [op: "checkCall", target: Passable, optVerb: PropertyKey | undefined, args: Passable[], callIndex: number])[];
|
|
18
|
+
getOutcome(): import("@agoric/vow").Vow<any>;
|
|
19
|
+
dump(): ([op: "doFulfill", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, fulfillment: import("@endo/pass-style").Passable] | [op: "doReject", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, reason: import("@endo/pass-style").Passable] | [op: "doReturn", callIndex: number, result: import("@endo/pass-style").Passable] | [op: "doThrow", callIndex: number, problem: import("@endo/pass-style").Passable] | [op: "checkCall", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSendOnly", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSend", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number])[];
|
|
20
20
|
getOptFatalProblem(): any;
|
|
21
21
|
};
|
|
22
22
|
admin: {
|
|
@@ -29,19 +29,20 @@ export function prepareAsyncFlowTools(outerZone: Zone, outerOptions?: Preparatio
|
|
|
29
29
|
onRejected(_fulfillment: any): void;
|
|
30
30
|
};
|
|
31
31
|
}>;
|
|
32
|
-
asyncFlow: (zone: Zone, tag: string, guestFunc:
|
|
32
|
+
asyncFlow: <F extends GuestAsyncFunc>(zone: Zone, tag: string, guestFunc: F, options?: {
|
|
33
33
|
startEager?: boolean;
|
|
34
|
-
} | undefined) =>
|
|
34
|
+
} | undefined) => HostOf<F>;
|
|
35
35
|
adminAsyncFlow: import("@endo/exo").Guarded<{
|
|
36
|
-
getFailures(): import("@endo/patterns").CopyMap<any, Passable>;
|
|
36
|
+
getFailures(): import("@endo/patterns").CopyMap<any, import("@endo/pass-style").Passable>;
|
|
37
37
|
wakeAll(): void;
|
|
38
38
|
getFlowForOutcomeVow(outcomeVow: any): any;
|
|
39
39
|
}>;
|
|
40
40
|
allWokenP: Promise<void>;
|
|
41
|
+
prepareEndowment: (zone: Zone, tag: string, e: unknown) => any;
|
|
41
42
|
};
|
|
42
43
|
export type AsyncFlowTools = ReturnType<(outerZone: Zone, outerOptions?: PreparationOptions | undefined) => {
|
|
43
44
|
prepareAsyncFlowKit: (zone: Zone, tag: string, guestAsyncFunc: GuestAsyncFunc, options?: {
|
|
44
|
-
startEager?: boolean
|
|
45
|
+
startEager?: boolean;
|
|
45
46
|
} | undefined) => (activationArgs: any) => import("@endo/exo").GuardedKit<{
|
|
46
47
|
flow: {
|
|
47
48
|
/**
|
|
@@ -56,8 +57,8 @@ export type AsyncFlowTools = ReturnType<(outerZone: Zone, outerOptions?: Prepara
|
|
|
56
57
|
*/
|
|
57
58
|
restart(eager?: boolean | undefined): void;
|
|
58
59
|
wake(): void;
|
|
59
|
-
getOutcome(): Vow<any>;
|
|
60
|
-
dump(): ([op: "doFulfill", vow: Vow<Passable>, fulfillment: Passable] | [op: "doReject", vow: Vow<Passable>, reason: Passable] | [op: "doReturn", callIndex: number, result: Passable] | [op: "doThrow", callIndex: number, problem: Passable] | [op: "checkCall", target: Passable, optVerb: PropertyKey | undefined, args: Passable[], callIndex: number])[];
|
|
60
|
+
getOutcome(): import("@agoric/vow").Vow<any>;
|
|
61
|
+
dump(): ([op: "doFulfill", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, fulfillment: import("@endo/pass-style").Passable] | [op: "doReject", vow: import("@agoric/vow").Vow<import("@endo/pass-style").Passable>, reason: import("@endo/pass-style").Passable] | [op: "doReturn", callIndex: number, result: import("@endo/pass-style").Passable] | [op: "doThrow", callIndex: number, problem: import("@endo/pass-style").Passable] | [op: "checkCall", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSendOnly", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number] | [op: "checkSend", target: import("@endo/pass-style").Passable, optVerb: PropertyKey | undefined, args: import("@endo/pass-style").Passable[], callIndex: number])[];
|
|
61
62
|
getOptFatalProblem(): any;
|
|
62
63
|
};
|
|
63
64
|
admin: {
|
|
@@ -70,18 +71,24 @@ export type AsyncFlowTools = ReturnType<(outerZone: Zone, outerOptions?: Prepara
|
|
|
70
71
|
onRejected(_fulfillment: any): void;
|
|
71
72
|
};
|
|
72
73
|
}>;
|
|
73
|
-
asyncFlow: (zone: Zone, tag: string, guestFunc:
|
|
74
|
-
startEager?: boolean
|
|
75
|
-
} | undefined) =>
|
|
74
|
+
asyncFlow: <F extends GuestAsyncFunc>(zone: Zone, tag: string, guestFunc: F, options?: {
|
|
75
|
+
startEager?: boolean;
|
|
76
|
+
} | undefined) => HostOf<F>;
|
|
76
77
|
adminAsyncFlow: import("@endo/exo").Guarded<{
|
|
77
|
-
getFailures(): import("@endo/patterns").CopyMap<any, Passable>;
|
|
78
|
+
getFailures(): import("@endo/patterns").CopyMap<any, import("@endo/pass-style").Passable>;
|
|
78
79
|
wakeAll(): void;
|
|
79
80
|
getFlowForOutcomeVow(outcomeVow: any): any;
|
|
80
81
|
}>;
|
|
81
82
|
allWokenP: Promise<void>;
|
|
83
|
+
prepareEndowment: (zone: Zone, tag: string, e: unknown) => any;
|
|
82
84
|
}>;
|
|
83
85
|
export type AdminAsyncFlow = AsyncFlowTools["adminAsyncFlow"];
|
|
84
86
|
export type MakeAsyncFlowKit = ReturnType<AsyncFlowTools["prepareAsyncFlowKit"]>;
|
|
85
87
|
export type AsyncFlowKit = ReturnType<MakeAsyncFlowKit>;
|
|
86
88
|
export type AsyncFlow = AsyncFlowKit["flow"];
|
|
89
|
+
import type { Zone } from '@agoric/base-zone';
|
|
90
|
+
import type { PreparationOptions } from '../src/types.js';
|
|
91
|
+
import type { GuestAsyncFunc } from '../src/types.js';
|
|
92
|
+
import type { FlowState } from '../src/types.js';
|
|
93
|
+
import type { HostOf } from '../src/types.js';
|
|
87
94
|
//# sourceMappingURL=async-flow.d.ts.map
|
package/src/async-flow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-flow.d.ts","sourceRoot":"","sources":["async-flow.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"async-flow.d.ts","sourceRoot":"","sources":["async-flow.js"],"names":[],"mappings":"AAgDO,iDAHI,IAAI;gCA6CF,IAAI,OACJ,MAAM,kBACN,cAAc;qBACC,OAAO;;;YA4BzB;;eAEG;4BADU,SAAS;YAkCtB;;;;;eAKG;;;;;;;;;;;;;;;;;gBAmRmB,CAAC,SAAlB,cAAgB,QAClB,IAAI,OACJ,MAAM,aACN,CAAC;qBACc,OAAO;sBACpB,OAAO,CAAC,CAAC;;;;;;;;EAsDvB;6BAIY,UAAU,aAtcZ,IAAI;gCA6CF,IAAI,OACJ,MAAM,kBACN,cAAc;qBACC,OAAO;;;YA4BzB;;eAEG;4BADU,SAAS;YAkCtB;;;;;eAKG;;;;;;;;;;;;;;;;;gBAmRmB,CAAC,SAAlB,cAAgB,QAClB,IAAI,OACJ,MAAM,aACN,CAAC;qBACc,OAAO;sBACpB,OAAO,CAAC,CAAC;;;;;;;;EA0DsB;6BAIjC,cAAc,CAAC,gBAAgB,CAAC;+BAIhC,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;2BAIjD,UAAU,CAAC,gBAAgB,CAAC;wBAI5B,YAAY,CAAC,MAAM,CAAC;0BArfV,mBAAmB;wCACoD,iBAAiB;oCAAjB,iBAAiB;+BAAjB,iBAAiB;4BAAjB,iBAAiB"}
|
package/src/async-flow.js
CHANGED
|
@@ -7,10 +7,14 @@ import { prepareVowTools, toPassableCap, VowShape } from '@agoric/vow';
|
|
|
7
7
|
import { makeReplayMembrane } from './replay-membrane.js';
|
|
8
8
|
import { prepareLogStore } from './log-store.js';
|
|
9
9
|
import { prepareBijection } from './bijection.js';
|
|
10
|
+
import { prepareEndowmentTools } from './endowments.js';
|
|
10
11
|
import { LogEntryShape, FlowStateShape } from './type-guards.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* @import {
|
|
14
|
+
* @import {WeakMapStore} from '@agoric/store'
|
|
15
|
+
* @import {Zone} from '@agoric/base-zone'
|
|
16
|
+
* @import {FlowState, GuestAsyncFunc, HostAsyncFuncWrapper, HostOf, PreparationOptions} from '../src/types.js'
|
|
17
|
+
* @import {ReplayMembrane} from '../src/replay-membrane.js'
|
|
14
18
|
*/
|
|
15
19
|
|
|
16
20
|
const { defineProperties } = Object;
|
|
@@ -46,7 +50,11 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
46
50
|
const {
|
|
47
51
|
vowTools = prepareVowTools(outerZone),
|
|
48
52
|
makeLogStore = prepareLogStore(outerZone),
|
|
49
|
-
|
|
53
|
+
endowmentTools: { prepareEndowment, unwrap } = prepareEndowmentTools(
|
|
54
|
+
outerZone,
|
|
55
|
+
{ vowTools },
|
|
56
|
+
),
|
|
57
|
+
makeBijection = prepareBijection(outerZone, unwrap),
|
|
50
58
|
} = outerOptions;
|
|
51
59
|
const { watch, makeVowKit } = vowTools;
|
|
52
60
|
|
|
@@ -170,7 +178,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
170
178
|
eagerWakers.delete(flow);
|
|
171
179
|
}
|
|
172
180
|
|
|
173
|
-
const
|
|
181
|
+
const watchWake = vowish => {
|
|
174
182
|
// Extra paranoid because we're getting
|
|
175
183
|
// "promise watcher must be a virtual object"
|
|
176
184
|
// in the general vicinity.
|
|
@@ -181,13 +189,13 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
181
189
|
watch(vowish, wakeWatcher);
|
|
182
190
|
};
|
|
183
191
|
const panic = err => admin.panic(err);
|
|
184
|
-
const membrane = makeReplayMembrane(
|
|
192
|
+
const membrane = makeReplayMembrane({
|
|
185
193
|
log,
|
|
186
194
|
bijection,
|
|
187
195
|
vowTools,
|
|
188
|
-
|
|
196
|
+
watchWake,
|
|
189
197
|
panic,
|
|
190
|
-
);
|
|
198
|
+
});
|
|
191
199
|
initMembrane(flow, membrane);
|
|
192
200
|
const guestArgs = membrane.hostToGuest(activationArgs);
|
|
193
201
|
|
|
@@ -218,7 +226,9 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
218
226
|
// gating condition, the next line could grow the bijection
|
|
219
227
|
// of a failed flow, subverting other gating checks on bijection
|
|
220
228
|
// membership.
|
|
221
|
-
bijection.
|
|
229
|
+
const g = bijection.unwrapInit(guestResultP, outcomeKit.vow);
|
|
230
|
+
g === guestResultP ||
|
|
231
|
+
Fail`internal: promises should not be unwrapped ${g}`;
|
|
222
232
|
}
|
|
223
233
|
// log is driven at first by guestAyncFunc interaction through the
|
|
224
234
|
// membrane with the host activationArgs. At the end of its first
|
|
@@ -415,7 +425,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
415
425
|
const asyncFlowKit = internalMakeAsyncFlowKit(activationArgs);
|
|
416
426
|
const { flow } = asyncFlowKit;
|
|
417
427
|
|
|
418
|
-
const vow =
|
|
428
|
+
const vow = flow.getOutcome();
|
|
419
429
|
flowForOutcomeVowKey.init(toPassableCap(vow), flow);
|
|
420
430
|
flow.restart();
|
|
421
431
|
return asyncFlowKit;
|
|
@@ -424,21 +434,25 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
424
434
|
};
|
|
425
435
|
|
|
426
436
|
/**
|
|
437
|
+
* @template {GuestAsyncFunc} F
|
|
427
438
|
* @param {Zone} zone
|
|
428
439
|
* @param {string} tag
|
|
429
|
-
* @param {
|
|
440
|
+
* @param {F} guestFunc
|
|
430
441
|
* @param {{ startEager?: boolean }} [options]
|
|
431
|
-
* @returns {
|
|
442
|
+
* @returns {HostOf<F>}
|
|
432
443
|
*/
|
|
433
444
|
const asyncFlow = (zone, tag, guestFunc, options = undefined) => {
|
|
434
445
|
const makeAsyncFlowKit = prepareAsyncFlowKit(zone, tag, guestFunc, options);
|
|
435
446
|
const hostFuncName = `${tag}_hostFlow`;
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
447
|
+
|
|
448
|
+
const wrapperFunc = /** @type {HostOf<F>} */ (
|
|
449
|
+
{
|
|
450
|
+
[hostFuncName](...args) {
|
|
451
|
+
const { flow } = makeAsyncFlowKit(args);
|
|
452
|
+
return flow.getOutcome();
|
|
453
|
+
},
|
|
454
|
+
}[hostFuncName]
|
|
455
|
+
);
|
|
442
456
|
defineProperties(wrapperFunc, {
|
|
443
457
|
length: { value: guestFunc.length },
|
|
444
458
|
});
|
|
@@ -477,6 +491,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
477
491
|
asyncFlow,
|
|
478
492
|
adminAsyncFlow,
|
|
479
493
|
allWokenP,
|
|
494
|
+
prepareEndowment,
|
|
480
495
|
});
|
|
481
496
|
};
|
|
482
497
|
harden(prepareAsyncFlowTools);
|
package/src/bijection.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export function prepareBijection(zone: Zone): () => import("@endo/exo").Guarded<{
|
|
1
|
+
export function prepareBijection(zone: Zone, unwrap?: ((hostWrapper: PassableCap | Vow, guestWrapper: PassableCap) => unknown) | undefined): () => import("@endo/exo").Guarded<{
|
|
2
2
|
reset(): void;
|
|
3
|
-
|
|
3
|
+
unwrapInit(g: any, h: any): unknown;
|
|
4
4
|
hasGuest(g: any): boolean;
|
|
5
5
|
hasHost(h: any): boolean;
|
|
6
6
|
has(g: any, h: any): boolean;
|
|
@@ -16,13 +16,16 @@ export type VowishStore = ReturnType<(name: string) => {
|
|
|
16
16
|
has: (k: any) => boolean;
|
|
17
17
|
get: (k: any) => any;
|
|
18
18
|
}>>;
|
|
19
|
-
export type Bijection = ReturnType<ReturnType<(zone: Zone) => () => import("@endo/exo").Guarded<{
|
|
19
|
+
export type Bijection = ReturnType<ReturnType<(zone: Zone, unwrap?: ((hostWrapper: PassableCap | Vow, guestWrapper: PassableCap) => unknown) | undefined) => () => import("@endo/exo").Guarded<{
|
|
20
20
|
reset(): void;
|
|
21
|
-
|
|
21
|
+
unwrapInit(g: any, h: any): unknown;
|
|
22
22
|
hasGuest(g: any): boolean;
|
|
23
23
|
hasHost(h: any): boolean;
|
|
24
24
|
has(g: any, h: any): boolean;
|
|
25
25
|
guestToHost(g: any): any;
|
|
26
26
|
hostToGuest(h: any): any;
|
|
27
27
|
}>>>;
|
|
28
|
+
import type { Zone } from '@agoric/base-zone';
|
|
29
|
+
import type { PassableCap } from '@endo/pass-style';
|
|
30
|
+
import type { Vow } from '@agoric/vow';
|
|
28
31
|
//# sourceMappingURL=bijection.d.ts.map
|
package/src/bijection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bijection.d.ts","sourceRoot":"","sources":["bijection.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bijection.d.ts","sourceRoot":"","sources":["bijection.js"],"names":[],"mappings":"AA+GO,uCAJI,IAAI,0BACU,WAAW,GAAG,GAAG,gBAAgB,WAAW,KAAK,OAAO;;;;;;;;GA6FhF;0BAtIa,UAAU,QAhCb,MAAM;;;;;;;;GAgCwB;wBA0I5B,UAAU,CAAC,UAAU,QAlGvB,IAAI,0BACU,WAAW,GAAG,GAAG,gBAAgB,WAAW,KAAK,OAAO;;;;;;;;GAiG7B,CAAC;0BArM9B,mBAAmB;iCADZ,kBAAkB;yBAE1B,aAAa"}
|
package/src/bijection.js
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
import { b, Fail } from '@endo/errors';
|
|
2
2
|
import { M } from '@endo/patterns';
|
|
3
|
-
import { Far } from '@endo/pass-style';
|
|
3
|
+
import { Far, isPassable } from '@endo/pass-style';
|
|
4
4
|
import { toPassableCap } from '@agoric/vow';
|
|
5
5
|
import { makeEphemera } from './ephemera.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @import {PassableCap} from '@endo/pass-style'
|
|
9
|
+
* @import {Zone} from '@agoric/base-zone'
|
|
10
|
+
* @import {Vow} from '@agoric/vow'
|
|
11
|
+
* @import {Ephemera} from './types.js';
|
|
12
|
+
*/
|
|
13
|
+
|
|
7
14
|
const BijectionI = M.interface('Bijection', {
|
|
8
15
|
reset: M.call().returns(),
|
|
9
|
-
|
|
10
|
-
hasGuest: M.call(M.
|
|
16
|
+
unwrapInit: M.call(M.raw(), M.any()).returns(M.raw()),
|
|
17
|
+
hasGuest: M.call(M.raw()).returns(M.boolean()),
|
|
11
18
|
hasHost: M.call(M.any()).returns(M.boolean()),
|
|
12
|
-
has: M.call(M.
|
|
13
|
-
guestToHost: M.call(M.
|
|
14
|
-
hostToGuest: M.call(M.any()).returns(M.
|
|
19
|
+
has: M.call(M.raw(), M.any()).returns(M.boolean()),
|
|
20
|
+
guestToHost: M.call(M.raw()).returns(M.any()),
|
|
21
|
+
hostToGuest: M.call(M.any()).returns(M.raw()),
|
|
15
22
|
});
|
|
16
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @param {unknown} k
|
|
26
|
+
*/
|
|
27
|
+
const toKey = k =>
|
|
28
|
+
// @ts-expect-error k specificity
|
|
29
|
+
isPassable(k) ? toPassableCap(k) : k;
|
|
30
|
+
|
|
17
31
|
/**
|
|
18
32
|
* Makes a store like a WeakMapStore except that Promises and Vows can also be
|
|
19
33
|
* used as keys.
|
|
@@ -34,15 +48,15 @@ const makeVowishStore = name => {
|
|
|
34
48
|
|
|
35
49
|
return Far(name, {
|
|
36
50
|
init: (k, v) => {
|
|
37
|
-
const k2 =
|
|
51
|
+
const k2 = toKey(k);
|
|
38
52
|
!map.has(k2) ||
|
|
39
53
|
// separate line so I can set a breakpoint
|
|
40
54
|
Fail`${b(name)} key already bound: ${k} -> ${map.get(k2)} vs ${v}`;
|
|
41
55
|
map.set(k2, v);
|
|
42
56
|
},
|
|
43
|
-
has: k => map.has(
|
|
57
|
+
has: k => map.has(toKey(k)),
|
|
44
58
|
get: k => {
|
|
45
|
-
const k2 =
|
|
59
|
+
const k2 = toKey(k);
|
|
46
60
|
map.has(k2) ||
|
|
47
61
|
// separate line so I can set a breakpoint
|
|
48
62
|
Fail`${b(name)} key not found: ${k}`;
|
|
@@ -54,14 +68,59 @@ const makeVowishStore = name => {
|
|
|
54
68
|
/** @typedef {ReturnType<makeVowishStore>} VowishStore */
|
|
55
69
|
|
|
56
70
|
/**
|
|
71
|
+
* As suggested by the name, this *mostly* represents a mathematical bijection,
|
|
72
|
+
* i.e., a one-to-one mapping. But rather than a general bijection map store
|
|
73
|
+
* (which would be interesting), this one is specialized to support the
|
|
74
|
+
* async-flow replay-membrane, where the two sides are "guest" and "host".
|
|
75
|
+
*
|
|
76
|
+
* If `unwrap` is omitted, it defaults to an identity function on its
|
|
77
|
+
* `guestWrapper` argument, in which case this does represent exactly a
|
|
78
|
+
* mathematical bijection between host and guest.
|
|
79
|
+
*
|
|
80
|
+
* If `unwrap` is provided, it supports the unwrapping of guest wrappers, into
|
|
81
|
+
* so-call unwrapped guests, like state records or functions,
|
|
82
|
+
* that are not themselves `Passable`. This was motivated to support endowments,
|
|
83
|
+
* which are often similar non-passables on the host-side.
|
|
84
|
+
* However, it can support the unwrapping of any guest remotable wrapper.
|
|
85
|
+
* When `unwrap` returns something `!==` its `guestWrapper` argument,
|
|
86
|
+
* then we preserve the bijection (one-to-one mapping) between the host
|
|
87
|
+
* and the unwrapped guest. To support the internal bookkeeping of the
|
|
88
|
+
* replay-membrane, we also map the guestWrapper to that same host, but
|
|
89
|
+
* not vice versa. Since the guest wrapper should not be visible outside
|
|
90
|
+
* the replay-membrane, this extra bookkeeping should be invisible.
|
|
91
|
+
*
|
|
92
|
+
* This bijection only grows monotonically until reset, which clears the entire
|
|
93
|
+
* mapping. Until reset, each pair, once entered, cannot be altered or deleted.
|
|
94
|
+
* The mapping itself is completely ephemeral, but the bijection object itself
|
|
95
|
+
* is durable. The mapping is also effectively reset by reincarnation, i.e,
|
|
96
|
+
* on upgrade.
|
|
97
|
+
* See also https://github.com/Agoric/agoric-sdk/issues/9365
|
|
98
|
+
*
|
|
99
|
+
* To eventually address https://github.com/Agoric/agoric-sdk/issues/9301
|
|
100
|
+
* the bijection itself persists to support passing guest-created remotables
|
|
101
|
+
* and promises through the membrane.
|
|
102
|
+
* The resulting host wrappers must not only survive upgrade, then must
|
|
103
|
+
* reestablish their mapping to the correct corresponding guest objects that
|
|
104
|
+
* they are taken to wrap. We plan to do this via `equate` repopulating
|
|
105
|
+
* the bijection by the time the host wrapper needs to know what
|
|
106
|
+
* corresponding guest it is now taken to wrap.
|
|
107
|
+
*
|
|
57
108
|
* @param {Zone} zone
|
|
109
|
+
* @param {(hostWrapper: PassableCap | Vow, guestWrapper: PassableCap) => unknown} [unwrap]
|
|
110
|
+
* defaults to identity function on `guestWrapper` arg
|
|
58
111
|
*/
|
|
59
|
-
export const prepareBijection =
|
|
112
|
+
export const prepareBijection = (
|
|
113
|
+
zone,
|
|
114
|
+
unwrap = (_hostWrapper, guestWrapper) => guestWrapper,
|
|
115
|
+
) => {
|
|
60
116
|
/** @type {Ephemera<Bijection, VowishStore>} */
|
|
61
117
|
const g2h = makeEphemera(() => makeVowishStore('guestToHost'));
|
|
62
118
|
/** @type {Ephemera<Bijection, VowishStore>} */
|
|
63
119
|
const h2g = makeEphemera(() => makeVowishStore('hostToGuest'));
|
|
64
120
|
|
|
121
|
+
// Guest arguments and results are now unguarded, i.e., guarded by `M.raw()`,
|
|
122
|
+
// so that they can be non-passables. Therefore, we need to harden these
|
|
123
|
+
// here.
|
|
65
124
|
return zone.exoClass('Bijection', BijectionI, () => ({}), {
|
|
66
125
|
reset() {
|
|
67
126
|
const { self } = this;
|
|
@@ -69,20 +128,31 @@ export const prepareBijection = zone => {
|
|
|
69
128
|
g2h.resetFor(self);
|
|
70
129
|
h2g.resetFor(self);
|
|
71
130
|
},
|
|
72
|
-
|
|
131
|
+
unwrapInit(g, h) {
|
|
132
|
+
harden(g);
|
|
73
133
|
const { self } = this;
|
|
74
134
|
const guestToHost = g2h.for(self);
|
|
75
135
|
const hostToGuest = h2g.for(self);
|
|
76
136
|
|
|
137
|
+
const gUnwrapped = unwrap(h, g);
|
|
77
138
|
!hostToGuest.has(h) ||
|
|
78
|
-
Fail`hostToGuest key already bound: ${h} -> ${hostToGuest.get(h)} vs ${
|
|
79
|
-
guestToHost.init(
|
|
80
|
-
hostToGuest.init(h,
|
|
81
|
-
self.has(
|
|
139
|
+
Fail`hostToGuest key already bound: ${h} -> ${hostToGuest.get(h)} vs ${gUnwrapped}`;
|
|
140
|
+
guestToHost.init(gUnwrapped, h);
|
|
141
|
+
hostToGuest.init(h, gUnwrapped);
|
|
142
|
+
self.has(gUnwrapped, h) ||
|
|
82
143
|
// separate line so I can set a breakpoint
|
|
83
144
|
Fail`internal: ${g} <-> ${h}`;
|
|
145
|
+
if (g !== gUnwrapped) {
|
|
146
|
+
// When they are different, also map g to h without mapping h to g
|
|
147
|
+
!guestToHost.has(g) ||
|
|
148
|
+
// separate line so I can set a breakpoint
|
|
149
|
+
Fail`hidden guest wrapper already bound ${g}`;
|
|
150
|
+
guestToHost.init(g, h);
|
|
151
|
+
}
|
|
152
|
+
return gUnwrapped;
|
|
84
153
|
},
|
|
85
154
|
hasGuest(g) {
|
|
155
|
+
harden(g);
|
|
86
156
|
const { self } = this;
|
|
87
157
|
const guestToHost = g2h.for(self);
|
|
88
158
|
|
|
@@ -95,6 +165,7 @@ export const prepareBijection = zone => {
|
|
|
95
165
|
return hostToGuest.has(h);
|
|
96
166
|
},
|
|
97
167
|
has(g, h) {
|
|
168
|
+
harden(g);
|
|
98
169
|
const { self } = this;
|
|
99
170
|
const guestToHost = g2h.for(self);
|
|
100
171
|
const hostToGuest = h2g.for(self);
|
|
@@ -112,6 +183,7 @@ export const prepareBijection = zone => {
|
|
|
112
183
|
}
|
|
113
184
|
},
|
|
114
185
|
guestToHost(g) {
|
|
186
|
+
harden(g);
|
|
115
187
|
const { self } = this;
|
|
116
188
|
const guestToHost = g2h.for(self);
|
|
117
189
|
|
|
@@ -121,6 +193,9 @@ export const prepareBijection = zone => {
|
|
|
121
193
|
const { self } = this;
|
|
122
194
|
const hostToGuest = h2g.for(self);
|
|
123
195
|
|
|
196
|
+
// Even though result is unguarded, i.e., guarded by `M.raw()`, don't
|
|
197
|
+
// need to harden here because was already harden when added to
|
|
198
|
+
// collection.
|
|
124
199
|
return hostToGuest.get(h);
|
|
125
200
|
},
|
|
126
201
|
});
|
package/src/convert.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export function makeConvertKit(bijection: any, makeGuestForHostRemotable: any, m
|
|
|
2
2
|
guestToHost: (specimen: Passable, label?: string | undefined) => any;
|
|
3
3
|
hostToGuest: (specimen: Passable, label?: string | undefined) => any;
|
|
4
4
|
};
|
|
5
|
+
import type { Passable } from '@endo/pass-style';
|
|
5
6
|
//# sourceMappingURL=convert.d.ts.map
|
package/src/convert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["convert.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["convert.js"],"names":[],"mappings":"AA+EO;4BARM,QAAQ;4BAAR,QAAQ;EA4DpB;8BAtH0B,kBAAkB"}
|
package/src/convert.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fail, X, annotateError, makeError, q } from '@endo/errors';
|
|
2
2
|
import { throwLabeled } from '@endo/common/throw-labeled.js';
|
|
3
|
+
import { objectMap } from '@endo/common/object-map.js';
|
|
3
4
|
import {
|
|
4
5
|
getErrorConstructor,
|
|
5
6
|
getTag,
|
|
@@ -8,7 +9,10 @@ import {
|
|
|
8
9
|
passStyleOf,
|
|
9
10
|
} from '@endo/pass-style';
|
|
10
11
|
import { isVow } from '@agoric/vow/src/vow-utils.js';
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @import {Passable} from '@endo/pass-style'
|
|
15
|
+
*/
|
|
12
16
|
|
|
13
17
|
const makeConvert = (convertRemotable, convertPromiseOrVow, convertError) => {
|
|
14
18
|
const convertRecur = (specimen, label) => {
|
|
@@ -106,16 +110,14 @@ export const makeConvertKit = (
|
|
|
106
110
|
return bijection.hostToGuest(hRem);
|
|
107
111
|
}
|
|
108
112
|
const gRem = makeGuestForHostRemotable(hRem);
|
|
109
|
-
bijection.
|
|
110
|
-
return gRem;
|
|
113
|
+
return bijection.unwrapInit(gRem, hRem);
|
|
111
114
|
},
|
|
112
115
|
hVow => {
|
|
113
116
|
if (bijection.hasHost(hVow)) {
|
|
114
117
|
return bijection.hostToGuest(hVow);
|
|
115
118
|
}
|
|
116
119
|
const gP = makeGuestForHostVow(hVow);
|
|
117
|
-
bijection.
|
|
118
|
-
return gP;
|
|
120
|
+
return bijection.unwrapInit(gP, hVow);
|
|
119
121
|
},
|
|
120
122
|
hErr => {
|
|
121
123
|
const gErr = harden(
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function forwardingMethods(rem: any): {
|
|
2
|
+
[k: string]: any;
|
|
3
|
+
};
|
|
4
|
+
export function makeSharedStateRecord<K extends string | number | symbol, R extends Record<K, any>>(dataRecord: R): R;
|
|
5
|
+
export function prepareEndowmentTools(outerZone: Zone, outerOptions?: PreparationOptions | undefined): {
|
|
6
|
+
prepareEndowment: (zone: Zone, tag: string, e: unknown) => any;
|
|
7
|
+
unwrap: (wrapped: any, guestWrapped: any) => any;
|
|
8
|
+
};
|
|
9
|
+
export type EndowmentKind = "promise" | "storable" | "far" | "function" | "array" | "record" | "state";
|
|
10
|
+
export type EndowmentTools = ReturnType<(outerZone: Zone, outerOptions?: PreparationOptions | undefined) => {
|
|
11
|
+
prepareEndowment: (zone: Zone, tag: string, e: unknown) => any;
|
|
12
|
+
unwrap: (wrapped: any, guestWrapped: any) => any;
|
|
13
|
+
}>;
|
|
14
|
+
import type { Zone } from '@agoric/base-zone';
|
|
15
|
+
import type { PreparationOptions } from '../src/types.js';
|
|
16
|
+
//# sourceMappingURL=endowments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endowments.d.ts","sourceRoot":"","sources":["endowments.js"],"names":[],"mappings":"AA4CO;;EASN;AAaM,sCALmC,CAAC,SAA5B,MAAM,GAAG,MAAM,GAAG,MAAQ,EACX,CAAC,SAAjB,MAAM,CAAC,CAAC,EAAE,GAAG,CAAE,cAClB,CAAC,GACC,CAAC,CAqBX;AAMI,iDAHI,IAAI;6BA6GF,IAAI,OACJ,MAAM,KACN,OAAO;;EAyFnB;4BA9QY,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO;6BAkR1E,UAAU,aA5MZ,IAAI;6BA6GF,IAAI,OACJ,MAAM,KACN,OAAO;;EA6F0B;0BAxRvB,mBAAmB;wCAEL,iBAAiB"}
|