@agoric/internal 0.3.3-dev-9b124b9.0.9b124b9 → 0.3.3-dev-c7e390e.0.c7e390e

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/internal",
3
- "version": "0.3.3-dev-9b124b9.0.9b124b9",
3
+ "version": "0.3.3-dev-c7e390e.0.c7e390e",
4
4
  "description": "Externally unsupported utilities internal to agoric-sdk",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -20,7 +20,7 @@
20
20
  "lint:types": "yarn run -T tsc"
21
21
  },
22
22
  "dependencies": {
23
- "@agoric/base-zone": "0.1.1-dev-9b124b9.0.9b124b9",
23
+ "@agoric/base-zone": "0.1.1-dev-c7e390e.0.c7e390e",
24
24
  "@endo/cache-map": "^1.1.0",
25
25
  "@endo/common": "^1.2.13",
26
26
  "@endo/compartment-mapper": "^1.6.3",
@@ -38,7 +38,7 @@
38
38
  "jessie.js": "^0.3.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@agoric/cosmic-proto": "0.4.1-dev-9b124b9.0.9b124b9",
41
+ "@agoric/cosmic-proto": "0.4.1-dev-c7e390e.0.c7e390e",
42
42
  "@endo/exo": "^1.5.12",
43
43
  "@endo/init": "^1.1.12",
44
44
  "@endo/ses-ava": "^1.3.2",
@@ -66,5 +66,5 @@
66
66
  "typeCoverage": {
67
67
  "atLeast": 92.89
68
68
  },
69
- "gitHead": "9b124b955c547718ecacf77e88a60c115a2fd8f7"
69
+ "gitHead": "c7e390e688fc2c97956ed6716b85f9a4c518b1e6"
70
70
  }
@@ -3,6 +3,13 @@
3
3
  */
4
4
  export const AVA_EXPECT_UNHANDLED_REJECTIONS: "AGORIC_AVA_EXPECT_UNHANDLED_REJECTIONS";
5
5
  export const SUBTEST_PREFIX: "(unhandled rejection subprocess): ";
6
+ export function countUnhandled(work: () => any | Promise<any>, { gcAndFinalize }: {
7
+ gcAndFinalize: () => Promise<void>;
8
+ }): Promise<{
9
+ unhandled: number;
10
+ pending: number;
11
+ seenUnhandled: number;
12
+ }>;
6
13
  export function makeExpectUnhandledRejection<C>({ test, importMetaUrl }: {
7
14
  test: TestFn<C>;
8
15
  importMetaUrl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ava-unhandled-rejection.d.ts","sourceRoot":"","sources":["ava-unhandled-rejection.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH,8CACE,wCAAwC,CAAC;AAE3C,6BAA8B,oCAAoC,CAAC;AAW5D,6CARM,CAAC,2BAEX;IAA0B,IAAI,EAAtB,OAAO,CAAC,CAAC;IACM,aAAa,EAA5B,MAAM;CACd,GAAU,CACR,iBAAiB,EAAE,MAAM,KACtB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CA0CtE;4BAzDiD,KAAK;sCAAL,KAAK;2BAAL,KAAK"}
1
+ {"version":3,"file":"ava-unhandled-rejection.d.ts","sourceRoot":"","sources":["ava-unhandled-rejection.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH,8CACE,wCAAwC,CAAC;AAE3C,6BAA8B,oCAAoC,CAAC;AA2E5D,qCAJI,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qBAEhC;IAAoC,aAAa,EAAzC,MAAM,OAAO,CAAC,IAAI,CAAC;CAC7B;;;;GA4BA;AAWM,6CARM,CAAC,2BAEX;IAA0B,IAAI,EAAtB,OAAO,CAAC,CAAC;IACM,aAAa,EAA5B,MAAM;CACd,GAAU,CACR,iBAAiB,EAAE,MAAM,KACtB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAqDtE;4BA1KiD,KAAK;sCAAL,KAAK;2BAAL,KAAK"}
@@ -14,6 +14,108 @@ export const AVA_EXPECT_UNHANDLED_REJECTIONS =
14
14
 
15
15
  export const SUBTEST_PREFIX = '(unhandled rejection subprocess): ';
16
16
 
17
+ const delayTurn = () => new Promise(resolve => setImmediate(resolve));
18
+ const settleUnhandled = async () => {
19
+ await delayTurn();
20
+ await delayTurn();
21
+ };
22
+
23
+ const stripListeners = event => {
24
+ const listeners = process.listeners(event);
25
+ for (const listener of listeners) {
26
+ process.off(event, listener);
27
+ }
28
+ return () => {
29
+ for (const listener of listeners) {
30
+ process.on(event, listener);
31
+ }
32
+ };
33
+ };
34
+
35
+ const makeUnhandledTracker = () => {
36
+ let unhandled = 0;
37
+ let seenUnhandled = 0;
38
+ const pending = new Set();
39
+ const handledLate = new Set();
40
+ const tokenByPromise = new WeakMap();
41
+ // Finalization callbacks run on the main thread; `pending` is only mutated
42
+ // here and after the flushes in countUnhandled, so no extra synchronization
43
+ // is required.
44
+ const registry = new FinalizationRegistry(token => {
45
+ if (pending.delete(token)) {
46
+ // Don't count promises that were handled late.
47
+ if (!handledLate.delete(token)) {
48
+ unhandled += 1;
49
+ }
50
+ }
51
+ });
52
+
53
+ const onUnhandled = (_reason, promise) => {
54
+ seenUnhandled += 1;
55
+ const token = Symbol('unhandledRejection');
56
+ tokenByPromise.set(promise, token);
57
+ pending.add(token);
58
+ registry.register(promise, token, token);
59
+ };
60
+
61
+ const onHandledLate = promise => {
62
+ const token = tokenByPromise.get(promise);
63
+ tokenByPromise.delete(promise);
64
+ // Mark this token as handled late so it won't be counted when the
65
+ // finalizer runs. We remove it from `pending` to exclude it from
66
+ // the pending count, and track it in `handledLate` to avoid counting
67
+ // it when GC'd.
68
+ if (token && pending.delete(token)) {
69
+ handledLate.add(token);
70
+ }
71
+ };
72
+
73
+ const snapshot = () => ({ unhandled, pending: pending.size, seenUnhandled });
74
+
75
+ return {
76
+ onUnhandled,
77
+ onHandledLate,
78
+ snapshot,
79
+ };
80
+ };
81
+
82
+ /**
83
+ * Count unhandled rejections for the given work by running it after removing
84
+ * any existing listeners (like AVA's) and waiting for GC/finalization.
85
+ *
86
+ * @param {() => any | Promise<any>} work
87
+ * @param {object} powers
88
+ * @param {() => Promise<void>} powers.gcAndFinalize
89
+ */
90
+ export const countUnhandled = async (work, { gcAndFinalize }) => {
91
+ await null; // for Jessie
92
+ const tracker = makeUnhandledTracker();
93
+ const restoreUnhandled = stripListeners('unhandledRejection');
94
+ const restoreHandled = stripListeners('rejectionHandled');
95
+ const flushUnhandled = async () => {
96
+ await settleUnhandled();
97
+ await gcAndFinalize();
98
+ };
99
+ process.on('unhandledRejection', tracker.onUnhandled);
100
+ process.on('rejectionHandled', tracker.onHandledLate);
101
+ try {
102
+ await work();
103
+ } finally {
104
+ // Two passes through settle+GC help ensure finalizers run before we snapshot
105
+ // the unhandled state across Node/XS runtimes, even when callbacks queue
106
+ // additional macrotasks. This count happens after the flushes so finalizer
107
+ // timing cannot race the snapshot.
108
+ await flushUnhandled();
109
+ await flushUnhandled();
110
+ await settleUnhandled();
111
+ process.off('unhandledRejection', tracker.onUnhandled);
112
+ process.off('rejectionHandled', tracker.onHandledLate);
113
+ restoreUnhandled();
114
+ restoreHandled();
115
+ }
116
+ return tracker.snapshot();
117
+ };
118
+
17
119
  /**
18
120
  * @template C
19
121
  * @param {object} powers
@@ -28,16 +130,27 @@ export const makeExpectUnhandledRejection = ({ test, importMetaUrl }) => {
28
130
  const gcAndFinalize = makeGcAndFinalize(engineGC);
29
131
 
30
132
  if (process.env[AVA_EXPECT_UNHANDLED_REJECTIONS]) {
31
- return _expectedUnhandled =>
133
+ return expectedUnhandled =>
32
134
  test.macro({
33
135
  title: (_, name, _impl) => SUBTEST_PREFIX + name,
34
136
  exec: async (t, _name, impl) => {
35
- await null;
36
- try {
37
- const result = await impl(t);
38
- return result;
39
- } finally {
40
- await gcAndFinalize();
137
+ const rawExpected =
138
+ process.env[AVA_EXPECT_UNHANDLED_REJECTIONS] ?? expectedUnhandled;
139
+ const expected = Number(rawExpected);
140
+ if (!Number.isSafeInteger(expected) || expected < 0) {
141
+ t.fail(
142
+ `expected unhandled rejection count to be a natural number, got ${rawExpected}`,
143
+ );
144
+ }
145
+ const { unhandled, pending, seenUnhandled } = await countUnhandled(
146
+ () => impl(t),
147
+ { gcAndFinalize },
148
+ );
149
+ const totalUnhandled = unhandled + pending;
150
+ if (totalUnhandled !== expected) {
151
+ t.fail(
152
+ `expected ${expected} unhandled promise rejections, got ${totalUnhandled} (of ${seenUnhandled} seen, ${pending} pending finalization)`,
153
+ );
41
154
  }
42
155
  },
43
156
  });
package/src/types.d.ts CHANGED
@@ -2,6 +2,19 @@ import type { ERef, RemotableBrand } from '@endo/eventual-send';
2
2
  import type { Primitive, RemotableObject } from '@endo/pass-style';
3
3
  import type { Pattern } from '@endo/patterns';
4
4
  import type { Callable } from './ses-utils.js';
5
+ /**
6
+ * A mapping of a tuple type (as from `Parameters<...>`) into a corresponding
7
+ * object type with named fields.
8
+ *
9
+ * @example
10
+ * ```
11
+ * RecordFromTuple<[string, bigint], ['denom', 'amount']>
12
+ * //=> { denom: string, amount: bigint }
13
+ * ```
14
+ */
15
+ export type RecordFromTuple<Types extends readonly unknown[], Names extends Record<Exclude<keyof Types, keyof unknown[]>, string>> = {
16
+ [K in Exclude<keyof Types, keyof any[]> as Names[K]]: Types[K];
17
+ };
5
18
  /**
6
19
  * A map corresponding with a total function such that `get(key)` is assumed to
7
20
  * always succeed.
@@ -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":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,KAAK,EAA8B,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,MAAM,eAAe,CACzB,KAAK,SAAS,SAAS,OAAO,EAAE,EAChC,KAAK,SAAS,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,EAAE,MAAM,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,IACjE;KAAG,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;CAAE,CAAC;AAEvE;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG;IACpD,6EAA6E;IAC7E,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;CACpB,CAAC;AACF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAC9C,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,IAChB,IAAI,GACJ,MAAM,GACN,OAAO,CAAC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;CAAE,CAAC,CAAC;AAEzE,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAC7D;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAC7B,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACvB,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GACtB,KAAK,GACP,KAAK;CACV,GACD,CAAC,CAAC;AAEN,MAAM,CAAC,OAAO,OAAO,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG;IAC7D,OAAO,CAAC,KAAK,CAAI;IAEV,MAAM,EAAE,GAAG,CAAC;IAEZ,UAAU,CAAC,EAAE,WAAW,CAAC;IAEzB,KAAK,EAAE,OAAO,EAAE,CAAC;IAEjB,MAAM,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,OAAO,YAAY,CAC/B,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,GAAG,CACrC,SAAQ,QAAQ,CAAC,CAAC,CAAC;IACnB,OAAO,CAAC,SAAS,CAAI;IAEd,MAAM,EAAE,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAGpE,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,eAAe,GAClD,IAAI,GACJ,CAAC,SAAS,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,GAChC,IAAI,GACJ,KAAK,CAAC;AAEZ,2DAA2D;AAC3D,MAAM,MAAM,QAAQ,CAAC,CAAC,IACpB,WAAW,CAAC,CAAC,CAAC,SAAS,IAAI,GACvB,CAAC,GACD,CAAC,SAAS,QAAQ,GAChB,KAAK,GACL;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,GAAG,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,MAAM,CAAC,OAAO,EAAE,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,IACjD,OAAO,GACP,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAGnC;;;GAGG;AACH,MAAM,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAC5D,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CACvB,CAAC;AAwBF,OAAO,CAAC,MAAM,aAAa,EAAE,uBAAuB,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,OAAO,GAAG;IAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEhE,MAAM,CAAC,OAAO,MAAM,WAAW,CAAC,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,IAC1D,EAAE,SAAS,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAG/C;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,OAAO,EAChD,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,CAAC,EACV,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,KACpB,OAAO,CAAC,QAAQ,IAAI,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAEhF,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/src/types.ts CHANGED
@@ -5,6 +5,21 @@ import type { Primitive, RemotableObject } from '@endo/pass-style';
5
5
  import type { mustMatch as endoMustMatch, Pattern } from '@endo/patterns';
6
6
  import type { Callable } from './ses-utils.js';
7
7
 
8
+ /**
9
+ * A mapping of a tuple type (as from `Parameters<...>`) into a corresponding
10
+ * object type with named fields.
11
+ *
12
+ * @example
13
+ * ```
14
+ * RecordFromTuple<[string, bigint], ['denom', 'amount']>
15
+ * //=> { denom: string, amount: bigint }
16
+ * ```
17
+ */
18
+ export type RecordFromTuple<
19
+ Types extends readonly unknown[],
20
+ Names extends Record<Exclude<keyof Types, keyof unknown[]>, string>,
21
+ > = { [K in Exclude<keyof Types, keyof any[]> as Names[K]]: Types[K] };
22
+
8
23
  /**
9
24
  * A map corresponding with a total function such that `get(key)` is assumed to
10
25
  * always succeed.