@agoric/network 0.2.0-u16.1 → 0.2.0-u17.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 +3 -10
- package/package.json +17 -17
- package/src/bytes.d.ts.map +1 -1
- package/src/bytes.js +3 -6
- package/src/network.d.ts +55 -43
- package/src/network.d.ts.map +1 -1
- package/src/network.js +165 -82
- package/src/router.d.ts +8 -18
- package/src/router.d.ts.map +1 -1
- package/src/router.js +4 -4
- package/src/shapes.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,15 +3,7 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
##
|
|
7
|
-
|
|
8
|
-
**Note:** Version bump only for package @agoric/network
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## 0.2.0-u16.0 (2024-07-02)
|
|
6
|
+
## 0.2.0-u17.0 (2024-09-17)
|
|
15
7
|
|
|
16
8
|
|
|
17
9
|
### ⚠ BREAKING CHANGES
|
|
@@ -32,6 +24,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
|
|
32
24
|
* **network:** Connection should have negotiated remoteAddress and localAddress ([2184ea3](https://github.com/Agoric/agoric-sdk/commit/2184ea3d655c1334653e27d163a09ceb5f61fd50)), closes [#9064](https://github.com/Agoric/agoric-sdk/issues/9064)
|
|
33
25
|
* **network:** create and use `coerceToData` ([39beecb](https://github.com/Agoric/agoric-sdk/commit/39beecba84ef6dfafca902a28a651dbba77cdb1e))
|
|
34
26
|
* **network:** improve naming and data coercion ([8bcd9e2](https://github.com/Agoric/agoric-sdk/commit/8bcd9e2100f4973fd788a6edf42c144d916c173d))
|
|
35
|
-
* **network:**
|
|
27
|
+
* **network:** introduce `Finalizer` to close network ([54b9b00](https://github.com/Agoric/agoric-sdk/commit/54b9b009fff3fd3ab54f731adee97195acaa238f))
|
|
28
|
+
* **network:** use new `ERef` and `FarRef` ([3027adf](https://github.com/Agoric/agoric-sdk/commit/3027adf8613154dec167c5fccf5f207f6d2af701))
|
|
36
29
|
* **network:** use vow types, correct revealed problems ([d1c1240](https://github.com/Agoric/agoric-sdk/commit/d1c1240bcf534a316533d4c203f45f01fdfc825d))
|
|
37
30
|
* **vats:** `vtransfer` code cleanup ([8ac8197](https://github.com/Agoric/agoric-sdk/commit/8ac819709ef9ced0badee25e6715a5847b1e3f4c))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/network",
|
|
3
|
-
"version": "0.2.0-
|
|
3
|
+
"version": "0.2.0-u17.0",
|
|
4
4
|
"description": "Agoric's network protocol API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -21,22 +21,22 @@
|
|
|
21
21
|
"author": "Agoric",
|
|
22
22
|
"license": "Apache-2.0",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@agoric/
|
|
25
|
-
"@agoric/
|
|
26
|
-
"@agoric/
|
|
27
|
-
"@
|
|
28
|
-
"@endo/
|
|
29
|
-
"@endo/far": "^1.1.
|
|
30
|
-
"@endo/pass-style": "^1.4.
|
|
31
|
-
"@endo/patterns": "^1.4.
|
|
32
|
-
"@endo/promise-kit": "^1.1.
|
|
24
|
+
"@agoric/internal": "^0.4.0-u17.0",
|
|
25
|
+
"@agoric/store": "^0.9.3-u17.0",
|
|
26
|
+
"@agoric/vat-data": "^0.5.3-u17.0",
|
|
27
|
+
"@endo/base64": "^1.0.7",
|
|
28
|
+
"@endo/errors": "^1.2.5",
|
|
29
|
+
"@endo/far": "^1.1.5",
|
|
30
|
+
"@endo/pass-style": "^1.4.3",
|
|
31
|
+
"@endo/patterns": "^1.4.3",
|
|
32
|
+
"@endo/promise-kit": "^1.1.5"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@agoric/swingset-liveslots": "^0.10.3-
|
|
36
|
-
"@agoric/swingset-vat": "^0.33.0-
|
|
37
|
-
"@agoric/vow": "^0.2.0-
|
|
38
|
-
"@agoric/zone": "^0.3.0-
|
|
39
|
-
"@endo/bundle-source": "^3.
|
|
35
|
+
"@agoric/swingset-liveslots": "^0.10.3-u17.0",
|
|
36
|
+
"@agoric/swingset-vat": "^0.33.0-u17.0",
|
|
37
|
+
"@agoric/vow": "^0.2.0-u17.0",
|
|
38
|
+
"@agoric/zone": "^0.3.0-u17.0",
|
|
39
|
+
"@endo/bundle-source": "^3.4.0",
|
|
40
40
|
"ava": "^5.3.0",
|
|
41
41
|
"c8": "^9.1.0"
|
|
42
42
|
},
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"workerThreads": false
|
|
67
67
|
},
|
|
68
68
|
"typeCoverage": {
|
|
69
|
-
"atLeast":
|
|
69
|
+
"atLeast": 91.15
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "515c4c0efccfc91b97da30037c10fc4b076851e2"
|
|
72
72
|
}
|
package/src/bytes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["bytes.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH,2EAA2E;AAE3E;;;;;;;GAOG;AACH,6CAHW,OAAO,GACL,UAAU,
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["bytes.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH,2EAA2E;AAE3E;;;;;;;GAOG;AACH,6CAHW,OAAO,GACL,UAAU,CAgBtB;AAuBD;;;;;;GAMG;AACH,oCAHW,UAAU,GACR,KAAK,CAOjB;AAED;;;;;GAKG;AACH,qCAHW,KAAK,GACH,MAAM,CAIlB;AAED;;;;;GAKG;AACH,+CAHW,UAAU,GACR,MAAM,CAKlB;AAED;;;;;GAKG;AACH,sCAHW,MAAM,GACJ,KAAK,CAIjB;yBA1Fa,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;2BAHpC,YAAY;sCAAZ,YAAY"}
|
package/src/bytes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
import {
|
|
2
|
+
import { X, Fail } from '@endo/errors';
|
|
3
3
|
import { encodeBase64, decodeBase64 } from '@endo/base64';
|
|
4
4
|
import { isObject } from '@endo/pass-style';
|
|
5
5
|
|
|
@@ -23,14 +23,11 @@ export function coerceToByteSource(specimen) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
isObject(specimen) ||
|
|
26
|
-
assert.fail(
|
|
26
|
+
assert.fail(X`non-object ${specimen} is not a ByteSource`, TypeError);
|
|
27
27
|
|
|
28
28
|
const obj = /** @type {{}} */ (specimen);
|
|
29
29
|
typeof obj[Symbol.iterator] === 'function' ||
|
|
30
|
-
assert.fail(
|
|
31
|
-
details`non-iterable ${specimen} is not a ByteSource`,
|
|
32
|
-
TypeError,
|
|
33
|
-
);
|
|
30
|
+
assert.fail(X`non-iterable ${specimen} is not a ByteSource`, TypeError);
|
|
34
31
|
|
|
35
32
|
// Good enough... it's iterable and can be converted later.
|
|
36
33
|
return /** @type {ByteSource} */ (specimen);
|
package/src/network.d.ts
CHANGED
|
@@ -9,18 +9,9 @@ export function getPrefixes(addr: string): string[];
|
|
|
9
9
|
* Create a protocol handler that just connects to itself.
|
|
10
10
|
*
|
|
11
11
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
12
|
-
* @param {
|
|
12
|
+
* @param {VowTools} powers
|
|
13
13
|
*/
|
|
14
|
-
export function prepareLoopbackProtocolHandler(zone: import("@agoric/base-zone").Zone, { watch, allVows }:
|
|
15
|
-
isRetryableReason?: import("@agoric/vow").IsRetryableReason | undefined;
|
|
16
|
-
} | undefined) => {
|
|
17
|
-
when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
18
|
-
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: import("@agoric/vow").EVow<T>, watcher?: import("@agoric/vow").Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => import("@agoric/vow").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
19
|
-
makeVowKit: <T>() => import("@agoric/vow").VowKit<T>;
|
|
20
|
-
allVows: (maybeVows: import("@agoric/vow").EVow<unknown>[]) => import("@agoric/vow").Vow<any[]>;
|
|
21
|
-
asVow: <T extends unknown>(fn: (...args: any[]) => import("@agoric/vow").Vow<Awaited<T>> | Awaited<T>) => import("@agoric/vow").Vow<Awaited<T>>;
|
|
22
|
-
asPromise: import("@agoric/vow").AsPromiseFunction;
|
|
23
|
-
}>): (instancePrefix?: string | undefined) => import("@endo/exo").Guarded<{
|
|
14
|
+
export function prepareLoopbackProtocolHandler(zone: import("@agoric/base-zone").Zone, { watch, allVows }: VowTools): (instancePrefix?: string | undefined) => import("@endo/exo").Guarded<{
|
|
24
15
|
onCreate(_impl: any, _protocolHandler: any): Promise<void>;
|
|
25
16
|
generatePortID(_localAddr: any, _protocolHandler: any): Promise<string>;
|
|
26
17
|
onBind(_port: any, _localAddr: any, _protocolHandler: any): Promise<void>;
|
|
@@ -34,34 +25,23 @@ export function prepareLoopbackProtocolHandler(zone: import("@agoric/base-zone")
|
|
|
34
25
|
onInstantiate(_port: any, _localAddr: any, _remote: any, _protocol: any): Promise<string>;
|
|
35
26
|
onListen(port: any, localAddr: any, listenHandler: any, _protocolHandler: any): Promise<void>;
|
|
36
27
|
/**
|
|
37
|
-
* @param {
|
|
28
|
+
* @param {Remote<Port>} port
|
|
38
29
|
* @param {Endpoint} localAddr
|
|
39
|
-
* @param {
|
|
30
|
+
* @param {Remote<ListenHandler>} listenHandler
|
|
40
31
|
* @param {*} _protocolHandler
|
|
41
32
|
*/
|
|
42
|
-
onListenRemove(port:
|
|
33
|
+
onListenRemove(port: Remote<Port>, localAddr: Endpoint, listenHandler: Remote<ListenHandler>, _protocolHandler: any): Promise<void>;
|
|
43
34
|
onRevoke(_port: any, _localAddr: any, _protocolHandler: any): Promise<void>;
|
|
44
35
|
}>;
|
|
45
|
-
/**
|
|
46
|
-
* @import {AttemptDescription, Bytes, Closable, CloseReason, Connection, ConnectionHandler, Endpoint, ListenHandler, Port, Protocol, ProtocolHandler, ProtocolImpl} from './types.js';
|
|
47
|
-
*/
|
|
48
36
|
/**
|
|
49
37
|
* Compatibility note: this must match what our peers use, so don't change it
|
|
50
38
|
* casually.
|
|
51
39
|
*/
|
|
52
40
|
export const ENDPOINT_SEPARATOR: "/";
|
|
41
|
+
export const CLOSE_REASON_FINALIZER: "closed-by-finalizer";
|
|
53
42
|
export function rethrowUnlessMissing(err: unknown): undefined;
|
|
54
|
-
export function crossoverConnection(zone: import("@agoric/zone").Zone, handler0:
|
|
55
|
-
export function prepareNetworkProtocol(zone: import("@agoric/base-zone").Zone, powers:
|
|
56
|
-
isRetryableReason?: import("@agoric/vow").IsRetryableReason | undefined;
|
|
57
|
-
} | undefined) => {
|
|
58
|
-
when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
59
|
-
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: import("@agoric/vow").EVow<T>, watcher?: import("@agoric/vow").Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => import("@agoric/vow").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
60
|
-
makeVowKit: <T>() => import("@agoric/vow").VowKit<T>;
|
|
61
|
-
allVows: (maybeVows: import("@agoric/vow").EVow<unknown>[]) => import("@agoric/vow").Vow<any[]>;
|
|
62
|
-
asVow: <T extends unknown>(fn: (...args: any[]) => import("@agoric/vow").Vow<Awaited<T>> | Awaited<T>) => import("@agoric/vow").Vow<Awaited<T>>;
|
|
63
|
-
asPromise: import("@agoric/vow").AsPromiseFunction;
|
|
64
|
-
}>): (protocolHandler: import("@agoric/vow").Remote<ProtocolHandler>) => Protocol;
|
|
43
|
+
export function crossoverConnection(zone: import("@agoric/zone").Zone, handler0: Remote<Required<ConnectionHandler>>, addr0: Endpoint, handler1: Remote<Required<ConnectionHandler>>, addr1: Endpoint, makeConnection: (opts: ConnectionOpts) => Connection, finalizer: Finalizer, current?: globalThis.WeakSetStore<Closable> | undefined): Connection[];
|
|
44
|
+
export function prepareNetworkProtocol(zone: import("@agoric/base-zone").Zone, powers: Powers): (protocolHandler: Remote<ProtocolHandler>) => Protocol;
|
|
65
45
|
export function prepareEchoConnectionKit(zone: import("@agoric/base-zone").Zone): () => import("@endo/exo").GuardedKit<{
|
|
66
46
|
handler: {
|
|
67
47
|
/**
|
|
@@ -72,10 +52,10 @@ export function prepareEchoConnectionKit(zone: import("@agoric/base-zone").Zone)
|
|
|
72
52
|
onReceive(_connection: Connection, bytes: Bytes, _connectionHandler: ConnectionHandler): Promise<string>;
|
|
73
53
|
/**
|
|
74
54
|
* @param {Connection} _connection
|
|
75
|
-
* @param {CloseReason} [
|
|
55
|
+
* @param {CloseReason} [reason]
|
|
76
56
|
* @param {ConnectionHandler} [_connectionHandler]
|
|
77
57
|
*/
|
|
78
|
-
onClose(_connection: Connection,
|
|
58
|
+
onClose(_connection: Connection, reason?: CloseReason, _connectionHandler?: ConnectionHandler | undefined): Promise<void>;
|
|
79
59
|
};
|
|
80
60
|
listener: {
|
|
81
61
|
onAccept(_port: any, _localAddr: any, _remoteAddr: any, _listenHandler: any): Promise<import("@endo/exo").Guarded<{
|
|
@@ -87,24 +67,15 @@ export function prepareEchoConnectionKit(zone: import("@agoric/base-zone").Zone)
|
|
|
87
67
|
onReceive(_connection: Connection, bytes: Bytes, _connectionHandler: ConnectionHandler): Promise<string>;
|
|
88
68
|
/**
|
|
89
69
|
* @param {Connection} _connection
|
|
90
|
-
* @param {CloseReason} [
|
|
70
|
+
* @param {CloseReason} [reason]
|
|
91
71
|
* @param {ConnectionHandler} [_connectionHandler]
|
|
92
72
|
*/
|
|
93
|
-
onClose(_connection: Connection,
|
|
73
|
+
onClose(_connection: Connection, reason?: CloseReason, _connectionHandler?: ConnectionHandler | undefined): Promise<void>;
|
|
94
74
|
}>>;
|
|
95
75
|
onListen(port: any, _listenHandler: any): Promise<void>;
|
|
96
76
|
};
|
|
97
77
|
}>;
|
|
98
|
-
export function preparePortAllocator(zone: import("@agoric/base-zone").Zone, { watch }:
|
|
99
|
-
isRetryableReason?: import("@agoric/vow").IsRetryableReason | undefined;
|
|
100
|
-
} | undefined) => {
|
|
101
|
-
when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
102
|
-
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: import("@agoric/vow").EVow<T>, watcher?: import("@agoric/vow").Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => import("@agoric/vow").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
103
|
-
makeVowKit: <T>() => import("@agoric/vow").VowKit<T>;
|
|
104
|
-
allVows: (maybeVows: import("@agoric/vow").EVow<unknown>[]) => import("@agoric/vow").Vow<any[]>;
|
|
105
|
-
asVow: <T extends unknown>(fn: (...args: any[]) => import("@agoric/vow").Vow<Awaited<T>> | Awaited<T>) => import("@agoric/vow").Vow<Awaited<T>>;
|
|
106
|
-
asPromise: import("@agoric/vow").AsPromiseFunction;
|
|
107
|
-
}>): (args_0: {
|
|
78
|
+
export function preparePortAllocator(zone: import("@agoric/base-zone").Zone, { watch }: Powers): (args_0: {
|
|
108
79
|
protocol: Protocol;
|
|
109
80
|
}) => import("@endo/exo").Guarded<{
|
|
110
81
|
allocateCustomIBCPort(specifiedName?: string): Promise<import("@agoric/vow").Vow<Port>>;
|
|
@@ -112,19 +83,26 @@ export function preparePortAllocator(zone: import("@agoric/base-zone").Zone, { w
|
|
|
112
83
|
allocateICQControllerPort(): Promise<import("@agoric/vow").Vow<Port>>;
|
|
113
84
|
allocateCustomLocalPort(specifiedName?: string): Promise<import("@agoric/vow").Vow<Port>>;
|
|
114
85
|
}>;
|
|
86
|
+
export function prepareNetworkPowers(zone: import("@agoric/base-zone").Zone, vowTools: VowTools): Powers;
|
|
115
87
|
export type MakeEchoConnectionKit = ReturnType<typeof prepareEchoConnectionKit>;
|
|
88
|
+
export type Powers = VowTools & {
|
|
89
|
+
finalizer: Finalizer;
|
|
90
|
+
};
|
|
116
91
|
export type ConnectionOpts = {
|
|
117
92
|
addrs: Endpoint[];
|
|
118
|
-
handlers:
|
|
93
|
+
handlers: Remote<Required<ConnectionHandler>>[];
|
|
119
94
|
conns: MapStore<number, Connection>;
|
|
120
95
|
current: WeakSetStore<Closable>;
|
|
121
96
|
l: 0 | 1;
|
|
122
97
|
r: 0 | 1;
|
|
123
98
|
};
|
|
124
99
|
export type PortAllocator = ReturnType<ReturnType<typeof preparePortAllocator>>;
|
|
100
|
+
export type Finalizer = ReturnType<typeof prepareFinalizer>;
|
|
101
|
+
import type { VowTools } from '@agoric/vow';
|
|
125
102
|
import type { Endpoint } from './types.js';
|
|
126
103
|
import type { AttemptDescription } from './types.js';
|
|
127
104
|
import type { Port } from './types.js';
|
|
105
|
+
import type { Remote } from '@agoric/vow';
|
|
128
106
|
import type { ListenHandler } from './types.js';
|
|
129
107
|
import type { ConnectionHandler } from './types.js';
|
|
130
108
|
import type { Connection } from './types.js';
|
|
@@ -133,4 +111,38 @@ import type { ProtocolHandler } from './types.js';
|
|
|
133
111
|
import type { Protocol } from './types.js';
|
|
134
112
|
import type { Bytes } from './types.js';
|
|
135
113
|
import type { CloseReason } from './types.js';
|
|
114
|
+
/** @typedef {ReturnType<ReturnType<typeof preparePortAllocator>>} PortAllocator */
|
|
115
|
+
/**
|
|
116
|
+
* Return a package-specific singleton that pins objects until they are
|
|
117
|
+
* explicitly unpinned or finalized. It needs to pin objects only because they
|
|
118
|
+
* are resources that need to be released.
|
|
119
|
+
*
|
|
120
|
+
* The reason this functionality wasn't just baked into the other network exos
|
|
121
|
+
* is to maintain upgrade-compatible with minimal additional changes.
|
|
122
|
+
*
|
|
123
|
+
* @param {import('@agoric/base-zone').Zone} zone
|
|
124
|
+
* @param {VowTools} vowTools
|
|
125
|
+
*/
|
|
126
|
+
declare function prepareFinalizer(zone: import("@agoric/base-zone").Zone, { watch }: VowTools): import("@endo/exo").Guarded<{
|
|
127
|
+
has(obj: any): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Add a connection and handler for an `onClose` method to be called upon
|
|
130
|
+
* finalization.
|
|
131
|
+
* @param {Remote<Connection>} conn
|
|
132
|
+
* @param {Remote<Required<ConnectionHandler>>} handler
|
|
133
|
+
*/
|
|
134
|
+
initConnection(conn: Remote<Connection>, handler: Remote<Required<ConnectionHandler>>): void;
|
|
135
|
+
/**
|
|
136
|
+
* Add an object with a `close` method to be called (such as an
|
|
137
|
+
* `inboundAttempt`) upon finalization.
|
|
138
|
+
* @param {Remote<{ close(): PromiseVow<any> }>} closer
|
|
139
|
+
*/
|
|
140
|
+
initCloser(closer: Remote<{
|
|
141
|
+
close(): PromiseVow<any>;
|
|
142
|
+
}>): void;
|
|
143
|
+
finalize(obj: any): import("@agoric/vow").Vow<any> | undefined;
|
|
144
|
+
unpin(obj: any): void;
|
|
145
|
+
}>;
|
|
146
|
+
import type { PromiseVow } from '@agoric/vow';
|
|
147
|
+
export {};
|
|
136
148
|
//# sourceMappingURL=network.d.ts.map
|
package/src/network.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["network.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["network.js"],"names":[],"mappings":"AA2CA;;;;GAIG;AACH,kCAFW,MAAM,YAahB;AAutCD,mFAAmF;AAEnF;;;;;GAKG;AACH,qDAHW,OAAO,mBAAmB,EAAE,IAAI,sBAChC,QAAQ;;;;IAmCX;;;;;OAKG;qBAJQ,GAAC,aACD,QAAQ,cACR,QAAQ,GACN,OAAO,aAAa,EAAE,UAAU,CAAC,kBAAkB,CAAC;;;IA+DjE;;;;;OAKG;yBAJQ,OAAO,IAAI,CAAC,aACZ,QAAQ,iBACR,OAAO,aAAa,CAAC,oBACrB,GAAC;;GA+CnB;AA55CD;;;GAGG;AACH,qCAAsC;AAGtC,2DAA4D;AAGrD,0CADK,OAAO,aAWlB;AA4JM,0CATI,OAAO,cAAc,EAAE,IAAI,YAC3B,OAAO,QAAQ,CAAC,iBAAiB,CAAC,CAAC,SACnC,QAAQ,YACR,OAAO,QAAQ,CAAC,iBAAiB,CAAC,CAAC,SACnC,QAAQ,kBACR,CAAC,IAAI,EAAE,cAAc,KAAK,UAAU,aACpC,SAAS,yEAqDnB;AAu6BM,6CAHI,OAAO,mBAAmB,EAAE,IAAI,UAChC,MAAM,qBAMJ,OAAO,eAAe,CAAC,KACrB,QAAQ,CA2BtB;AAOM,+CAFI,OAAO,mBAAmB,EAAE,IAAI;;QAsCnC;;;;WAIG;+BAHQ,UAAU,SACV,KAAK,sBACL,iBAAiB;QAU5B;;;;WAIG;6BAHQ,UAAU,WACV,WAAW;;;;YAftB;;;;eAIG;mCAHQ,UAAU,SACV,KAAK,sBACL,iBAAiB;YAU5B;;;;eAIG;iCAHQ,UAAU,WACV,WAAW;;;;GAyB7B;AAuKM,2CAHI,OAAO,mBAAmB,EAAE,IAAI,aAChC,MAAM;cAkBF,QAAQ;;;;;;GAkDpB;AAwEI,2CAJI,OAAO,mBAAmB,EAAE,IAAI,YAChC,QAAQ,GACN,MAAM,CAKlB;oCAnTa,UAAU,CAAC,OAAO,wBAAwB,CAAC;qBAlwC3C,QAAQ,GAAG;IAAE,SAAS,EAAE,SAAS,CAAA;CAAE;;WA6DnC,QAAQ,EAAE;cACV,OAAO,QAAQ,CAAC,iBAAiB,CAAC,CAAC,EAAE;WACrC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;aAC5B,YAAY,CAAC,QAAQ,CAAC;OACtB,CAAC,GAAC,CAAC;OACH,CAAC,GAAC,CAAC;;4BAy6CH,UAAU,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;wBA4EnD,UAAU,CAAC,OAAO,gBAAgB,CAAC;8BA1jDF,aAAa;8BAD8G,YAAY;wCAAZ,YAAY;0BAAZ,YAAY;4BACvI,aAAa;mCAD8G,YAAY;uCAAZ,YAAY;gCAAZ,YAAY;8BAAZ,YAAY;qCAAZ,YAAY;8BAAZ,YAAY;2BAAZ,YAAY;iCAAZ,YAAY;AA++CtL,mFAAmF;AAEnF;;;;;;;;;;GAUG;AACH,wCAHW,OAAO,mBAAmB,EAAE,IAAI,aAChC,QAAQ;;IAcf;;;;;OAKG;yBAFQ,OAAO,UAAU,CAAC,WAClB,OAAO,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAK9C;;;;OAIG;uBADQ,OAAO;QAAE,KAAK,IAAI,WAAW,GAAG,CAAC,CAAA;KAAE,CAAC;;;GA0BlD;gCA7iD8C,aAAa"}
|
package/src/network.js
CHANGED
|
@@ -2,23 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
/// <reference types="@agoric/store/exported.js" />
|
|
4
4
|
|
|
5
|
+
import { Fail } from '@endo/errors';
|
|
5
6
|
import { E } from '@endo/far';
|
|
6
7
|
import { M } from '@endo/patterns';
|
|
7
|
-
import { Fail } from '@agoric/assert';
|
|
8
8
|
import { toBytes } from './bytes.js';
|
|
9
9
|
import { Shape } from './shapes.js';
|
|
10
10
|
|
|
11
11
|
/// <reference path="./types.js" />
|
|
12
12
|
/**
|
|
13
|
-
* @import {AttemptDescription, Bytes,
|
|
13
|
+
* @import {AttemptDescription, Bytes, CloseReason, Closable, Connection, ConnectionHandler, Endpoint, ListenHandler, Port, Protocol, ProtocolHandler, ProtocolImpl} from './types.js';
|
|
14
|
+
* @import {PromiseVow, Remote, VowTools} from '@agoric/vow';
|
|
14
15
|
*/
|
|
15
16
|
|
|
17
|
+
/** @typedef {VowTools & { finalizer: Finalizer }} Powers */
|
|
18
|
+
|
|
19
|
+
const sink = () => {};
|
|
20
|
+
harden(sink);
|
|
21
|
+
|
|
16
22
|
/**
|
|
17
23
|
* Compatibility note: this must match what our peers use, so don't change it
|
|
18
24
|
* casually.
|
|
19
25
|
*/
|
|
20
26
|
export const ENDPOINT_SEPARATOR = '/';
|
|
21
27
|
|
|
28
|
+
// Mark the finalizer close reason.
|
|
29
|
+
export const CLOSE_REASON_FINALIZER = 'closed-by-finalizer';
|
|
30
|
+
|
|
22
31
|
/** @param {unknown} err */
|
|
23
32
|
export const rethrowUnlessMissing = err => {
|
|
24
33
|
// Ugly hack rather than being able to determine if the function
|
|
@@ -60,14 +69,14 @@ function throwIfInvalidPortName(specifiedName) {
|
|
|
60
69
|
// Valid symbols: ., ,, _, +, -, #, [, ], <, >
|
|
61
70
|
const portNameRegex = new RegExp('^[a-zA-Z0-9.,_+\\-#<>\\[\\]]{2,128}$');
|
|
62
71
|
if (!portNameRegex.test(specifiedName)) {
|
|
63
|
-
throw
|
|
72
|
+
throw Error(`Invalid IBC port name: ${specifiedName}`);
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
/**
|
|
68
77
|
* @typedef {object} ConnectionOpts
|
|
69
78
|
* @property {Endpoint[]} addrs
|
|
70
|
-
* @property {
|
|
79
|
+
* @property {Remote<Required<ConnectionHandler>>[]} handlers
|
|
71
80
|
* @property {MapStore<number, Connection>} conns
|
|
72
81
|
* @property {WeakSetStore<Closable>} current
|
|
73
82
|
* @property {0|1} l
|
|
@@ -76,9 +85,9 @@ function throwIfInvalidPortName(specifiedName) {
|
|
|
76
85
|
|
|
77
86
|
/**
|
|
78
87
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
79
|
-
* @param {
|
|
88
|
+
* @param {Powers} powers
|
|
80
89
|
*/
|
|
81
|
-
const prepareHalfConnection = (zone, { watch }) => {
|
|
90
|
+
const prepareHalfConnection = (zone, { watch, allVows, finalizer }) => {
|
|
82
91
|
const makeHalfConnectionKit = zone.exoClassKit(
|
|
83
92
|
'Connection',
|
|
84
93
|
Shape.ConnectionI,
|
|
@@ -123,18 +132,20 @@ const prepareHalfConnection = (zone, { watch }) => {
|
|
|
123
132
|
return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
|
|
124
133
|
},
|
|
125
134
|
async close() {
|
|
126
|
-
const { closed, current, conns, l,
|
|
135
|
+
const { closed, current, conns, l, r } = this.state;
|
|
127
136
|
if (closed) {
|
|
128
137
|
throw Error(closed);
|
|
129
138
|
}
|
|
130
139
|
this.state.closed = 'Connection closed';
|
|
131
|
-
|
|
140
|
+
|
|
141
|
+
// Tear down both sides.
|
|
142
|
+
const lconn = conns.get(l);
|
|
143
|
+
const rconn = conns.get(r);
|
|
144
|
+
current.delete(lconn);
|
|
145
|
+
current.delete(rconn);
|
|
146
|
+
|
|
132
147
|
const innerVow = watch(
|
|
133
|
-
|
|
134
|
-
conns.get(l),
|
|
135
|
-
undefined,
|
|
136
|
-
handlers[l],
|
|
137
|
-
),
|
|
148
|
+
allVows([finalizer.finalize(lconn), finalizer.finalize(rconn)]),
|
|
138
149
|
this.facets.sinkWatcher,
|
|
139
150
|
);
|
|
140
151
|
|
|
@@ -176,11 +187,12 @@ const prepareHalfConnection = (zone, { watch }) => {
|
|
|
176
187
|
|
|
177
188
|
/**
|
|
178
189
|
* @param {import('@agoric/zone').Zone} zone
|
|
179
|
-
* @param {
|
|
190
|
+
* @param {Remote<Required<ConnectionHandler>>} handler0
|
|
180
191
|
* @param {Endpoint} addr0
|
|
181
|
-
* @param {
|
|
192
|
+
* @param {Remote<Required<ConnectionHandler>>} handler1
|
|
182
193
|
* @param {Endpoint} addr1
|
|
183
194
|
* @param {(opts: ConnectionOpts) => Connection} makeConnection
|
|
195
|
+
* @param {Finalizer} finalizer
|
|
184
196
|
* @param {WeakSetStore<Closable>} [current]
|
|
185
197
|
*/
|
|
186
198
|
export const crossoverConnection = (
|
|
@@ -190,6 +202,7 @@ export const crossoverConnection = (
|
|
|
190
202
|
handler1,
|
|
191
203
|
addr1,
|
|
192
204
|
makeConnection,
|
|
205
|
+
finalizer,
|
|
193
206
|
current = zone.detached().weakSetStore('crossoverCurrentConnections'),
|
|
194
207
|
) => {
|
|
195
208
|
const detached = zone.detached();
|
|
@@ -197,7 +210,7 @@ export const crossoverConnection = (
|
|
|
197
210
|
/** @type {MapStore<number, Connection>} */
|
|
198
211
|
const conns = detached.mapStore('addrToConnections');
|
|
199
212
|
|
|
200
|
-
/** @type {
|
|
213
|
+
/** @type {Remote<Required<ConnectionHandler>>[]} */
|
|
201
214
|
const handlers = harden([handler0, handler1]);
|
|
202
215
|
/** @type {Endpoint[]} */
|
|
203
216
|
const addrs = harden([addr0, addr1]);
|
|
@@ -215,9 +228,13 @@ export const crossoverConnection = (
|
|
|
215
228
|
* @param {number} r remote side of the connection
|
|
216
229
|
*/
|
|
217
230
|
const openHalfConnection = (l, r) => {
|
|
218
|
-
|
|
231
|
+
const lconn = conns.get(l);
|
|
232
|
+
current.add(lconn);
|
|
233
|
+
if (!finalizer.has(lconn)) {
|
|
234
|
+
finalizer.initConnection(lconn, handlers[l]);
|
|
235
|
+
}
|
|
219
236
|
E(handlers[l])
|
|
220
|
-
.onOpen(
|
|
237
|
+
.onOpen(lconn, addrs[l], addrs[r], handlers[l])
|
|
221
238
|
.catch(rethrowUnlessMissing);
|
|
222
239
|
};
|
|
223
240
|
|
|
@@ -233,9 +250,9 @@ export const crossoverConnection = (
|
|
|
233
250
|
/**
|
|
234
251
|
* @param {import('@agoric/zone').Zone} zone
|
|
235
252
|
* @param {(opts: ConnectionOpts) => Connection} makeConnection
|
|
236
|
-
* @param {
|
|
253
|
+
* @param {Powers} powers
|
|
237
254
|
*/
|
|
238
|
-
const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
|
|
255
|
+
const prepareInboundAttempt = (zone, makeConnection, { watch, finalizer }) => {
|
|
239
256
|
const makeInboundAttemptKit = zone.exoClassKit(
|
|
240
257
|
'InboundAttempt',
|
|
241
258
|
Shape.InboundAttemptI,
|
|
@@ -245,7 +262,7 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
|
|
|
245
262
|
* @param {string} opts.remoteAddr
|
|
246
263
|
* @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
|
|
247
264
|
* @param {string} opts.listenPrefix
|
|
248
|
-
* @param {MapStore<Endpoint, [Port,
|
|
265
|
+
* @param {MapStore<Endpoint, [Port, Remote<Required<ListenHandler>>]>} opts.listening
|
|
249
266
|
*/
|
|
250
267
|
({
|
|
251
268
|
localAddr,
|
|
@@ -288,6 +305,7 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
|
|
|
288
305
|
|
|
289
306
|
const current = currentConnections.get(port);
|
|
290
307
|
current.delete(this.facets.inboundAttempt);
|
|
308
|
+
finalizer.unpin(this.facets.inboundAttempt);
|
|
291
309
|
|
|
292
310
|
const innerVow = watch(
|
|
293
311
|
E(listener).onReject(port, localAddr, remoteAddr, listener),
|
|
@@ -300,7 +318,7 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
|
|
|
300
318
|
* @param {object} opts
|
|
301
319
|
* @param {string} [opts.localAddress]
|
|
302
320
|
* @param {string} [opts.remoteAddress]
|
|
303
|
-
* @param {
|
|
321
|
+
* @param {Remote<ConnectionHandler>} opts.handler
|
|
304
322
|
*/
|
|
305
323
|
async accept({ localAddress, remoteAddress, handler: rchandler }) {
|
|
306
324
|
const { consummated, localAddr, remoteAddr } = this.state;
|
|
@@ -342,15 +360,12 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
|
|
|
342
360
|
|
|
343
361
|
return crossoverConnection(
|
|
344
362
|
zone,
|
|
345
|
-
/** @type {
|
|
346
|
-
lchandler
|
|
347
|
-
),
|
|
363
|
+
/** @type {Remote<Required<ConnectionHandler>>} */ (lchandler),
|
|
348
364
|
localAddress,
|
|
349
|
-
/** @type {
|
|
350
|
-
rchandler
|
|
351
|
-
),
|
|
365
|
+
/** @type {Remote<Required<ConnectionHandler>>} */ (rchandler),
|
|
352
366
|
remoteAddress,
|
|
353
367
|
makeConnection,
|
|
368
|
+
finalizer,
|
|
354
369
|
current,
|
|
355
370
|
)[1];
|
|
356
371
|
},
|
|
@@ -398,22 +413,22 @@ const RevokeState = /** @type {const} */ ({
|
|
|
398
413
|
|
|
399
414
|
/**
|
|
400
415
|
* @param {import('@agoric/zone').Zone} zone
|
|
401
|
-
* @param {
|
|
416
|
+
* @param {Powers} powers
|
|
402
417
|
*/
|
|
403
418
|
const preparePort = (zone, powers) => {
|
|
404
419
|
const makeIncapable = zone.exoClass('Incapable', undefined, () => ({}), {});
|
|
405
420
|
|
|
406
|
-
const { watch, allVows } = powers;
|
|
421
|
+
const { finalizer, watch, allVows } = powers;
|
|
407
422
|
|
|
408
423
|
/**
|
|
409
424
|
* @param {object} opts
|
|
410
425
|
* @param {Endpoint} opts.localAddr
|
|
411
|
-
* @param {MapStore<Endpoint, [Port,
|
|
412
|
-
* @param {SetStore<
|
|
426
|
+
* @param {MapStore<Endpoint, [Port, Remote<Required<ListenHandler>>]>} opts.listening
|
|
427
|
+
* @param {SetStore<Remote<Connection>>} opts.openConnections
|
|
413
428
|
* @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
|
|
414
429
|
* @param {MapStore<string, Port>} opts.boundPorts
|
|
415
|
-
* @param {
|
|
416
|
-
* @param {
|
|
430
|
+
* @param {Remote<ProtocolHandler>} opts.protocolHandler
|
|
431
|
+
* @param {Remote<ProtocolImpl>} opts.protocolImpl
|
|
417
432
|
*/
|
|
418
433
|
const initPort = ({
|
|
419
434
|
localAddr,
|
|
@@ -443,7 +458,7 @@ const preparePort = (zone, powers) => {
|
|
|
443
458
|
// Works even after revoke().
|
|
444
459
|
return this.state.localAddr;
|
|
445
460
|
},
|
|
446
|
-
/** @param {
|
|
461
|
+
/** @param {Remote<ListenHandler>} listenHandler */
|
|
447
462
|
async addListener(listenHandler) {
|
|
448
463
|
const { revoked, listening, localAddr, protocolHandler } = this.state;
|
|
449
464
|
|
|
@@ -458,9 +473,7 @@ const preparePort = (zone, powers) => {
|
|
|
458
473
|
}
|
|
459
474
|
listening.set(localAddr, [
|
|
460
475
|
this.facets.port,
|
|
461
|
-
/** @type {
|
|
462
|
-
listenHandler
|
|
463
|
-
),
|
|
476
|
+
/** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
|
|
464
477
|
]);
|
|
465
478
|
E(lhandler).onRemove(lport, lhandler).catch(rethrowUnlessMissing);
|
|
466
479
|
} else {
|
|
@@ -468,9 +481,7 @@ const preparePort = (zone, powers) => {
|
|
|
468
481
|
localAddr,
|
|
469
482
|
harden([
|
|
470
483
|
this.facets.port,
|
|
471
|
-
/** @type {
|
|
472
|
-
listenHandler
|
|
473
|
-
),
|
|
484
|
+
/** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
|
|
474
485
|
]),
|
|
475
486
|
);
|
|
476
487
|
}
|
|
@@ -489,7 +500,7 @@ const preparePort = (zone, powers) => {
|
|
|
489
500
|
);
|
|
490
501
|
return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
|
|
491
502
|
},
|
|
492
|
-
/** @param {
|
|
503
|
+
/** @param {Remote<ListenHandler>} listenHandler */
|
|
493
504
|
async removeListener(listenHandler) {
|
|
494
505
|
const { listening, localAddr, protocolHandler } = this.state;
|
|
495
506
|
listening.has(localAddr) || Fail`Port ${localAddr} is not listening`;
|
|
@@ -511,11 +522,11 @@ const preparePort = (zone, powers) => {
|
|
|
511
522
|
},
|
|
512
523
|
/**
|
|
513
524
|
* @param {Endpoint} remotePort
|
|
514
|
-
* @param {
|
|
525
|
+
* @param {Remote<ConnectionHandler>} [connectionHandler]
|
|
515
526
|
*/
|
|
516
527
|
async connect(
|
|
517
528
|
remotePort,
|
|
518
|
-
connectionHandler = /** @type {
|
|
529
|
+
connectionHandler = /** @type {Remote<ConnectionHandler>} */ (
|
|
519
530
|
makeIncapable()
|
|
520
531
|
),
|
|
521
532
|
) {
|
|
@@ -527,7 +538,7 @@ const preparePort = (zone, powers) => {
|
|
|
527
538
|
return watch(
|
|
528
539
|
E(protocolImpl).outbound(this.facets.port, dst, connectionHandler),
|
|
529
540
|
this.facets.portConnectWatcher,
|
|
530
|
-
{
|
|
541
|
+
{ chandler: connectionHandler },
|
|
531
542
|
);
|
|
532
543
|
},
|
|
533
544
|
async revoke() {
|
|
@@ -538,7 +549,6 @@ const preparePort = (zone, powers) => {
|
|
|
538
549
|
Fail`Port ${localAddr} is already revoked`;
|
|
539
550
|
|
|
540
551
|
this.state.revoked = RevokeState.REVOKING;
|
|
541
|
-
|
|
542
552
|
const revokeVow = watch(
|
|
543
553
|
E(protocolHandler).onRevoke(
|
|
544
554
|
this.facets.port,
|
|
@@ -564,15 +574,16 @@ const preparePort = (zone, powers) => {
|
|
|
564
574
|
},
|
|
565
575
|
},
|
|
566
576
|
portConnectWatcher: {
|
|
567
|
-
onFulfilled(conn,
|
|
568
|
-
const { revoked } =
|
|
569
|
-
const { openConnections } = this.state;
|
|
577
|
+
onFulfilled(conn, { chandler }) {
|
|
578
|
+
const { openConnections, revoked } = this.state;
|
|
570
579
|
|
|
580
|
+
if (!finalizer.has(conn)) {
|
|
581
|
+
finalizer.initConnection(conn, chandler);
|
|
582
|
+
}
|
|
571
583
|
if (revoked) {
|
|
572
|
-
|
|
573
|
-
} else {
|
|
574
|
-
openConnections.add(conn);
|
|
584
|
+
return finalizer.finalize(conn);
|
|
575
585
|
}
|
|
586
|
+
openConnections.add(conn);
|
|
576
587
|
return conn;
|
|
577
588
|
},
|
|
578
589
|
},
|
|
@@ -586,8 +597,8 @@ const preparePort = (zone, powers) => {
|
|
|
586
597
|
|
|
587
598
|
const ps = [];
|
|
588
599
|
ps.push(
|
|
589
|
-
...values.map(
|
|
590
|
-
watch(
|
|
600
|
+
...values.map(obj =>
|
|
601
|
+
watch(finalizer.finalize(obj), this.facets.sinkWatcher),
|
|
591
602
|
),
|
|
592
603
|
);
|
|
593
604
|
|
|
@@ -650,12 +661,12 @@ const preparePort = (zone, powers) => {
|
|
|
650
661
|
|
|
651
662
|
/**
|
|
652
663
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
653
|
-
* @param {
|
|
664
|
+
* @param {Powers} powers
|
|
654
665
|
*/
|
|
655
666
|
const prepareBinder = (zone, powers) => {
|
|
656
667
|
const makeConnection = prepareHalfConnection(zone, powers);
|
|
657
668
|
|
|
658
|
-
const { watch } = powers;
|
|
669
|
+
const { watch, finalizer } = powers;
|
|
659
670
|
|
|
660
671
|
const makeInboundAttempt = prepareInboundAttempt(
|
|
661
672
|
zone,
|
|
@@ -730,8 +741,8 @@ const prepareBinder = (zone, powers) => {
|
|
|
730
741
|
* @param {object} opts
|
|
731
742
|
* @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
|
|
732
743
|
* @param {MapStore<string, Port>} opts.boundPorts
|
|
733
|
-
* @param {MapStore<Endpoint, [Port,
|
|
734
|
-
* @param {
|
|
744
|
+
* @param {MapStore<Endpoint, [Port, Remote<Required<ListenHandler>>]>} opts.listening
|
|
745
|
+
* @param {Remote<ProtocolHandler>} opts.protocolHandler
|
|
735
746
|
*/
|
|
736
747
|
({ currentConnections, boundPorts, listening, protocolHandler }) => {
|
|
737
748
|
/** @type {SetStore<Connection>} */
|
|
@@ -777,7 +788,7 @@ const prepareBinder = (zone, powers) => {
|
|
|
777
788
|
|
|
778
789
|
const innerVow = watch(
|
|
779
790
|
E(
|
|
780
|
-
/** @type {
|
|
791
|
+
/** @type {Remote<Required<ProtocolHandler>>} */ (
|
|
781
792
|
protocolHandler
|
|
782
793
|
),
|
|
783
794
|
).onInstantiate(
|
|
@@ -819,7 +830,7 @@ const prepareBinder = (zone, powers) => {
|
|
|
819
830
|
// Allocate a local address.
|
|
820
831
|
const instantiateInnerVow = watch(
|
|
821
832
|
E(
|
|
822
|
-
/** @type {
|
|
833
|
+
/** @type {Remote<Required<ProtocolHandler>>} */ (
|
|
823
834
|
protocolHandler
|
|
824
835
|
),
|
|
825
836
|
).onInstantiate(port, localAddr, remoteAddr, protocolHandler),
|
|
@@ -904,6 +915,7 @@ const prepareBinder = (zone, powers) => {
|
|
|
904
915
|
});
|
|
905
916
|
|
|
906
917
|
current.add(inboundAttempt);
|
|
918
|
+
finalizer.initCloser(inboundAttempt);
|
|
907
919
|
return inboundAttempt;
|
|
908
920
|
},
|
|
909
921
|
},
|
|
@@ -945,7 +957,7 @@ const prepareBinder = (zone, powers) => {
|
|
|
945
957
|
|
|
946
958
|
const innerVow = watch(
|
|
947
959
|
E(
|
|
948
|
-
/** @type {
|
|
960
|
+
/** @type {Remote<Required<ProtocolHandler>>} */ (
|
|
949
961
|
protocolHandler
|
|
950
962
|
),
|
|
951
963
|
).onInstantiate(
|
|
@@ -1008,15 +1020,12 @@ const prepareBinder = (zone, powers) => {
|
|
|
1008
1020
|
|
|
1009
1021
|
return crossoverConnection(
|
|
1010
1022
|
zone,
|
|
1011
|
-
/** @type {
|
|
1012
|
-
lchandler
|
|
1013
|
-
),
|
|
1023
|
+
/** @type {Remote<Required<ConnectionHandler>>} */ (lchandler),
|
|
1014
1024
|
negotiatedLocalAddress || requestedLocalAddress,
|
|
1015
|
-
/** @type {
|
|
1016
|
-
rchandler
|
|
1017
|
-
),
|
|
1025
|
+
/** @type {Remote<Required<ConnectionHandler>>} */ (rchandler),
|
|
1018
1026
|
negotiatedRemoteAddress || requestedRemoteAddress,
|
|
1019
1027
|
makeConnection,
|
|
1028
|
+
finalizer,
|
|
1020
1029
|
current,
|
|
1021
1030
|
)[0];
|
|
1022
1031
|
},
|
|
@@ -1169,13 +1178,13 @@ const prepareBinder = (zone, powers) => {
|
|
|
1169
1178
|
|
|
1170
1179
|
/**
|
|
1171
1180
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
1172
|
-
* @param {
|
|
1181
|
+
* @param {Powers} powers
|
|
1173
1182
|
*/
|
|
1174
1183
|
export const prepareNetworkProtocol = (zone, powers) => {
|
|
1175
1184
|
const makeBinderKit = prepareBinder(zone, powers);
|
|
1176
1185
|
|
|
1177
1186
|
/**
|
|
1178
|
-
* @param {
|
|
1187
|
+
* @param {Remote<ProtocolHandler>} protocolHandler
|
|
1179
1188
|
* @returns {Protocol}
|
|
1180
1189
|
*/
|
|
1181
1190
|
const makeNetworkProtocol = protocolHandler => {
|
|
@@ -1187,7 +1196,7 @@ export const prepareNetworkProtocol = (zone, powers) => {
|
|
|
1187
1196
|
/** @type {MapStore<string, Port>} */
|
|
1188
1197
|
const boundPorts = detached.mapStore('addrToPort');
|
|
1189
1198
|
|
|
1190
|
-
/** @type {MapStore<Endpoint, [Port,
|
|
1199
|
+
/** @type {MapStore<Endpoint, [Port, Remote<Required<ListenHandler>>]>} */
|
|
1191
1200
|
const listening = detached.mapStore('listening');
|
|
1192
1201
|
|
|
1193
1202
|
const { binder, protocolImpl } = makeBinderKit({
|
|
@@ -1261,17 +1270,17 @@ export const prepareEchoConnectionKit = zone => {
|
|
|
1261
1270
|
},
|
|
1262
1271
|
/**
|
|
1263
1272
|
* @param {Connection} _connection
|
|
1264
|
-
* @param {CloseReason} [
|
|
1273
|
+
* @param {CloseReason} [reason]
|
|
1265
1274
|
* @param {ConnectionHandler} [_connectionHandler]
|
|
1266
1275
|
*/
|
|
1267
|
-
async onClose(_connection,
|
|
1276
|
+
async onClose(_connection, reason, _connectionHandler) {
|
|
1268
1277
|
const { closed } = this.state;
|
|
1269
1278
|
|
|
1270
1279
|
if (closed) {
|
|
1271
1280
|
throw Error(closed);
|
|
1272
1281
|
}
|
|
1273
1282
|
|
|
1274
|
-
this.state.closed = 'Connection closed';
|
|
1283
|
+
this.state.closed = reason || 'Connection closed';
|
|
1275
1284
|
},
|
|
1276
1285
|
},
|
|
1277
1286
|
listener: {
|
|
@@ -1293,14 +1302,14 @@ export const prepareEchoConnectionKit = zone => {
|
|
|
1293
1302
|
* Create a protocol handler that just connects to itself.
|
|
1294
1303
|
*
|
|
1295
1304
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
1296
|
-
* @param {
|
|
1305
|
+
* @param {VowTools} powers
|
|
1297
1306
|
*/
|
|
1298
1307
|
export function prepareLoopbackProtocolHandler(zone, { watch, allVows }) {
|
|
1299
1308
|
const detached = zone.detached();
|
|
1300
1309
|
|
|
1301
1310
|
/** @param {string} [instancePrefix] */
|
|
1302
1311
|
const initHandler = (instancePrefix = 'nonce/') => {
|
|
1303
|
-
/** @type {MapStore<string, [
|
|
1312
|
+
/** @type {MapStore<string, [Remote<Port>, Remote<Required<ListenHandler>>]>} */
|
|
1304
1313
|
const listeners = detached.mapStore('localAddr');
|
|
1305
1314
|
|
|
1306
1315
|
return {
|
|
@@ -1379,7 +1388,7 @@ export function prepareLoopbackProtocolHandler(zone, { watch, allVows }) {
|
|
|
1379
1388
|
localAddr,
|
|
1380
1389
|
harden([
|
|
1381
1390
|
port,
|
|
1382
|
-
/** @type {
|
|
1391
|
+
/** @type {Remote<Required<ListenHandler>>} */ (
|
|
1383
1392
|
listenHandler
|
|
1384
1393
|
),
|
|
1385
1394
|
]),
|
|
@@ -1390,17 +1399,15 @@ export function prepareLoopbackProtocolHandler(zone, { watch, allVows }) {
|
|
|
1390
1399
|
localAddr,
|
|
1391
1400
|
harden([
|
|
1392
1401
|
port,
|
|
1393
|
-
/** @type {
|
|
1394
|
-
listenHandler
|
|
1395
|
-
),
|
|
1402
|
+
/** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
|
|
1396
1403
|
]),
|
|
1397
1404
|
);
|
|
1398
1405
|
}
|
|
1399
1406
|
},
|
|
1400
1407
|
/**
|
|
1401
|
-
* @param {
|
|
1408
|
+
* @param {Remote<Port>} port
|
|
1402
1409
|
* @param {Endpoint} localAddr
|
|
1403
|
-
* @param {
|
|
1410
|
+
* @param {Remote<ListenHandler>} listenHandler
|
|
1404
1411
|
* @param {*} _protocolHandler
|
|
1405
1412
|
*/
|
|
1406
1413
|
async onListenRemove(port, localAddr, listenHandler, _protocolHandler) {
|
|
@@ -1453,7 +1460,7 @@ export function prepareLoopbackProtocolHandler(zone, { watch, allVows }) {
|
|
|
1453
1460
|
/**
|
|
1454
1461
|
*
|
|
1455
1462
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
1456
|
-
* @param {
|
|
1463
|
+
* @param {Powers} powers
|
|
1457
1464
|
*/
|
|
1458
1465
|
export const preparePortAllocator = (zone, { watch }) =>
|
|
1459
1466
|
zone.exoClass(
|
|
@@ -1523,3 +1530,79 @@ export const preparePortAllocator = (zone, { watch }) =>
|
|
|
1523
1530
|
},
|
|
1524
1531
|
);
|
|
1525
1532
|
/** @typedef {ReturnType<ReturnType<typeof preparePortAllocator>>} PortAllocator */
|
|
1533
|
+
|
|
1534
|
+
/**
|
|
1535
|
+
* Return a package-specific singleton that pins objects until they are
|
|
1536
|
+
* explicitly unpinned or finalized. It needs to pin objects only because they
|
|
1537
|
+
* are resources that need to be released.
|
|
1538
|
+
*
|
|
1539
|
+
* The reason this functionality wasn't just baked into the other network exos
|
|
1540
|
+
* is to maintain upgrade-compatible with minimal additional changes.
|
|
1541
|
+
*
|
|
1542
|
+
* @param {import('@agoric/base-zone').Zone} zone
|
|
1543
|
+
* @param {VowTools} vowTools
|
|
1544
|
+
*/
|
|
1545
|
+
const prepareFinalizer = (zone, { watch }) => {
|
|
1546
|
+
/**
|
|
1547
|
+
* @type {MapStore<{},
|
|
1548
|
+
* { conn: Remote<Connection>, handler: Remote<Required<ConnectionHandler>>} |
|
|
1549
|
+
* { closer: Remote<{ close(): PromiseVow<any> }> }
|
|
1550
|
+
* >}
|
|
1551
|
+
*/
|
|
1552
|
+
const objToFinalizerInfo = zone.mapStore('objToFinalizerInfo');
|
|
1553
|
+
return zone.exo('NetworkFinalizer', undefined, {
|
|
1554
|
+
has(obj) {
|
|
1555
|
+
return objToFinalizerInfo.has(obj);
|
|
1556
|
+
},
|
|
1557
|
+
/**
|
|
1558
|
+
* Add a connection and handler for an `onClose` method to be called upon
|
|
1559
|
+
* finalization.
|
|
1560
|
+
* @param {Remote<Connection>} conn
|
|
1561
|
+
* @param {Remote<Required<ConnectionHandler>>} handler
|
|
1562
|
+
*/
|
|
1563
|
+
initConnection(conn, handler) {
|
|
1564
|
+
objToFinalizerInfo.init(conn, harden({ conn, handler }));
|
|
1565
|
+
},
|
|
1566
|
+
/**
|
|
1567
|
+
* Add an object with a `close` method to be called (such as an
|
|
1568
|
+
* `inboundAttempt`) upon finalization.
|
|
1569
|
+
* @param {Remote<{ close(): PromiseVow<any> }>} closer
|
|
1570
|
+
*/
|
|
1571
|
+
initCloser(closer) {
|
|
1572
|
+
objToFinalizerInfo.init(closer, harden({ closer }));
|
|
1573
|
+
},
|
|
1574
|
+
finalize(obj) {
|
|
1575
|
+
if (!objToFinalizerInfo.has(obj)) {
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
const disposeInfo = objToFinalizerInfo.get(obj);
|
|
1579
|
+
if ('conn' in disposeInfo) {
|
|
1580
|
+
// A connection+handler.
|
|
1581
|
+
const { conn, handler } = disposeInfo;
|
|
1582
|
+
objToFinalizerInfo.delete(obj);
|
|
1583
|
+
return watch(E(handler).onClose(conn, CLOSE_REASON_FINALIZER, handler));
|
|
1584
|
+
} else if ('closer' in disposeInfo) {
|
|
1585
|
+
// Just something with a `close` method.
|
|
1586
|
+
const { closer } = disposeInfo;
|
|
1587
|
+
objToFinalizerInfo.delete(obj);
|
|
1588
|
+
return watch(E(closer).close());
|
|
1589
|
+
}
|
|
1590
|
+
},
|
|
1591
|
+
unpin(obj) {
|
|
1592
|
+
objToFinalizerInfo.delete(obj);
|
|
1593
|
+
},
|
|
1594
|
+
});
|
|
1595
|
+
};
|
|
1596
|
+
harden(prepareFinalizer);
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* @param {import('@agoric/base-zone').Zone} zone
|
|
1600
|
+
* @param {VowTools} vowTools
|
|
1601
|
+
* @returns {Powers}
|
|
1602
|
+
*/
|
|
1603
|
+
export const prepareNetworkPowers = (zone, vowTools) => {
|
|
1604
|
+
const finalizer = prepareFinalizer(zone, vowTools);
|
|
1605
|
+
return harden({ ...vowTools, finalizer });
|
|
1606
|
+
};
|
|
1607
|
+
|
|
1608
|
+
/** @typedef {ReturnType<typeof prepareFinalizer>} Finalizer */
|
package/src/router.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
* @import {PromiseVow, Remote,
|
|
2
|
+
* @import {Endpoint, Port, Protocol, ProtocolHandler} from './types.js';
|
|
3
|
+
* @import {PromiseVow, Remote, VowTools} from '@agoric/vow';
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* @template T
|
|
@@ -31,24 +31,15 @@ export function prepareRouter<T>(zone: import("@agoric/base-zone").Zone): () =>
|
|
|
31
31
|
*/
|
|
32
32
|
unregister(prefix: string, route: T): void;
|
|
33
33
|
}>;
|
|
34
|
-
export function prepareRouterProtocol(zone: import("@agoric/base-zone").Zone, powers:
|
|
35
|
-
|
|
36
|
-
} | undefined) => {
|
|
37
|
-
when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
38
|
-
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: import("@agoric/vow").EVow<T>, watcher?: import("@agoric/vow").Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => import("@agoric/vow").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
39
|
-
makeVowKit: <T>() => VowKit<T>;
|
|
40
|
-
allVows: (maybeVows: import("@agoric/vow").EVow<unknown>[]) => import("@agoric/vow").Vow<any[]>;
|
|
41
|
-
asVow: <T extends unknown>(fn: (...args: any[]) => import("@agoric/vow").Vow<Awaited<T>> | Awaited<T>) => import("@agoric/vow").Vow<Awaited<T>>;
|
|
42
|
-
asPromise: import("@agoric/vow").AsPromiseFunction;
|
|
43
|
-
}>, E?: ((<T>(x: T) => import("../../../node_modules/@endo/eventual-send/src/E.js").ECallableOrMethods<import("@endo/eventual-send").RemoteFunctions<T>>) & {
|
|
44
|
-
readonly get: <T_1>(x: T_1) => import("../../../node_modules/@endo/eventual-send/src/E.js").EGetters<import("@endo/eventual-send").LocalRecord<T_1>>;
|
|
34
|
+
export function prepareRouterProtocol(zone: import("@agoric/base-zone").Zone, powers: import("./network.js").Powers, E?: ((<T>(x: T) => import("../../../node_modules/@endo/eventual-send/src/E.js").ECallableOrMethods<import("@endo/eventual-send").RemoteFunctions<T>>) & {
|
|
35
|
+
readonly get: <T>(x: T) => import("../../../node_modules/@endo/eventual-send/src/E.js").EGetters<import("@endo/eventual-send").LocalRecord<T>>;
|
|
45
36
|
readonly resolve: {
|
|
46
37
|
(): Promise<void>;
|
|
47
|
-
<
|
|
48
|
-
<
|
|
38
|
+
<T>(value: T): Promise<Awaited<T>>;
|
|
39
|
+
<T>(value: T | PromiseLike<T>): Promise<Awaited<T>>;
|
|
49
40
|
};
|
|
50
|
-
readonly sendOnly: <
|
|
51
|
-
readonly when: <
|
|
41
|
+
readonly sendOnly: <T>(x: T) => import("../../../node_modules/@endo/eventual-send/src/E.js").ESendOnlyCallableOrMethods<import("@endo/eventual-send").RemoteFunctions<T>>;
|
|
42
|
+
readonly when: <T, U = T>(x: T | PromiseLike<T>, onfulfilled?: ((value: T) => import("@endo/eventual-send").ERef<U>) | undefined, onrejected?: ((reason: any) => import("@endo/eventual-send").ERef<U>) | undefined) => Promise<U>;
|
|
52
43
|
}) | undefined): () => import("@endo/exo").Guarded<{
|
|
53
44
|
/**
|
|
54
45
|
* @param {string[]} paths
|
|
@@ -89,7 +80,6 @@ export type RouterProtocol = {
|
|
|
89
80
|
unregisterProtocolHandler: (prefix: string, protocolHandler: ProtocolHandler) => void;
|
|
90
81
|
};
|
|
91
82
|
import type { Endpoint } from './types.js';
|
|
92
|
-
import type { VowKit } from '@agoric/vow';
|
|
93
83
|
import type { ProtocolHandler } from './types.js';
|
|
94
84
|
import type { Remote } from '@agoric/vow';
|
|
95
85
|
import type { Port } from './types.js';
|
package/src/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["router.js"],"names":[],"mappings":"AAWA;;;GAGG;AAEH;;;;;;;;;GASG;AAEH;;;;GAIG;AAMI,8BAHM,CAAC,QACH,OAAO,mBAAmB,EAAE,IAAI;IAiBrC,6BAA6B;oBAAjB,QAAQ;IAyBpB;;;OAGG;qBAFQ,MAAM,SACN,CAAC;IAKZ;;;OAGG;uBAFQ,MAAM,SACN,CAAC;GAWjB;AAgBM,4CAJI,OAAO,mBAAmB,EAAE,IAAI,UAChC,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["router.js"],"names":[],"mappings":"AAWA;;;GAGG;AAEH;;;;;;;;;GASG;AAEH;;;;GAIG;AAMI,8BAHM,CAAC,QACH,OAAO,mBAAmB,EAAE,IAAI;IAiBrC,6BAA6B;oBAAjB,QAAQ;IAyBpB;;;OAGG;qBAFQ,MAAM,SACN,CAAC;IAKZ;;;OAGG;uBAFQ,MAAM,SACN,CAAC;GAWjB;AAgBM,4CAJI,OAAO,mBAAmB,EAAE,IAAI,UAChC,OAAO,cAAc,EAAE,MAAM;;;;;;;;gEAjGR,CAAC,+EAItB,CAAC;;IAiIN;;;OAGG;mCAFQ,MAAM,EAAE,mBACR,OAAO,eAAe,CAAC;IAYlC;;;OAGG;sCAFQ,MAAM,mBACN,OAAO,eAAe,CAAC;IAclC,kCAAkC;wBAAtB,QAAQ;GAUzB;;;;mBAzKY,CAAC;;;;;eAEA,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE;;;;;cAE/B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI;;;;;gBAElC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI;;;cA8ElC,CAAC,MAAM,EAAE,MAAM,KAAK,WAAW,IAAI,CAAC;6BACpC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,eAAe,KAAK,IAAI;+BAC3D,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,KAAK,IAAI;;8BA3FZ,YAAY;qCAAZ,YAAY;4BACzB,aAAa;0BADA,YAAY;gCACzB,aAAa"}
|
package/src/router.js
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
/// <reference types="@agoric/store/exported.js" />
|
|
4
4
|
/// <reference path="./types.js" />
|
|
5
5
|
|
|
6
|
+
import { Fail } from '@endo/errors';
|
|
6
7
|
import { E as defaultE } from '@endo/far';
|
|
7
8
|
import { M } from '@endo/patterns';
|
|
8
|
-
import { Fail } from '@agoric/assert';
|
|
9
9
|
import { ENDPOINT_SEPARATOR, prepareNetworkProtocol } from './network.js';
|
|
10
10
|
import { Shape } from './shapes.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @import {
|
|
14
|
-
* @import {PromiseVow, Remote,
|
|
13
|
+
* @import {Endpoint, Port, Protocol, ProtocolHandler} from './types.js';
|
|
14
|
+
* @import {PromiseVow, Remote, VowTools} from '@agoric/vow';
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -108,7 +108,7 @@ export const prepareRouter = zone => {
|
|
|
108
108
|
* Create a router that behaves like a Protocol.
|
|
109
109
|
*
|
|
110
110
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
111
|
-
* @param {
|
|
111
|
+
* @param {import('./network.js').Powers} powers
|
|
112
112
|
* @param {typeof defaultE} [E] Eventual sender
|
|
113
113
|
*/
|
|
114
114
|
export const prepareRouterProtocol = (zone, powers, E = defaultE) => {
|
package/src/shapes.js
CHANGED
|
@@ -158,18 +158,18 @@ export const Shape = /** @type {const} */ harden({
|
|
|
158
158
|
).returns(Shape2.Vow$(M.undefined())),
|
|
159
159
|
}),
|
|
160
160
|
protocolHandlerAcceptWatcher: M.interface('ProtocolHandlerAcceptWatcher', {
|
|
161
|
-
onFulfilled: M.call(M.any()).rest(M.any()).returns(),
|
|
161
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
162
162
|
}),
|
|
163
163
|
protocolHandlerInstantiateWatcher: M.interface(
|
|
164
164
|
'ProtocolHandlerInstantiateWatcher',
|
|
165
165
|
{
|
|
166
|
-
onFulfilled: M.call(M.any()).rest(M.any()).returns(),
|
|
166
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
167
167
|
},
|
|
168
168
|
),
|
|
169
169
|
protocolHandlerConnectWatcher: M.interface(
|
|
170
170
|
'ProtocolHandlerConnectWatcher',
|
|
171
171
|
{
|
|
172
|
-
onFulfilled: M.call(M.any()).rest(M.any()).returns(),
|
|
172
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
173
173
|
},
|
|
174
174
|
),
|
|
175
175
|
rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
|