@agoric/vow 0.2.0-upgrade-18a-dev-2899fb9.0 → 0.2.0-upgrade-19-dev-0754752.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/vow",
3
- "version": "0.2.0-upgrade-18a-dev-2899fb9.0+2899fb9",
3
+ "version": "0.2.0-upgrade-19-dev-0754752.0+0754752",
4
4
  "description": "Remote (shortening and disconnection-tolerant) Promise-likes",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -13,27 +13,28 @@
13
13
  "postpack": "git clean -f '*.d.ts*' '*.tsbuildinfo'",
14
14
  "test": "ava",
15
15
  "test:xs": "exit 0",
16
+ "test:xs:ci": "npm run test:xs",
16
17
  "lint-fix": "yarn lint:eslint --fix",
17
18
  "lint": "run-s --continue-on-error lint:*",
18
19
  "lint:eslint": "eslint .",
19
20
  "lint:types": "tsc"
20
21
  },
21
22
  "dependencies": {
22
- "@agoric/base-zone": "0.1.1-upgrade-18a-dev-2899fb9.0+2899fb9",
23
- "@agoric/internal": "0.4.0-upgrade-18a-dev-2899fb9.0+2899fb9",
23
+ "@agoric/base-zone": "0.1.1-upgrade-19-dev-0754752.0+0754752",
24
+ "@agoric/internal": "0.4.0-upgrade-19-dev-0754752.0+0754752",
24
25
  "@endo/env-options": "^1.1.8",
25
- "@endo/errors": "^1.2.8",
26
- "@endo/eventual-send": "^1.2.8",
27
- "@endo/pass-style": "^1.4.7",
28
- "@endo/patterns": "^1.4.7",
29
- "@endo/promise-kit": "^1.1.8"
26
+ "@endo/errors": "^1.2.9",
27
+ "@endo/eventual-send": "^1.3.0",
28
+ "@endo/pass-style": "^1.4.8",
29
+ "@endo/patterns": "^1.4.8",
30
+ "@endo/promise-kit": "^1.1.9"
30
31
  },
31
32
  "devDependencies": {
32
- "@agoric/internal": "^0.4.0-u18.0",
33
- "@agoric/swingset-vat": "0.33.0-upgrade-18a-dev-2899fb9.0+2899fb9",
34
- "@agoric/zone": "0.3.0-upgrade-18a-dev-2899fb9.0+2899fb9",
35
- "@endo/far": "^1.1.9",
36
- "@endo/init": "^1.1.7",
33
+ "@agoric/internal": "^0.3.2",
34
+ "@agoric/swingset-vat": "0.33.0-upgrade-19-dev-0754752.0+0754752",
35
+ "@agoric/zone": "0.3.0-upgrade-19-dev-0754752.0+0754752",
36
+ "@endo/far": "^1.1.10",
37
+ "@endo/init": "^1.1.8",
37
38
  "ava": "^5.3.0",
38
39
  "tsd": "^0.31.1"
39
40
  },
@@ -57,5 +58,5 @@
57
58
  "typeCoverage": {
58
59
  "atLeast": 91.62
59
60
  },
60
- "gitHead": "2899fb9f83681eeb3dde7e29bbc9238b20e2f49a"
61
+ "gitHead": "07547522e9d8a06692fa5ff12c35230ddb4b252b"
61
62
  }
@@ -0,0 +1,15 @@
1
+ export function prepareVowRejectionTracker(zone: Zone): import("@endo/exo").Guarded<{
2
+ /**
3
+ * @param {PassableCap} vowCap
4
+ */
5
+ handle(vowCap: PassableCap): void;
6
+ /**
7
+ * @param {PassableCap} vowCap
8
+ * @param {any} reason
9
+ */
10
+ reject(vowCap: PassableCap, reason: any): void;
11
+ }>;
12
+ export type VowRejectionTracker = ReturnType<typeof prepareVowRejectionTracker>;
13
+ import type { Zone } from '@agoric/base-zone';
14
+ import type { PassableCap } from '@endo/pass-style';
15
+ //# sourceMappingURL=rejection-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejection-tracker.d.ts","sourceRoot":"","sources":["rejection-tracker.js"],"names":[],"mappings":"AA4BO,iDADK,IAAI;IA4BV;;OAEG;mBADQ,WAAW;IAetB;;;OAGG;mBAFQ,WAAW,UACX,GAAG;GA8BnB;kCAEa,UAAU,CAAC,OAAO,0BAA0B,CAAC;0BA/FpC,mBAAmB;iCAFZ,kBAAkB"}
@@ -0,0 +1,106 @@
1
+ // @ts-check
2
+ import { X } from '@endo/errors';
3
+ import { makePromiseKit } from '@endo/promise-kit';
4
+ import { M } from '@endo/patterns';
5
+
6
+ import { sink } from './vow-utils.js';
7
+
8
+ /**
9
+ * @import {PassableCap} from '@endo/pass-style';
10
+ * @import {PromiseKit} from '@endo/promise-kit';
11
+ * @import {Zone} from '@agoric/base-zone';
12
+ */
13
+
14
+ /**
15
+ * @param {Promise<void>} [rejected]
16
+ * @param {PromiseKit<void>} [upgradedPK]
17
+ */
18
+ const makeUnhandledRejectionCanceller = (rejected, upgradedPK) => {
19
+ return () => {
20
+ // Handle the rejected promise to silence it.
21
+ rejected?.catch(sink);
22
+ // Resolve the upgraded promise to prevent it from being rejected by a
23
+ // future upgrade.
24
+ upgradedPK?.resolve();
25
+ };
26
+ };
27
+
28
+ /** @param {Zone} zone */
29
+ export const prepareVowRejectionTracker = zone => {
30
+ /** @type {WeakMap<PassableCap, () => void>} */
31
+ const vowToCancelUnhandledRejection = new WeakMap();
32
+
33
+ const upgradeRejectionWatcher = zone.exo(
34
+ 'UpgradeRejectionWatcher',
35
+ M.interface('UpgradeRejectionWatcher', {
36
+ onRejected: M.call(M.raw(), M.raw()).returns(),
37
+ }),
38
+ {
39
+ onRejected(upgradeReason, baseReason) {
40
+ const reason = assert.error(
41
+ X`VOW_REJECTION ${baseReason} not handled before upgrade ${upgradeReason}`,
42
+ );
43
+ // console.warn(reason);
44
+ throw reason;
45
+ },
46
+ },
47
+ );
48
+
49
+ const vowRejectionTracker = zone.exo(
50
+ 'VowRejectionTracker',
51
+ M.interface('VowRejectionTracker', {
52
+ handle: M.call(M.remotable()).returns(),
53
+ reject: M.call(M.remotable(), M.raw()).returns(),
54
+ }),
55
+ {
56
+ /**
57
+ * @param {PassableCap} vowCap
58
+ */
59
+ handle(vowCap) {
60
+ const cancel = vowToCancelUnhandledRejection.get(vowCap);
61
+ if (!cancel) {
62
+ console.warn(
63
+ assert.error(
64
+ X`Now handling a VOW_REJECTION from a prior incarnation for ${vowCap}`,
65
+ ),
66
+ );
67
+ return;
68
+ }
69
+ vowToCancelUnhandledRejection.delete(vowCap);
70
+ cancel();
71
+ },
72
+ /**
73
+ * @param {PassableCap} vowCap
74
+ * @param {any} reason
75
+ */
76
+ reject(vowCap, reason) {
77
+ if (vowToCancelUnhandledRejection.has(vowCap)) {
78
+ return;
79
+ }
80
+
81
+ harden(reason);
82
+ const baseReason = zone.isStorable(reason)
83
+ ? reason
84
+ : assert.error(X`Vow rejection reason was not stored: ${reason}`);
85
+
86
+ // Register a never-resolved native promise with liveslots, so it
87
+ // can reject on upgrade.
88
+ const upgradedPK = makePromiseKit();
89
+ zone.watchPromise(
90
+ upgradedPK.promise,
91
+ upgradeRejectionWatcher,
92
+ baseReason,
93
+ );
94
+
95
+ // Save the cancel function.
96
+ const rejected = Promise.reject(reason);
97
+ const cancel = makeUnhandledRejectionCanceller(rejected, upgradedPK);
98
+ vowToCancelUnhandledRejection.set(vowCap, cancel);
99
+ },
100
+ },
101
+ );
102
+
103
+ return vowRejectionTracker;
104
+ };
105
+
106
+ /** @typedef {ReturnType<typeof prepareVowRejectionTracker>} VowRejectionTracker */
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["tools.js"],"names":[],"mappings":"AAuBO,2CALI,IAAI,WAEZ;IAAmC,iBAAiB;CACpD,GAAU,QAAQ,CAiEpB;0BA7EsB,mBAAmB;uCAE4B,YAAY;8BAAZ,YAAY"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["tools.js"],"names":[],"mappings":"AAwBO,2CALI,IAAI,WAEZ;IAAmC,iBAAiB;CACpD,GAAU,QAAQ,CAkEpB;0BA9EsB,mBAAmB;uCAE4B,YAAY;8BAAZ,YAAY"}
package/src/tools.js CHANGED
@@ -3,6 +3,7 @@ import { makeAsVow } from './vow-utils.js';
3
3
  import { prepareVowKit } from './vow.js';
4
4
  import { prepareWatchUtils } from './watch-utils.js';
5
5
  import { prepareWatch } from './watch.js';
6
+ import { prepareVowRejectionTracker } from './rejection-tracker.js';
6
7
  import { prepareRetryableTools } from './retryable.js';
7
8
  import { makeWhen } from './when.js';
8
9
 
@@ -24,7 +25,8 @@ import { makeWhen } from './when.js';
24
25
  export const prepareBasicVowTools = (zone, powers = {}) => {
25
26
  const { isRetryableReason = /** @type {IsRetryableReason} */ (() => false) } =
26
27
  powers;
27
- const makeVowKit = prepareVowKit(zone);
28
+ const vowRejectionTracker = prepareVowRejectionTracker(zone);
29
+ const makeVowKit = prepareVowKit(zone, vowRejectionTracker);
28
30
  const when = makeWhen(isRetryableReason);
29
31
  const watch = prepareWatch(zone, makeVowKit, isRetryableReason);
30
32
  const makeWatchUtils = prepareWatchUtils(zone, {
package/src/types.d.ts CHANGED
@@ -26,7 +26,7 @@ export type EUnwrap<T> = T extends Vow<infer U> ? EUnwrap<U> : T extends Promise
26
26
  * forward/backward compatibility. Create a new object and bump its version
27
27
  * number instead.
28
28
  */
29
- export type VowV0<T = any> = {
29
+ export type VowPayloadV0<T = any> = {
30
30
  /**
31
31
  * Attempt to unwrap all vows in this
32
32
  * promise chain, returning a promise for the final value. A rejection may
@@ -36,7 +36,7 @@ export type VowV0<T = any> = {
36
36
  shorten: () => Promise<T>;
37
37
  };
38
38
  export type VowPayload<T = any> = {
39
- vowV0: RemotableObject & Remote<VowV0<T>>;
39
+ vowV0: RemotableObject & Remote<VowPayloadV0<T>>;
40
40
  };
41
41
  /**
42
42
  * Vows are objects that represent promises that can be stored durably.
@@ -105,7 +105,7 @@ export type VowTools = {
105
105
  * coerces the result of a function to a Vow. Helpful for scenarios like a
106
106
  * synchronously thrown error.
107
107
  */
108
- asVow: <T extends unknown>(fn: (...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>) => Vow<Awaited<T>>;
108
+ asVow: <T>(fn: (...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>) => Vow<Awaited<T>>;
109
109
  makeVowKit: <T>() => VowKit<T>;
110
110
  retryable: RetryableTool;
111
111
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}
package/src/types.ts CHANGED
@@ -36,7 +36,7 @@ export type EUnwrap<T> =
36
36
  * forward/backward compatibility. Create a new object and bump its version
37
37
  * number instead.
38
38
  */
39
- export type VowV0<T = any> = {
39
+ export type VowPayloadV0<T = any> = {
40
40
  /**
41
41
  * Attempt to unwrap all vows in this
42
42
  * promise chain, returning a promise for the final value. A rejection may
@@ -47,7 +47,7 @@ export type VowV0<T = any> = {
47
47
  };
48
48
 
49
49
  export type VowPayload<T = any> = {
50
- vowV0: RemotableObject & Remote<VowV0<T>>;
50
+ vowV0: RemotableObject & Remote<VowPayloadV0<T>>;
51
51
  };
52
52
 
53
53
  /**
@@ -158,7 +158,7 @@ export type VowTools = {
158
158
  * coerces the result of a function to a Vow. Helpful for scenarios like a
159
159
  * synchronously thrown error.
160
160
  */
161
- asVow: <T extends unknown>(
161
+ asVow: <T>(
162
162
  fn: (...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>,
163
163
  ) => Vow<Awaited<T>>;
164
164
  makeVowKit: <T>() => VowKit<T>;
@@ -1,3 +1,4 @@
1
+ export function sink(): void;
1
2
  export { basicE };
2
3
  export const VowShape: import("@endo/patterns").Matcher;
3
4
  export function isVow(specimen: unknown): specimen is Vow;
@@ -1 +1 @@
1
- {"version":3,"file":"vow-utils.d.ts","sourceRoot":"","sources":["vow-utils.js"],"names":[],"mappings":";AAaA,wDAKE;AAMK,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;4BApG2B,qBAAqB;yBAMH,YAAY;gCAAZ,YAAY;iCAD5B,kBAAkB;gCAEnB,UAAU;gCADO,YAAY"}
1
+ {"version":3,"file":"vow-utils.d.ts","sourceRoot":"","sources":["vow-utils.js"],"names":[],"mappings":"AAWO,6BAAqB;;AAK5B,wDAKE;AAMK,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;4BAvG2B,qBAAqB;yBAMH,YAAY;gCAAZ,YAAY;iCAD5B,kBAAkB;gCAEnB,UAAU;gCADO,YAAY"}
package/src/vow-utils.js CHANGED
@@ -9,6 +9,9 @@ import { M, matches } from '@endo/patterns';
9
9
  * @import {MakeVowKit} from './vow.js';
10
10
  */
11
11
 
12
+ export const sink = () => {};
13
+ harden(sink);
14
+
12
15
  export { basicE };
13
16
 
14
17
  export const VowShape = M.tagged(
package/src/vow.d.ts CHANGED
@@ -1,7 +1,10 @@
1
- export function prepareVowKit(zone: Zone): <T>() => VowKit<T>;
2
- export type VowEphemera = Partial<PromiseKit<any>> & Pick<PromiseKit<any>, "promise">;
1
+ export function prepareVowKit(zone: Zone, vowRejectionTracker?: VowRejectionTracker): <T>() => VowKit<T>;
2
+ export type VowEphemera = Partial<PromiseKit<any>> & Pick<PromiseKit<any>, "promise"> & {
3
+ potentiallyHandled?: boolean;
4
+ };
3
5
  export type MakeVowKit = ReturnType<typeof prepareVowKit>;
4
6
  import type { Zone } from '@agoric/base-zone';
7
+ import type { VowRejectionTracker } from './rejection-tracker.js';
5
8
  import type { VowKit } from './types.js';
6
9
  import type { PromiseKit } from '@endo/promise-kit';
7
10
  //# sourceMappingURL=vow.d.ts.map
package/src/vow.d.ts.map CHANGED
@@ -1 +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,GAChC,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,SAAS,CAAC;yBAiMvB,UAAU,CAAC,OAAO,aAAa,CAAC;0BA3MvB,mBAAmB;4BAEJ,YAAY;gCAHrB,mBAAmB"}
1
+ {"version":3,"file":"vow.d.ts","sourceRoot":"","sources":["vow.js"],"names":[],"mappings":"AA4BO,oCAHI,IAAI,wBACJ,mBAAmB,IAgNf,CAAC,OACD,OAAO,CAAC,CAAC,CASvB;0BAjOY,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,GAChC,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,SAAS,CAAC,GACpC;IAAM,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE;yBAgOvB,UAAU,CAAC,OAAO,aAAa,CAAC;0BAxOvB,mBAAmB;yCAEJ,wBAAwB;4BADxB,YAAY;gCAFrB,mBAAmB"}
package/src/vow.js CHANGED
@@ -6,25 +6,27 @@ import { PromiseWatcherI } from '@agoric/base-zone';
6
6
 
7
7
  const { details: X } = assert;
8
8
 
9
+ const noop = () => {};
10
+ harden(noop);
11
+
9
12
  /**
10
13
  * @import {PromiseKit} from '@endo/promise-kit';
11
14
  * @import {Zone} from '@agoric/base-zone';
12
- * @import {MapStore} from '@agoric/store';
13
15
  * @import {VowResolver, VowKit} from './types.js';
16
+ * @import {VowRejectionTracker} from './rejection-tracker.js';
14
17
  */
15
18
 
16
- const sink = () => {};
17
- harden(sink);
18
-
19
19
  /**
20
20
  * @typedef {Partial<PromiseKit<any>> &
21
- * Pick<PromiseKit<any>, 'promise'>} VowEphemera
21
+ * Pick<PromiseKit<any>, 'promise'> &
22
+ * { potentiallyHandled?: boolean }} VowEphemera
22
23
  */
23
24
 
24
25
  /**
25
26
  * @param {Zone} zone
27
+ * @param {VowRejectionTracker} [vowRejectionTracker]
26
28
  */
27
- export const prepareVowKit = zone => {
29
+ export const prepareVowKit = (zone, vowRejectionTracker) => {
28
30
  /** @type {WeakMap<VowResolver, VowEphemera>} */
29
31
  const resolverToEphemera = new WeakMap();
30
32
 
@@ -32,32 +34,36 @@ export const prepareVowKit = zone => {
32
34
  const resolverToNonStoredValue = new WeakMap();
33
35
 
34
36
  /**
35
- * Get the current incarnation's promise kit associated with a vowV0.
37
+ * Get the ephemera associated with a vowKit.resolver.
36
38
  *
37
39
  * @param {VowResolver} resolver
40
+ * @param {{ potentiallyHandled?: boolean }} [options]
38
41
  */
39
- const provideCurrentKit = resolver => {
40
- let pk = resolverToEphemera.get(resolver);
41
- if (pk) {
42
- return pk;
42
+ const provideEphemera = (resolver, options) => {
43
+ let ephemera = resolverToEphemera.get(resolver);
44
+ if (!ephemera) {
45
+ ephemera = makePromiseKit();
46
+ // Silence this internal promise's rejections, since we use the
47
+ // rejectionTracker instead.
48
+ ephemera.promise.catch(noop);
43
49
  }
44
50
 
45
- pk = makePromiseKit();
46
- pk.promise.catch(sink); // silence unhandled rejection
47
- resolverToEphemera.set(resolver, pk);
48
- return pk;
51
+ ephemera = harden({ ...ephemera, ...options });
52
+ resolverToEphemera.set(resolver, ephemera);
53
+ return ephemera;
49
54
  };
50
55
 
51
56
  /**
52
57
  * @param {VowResolver} resolver
53
58
  */
54
- const getPromiseKitForResolution = resolver => {
55
- const kit = provideCurrentKit(resolver);
56
- if (kit.resolve) {
59
+ const provideEphemeraForResolution = resolver => {
60
+ const ephemera = provideEphemera(resolver);
61
+ if (ephemera.resolve) {
57
62
  // Resolution is a one-time event, so forget the resolve/reject functions.
58
- resolverToEphemera.set(resolver, harden({ promise: kit.promise }));
63
+ const { resolve: _1, reject: _2, ...rest } = ephemera;
64
+ resolverToEphemera.set(resolver, harden(rest));
59
65
  }
60
- return kit;
66
+ return ephemera;
61
67
  };
62
68
 
63
69
  const makeVowInternalsKit = zone.exoClassKit(
@@ -73,16 +79,24 @@ export const prepareVowKit = zone => {
73
79
  watchNextStep: PromiseWatcherI,
74
80
  },
75
81
  () => ({
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
+ /** @type {any} */
83
+ value: undefined,
84
+ /**
85
+ * The stepStatus is null if the promise step hasn't settled yet.
86
+ * @type {null | 'pending' | 'fulfilled' | 'rejected'}
87
+ */
88
+ stepStatus: null,
89
+ isStoredValue: false,
82
90
  /**
83
- * Map for future properties that aren't in the schema.
91
+ * Some versions of the VowInternalsKit will not have this property,
92
+ * (and it cannot be added dynamically).
93
+ * @type {boolean | undefined}
94
+ */
95
+ vowIsHandled: false,
96
+ /**
97
+ * Record for future properties that aren't in the schema.
84
98
  * UNTIL https://github.com/Agoric/agoric-sdk/issues/7407
85
- * @type {MapStore<any, any> | undefined}
99
+ * @type {Record<string, any> | undefined}
86
100
  */
87
101
  extra: undefined,
88
102
  }),
@@ -92,11 +106,14 @@ export const prepareVowKit = zone => {
92
106
  * @returns {Promise<any>}
93
107
  */
94
108
  async shorten() {
95
- const { stepStatus, isStoredValue, value } = this.state;
96
- const { resolver } = this.facets;
109
+ const { stepStatus, isStoredValue, value, vowIsHandled } = this.state;
110
+ const { resolver, vowV0 } = this.facets;
97
111
 
98
112
  switch (stepStatus) {
99
113
  case 'fulfilled': {
114
+ if (vowIsHandled === false) {
115
+ this.state.vowIsHandled = true;
116
+ }
100
117
  if (isStoredValue) {
101
118
  // Always return a stored fulfilled value.
102
119
  return value;
@@ -109,16 +126,21 @@ export const prepareVowKit = zone => {
109
126
  throw value;
110
127
  }
111
128
  case 'rejected': {
112
- if (!isStoredValue && resolverToNonStoredValue.has(resolver)) {
113
- // Non-stored reason is available.
114
- throw resolverToNonStoredValue.get(resolver);
129
+ if (vowIsHandled === false) {
130
+ this.state.vowIsHandled = true;
131
+ vowRejectionTracker?.handle(vowV0);
115
132
  }
116
- // Always throw a stored rejection reason.
117
- throw value;
133
+ const reason = resolverToNonStoredValue.has(resolver)
134
+ ? resolverToNonStoredValue.get(resolver)
135
+ : value;
136
+
137
+ throw reason;
118
138
  }
119
139
  case null:
120
140
  case 'pending':
121
- return provideCurrentKit(this.facets.resolver).promise;
141
+ return provideEphemera(this.facets.resolver, {
142
+ potentiallyHandled: true,
143
+ }).promise;
122
144
  default:
123
145
  throw TypeError(`unexpected stepStatus ${stepStatus}`);
124
146
  }
@@ -129,44 +151,46 @@ export const prepareVowKit = zone => {
129
151
  * @param {any} [value]
130
152
  */
131
153
  resolve(value) {
132
- const { resolver } = this.facets;
133
154
  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
- );
155
+ if (stepStatus !== null) {
156
+ return;
144
157
  }
158
+ this.state.stepStatus = 'pending';
159
+
160
+ const { resolver } = this.facets;
161
+ const { resolve } = provideEphemeraForResolution(resolver);
162
+ resolve && resolve(value);
163
+
164
+ zone.watchPromise(
165
+ HandledPromise.resolve(value),
166
+ this.facets.watchNextStep,
167
+ );
145
168
  },
146
169
  /**
147
170
  * @param {any} [reason]
148
171
  */
149
172
  reject(reason) {
150
- const { resolver, watchNextStep } = this.facets;
151
173
  const { stepStatus } = this.state;
152
- const { reject } = getPromiseKitForResolution(resolver);
153
- if (reject) {
154
- reject(reason);
155
- }
156
- if (stepStatus === null) {
157
- watchNextStep.onRejected(reason);
174
+ if (stepStatus !== null) {
175
+ return;
158
176
  }
177
+ this.state.stepStatus = 'rejected';
178
+
179
+ const { resolver, watchNextStep } = this.facets;
180
+ const { reject } = provideEphemeraForResolution(resolver);
181
+ reject && reject(reason);
182
+ watchNextStep.onRejected(reason);
159
183
  },
160
184
  },
161
185
  watchNextStep: {
162
186
  onFulfilled(value) {
187
+ this.state.stepStatus = 'fulfilled';
188
+
163
189
  const { resolver } = this.facets;
164
- const { resolve } = getPromiseKitForResolution(resolver);
190
+ const { resolve } = provideEphemeraForResolution(resolver);
165
191
  harden(value);
166
- if (resolve) {
167
- resolve(value);
168
- }
169
- this.state.stepStatus = 'fulfilled';
192
+ resolve && resolve(value);
193
+
170
194
  this.state.isStoredValue = zone.isStorable(value);
171
195
  if (this.state.isStoredValue) {
172
196
  this.state.value = value;
@@ -178,13 +202,21 @@ export const prepareVowKit = zone => {
178
202
  }
179
203
  },
180
204
  onRejected(reason) {
181
- const { resolver } = this.facets;
182
- const { reject } = getPromiseKitForResolution(resolver);
205
+ this.state.stepStatus = 'rejected';
206
+
207
+ const { resolver, vowV0 } = this.facets;
208
+ const { reject, potentiallyHandled } =
209
+ provideEphemeraForResolution(resolver);
183
210
  harden(reason);
184
- if (reject) {
185
- reject(reason);
211
+ reject && reject(reason);
212
+
213
+ if (this.state.vowIsHandled === false) {
214
+ if (potentiallyHandled) {
215
+ this.state.vowIsHandled = true;
216
+ } else {
217
+ vowRejectionTracker?.reject(vowV0, reason);
218
+ }
186
219
  }
187
- this.state.stepStatus = 'rejected';
188
220
  this.state.isStoredValue = zone.isStorable(reason);
189
221
  if (this.state.isStoredValue) {
190
222
  this.state.value = reason;
package/src/watch.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- export function prepareWatch(zone: Zone, makeVowKit: () => VowKit<any>, isRetryableReason?: (reason: any, lastValue: any) => any): <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: EVow<T>, watcher?: Watcher<T, TResult1, TResult2, C>, ...watcherArgs: C) => Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
1
+ export function prepareWatch(zone: Zone, makeVowKit: () => VowKit<any>, isRetryableReason?: (reason: any, lastValue: any) => any): <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: EVow<T>, watcher?: Watcher<T, TResult1, TResult2, C>, ...watcherArgs: C) => import("./types.js").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
2
2
  export type Watch = ReturnType<typeof prepareWatch>;
3
3
  import type { Zone } from '@agoric/base-zone';
4
4
  import type { VowKit } from './types.js';
5
5
  import type { EVow } from './types.js';
6
6
  import type { Watcher } from './types.js';
7
- import type { Vow } from './types.js';
8
7
  //# sourceMappingURL=watch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["watch.js"],"names":[],"mappings":"AA2JO,mCAJI,IAAI,cACJ,MAAM,OAAO,GAAG,CAAC,sBACjB,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,KAAK,GAAG,IAe/B,CAAC,QACD,QAAQ,MACR,QAAQ,UACA,CAAC,SAAT,GAAG,EAAG,qBACT,KAAK,CAAC,CAAC,YACP,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,kBACjC,CAAC,yIAoBb;oBAIa,UAAU,CAAC,OAAO,YAAY,CAAC;0BA/LJ,mBAAmB;4BACyB,YAAY;0BAAZ,YAAY;6BAAZ,YAAY;yBAAZ,YAAY"}
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["watch.js"],"names":[],"mappings":"AA4KO,mCAJI,IAAI,cACJ,MAAM,OAAO,GAAG,CAAC,sBACjB,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,KAAK,GAAG,IAe/B,CAAC,QACD,QAAQ,MACR,QAAQ,UACA,CAAC,SAAT,GAAG,EAAG,qBACT,KAAK,CAAC,CAAC,YACP,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,kBACjC,CAAC,8JAqBb;oBAIa,UAAU,CAAC,OAAO,YAAY,CAAC;0BAjNJ,mBAAmB;4BACc,YAAY;0BAAZ,YAAY;6BAAZ,YAAY"}
package/src/watch.js CHANGED
@@ -6,7 +6,7 @@ const { apply } = Reflect;
6
6
 
7
7
  /**
8
8
  * @import { PromiseWatcher, Zone } from '@agoric/base-zone';
9
- * @import { ERef, EVow, IsRetryableReason, Vow, VowKit, VowResolver, Watcher } from './types.js';
9
+ * @import { EVow, IsRetryableReason, VowKit, VowResolver, Watcher } from './types.js';
10
10
  */
11
11
 
12
12
  /**
@@ -40,7 +40,8 @@ const makeWatchNextStep =
40
40
  * @param {unknown} value
41
41
  * @param {unknown[]} [watcherArgs]
42
42
  */
43
- const settle = (resolver, watcher, wcb, value, watcherArgs = []) => {
43
+ const settle = async (resolver, watcher, wcb, value, watcherArgs = []) => {
44
+ await null;
44
45
  try {
45
46
  let chainedValue = value;
46
47
  const w = watcher && watcher[wcb];
@@ -49,14 +50,23 @@ const settle = (resolver, watcher, wcb, value, watcherArgs = []) => {
49
50
  } else if (wcb === 'onRejected') {
50
51
  throw value;
51
52
  }
52
- resolver && resolver.resolve(chainedValue);
53
+
54
+ if (resolver) {
55
+ resolver.resolve(chainedValue);
56
+ return;
57
+ }
58
+
59
+ // We want to propagate rejections (but not fulfillment values) to our
60
+ // caller if no resolver was provided.
61
+ await chainedValue;
53
62
  } catch (e) {
54
63
  if (resolver) {
55
64
  resolver.reject(e);
56
- } else {
57
- // for host's unhandled rejection handler to catch
58
- throw e;
65
+ return;
59
66
  }
67
+
68
+ // Create a native unhandled rejection.
69
+ throw e;
60
70
  }
61
71
  };
62
72
 
@@ -106,6 +116,9 @@ const preparePromiseWatcher = (zone, isRetryableReason, watchNextStep) => {
106
116
  /** @type {Required<PromiseWatcher>['onFulfilled']} */
107
117
  onFulfilled(value) {
108
118
  const { watcher, watcherArgs, resolver } = this.state;
119
+ if (!resolver) {
120
+ throw Error('Unexpected multiple calls to PromiseWatcher');
121
+ }
109
122
  const payload = getVowPayload(value);
110
123
  if (payload) {
111
124
  const seenPayloads = getSeenPayloads(this.self);
@@ -123,26 +136,30 @@ const preparePromiseWatcher = (zone, isRetryableReason, watchNextStep) => {
123
136
  this.state.priorRetryValue = undefined;
124
137
  this.state.watcher = undefined;
125
138
  this.state.resolver = undefined;
126
- settle(resolver, watcher, 'onFulfilled', value, watcherArgs);
139
+ void settle(resolver, watcher, 'onFulfilled', value, watcherArgs);
127
140
  },
128
141
  /** @type {Required<PromiseWatcher>['onRejected']} */
129
142
  onRejected(reason) {
130
143
  const { vow, watcher, watcherArgs, resolver, priorRetryValue } =
131
144
  this.state;
132
- if (vow) {
133
- const retryValue = isRetryableReason(reason, priorRetryValue);
134
- if (retryValue) {
145
+ if (!resolver) {
146
+ throw Error('Unexpected multiple calls to PromiseWatcher');
147
+ }
148
+ const retryValue = isRetryableReason(reason, priorRetryValue);
149
+ if (retryValue) {
150
+ this.state.priorRetryValue = retryValue;
151
+ if (vow) {
135
152
  // Retry the same specimen.
136
- this.state.priorRetryValue = retryValue;
137
153
  watchNextStep(vow, this.self);
138
154
  return;
139
155
  }
140
156
  }
157
+ // Final rejection.
141
158
  watcherSeenPayloads.delete(this.self);
142
159
  this.state.priorRetryValue = undefined;
143
160
  this.state.resolver = undefined;
144
161
  this.state.watcher = undefined;
145
- settle(resolver, watcher, 'onRejected', reason, watcherArgs);
162
+ void settle(resolver, watcher, 'onRejected', reason, watcherArgs);
146
163
  },
147
164
  },
148
165
  );
@@ -185,7 +202,8 @@ export const prepareWatch = (
185
202
  const promiseWatcher = makePromiseWatcher(resolver, watcher, watcherArgs);
186
203
 
187
204
  // Coerce the specimen to a promise, and start the watcher cycle.
188
- zone.watchPromise(basicE.resolve(specimenP), promiseWatcher);
205
+ const promise = basicE.resolve(specimenP);
206
+ zone.watchPromise(promise, promiseWatcher);
189
207
 
190
208
  return vow;
191
209
  };