@agoric/vow 0.1.1-calypso-dev-84eb287.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/LICENSE +201 -0
- package/README.md +114 -0
- package/package.json +58 -0
- package/src/E.d.ts +165 -0
- package/src/E.d.ts.map +1 -0
- package/src/E.js +484 -0
- package/src/index.d.ts +6 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +16 -0
- package/src/message-breakpoints.d.ts +44 -0
- package/src/message-breakpoints.d.ts.map +1 -0
- package/src/message-breakpoints.js +180 -0
- package/src/tools.d.ts +25 -0
- package/src/tools.d.ts.map +1 -0
- package/src/tools.js +50 -0
- package/src/track-turns.d.ts +7 -0
- package/src/track-turns.d.ts.map +1 -0
- package/src/track-turns.js +114 -0
- package/src/types.d.ts +62 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.js +116 -0
- package/src/vow-e.d.ts +14 -0
- package/src/vow-e.d.ts.map +1 -0
- package/src/vow-e.js +101 -0
- package/src/vow-utils.d.ts +20 -0
- package/src/vow-utils.d.ts.map +1 -0
- package/src/vow-utils.js +112 -0
- package/src/vow.d.ts +7 -0
- package/src/vow.d.ts.map +1 -0
- package/src/vow.js +216 -0
- package/src/watch-utils.d.ts +20 -0
- package/src/watch-utils.d.ts.map +1 -0
- package/src/watch-utils.js +220 -0
- package/src/watch.d.ts +8 -0
- package/src/watch.d.ts.map +1 -0
- package/src/watch.js +199 -0
- package/src/when.d.ts +5 -0
- package/src/when.d.ts.map +1 -0
- package/src/when.js +76 -0
- package/vat.js +43 -0
package/src/vow-e.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/* global globalThis */
|
|
3
|
+
import { PromiseWatcherI } from '@agoric/base-zone';
|
|
4
|
+
import makeE from './E.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @import {PromiseWatcher} from '@agoric/base-zone'
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { Fail, bare } = assert;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {import('@agoric/base-zone').Zone} zone
|
|
14
|
+
* @param {object} powers
|
|
15
|
+
* @param {import('./when.js').When} powers.when
|
|
16
|
+
* @param {import('./watch.js').Watch} powers.watch
|
|
17
|
+
* @param {import('./types.js').IsRetryableReason} powers.isRetryableReason
|
|
18
|
+
*/
|
|
19
|
+
export const makeVowE = (zone, { when, watch, isRetryableReason }) => {
|
|
20
|
+
/** @type {import('@agoric/base-zone').PromiseWatcher} */
|
|
21
|
+
const retryRejectionPromiseWatcher = zone.exo(
|
|
22
|
+
'rejectRetriesPromiseWatcher',
|
|
23
|
+
PromiseWatcherI,
|
|
24
|
+
{
|
|
25
|
+
onFulfilled(_result) {},
|
|
26
|
+
onRejected(reason, failedOp) {
|
|
27
|
+
if (isRetryableReason(reason)) {
|
|
28
|
+
Fail`Pending ${bare(failedOp)} could not retry; ${reason}`;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {unknown} specimenP
|
|
36
|
+
* @param {string} opDescription
|
|
37
|
+
* @param {import('./E.js').EOptions} [opts]
|
|
38
|
+
* @returns {Promise<any>}
|
|
39
|
+
*/
|
|
40
|
+
const unwrap = (specimenP, opDescription, opts = {}) => {
|
|
41
|
+
const { watch: optWatch = false } = opts;
|
|
42
|
+
|
|
43
|
+
// Watch the specimen in case it is an ephemeral promise.
|
|
44
|
+
/** @type {Promise<any>} */
|
|
45
|
+
let promise;
|
|
46
|
+
|
|
47
|
+
if (optWatch) {
|
|
48
|
+
/** @type {import('./types.js').Vow<any>} */
|
|
49
|
+
let vow;
|
|
50
|
+
if (Array.isArray(optWatch)) {
|
|
51
|
+
// Arguments for the watch.
|
|
52
|
+
vow = watch(specimenP, ...optWatch);
|
|
53
|
+
} else if (
|
|
54
|
+
Object(optWatch) === optWatch &&
|
|
55
|
+
typeof optWatch === 'object'
|
|
56
|
+
) {
|
|
57
|
+
// Just a watcher.
|
|
58
|
+
vow = watch(specimenP, optWatch);
|
|
59
|
+
} else {
|
|
60
|
+
vow = watch(specimenP);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Make a prompt ephemeral promise for a (potentially durable) vow.
|
|
64
|
+
promise = HandledPromise.resolve(vow);
|
|
65
|
+
} else {
|
|
66
|
+
// Resolve to an non-prompt ephemeral promise.
|
|
67
|
+
promise = when(specimenP);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Watch the ephemeral result promise to ensure that if its settlement is
|
|
71
|
+
// lost due to upgrade of this incarnation, we will at least cause an
|
|
72
|
+
// unhandled rejection in the new incarnation.
|
|
73
|
+
zone.watchPromise(
|
|
74
|
+
harden(promise),
|
|
75
|
+
retryRejectionPromiseWatcher,
|
|
76
|
+
opDescription,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return promise;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* A convenient vow-shortening E, which returns platform result promises. It
|
|
84
|
+
* can cause problems when used in a durable context, because the resulting
|
|
85
|
+
* promises are ephemeral and likely not promptly resolved.
|
|
86
|
+
*
|
|
87
|
+
* Instead of this `vowE`, when manipulating durable vows, use
|
|
88
|
+
* `vowTools.watch` prepared in a durable zone with the standard,
|
|
89
|
+
* non-unwrapping `import('@endo/far').E`. This avoids the creation of
|
|
90
|
+
* promise/vow chains containing non-prompt ephemeral promises.
|
|
91
|
+
*/
|
|
92
|
+
const vowE = makeE(globalThis.HandledPromise, {
|
|
93
|
+
unwrap,
|
|
94
|
+
additional: {
|
|
95
|
+
when,
|
|
96
|
+
watch,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return vowE;
|
|
101
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { basicE };
|
|
2
|
+
/**
|
|
3
|
+
* The least possibly restrictive guard for a `watch` watcher's `onFulfilled` or
|
|
4
|
+
* `onRejected` reaction
|
|
5
|
+
*/
|
|
6
|
+
export const ReactionGuard: import("@endo/patterns").MethodGuard;
|
|
7
|
+
export const VowShape: import("@endo/patterns").Matcher;
|
|
8
|
+
export function OrVow$(shape: any): import("@endo/patterns").Matcher;
|
|
9
|
+
export function EVow$(shape: any): import("@endo/patterns").Matcher;
|
|
10
|
+
export function isVow(specimen: unknown): specimen is Vow;
|
|
11
|
+
export function getVowPayload<T>(specimen: any): VowPayload<T> | undefined;
|
|
12
|
+
export function toPassableCap(k: PassableCap | Vow): PassableCap;
|
|
13
|
+
export function makeAsVow(makeVowKit: MakeVowKit): <T extends unknown>(fn: (...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>) => Vow<Awaited<T>>;
|
|
14
|
+
import { E as basicE } from '@endo/eventual-send';
|
|
15
|
+
import type { Vow } from './types.js';
|
|
16
|
+
import type { VowPayload } from './types.js';
|
|
17
|
+
import type { PassableCap } from '@endo/pass-style';
|
|
18
|
+
import type { MakeVowKit } from './vow.js';
|
|
19
|
+
import type { PromiseVow } from './types.js';
|
|
20
|
+
//# sourceMappingURL=vow-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vow-utils.d.ts","sourceRoot":"","sources":["vow-utils.js"],"names":[],"mappings":";AAaA;;;GAGG;AACH,iEAAgF;AAEhF,wDAKE;AAEK,qEAA6C;AAC7C,oEAAkE;AAMlE,gCAHI,OAAO,GACL,QAAQ,IAAI,GAAG,CAGyB;AAc9C,8BAJM,CAAC,YACH,GAAG,GACD,WAAW,CAAC,CAAC,GAAG,SAAS,CASrC;AAoBM,iCAHI,WAAW,GAAG,GAAG,GACf,WAAW,CAUvB;AAIM,sCADK,UAAU,IAKD,CAAC,sBACT,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,KAC9D,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAiB7B;4BA7G2B,qBAAqB;yBAMH,YAAY;gCAAZ,YAAY;iCAD5B,kBAAkB;gCAEnB,UAAU;gCADO,YAAY"}
|
package/src/vow-utils.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { E as basicE } from '@endo/eventual-send';
|
|
3
|
+
import { isPassable } from '@endo/pass-style';
|
|
4
|
+
import { M, matches } from '@endo/patterns';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @import {PassableCap} from '@endo/pass-style';
|
|
8
|
+
* @import {VowPayload, Vow, PromiseVow} from './types.js';
|
|
9
|
+
* @import {MakeVowKit} from './vow.js';
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export { basicE };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The least possibly restrictive guard for a `watch` watcher's `onFulfilled` or
|
|
16
|
+
* `onRejected` reaction
|
|
17
|
+
*/
|
|
18
|
+
export const ReactionGuard = M.call(M.any()).optional(M.any()).returns(M.any());
|
|
19
|
+
|
|
20
|
+
export const VowShape = M.tagged(
|
|
21
|
+
'Vow',
|
|
22
|
+
M.splitRecord({
|
|
23
|
+
vowV0: M.remotable('VowV0'),
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export const OrVow$ = shape => M.or(shape, VowShape);
|
|
28
|
+
export const EVow$ = shape => M.or(OrVow$(shape), M.promise(/* shape */));
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {unknown} specimen
|
|
32
|
+
* @returns {specimen is Vow}
|
|
33
|
+
*/
|
|
34
|
+
export const isVow = specimen =>
|
|
35
|
+
isPassable(specimen) && matches(specimen, VowShape);
|
|
36
|
+
harden(isVow);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A vow is a passable tagged as 'Vow'. Its payload is a record with
|
|
40
|
+
* API-versioned remotables. payload.vowV0 is the API for the `watch` and
|
|
41
|
+
* `when` operators to use for retriable shortening of the vow chain.
|
|
42
|
+
*
|
|
43
|
+
* If the specimen is a Vow, return its payload, otherwise undefined.
|
|
44
|
+
*
|
|
45
|
+
* @template T
|
|
46
|
+
* @param {any} specimen any value to verify as a vow
|
|
47
|
+
* @returns {VowPayload<T> | undefined} undefined if specimen is not a vow, otherwise the vow's payload.
|
|
48
|
+
*/
|
|
49
|
+
export const getVowPayload = specimen => {
|
|
50
|
+
if (!isVow(specimen)) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const vow = /** @type {Vow<T>} */ (/** @type {unknown} */ (specimen));
|
|
55
|
+
return vow.payload;
|
|
56
|
+
};
|
|
57
|
+
harden(getVowPayload);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* For when you have a Vow or a `PassableCap` (`RemotableObject` or
|
|
61
|
+
* passable `Promise`) and you need `PassableCap`,
|
|
62
|
+
* typically to serve as a key in a `Map`, `WeakMap`, `Store`, or `WeakStore`.
|
|
63
|
+
*
|
|
64
|
+
* Relies on, and encapsulates, the current "V0" representation of a vow
|
|
65
|
+
* as containing a unique remotable shortener.
|
|
66
|
+
*
|
|
67
|
+
* Note: if `k` is not a `Vow`, `toPassableCap` does no enforcement that `k`
|
|
68
|
+
* is already a `PassableCap`. Rather, it just acts as an identity function
|
|
69
|
+
* returning `k` without further checking. The types only describe the
|
|
70
|
+
* intended use. (If warranted, we may later add such enforcement, so please
|
|
71
|
+
* do not rely on either the presence or absence of such enforcement.)
|
|
72
|
+
*
|
|
73
|
+
* @param {PassableCap | Vow} k
|
|
74
|
+
* @returns {PassableCap}
|
|
75
|
+
*/
|
|
76
|
+
export const toPassableCap = k => {
|
|
77
|
+
const payload = getVowPayload(k);
|
|
78
|
+
if (payload === undefined) {
|
|
79
|
+
return /** @type {PassableCap} */ (k);
|
|
80
|
+
}
|
|
81
|
+
const { vowV0 } = payload;
|
|
82
|
+
// vowMap.set(vowV0, h);
|
|
83
|
+
return vowV0;
|
|
84
|
+
};
|
|
85
|
+
harden(toPassableCap);
|
|
86
|
+
|
|
87
|
+
/** @param {MakeVowKit} makeVowKit */
|
|
88
|
+
export const makeAsVow = makeVowKit => {
|
|
89
|
+
/**
|
|
90
|
+
* Helper function that coerces the result of a function to a Vow. Helpful
|
|
91
|
+
* for scenarios like a synchronously thrown error.
|
|
92
|
+
* @template {any} T
|
|
93
|
+
* @param {(...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>} fn
|
|
94
|
+
* @returns {Vow<Awaited<T>>}
|
|
95
|
+
*/
|
|
96
|
+
const asVow = fn => {
|
|
97
|
+
let result;
|
|
98
|
+
try {
|
|
99
|
+
result = fn();
|
|
100
|
+
} catch (e) {
|
|
101
|
+
result = Promise.reject(e);
|
|
102
|
+
}
|
|
103
|
+
if (isVow(result)) {
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
const kit = makeVowKit();
|
|
107
|
+
kit.resolver.resolve(result);
|
|
108
|
+
return kit.vow;
|
|
109
|
+
};
|
|
110
|
+
return harden(asVow);
|
|
111
|
+
};
|
|
112
|
+
harden(makeAsVow);
|
package/src/vow.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function prepareVowKit(zone: Zone): <T>() => VowKit<T>;
|
|
2
|
+
export type VowEphemera = Partial<PromiseKit<any>> & Pick<PromiseKit<any>, "promise">;
|
|
3
|
+
export type MakeVowKit = ReturnType<typeof prepareVowKit>;
|
|
4
|
+
import type { Zone } from '@agoric/base-zone';
|
|
5
|
+
import type { VowKit } from './types.js';
|
|
6
|
+
import type { PromiseKit } from '@endo/promise-kit';
|
|
7
|
+
//# sourceMappingURL=vow.d.ts.map
|
package/src/vow.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vow.d.ts","sourceRoot":"","sources":["vow.js"],"names":[],"mappings":"AA0BO,oCAFI,IAAI,IAkLA,CAAC,OACD,OAAO,CAAC,CAAC,CASvB;0BAjMY,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,GACpC,IAAQ,CAAC,WAAW,GAAG,CAAC,EAAE,SAAS,CAAC;yBAiMvB,UAAU,CAAC,OAAO,aAAa,CAAC;0BA3MvB,mBAAmB;4BAEJ,YAAY;gCAHrB,mBAAmB"}
|
package/src/vow.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { makePromiseKit } from '@endo/promise-kit';
|
|
3
|
+
import { M } from '@endo/patterns';
|
|
4
|
+
import { makeTagged } from '@endo/pass-style';
|
|
5
|
+
import { PromiseWatcherI } from '@agoric/base-zone';
|
|
6
|
+
|
|
7
|
+
const { details: X } = assert;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @import {PromiseKit} from '@endo/promise-kit';
|
|
11
|
+
* @import {Zone} from '@agoric/base-zone';
|
|
12
|
+
* @import {MapStore} from '@agoric/store';
|
|
13
|
+
* @import {VowResolver, VowKit} from './types.js';
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const sink = () => {};
|
|
17
|
+
harden(sink);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {Partial<PromiseKit<any>> &
|
|
21
|
+
* Pick<PromiseKit<any>, 'promise'>} VowEphemera
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Zone} zone
|
|
26
|
+
*/
|
|
27
|
+
export const prepareVowKit = zone => {
|
|
28
|
+
/** @type {WeakMap<VowResolver, VowEphemera>} */
|
|
29
|
+
const resolverToEphemera = new WeakMap();
|
|
30
|
+
|
|
31
|
+
/** @type {WeakMap<VowResolver, any>} */
|
|
32
|
+
const resolverToNonStoredValue = new WeakMap();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get the current incarnation's promise kit associated with a vowV0.
|
|
36
|
+
*
|
|
37
|
+
* @param {VowResolver} resolver
|
|
38
|
+
*/
|
|
39
|
+
const provideCurrentKit = resolver => {
|
|
40
|
+
let pk = resolverToEphemera.get(resolver);
|
|
41
|
+
if (pk) {
|
|
42
|
+
return pk;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pk = makePromiseKit();
|
|
46
|
+
pk.promise.catch(sink); // silence unhandled rejection
|
|
47
|
+
resolverToEphemera.set(resolver, pk);
|
|
48
|
+
return pk;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param {VowResolver} resolver
|
|
53
|
+
*/
|
|
54
|
+
const getPromiseKitForResolution = resolver => {
|
|
55
|
+
const kit = provideCurrentKit(resolver);
|
|
56
|
+
if (kit.resolve) {
|
|
57
|
+
// Resolution is a one-time event, so forget the resolve/reject functions.
|
|
58
|
+
resolverToEphemera.set(resolver, harden({ promise: kit.promise }));
|
|
59
|
+
}
|
|
60
|
+
return kit;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const makeVowInternalsKit = zone.exoClassKit(
|
|
64
|
+
'VowInternalsKit',
|
|
65
|
+
{
|
|
66
|
+
vowV0: M.interface('VowV0', {
|
|
67
|
+
shorten: M.call().returns(M.promise()),
|
|
68
|
+
}),
|
|
69
|
+
resolver: M.interface('VowResolver', {
|
|
70
|
+
resolve: M.call().optional(M.raw()).returns(),
|
|
71
|
+
reject: M.call().optional(M.raw()).returns(),
|
|
72
|
+
}),
|
|
73
|
+
watchNextStep: PromiseWatcherI,
|
|
74
|
+
},
|
|
75
|
+
() => ({
|
|
76
|
+
value: /** @type {any} */ (undefined),
|
|
77
|
+
// The stepStatus is null if the promise step hasn't settled yet.
|
|
78
|
+
stepStatus: /** @type {null | 'pending' | 'fulfilled' | 'rejected'} */ (
|
|
79
|
+
null
|
|
80
|
+
),
|
|
81
|
+
isStoredValue: /** @type {boolean} */ (false),
|
|
82
|
+
/**
|
|
83
|
+
* Map for future properties that aren't in the schema.
|
|
84
|
+
* UNTIL https://github.com/Agoric/agoric-sdk/issues/7407
|
|
85
|
+
* @type {MapStore<any, any> | undefined}
|
|
86
|
+
*/
|
|
87
|
+
extra: undefined,
|
|
88
|
+
}),
|
|
89
|
+
{
|
|
90
|
+
vowV0: {
|
|
91
|
+
/**
|
|
92
|
+
* @returns {Promise<any>}
|
|
93
|
+
*/
|
|
94
|
+
async shorten() {
|
|
95
|
+
const { stepStatus, isStoredValue, value } = this.state;
|
|
96
|
+
const { resolver } = this.facets;
|
|
97
|
+
|
|
98
|
+
switch (stepStatus) {
|
|
99
|
+
case 'fulfilled': {
|
|
100
|
+
if (isStoredValue) {
|
|
101
|
+
// Always return a stored fulfilled value.
|
|
102
|
+
return value;
|
|
103
|
+
} else if (resolverToNonStoredValue.has(resolver)) {
|
|
104
|
+
// Non-stored value is available.
|
|
105
|
+
return resolverToNonStoredValue.get(resolver);
|
|
106
|
+
}
|
|
107
|
+
// We can't recover the non-stored value, so throw the
|
|
108
|
+
// explanation.
|
|
109
|
+
throw value;
|
|
110
|
+
}
|
|
111
|
+
case 'rejected': {
|
|
112
|
+
if (!isStoredValue && resolverToNonStoredValue.has(resolver)) {
|
|
113
|
+
// Non-stored reason is available.
|
|
114
|
+
throw resolverToNonStoredValue.get(resolver);
|
|
115
|
+
}
|
|
116
|
+
// Always throw a stored rejection reason.
|
|
117
|
+
throw value;
|
|
118
|
+
}
|
|
119
|
+
case null:
|
|
120
|
+
case 'pending':
|
|
121
|
+
return provideCurrentKit(this.facets.resolver).promise;
|
|
122
|
+
default:
|
|
123
|
+
throw new TypeError(`unexpected stepStatus ${stepStatus}`);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
resolver: {
|
|
128
|
+
/**
|
|
129
|
+
* @param {any} [value]
|
|
130
|
+
*/
|
|
131
|
+
resolve(value) {
|
|
132
|
+
const { resolver } = this.facets;
|
|
133
|
+
const { stepStatus } = this.state;
|
|
134
|
+
const { resolve } = getPromiseKitForResolution(resolver);
|
|
135
|
+
if (resolve) {
|
|
136
|
+
resolve(value);
|
|
137
|
+
}
|
|
138
|
+
if (stepStatus === null) {
|
|
139
|
+
this.state.stepStatus = 'pending';
|
|
140
|
+
zone.watchPromise(
|
|
141
|
+
HandledPromise.resolve(value),
|
|
142
|
+
this.facets.watchNextStep,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
/**
|
|
147
|
+
* @param {any} [reason]
|
|
148
|
+
*/
|
|
149
|
+
reject(reason) {
|
|
150
|
+
const { resolver, watchNextStep } = this.facets;
|
|
151
|
+
const { stepStatus } = this.state;
|
|
152
|
+
const { reject } = getPromiseKitForResolution(resolver);
|
|
153
|
+
if (reject) {
|
|
154
|
+
reject(reason);
|
|
155
|
+
}
|
|
156
|
+
if (stepStatus === null) {
|
|
157
|
+
watchNextStep.onRejected(reason);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
watchNextStep: {
|
|
162
|
+
onFulfilled(value) {
|
|
163
|
+
const { resolver } = this.facets;
|
|
164
|
+
const { resolve } = getPromiseKitForResolution(resolver);
|
|
165
|
+
harden(value);
|
|
166
|
+
if (resolve) {
|
|
167
|
+
resolve(value);
|
|
168
|
+
}
|
|
169
|
+
this.state.stepStatus = 'fulfilled';
|
|
170
|
+
this.state.isStoredValue = zone.isStorable(value);
|
|
171
|
+
if (this.state.isStoredValue) {
|
|
172
|
+
this.state.value = value;
|
|
173
|
+
} else {
|
|
174
|
+
resolverToNonStoredValue.set(resolver, value);
|
|
175
|
+
this.state.value = assert.error(
|
|
176
|
+
X`Vow fulfillment value was not stored: ${value}`,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
onRejected(reason) {
|
|
181
|
+
const { resolver } = this.facets;
|
|
182
|
+
const { reject } = getPromiseKitForResolution(resolver);
|
|
183
|
+
harden(reason);
|
|
184
|
+
if (reject) {
|
|
185
|
+
reject(reason);
|
|
186
|
+
}
|
|
187
|
+
this.state.stepStatus = 'rejected';
|
|
188
|
+
this.state.isStoredValue = zone.isStorable(reason);
|
|
189
|
+
if (this.state.isStoredValue) {
|
|
190
|
+
this.state.value = reason;
|
|
191
|
+
} else {
|
|
192
|
+
resolverToNonStoredValue.set(resolver, reason);
|
|
193
|
+
this.state.value = assert.error(
|
|
194
|
+
X`Vow rejection reason was not stored: ${reason}`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @template T
|
|
204
|
+
* @returns {VowKit<T>}
|
|
205
|
+
*/
|
|
206
|
+
const makeVowKit = () => {
|
|
207
|
+
const { resolver, vowV0 } = makeVowInternalsKit();
|
|
208
|
+
const vow = makeTagged('Vow', harden({ vowV0 }));
|
|
209
|
+
return harden({ resolver, vow });
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
return makeVowKit;
|
|
213
|
+
};
|
|
214
|
+
/** @typedef {ReturnType<typeof prepareVowKit>} MakeVowKit */
|
|
215
|
+
|
|
216
|
+
harden(prepareVowKit);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function prepareWatchUtils(zone: Zone, { watch, when, makeVowKit, isRetryableReason }: {
|
|
2
|
+
watch: Watch;
|
|
3
|
+
when: When;
|
|
4
|
+
makeVowKit: () => VowKit<any>;
|
|
5
|
+
isRetryableReason: IsRetryableReason;
|
|
6
|
+
}): () => import("@endo/exo").Guarded<{
|
|
7
|
+
/**
|
|
8
|
+
* @param {EVow<unknown>[]} vows
|
|
9
|
+
*/
|
|
10
|
+
all(vows: EVow<unknown>[]): import("./types.js").Vow<any[]>;
|
|
11
|
+
/** @type {AsPromiseFunction} */
|
|
12
|
+
asPromise(specimenP: any, watcher: import("./types.js").Watcher<any, any, never, any[]> | undefined, watcherArgs: any[] | undefined): Promise<any | never>;
|
|
13
|
+
}>;
|
|
14
|
+
import type { Zone } from '@agoric/base-zone';
|
|
15
|
+
import type { Watch } from './watch.js';
|
|
16
|
+
import type { When } from './when.js';
|
|
17
|
+
import type { VowKit } from './types.js';
|
|
18
|
+
import type { IsRetryableReason } from './types.js';
|
|
19
|
+
import type { EVow } from './types.js';
|
|
20
|
+
//# sourceMappingURL=watch-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-utils.d.ts","sourceRoot":"","sources":["watch-utils.js"],"names":[],"mappings":"AA4CO,wCAPI,IAAI,kDAEZ;IAAsB,KAAK,EAAnB,KAAK;IACQ,IAAI,EAAjB,IAAI;IACsB,UAAU,EAApC,MAAM,OAAO,GAAG,CAAC;IACS,iBAAiB,EAA3C,iBAAiB;CAC3B;IAsCO;;OAEG;cADQ,KAAK,OAAO,CAAC,EAAE;IAuC1B,gCAAgC;;GAgGvC;0BAhNsB,mBAAmB;2BAClB,YAAY;0BACb,WAAW;4BACmC,YAAY;uCAAZ,YAAY;0BAAZ,YAAY"}
|