@agoric/async-flow 0.1.1-upgrade-17-dev-a1453b2.0 → 0.1.1-upgrade-18-dev-d7c994b.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/CHANGELOG.md +0 -20
- package/docs/async-flow-states.key +0 -0
- package/docs/async-flow-states.md +2 -1
- package/docs/async-flow-states.png +0 -0
- package/index.d.ts +1 -2
- package/index.js +1 -2
- package/package.json +18 -19
- package/src/async-flow.d.ts.map +1 -1
- package/src/async-flow.js +47 -3
- package/src/endowments.d.ts +0 -1
- package/src/endowments.d.ts.map +1 -1
- package/src/endowments.js +7 -35
- package/src/equate.d.ts.map +1 -1
- package/src/equate.js +16 -8
- package/src/log-store.d.ts +39 -2
- package/src/log-store.d.ts.map +1 -1
- package/src/log-store.js +121 -22
- package/src/replay-membrane.d.ts +23 -4
- package/src/replay-membrane.d.ts.map +1 -1
- package/src/replay-membrane.js +61 -35
- package/src/type-guards.d.ts.map +1 -1
- package/src/type-guards.js +1 -0
- package/src/types-index.d.ts +2 -0
- package/src/types.d.ts +86 -166
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +213 -0
- package/test/_utils.js +22 -0
- package/test/async-flow-crank.test.js +4 -6
- package/test/async-flow-early-completion.test.js +28 -8
- package/test/async-flow-no-this.js +2 -4
- package/test/async-flow.test.js +13 -5
- package/test/bad-host.test.js +13 -3
- package/test/endowments.test.js +22 -2
- package/test/equate.test.js +5 -5
- package/test/exports.test.js +8 -0
- package/test/log-store.test.js +46 -11
- package/test/prepare-test-env-ava.js +2 -20
- package/test/replay-membrane-eventual.test.js +97 -41
- package/test/snapshots/exports.test.js.md +14 -0
- package/test/snapshots/exports.test.js.snap +0 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +0 -3
- /package/src/{types.js → types-index.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,21 +1 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
-
|
|
6
|
-
### 0.1.1-u17.0 (2024-09-17)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### Features
|
|
10
|
-
|
|
11
|
-
* **async-flow:** asyncFlow ([#9097](https://github.com/Agoric/agoric-sdk/issues/9097)) ([16095c5](https://github.com/Agoric/agoric-sdk/commit/16095c5076043133aff0f25721131be2ca1ef5af)), closes [#9302](https://github.com/Agoric/agoric-sdk/issues/9302) [#9125](https://github.com/Agoric/agoric-sdk/issues/9125) [#9126](https://github.com/Agoric/agoric-sdk/issues/9126) [#9153](https://github.com/Agoric/agoric-sdk/issues/9153) [#9154](https://github.com/Agoric/agoric-sdk/issues/9154) [#9280](https://github.com/Agoric/agoric-sdk/issues/9280) [#9126](https://github.com/Agoric/agoric-sdk/issues/9126)
|
|
12
|
-
* **async-flow:** endowments ([#9566](https://github.com/Agoric/agoric-sdk/issues/9566)) ([4390d8c](https://github.com/Agoric/agoric-sdk/commit/4390d8c21fd8ac80a9c83f55d38c52e3f98faa1e)), closes [Error#1](https://github.com/Agoric/Error/issues/1) [Error#1](https://github.com/Agoric/Error/issues/1)
|
|
13
|
-
* **async-flow:** error on guest E use ([#9443](https://github.com/Agoric/agoric-sdk/issues/9443)) ([e193e66](https://github.com/Agoric/agoric-sdk/commit/e193e66fc578b1c00eda5f5ab6599f1cfbdc542f)), closes [#9299](https://github.com/Agoric/agoric-sdk/issues/9299) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322)
|
|
14
|
-
* **asyncFlow:** Stopgap E support ([#9519](https://github.com/Agoric/agoric-sdk/issues/9519)) ([4adf64f](https://github.com/Agoric/agoric-sdk/commit/4adf64fd53a1a3c68ca52728710830201c9a4418)), closes [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9299](https://github.com/Agoric/agoric-sdk/issues/9299) [#9443](https://github.com/Agoric/agoric-sdk/issues/9443) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9299](https://github.com/Agoric/agoric-sdk/issues/9299) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322) [#9322](https://github.com/Agoric/agoric-sdk/issues/9322)
|
|
15
|
-
* error on membrane promise ([94dfab1](https://github.com/Agoric/agoric-sdk/commit/94dfab1cfd960aada452753b1482ed797bc2da13))
|
|
16
|
-
* **types:** HostOf, GuestOf ([35380af](https://github.com/Agoric/agoric-sdk/commit/35380af4bbda51be2a9cd047f9c4992791090e94))
|
|
17
|
-
* **types:** infer orchestrate() return ([67665a8](https://github.com/Agoric/agoric-sdk/commit/67665a89cb162c350389e52fd812c895d42f37fb))
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
1
|
# Change Log
|
|
Binary file
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
- ***Replaying***. To start ***Replaying***, the activation first translates the saved activation arguments from host to guest, invokes the guest function, and starts the membrane replaying from its durable log. The replay is finished when the last log entry has been replayed. Once replaying is finished, the activation has caught up and transitions back to ***Running***.
|
|
12
12
|
|
|
13
|
-
- ***Failed***. If during the ***Replaying*** state
|
|
13
|
+
- ***Failed***. If the guest activation misbehaves during the ***Replaying*** state (by failing to exactly produce its previously logged behavior) or during the ***Running*** state (by an invalid or unsupported interaction with the `asyncFlow` mechanism), it goes into the inactive ***Failed*** state, with a diagnostic explaining how the replay failed, so it can be repaired by another future upgrade. As of the next reincarnation, the failure status is cleared and it starts ***Replaying***, then ***Running*** again, hoping not to fail this time. If replay or running failed because the previous guest async function misbehaved, then to make progress, an upgrade needs to replace the function with one which behaves correctly. If a ***Replaying*** or ***Running*** guest failed because of a failure of the `asyncFlow` mechanism, whether a bug or merely hitting a case that is not yet implemented, then an upgrade needs to replace the relevant part of the `asyncFlow`'s mechanism.
|
|
14
14
|
|
|
15
15
|
- ***Done***. The guest async function invocation returned a promise for its eventual outcome. Once that promise settles, we assume that the job of the guest activation is done. It then goes into a durably ***Done*** state, dropping all its bookkeeping beyond just remembering the corresponding settled outcome vow, and that it is ***Done***. The replay logs and membrane state of this activation are dropped, to be garbage collected.
|
|
16
|
+
|
|
Binary file
|
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-18-dev-d7c994b.0+d7c994b",
|
|
4
4
|
"description": "Upgrade async functions at await points by replay",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/Agoric/agoric-sdk",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "exit 0",
|
|
10
10
|
"prepack": "tsc --build tsconfig.build.json",
|
|
11
|
-
"postpack": "git clean -f '*.d.ts*'",
|
|
11
|
+
"postpack": "git clean -f '*.d.ts*' '*.tsbuildinfo'",
|
|
12
12
|
"test": "ava",
|
|
13
13
|
"test:c8": "c8 $C8_OPTIONS ava --config=ava-nesm.config.js",
|
|
14
14
|
"test:xs": "exit 0",
|
|
@@ -24,23 +24,22 @@
|
|
|
24
24
|
"author": "Agoric",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@agoric/base-zone": "0.1.1-upgrade-
|
|
28
|
-
"@agoric/internal": "0.
|
|
29
|
-
"@agoric/store": "0.9.3-upgrade-
|
|
30
|
-
"@agoric/vow": "0.
|
|
31
|
-
"@endo/common": "^1.2.
|
|
32
|
-
"@endo/errors": "^1.2.
|
|
33
|
-
"@endo/eventual-send": "^1.2.
|
|
34
|
-
"@endo/marshal": "^1.
|
|
35
|
-
"@endo/pass-style": "^1.4.
|
|
36
|
-
"@endo/patterns": "^1.4.
|
|
37
|
-
"@endo/promise-kit": "^1.1.
|
|
27
|
+
"@agoric/base-zone": "0.1.1-upgrade-18-dev-d7c994b.0+d7c994b",
|
|
28
|
+
"@agoric/internal": "0.3.3-upgrade-18-dev-d7c994b.0+d7c994b",
|
|
29
|
+
"@agoric/store": "0.9.3-upgrade-18-dev-d7c994b.0+d7c994b",
|
|
30
|
+
"@agoric/vow": "0.1.1-upgrade-18-dev-d7c994b.0+d7c994b",
|
|
31
|
+
"@endo/common": "^1.2.7",
|
|
32
|
+
"@endo/errors": "^1.2.7",
|
|
33
|
+
"@endo/eventual-send": "^1.2.7",
|
|
34
|
+
"@endo/marshal": "^1.6.1",
|
|
35
|
+
"@endo/pass-style": "^1.4.6",
|
|
36
|
+
"@endo/patterns": "^1.4.6",
|
|
37
|
+
"@endo/promise-kit": "^1.1.7"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@agoric/swingset-
|
|
41
|
-
"@agoric/zone": "0.3
|
|
42
|
-
"@endo/env-options": "^1.1.
|
|
43
|
-
"@endo/ses-ava": "^1.2.5",
|
|
40
|
+
"@agoric/swingset-vat": "0.32.3-upgrade-18-dev-d7c994b.0+d7c994b",
|
|
41
|
+
"@agoric/zone": "0.2.3-upgrade-18-dev-d7c994b.0+d7c994b",
|
|
42
|
+
"@endo/env-options": "^1.1.7",
|
|
44
43
|
"ava": "^5.3.0",
|
|
45
44
|
"tsd": "^0.31.1"
|
|
46
45
|
},
|
|
@@ -61,7 +60,7 @@
|
|
|
61
60
|
"workerThreads": false
|
|
62
61
|
},
|
|
63
62
|
"typeCoverage": {
|
|
64
|
-
"atLeast":
|
|
63
|
+
"atLeast": 76.93
|
|
65
64
|
},
|
|
66
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "d7c994b8d33c0cd22b257f3e33b579588ab6c6d8"
|
|
67
66
|
}
|
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":"AAgDO,iDAHI,IAAI;
|
|
1
|
+
{"version":3,"file":"async-flow.d.ts","sourceRoot":"","sources":["async-flow.js"],"names":[],"mappings":"AAgDO,iDAHI,IAAI;gCAgDF,IAAI,OACJ,MAAM,kBACN,cAAc;qBACC,OAAO;;;YA4BzB;;eAEG;4BADU,SAAS;YAkCtB;;;;;eAKG;;;;;;;;;;;;;;;;;gBA4TmB,CAAC,SAAlB,cAAgB,QAClB,IAAI,OACJ,MAAM,aACN,CAAC;qBACc,OAAO;sBACpB,OAAO,CAAC,CAAC;;;;;;;;EAsDvB;6BAIY,UAAU,aAlfZ,IAAI;gCAgDF,IAAI,OACJ,MAAM,kBACN,cAAc;qBACC,OAAO;;;YA4BzB;;eAEG;4BADU,SAAS;YAkCtB;;;;;eAKG;;;;;;;;;;;;;;;;;gBA4TmB,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;0BAjiBV,mBAAmB;wCACoD,iBAAiB;oCAAjB,iBAAiB;+BAAjB,iBAAiB;4BAAjB,iBAAiB"}
|
package/src/async-flow.js
CHANGED
|
@@ -11,7 +11,7 @@ import { prepareEndowmentTools } from './endowments.js';
|
|
|
11
11
|
import { LogEntryShape, FlowStateShape } from './type-guards.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* @import {WeakMapStore} from '@agoric/store'
|
|
14
|
+
* @import {WeakMapStore, MapStore} from '@agoric/store'
|
|
15
15
|
* @import {Zone} from '@agoric/base-zone'
|
|
16
16
|
* @import {FlowState, GuestAsyncFunc, HostAsyncFuncWrapper, HostOf, PreparationOptions} from '../src/types.js'
|
|
17
17
|
* @import {ReplayMembrane} from '../src/replay-membrane.js'
|
|
@@ -55,6 +55,9 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
55
55
|
{ vowTools },
|
|
56
56
|
),
|
|
57
57
|
makeBijection = prepareBijection(outerZone, unwrap),
|
|
58
|
+
panicHandler = err => {
|
|
59
|
+
throw err;
|
|
60
|
+
},
|
|
58
61
|
} = outerOptions;
|
|
59
62
|
const { watch, makeVowKit } = vowTools;
|
|
60
63
|
|
|
@@ -67,7 +70,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
67
70
|
keyShape: M.remotable('flow'), // flowState !== 'Done'
|
|
68
71
|
});
|
|
69
72
|
|
|
70
|
-
/** @type WeakMapStore<AsyncFlow, ReplayMembrane> */
|
|
73
|
+
/** @type {WeakMapStore<AsyncFlow, ReplayMembrane>} */
|
|
71
74
|
const membraneMap = makeScalarWeakMapStore('membraneFor', {
|
|
72
75
|
keyShape: M.remotable('flow'),
|
|
73
76
|
valueShape: M.remotable('membrane'),
|
|
@@ -247,6 +250,12 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
247
250
|
guestResultP,
|
|
248
251
|
gFulfillment => {
|
|
249
252
|
if (bijection.hasGuest(guestResultP)) {
|
|
253
|
+
!log.isReplaying() ||
|
|
254
|
+
panic(
|
|
255
|
+
makeError(
|
|
256
|
+
X`guest fulfilled with ${gFulfillment} before finishing replay`,
|
|
257
|
+
),
|
|
258
|
+
);
|
|
250
259
|
outcomeKit.resolver.resolve(
|
|
251
260
|
membrane.guestToHost(gFulfillment),
|
|
252
261
|
);
|
|
@@ -262,11 +271,46 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => {
|
|
|
262
271
|
// in the `guestResultP` being absent from the bijection,
|
|
263
272
|
// so this leave the outcome vow unsettled, as it must.
|
|
264
273
|
if (bijection.hasGuest(guestResultP)) {
|
|
274
|
+
!log.isReplaying() ||
|
|
275
|
+
panic(
|
|
276
|
+
makeError(
|
|
277
|
+
X`guest rejected with ${guestReason} before finishing replay`,
|
|
278
|
+
),
|
|
279
|
+
);
|
|
265
280
|
outcomeKit.resolver.reject(membrane.guestToHost(guestReason));
|
|
266
281
|
admin.complete();
|
|
267
282
|
}
|
|
268
283
|
},
|
|
269
|
-
)
|
|
284
|
+
)
|
|
285
|
+
.then(
|
|
286
|
+
() => {
|
|
287
|
+
if (flow.getFlowState() === 'Failed') {
|
|
288
|
+
// If the flow fails, we need to trigger the panic handler with
|
|
289
|
+
// the failure.
|
|
290
|
+
throw flow.getOptFatalProblem();
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
maybePanicReason => {
|
|
294
|
+
if (flow.getFlowState() === 'Failed') {
|
|
295
|
+
const err = flow.getOptFatalProblem();
|
|
296
|
+
// TODO: Annotate maybePanicReason robustly with err if it
|
|
297
|
+
// is indeed not the same as one we already threw from
|
|
298
|
+
// panic.
|
|
299
|
+
throw err;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Definitely not a reason from an existing panic, so raise a new panic.
|
|
303
|
+
const err = makeError(
|
|
304
|
+
X`internal: unexpected error in guest completion handling ${maybePanicReason}`,
|
|
305
|
+
);
|
|
306
|
+
try {
|
|
307
|
+
panic(err);
|
|
308
|
+
} catch (_e) {
|
|
309
|
+
throw err;
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
)
|
|
313
|
+
.catch(panicHandler);
|
|
270
314
|
},
|
|
271
315
|
wake() {
|
|
272
316
|
const { facets } = this;
|
package/src/endowments.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export function forwardingMethods(rem: any): {
|
|
2
2
|
[k: string]: any;
|
|
3
3
|
};
|
|
4
|
-
export function makeSharedStateRecord<K extends string | number | symbol, R extends Record<K, any>>(dataRecord: R): R;
|
|
5
4
|
export function prepareEndowmentTools(outerZone: Zone, outerOptions?: PreparationOptions | undefined): {
|
|
6
5
|
prepareEndowment: (zone: Zone, tag: string, e: unknown) => any;
|
|
7
6
|
unwrap: (wrapped: any, guestWrapped: any) => any;
|
package/src/endowments.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endowments.d.ts","sourceRoot":"","sources":["endowments.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"endowments.d.ts","sourceRoot":"","sources":["endowments.js"],"names":[],"mappings":"AAiDO;;EASN;AAMM,iDAHI,IAAI;6BA4GF,IAAI,OACJ,MAAM,KACN,OAAO;;EAyFnB;4BA7OY,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO;6BAiP1E,UAAU,aA3MZ,IAAI;6BA4GF,IAAI,OACJ,MAAM,KACN,OAAO;;EA6F0B;0BAvPvB,mBAAmB;wCAEL,iBAAiB"}
|
package/src/endowments.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Fail } from '@endo/errors';
|
|
2
2
|
import { E } from '@endo/eventual-send';
|
|
3
3
|
import { isPromise } from '@endo/promise-kit';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
isRemotable,
|
|
6
|
+
isPassable,
|
|
7
|
+
GET_METHOD_NAMES,
|
|
8
|
+
Far,
|
|
9
|
+
} from '@endo/pass-style';
|
|
5
10
|
import { M, objectMap } from '@endo/patterns';
|
|
6
11
|
import { prepareVowTools, toPassableCap } from '@agoric/vow';
|
|
7
12
|
import { isVow } from '@agoric/vow/src/vow-utils.js';
|
|
@@ -53,38 +58,6 @@ export const forwardingMethods = rem => {
|
|
|
53
58
|
return fromEntries(keys.map(makeMethodEntry));
|
|
54
59
|
};
|
|
55
60
|
|
|
56
|
-
/**
|
|
57
|
-
* Given a possibly mutable (and therefore unhardened) record, return a
|
|
58
|
-
* corresponding state record that acts identically for normal
|
|
59
|
-
* gets and sets, but is implemented using accessors, so it will be recognized
|
|
60
|
-
* as a state record.
|
|
61
|
-
*
|
|
62
|
-
* @template { string | number | symbol } K
|
|
63
|
-
* @template {Record<K, any>} R
|
|
64
|
-
* @param {R} dataRecord
|
|
65
|
-
* @returns {R}
|
|
66
|
-
*/
|
|
67
|
-
export const makeSharedStateRecord = dataRecord =>
|
|
68
|
-
harden(
|
|
69
|
-
create(
|
|
70
|
-
objectPrototype,
|
|
71
|
-
fromEntries(
|
|
72
|
-
ownKeys(dataRecord).flatMap(key =>
|
|
73
|
-
entries(
|
|
74
|
-
getOwnPropertyDescriptors({
|
|
75
|
-
get [key]() {
|
|
76
|
-
return dataRecord[key];
|
|
77
|
-
},
|
|
78
|
-
set [key](newValue) {
|
|
79
|
-
dataRecord[key] = newValue;
|
|
80
|
-
},
|
|
81
|
-
}),
|
|
82
|
-
),
|
|
83
|
-
),
|
|
84
|
-
),
|
|
85
|
-
),
|
|
86
|
-
);
|
|
87
|
-
|
|
88
61
|
/**
|
|
89
62
|
* @param {Zone} outerZone
|
|
90
63
|
* @param {PreparationOptions} [outerOptions]
|
|
@@ -95,8 +68,7 @@ export const prepareEndowmentTools = (outerZone, outerOptions = {}) => {
|
|
|
95
68
|
|
|
96
69
|
const functionUnwrapper = outerZone.exo('FunctionUnwrapper', UnwrapperI, {
|
|
97
70
|
unwrap(guestWrapped) {
|
|
98
|
-
|
|
99
|
-
return harden(unwrapped);
|
|
71
|
+
return Far('UnwrappedFunction', (...args) => guestWrapped.apply(args));
|
|
100
72
|
},
|
|
101
73
|
});
|
|
102
74
|
|
package/src/equate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"equate.d.ts","sourceRoot":"","sources":["equate.js"],"names":[],"mappings":"AAQO,
|
|
1
|
+
{"version":3,"file":"equate.d.ts","sourceRoot":"","sources":["equate.js"],"names":[],"mappings":"AAQO,iFAyHN"}
|
package/src/equate.js
CHANGED
|
@@ -31,7 +31,14 @@ export const makeEquate = bijection => {
|
|
|
31
31
|
Fail`unequal ${g} vs ${h}`;
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
if (bijection.
|
|
34
|
+
if (bijection.hasGuest(g) && bijection.guestToHost(g) === h) {
|
|
35
|
+
// Note that this can be true even when
|
|
36
|
+
// `bijection.hostToGuest(h) !== g`
|
|
37
|
+
// but only when the two guests represent the same host, as
|
|
38
|
+
// happens with unwrapping. That why we do this one-way test
|
|
39
|
+
// rather than the two way `bijection.has` test.
|
|
40
|
+
// Even in this one-way case, we have still satisfied
|
|
41
|
+
// the equate, so return.
|
|
35
42
|
return;
|
|
36
43
|
}
|
|
37
44
|
const gPassStyle = passStyleOf(g);
|
|
@@ -41,7 +48,8 @@ export const makeEquate = bijection => {
|
|
|
41
48
|
// TODO when we do, delete the `throw Fail` line and uncomment
|
|
42
49
|
// the two lines below it.
|
|
43
50
|
// We *do* support passing a guest wrapper of a hostVow back
|
|
44
|
-
// to the host, but that would be
|
|
51
|
+
// to the host, but that would be caught by `bijection.guestToHost`
|
|
52
|
+
// test above.
|
|
45
53
|
throw Fail`guest promises not yet passable`;
|
|
46
54
|
// `init` does not yet do enough checking anyway. For this case,
|
|
47
55
|
// we should ensure that h is a host wrapper of a guest promise,
|
|
@@ -92,10 +100,10 @@ export const makeEquate = bijection => {
|
|
|
92
100
|
case 'remotable': {
|
|
93
101
|
// Note that we can send a guest wrapping of a host remotable
|
|
94
102
|
// back to the host,
|
|
95
|
-
// but that should have already been
|
|
96
|
-
// `bijection.
|
|
103
|
+
// but that should have already been caught by the
|
|
104
|
+
// `bijection.guestToHost` above.
|
|
97
105
|
throw Fail`cannot yet send guest remotables to host ${g} vs ${h}`;
|
|
98
|
-
// `
|
|
106
|
+
// `unwrapInit` does not yet do enough checking anyway. For this case,
|
|
99
107
|
// we should ensure that h is a host wrapper of a guest remotable,
|
|
100
108
|
// which is a wrapping we don't yet support.
|
|
101
109
|
// bijection.unwrapInit(g, h);
|
|
@@ -104,10 +112,10 @@ export const makeEquate = bijection => {
|
|
|
104
112
|
case 'promise': {
|
|
105
113
|
// Note that we can send a guest wrapping of a host promise
|
|
106
114
|
// (or vow) back to the host,
|
|
107
|
-
// but that should have already been
|
|
108
|
-
// `bijection.
|
|
115
|
+
// but that should have already been caught by the
|
|
116
|
+
// `bijection.guestToHost` above.
|
|
109
117
|
throw Fail`cannot yet send guest promises to host ${g} vs ${h}`;
|
|
110
|
-
// `
|
|
118
|
+
// `unwrapInit` does not yet do enough checking anyway. For this case,
|
|
111
119
|
// we should ensure that h is a host wrapper of a guest promise,
|
|
112
120
|
// which is a wrapping we don't yet support.
|
|
113
121
|
// bijection.unwrapInit(g, h);
|
package/src/log-store.d.ts
CHANGED
|
@@ -1,24 +1,61 @@
|
|
|
1
|
+
export function nextGeneration(zone: Zone): number;
|
|
1
2
|
export function prepareLogStore(zone: Zone): () => import("@endo/exo").Guarded<{
|
|
2
3
|
reset(): void;
|
|
3
4
|
dispose(): void;
|
|
5
|
+
getUnfilteredIndex(): number;
|
|
4
6
|
getIndex(): number;
|
|
5
7
|
getLength(): number;
|
|
6
8
|
isReplaying(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* @returns {LogEntry}
|
|
11
|
+
*/
|
|
7
12
|
peekEntry(): LogEntry;
|
|
13
|
+
/**
|
|
14
|
+
* @returns {LogEntry}
|
|
15
|
+
*/
|
|
16
|
+
nextUnfilteredEntry(): LogEntry;
|
|
17
|
+
/**
|
|
18
|
+
* @returns {LogEntry}
|
|
19
|
+
*/
|
|
8
20
|
nextEntry(): LogEntry;
|
|
9
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @param {LogEntry} latestEntry
|
|
23
|
+
*/
|
|
24
|
+
pushEntry(latestEntry: LogEntry): number;
|
|
25
|
+
/**
|
|
26
|
+
* @returns {LogEntry[]}
|
|
27
|
+
*/
|
|
28
|
+
dumpUnfiltered(): LogEntry[];
|
|
10
29
|
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])[];
|
|
11
30
|
promiseReplayDone(): Promise<undefined>;
|
|
12
31
|
}>;
|
|
13
32
|
export type LogStore = ReturnType<ReturnType<(zone: Zone) => () => import("@endo/exo").Guarded<{
|
|
14
33
|
reset(): void;
|
|
15
34
|
dispose(): void;
|
|
35
|
+
getUnfilteredIndex(): number;
|
|
16
36
|
getIndex(): number;
|
|
17
37
|
getLength(): number;
|
|
18
38
|
isReplaying(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* @returns {LogEntry}
|
|
41
|
+
*/
|
|
19
42
|
peekEntry(): LogEntry;
|
|
43
|
+
/**
|
|
44
|
+
* @returns {LogEntry}
|
|
45
|
+
*/
|
|
46
|
+
nextUnfilteredEntry(): LogEntry;
|
|
47
|
+
/**
|
|
48
|
+
* @returns {LogEntry}
|
|
49
|
+
*/
|
|
20
50
|
nextEntry(): LogEntry;
|
|
21
|
-
|
|
51
|
+
/**
|
|
52
|
+
* @param {LogEntry} latestEntry
|
|
53
|
+
*/
|
|
54
|
+
pushEntry(latestEntry: LogEntry): number;
|
|
55
|
+
/**
|
|
56
|
+
* @returns {LogEntry[]}
|
|
57
|
+
*/
|
|
58
|
+
dumpUnfiltered(): LogEntry[];
|
|
22
59
|
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])[];
|
|
23
60
|
promiseReplayDone(): Promise<undefined>;
|
|
24
61
|
}>>>;
|
package/src/log-store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-store.d.ts","sourceRoot":"","sources":["log-store.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"log-store.d.ts","sourceRoot":"","sources":["log-store.js"],"names":[],"mappings":"AAmCO,qCAHI,IAAI,GACF,MAAM,CAgBlB;AAOM,sCAFI,IAAI;;;;;;;IAoGT;;OAEG;iBADU,QAAQ;IAcrB;;OAEG;2BADU,QAAQ;IAgBrB;;OAEG;iBADU,QAAQ;IAWrB;;OAEG;2BADQ,QAAQ;IAuCnB;;OAEG;sBADU,QAAQ,EAAE;;;GAwB5B;uBAGY,UAAU,CAAC,UAAU,QApNvB,IAAI;;;;;;;IAoGT;;OAEG;iBADU,QAAQ;IAcrB;;OAEG;2BADU,QAAQ;IAgBrB;;OAEG;iBADU,QAAQ;IAWrB;;OAEG;2BADQ,QAAQ;IAuCnB;;OAEG;sBADU,QAAQ,EAAE;;;GA2BsB,CAAC;0BAlQ7B,mBAAmB;8BAEL,YAAY"}
|
package/src/log-store.js
CHANGED
|
@@ -14,31 +14,76 @@ import { makeEphemera } from './ephemera.js';
|
|
|
14
14
|
const LogStoreI = M.interface('LogStore', {
|
|
15
15
|
reset: M.call().returns(),
|
|
16
16
|
dispose: M.call().returns(),
|
|
17
|
+
getUnfilteredIndex: M.call().returns(M.number()),
|
|
17
18
|
getIndex: M.call().returns(M.number()),
|
|
18
19
|
getLength: M.call().returns(M.number()),
|
|
19
20
|
isReplaying: M.call().returns(M.boolean()),
|
|
20
21
|
peekEntry: M.call().returns(LogEntryShape),
|
|
21
22
|
nextEntry: M.call().returns(LogEntryShape),
|
|
23
|
+
nextUnfilteredEntry: M.call().returns(LogEntryShape),
|
|
22
24
|
pushEntry: M.call(LogEntryShape).returns(M.number()),
|
|
25
|
+
dumpUnfiltered: M.call().returns(M.arrayOf(LogEntryShape)),
|
|
23
26
|
dump: M.call().returns(M.arrayOf(LogEntryShape)),
|
|
24
27
|
promiseReplayDone: M.call().returns(M.promise()),
|
|
25
28
|
});
|
|
26
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Get a generation number to use in `startGeneration` log entries.
|
|
32
|
+
*
|
|
33
|
+
* @param {Zone} zone
|
|
34
|
+
* @returns {number}
|
|
35
|
+
*/
|
|
36
|
+
export const nextGeneration = zone => {
|
|
37
|
+
/** @type {MapStore<'generation', number>} */
|
|
38
|
+
const logStoreMetadata = zone.mapStore('LogStoreMetadata');
|
|
39
|
+
const generationKey = 'generation';
|
|
40
|
+
|
|
41
|
+
if (!logStoreMetadata.has(generationKey)) {
|
|
42
|
+
const firstGen = 0;
|
|
43
|
+
logStoreMetadata.init(generationKey, firstGen);
|
|
44
|
+
return firstGen;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const nextGen = logStoreMetadata.get(generationKey) + 1;
|
|
48
|
+
logStoreMetadata.set(generationKey, nextGen);
|
|
49
|
+
return nextGen;
|
|
50
|
+
};
|
|
51
|
+
|
|
27
52
|
/**
|
|
28
53
|
* A growable, replayable, sequence of `LogEntry`s.
|
|
29
54
|
*
|
|
30
55
|
* @param {Zone} zone
|
|
31
56
|
*/
|
|
32
57
|
export const prepareLogStore = zone => {
|
|
58
|
+
/**
|
|
59
|
+
* Ensure that any new or reset LogStore instance that (for a given
|
|
60
|
+
* incarnation) pushes at least one entry will insert these entries first,
|
|
61
|
+
* even if the log is reset, replayed, and pushed to in the same incarnation.
|
|
62
|
+
* @type {LogEntry[]}
|
|
63
|
+
*/
|
|
64
|
+
const initialPush = harden([['startGeneration', nextGeneration(zone)]]);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A predicate to indicate whether the entry is normally visible to the
|
|
68
|
+
* LogStore user, or is a more internal entry that only is visible via the
|
|
69
|
+
* Unfiltered methods.
|
|
70
|
+
* @param {LogEntry} entry
|
|
71
|
+
*/
|
|
72
|
+
const entryIsVisible = entry => entry[0] !== 'startGeneration';
|
|
73
|
+
|
|
33
74
|
/**
|
|
34
75
|
* @type {Ephemera<LogStore, {
|
|
35
|
-
* index: number
|
|
36
|
-
*
|
|
76
|
+
* index: number;
|
|
77
|
+
* unfilteredIndex: number;
|
|
78
|
+
* initialPush: LogEntry[] | undefined;
|
|
79
|
+
* replayDoneKit: PromiseKit<undefined>;
|
|
37
80
|
* }>}
|
|
38
81
|
*/
|
|
39
82
|
const tmp = makeEphemera(log => {
|
|
40
83
|
const result = {
|
|
41
84
|
index: 0,
|
|
85
|
+
unfilteredIndex: 0,
|
|
86
|
+
initialPush,
|
|
42
87
|
replayDoneKit: makePromiseKit(),
|
|
43
88
|
};
|
|
44
89
|
if (log.getLength() === 0) {
|
|
@@ -82,6 +127,12 @@ export const prepareLogStore = zone => {
|
|
|
82
127
|
tmp.resetFor(self);
|
|
83
128
|
mapStore.clear();
|
|
84
129
|
},
|
|
130
|
+
getUnfilteredIndex() {
|
|
131
|
+
const { self } = this;
|
|
132
|
+
const eph = tmp.for(self);
|
|
133
|
+
|
|
134
|
+
return eph.unfilteredIndex;
|
|
135
|
+
},
|
|
85
136
|
getIndex() {
|
|
86
137
|
const { self } = this;
|
|
87
138
|
const eph = tmp.for(self);
|
|
@@ -99,52 +150,96 @@ export const prepareLogStore = zone => {
|
|
|
99
150
|
const { mapStore } = state;
|
|
100
151
|
const eph = tmp.for(self);
|
|
101
152
|
|
|
102
|
-
return eph.
|
|
153
|
+
return eph.unfilteredIndex < mapStore.getSize();
|
|
103
154
|
},
|
|
155
|
+
/**
|
|
156
|
+
* @returns {LogEntry}
|
|
157
|
+
*/
|
|
104
158
|
peekEntry() {
|
|
105
159
|
const { state, self } = this;
|
|
106
160
|
const { mapStore } = state;
|
|
107
161
|
const eph = tmp.for(self);
|
|
108
162
|
|
|
109
163
|
self.isReplaying() ||
|
|
110
|
-
Fail`No longer replaying: ${q(eph.
|
|
164
|
+
Fail`No longer replaying: ${q(eph.unfilteredIndex)} vs ${q(
|
|
111
165
|
mapStore.getSize(),
|
|
112
166
|
)}`;
|
|
113
|
-
const result = mapStore.get(eph.
|
|
167
|
+
const result = mapStore.get(eph.unfilteredIndex);
|
|
114
168
|
return result;
|
|
115
169
|
},
|
|
116
|
-
|
|
170
|
+
/**
|
|
171
|
+
* @returns {LogEntry}
|
|
172
|
+
*/
|
|
173
|
+
nextUnfilteredEntry() {
|
|
117
174
|
const { self } = this;
|
|
118
175
|
const eph = tmp.for(self);
|
|
119
176
|
|
|
120
177
|
const result = self.peekEntry();
|
|
121
|
-
eph.
|
|
178
|
+
eph.unfilteredIndex += 1;
|
|
179
|
+
if (entryIsVisible(result)) {
|
|
180
|
+
eph.index += 1;
|
|
181
|
+
}
|
|
122
182
|
if (!self.isReplaying()) {
|
|
123
183
|
eph.replayDoneKit.resolve(undefined);
|
|
124
184
|
}
|
|
125
185
|
return result;
|
|
126
186
|
},
|
|
127
|
-
|
|
187
|
+
/**
|
|
188
|
+
* @returns {LogEntry}
|
|
189
|
+
*/
|
|
190
|
+
nextEntry() {
|
|
191
|
+
const { self } = this;
|
|
192
|
+
let result = self.nextUnfilteredEntry();
|
|
193
|
+
while (!entryIsVisible(result)) {
|
|
194
|
+
self.isReplaying() || Fail`Unexpected entry at log tail: ${result}`;
|
|
195
|
+
result = self.nextUnfilteredEntry();
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
},
|
|
199
|
+
/**
|
|
200
|
+
* @param {LogEntry} latestEntry
|
|
201
|
+
*/
|
|
202
|
+
pushEntry(latestEntry) {
|
|
128
203
|
const { state, self } = this;
|
|
204
|
+
|
|
129
205
|
const { mapStore } = state;
|
|
130
206
|
const eph = tmp.for(self);
|
|
131
207
|
|
|
132
208
|
!self.isReplaying() ||
|
|
133
|
-
Fail`still replaying: ${q(eph.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
209
|
+
Fail`still replaying: ${q(eph.unfilteredIndex)} vs ${q(mapStore.getSize())}`;
|
|
210
|
+
|
|
211
|
+
const pushOne = entry => {
|
|
212
|
+
eph.unfilteredIndex === mapStore.getSize() ||
|
|
213
|
+
Fail`internal: unfilteredIndex confusion ${q(eph.unfilteredIndex)} vs ${q(
|
|
214
|
+
mapStore.getSize(),
|
|
215
|
+
)}`;
|
|
216
|
+
mapStore.init(eph.unfilteredIndex, entry);
|
|
217
|
+
eph.unfilteredIndex += 1;
|
|
218
|
+
if (entryIsVisible(entry)) {
|
|
219
|
+
eph.index += 1;
|
|
220
|
+
}
|
|
221
|
+
eph.unfilteredIndex === mapStore.getSize() ||
|
|
222
|
+
Fail`internal: unfilteredIndex confusion ${q(eph.unfilteredIndex)} vs ${q(
|
|
223
|
+
mapStore.getSize(),
|
|
224
|
+
)}`;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
if (eph.initialPush) {
|
|
228
|
+
const initialEntries = eph.initialPush;
|
|
229
|
+
eph.initialPush = undefined;
|
|
230
|
+
for (const initialEntry of initialEntries) {
|
|
231
|
+
pushOne(initialEntry);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
pushOne(latestEntry);
|
|
235
|
+
|
|
236
|
+
// console.log('LOG ENTRY ', eph.unfilteredIndex - 1, entry);
|
|
237
|
+
return eph.unfilteredIndex;
|
|
146
238
|
},
|
|
147
|
-
|
|
239
|
+
/**
|
|
240
|
+
* @returns {LogEntry[]}
|
|
241
|
+
*/
|
|
242
|
+
dumpUnfiltered() {
|
|
148
243
|
const { state } = this;
|
|
149
244
|
const { mapStore } = state;
|
|
150
245
|
const len = mapStore.getSize();
|
|
@@ -154,6 +249,10 @@ export const prepareLogStore = zone => {
|
|
|
154
249
|
}
|
|
155
250
|
return harden(result);
|
|
156
251
|
},
|
|
252
|
+
dump() {
|
|
253
|
+
const { self } = this;
|
|
254
|
+
return harden(self.dumpUnfiltered().filter(entryIsVisible));
|
|
255
|
+
},
|
|
157
256
|
promiseReplayDone() {
|
|
158
257
|
const { self } = this;
|
|
159
258
|
const eph = tmp.for(self);
|