@agoric/network 0.2.0-upgrade-16-dev-12b78e3.0 → 0.2.0-upgrade-17-dev-a61cdab.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 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
- ## [0.2.0-u16.1](https://github.com/Agoric/agoric-sdk/compare/@agoric/network@0.2.0-u16.0...@agoric/network@0.2.0-u16.1) (2024-07-10)
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:** use new `ERef` and `FarRef` ([55adb2b](https://github.com/Agoric/agoric-sdk/commit/55adb2b1f5b644ef5b7cf40ea8b7d87488218229))
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-upgrade-16-dev-12b78e3.0+12b78e3",
3
+ "version": "0.2.0-upgrade-17-dev-a61cdab.0+a61cdab",
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/assert": "0.6.1-upgrade-16-dev-12b78e3.0+12b78e3",
25
- "@agoric/internal": "0.4.0-upgrade-16-dev-12b78e3.0+12b78e3",
26
- "@agoric/store": "0.9.3-upgrade-16-dev-12b78e3.0+12b78e3",
27
- "@agoric/vat-data": "0.5.3-upgrade-16-dev-12b78e3.0+12b78e3",
28
- "@endo/base64": "^1.0.5",
29
- "@endo/far": "^1.1.2",
30
- "@endo/pass-style": "^1.4.0",
31
- "@endo/patterns": "^1.4.0",
32
- "@endo/promise-kit": "^1.1.2"
24
+ "@agoric/internal": "0.4.0-upgrade-17-dev-a61cdab.0+a61cdab",
25
+ "@agoric/store": "0.9.3-upgrade-17-dev-a61cdab.0+a61cdab",
26
+ "@agoric/vat-data": "0.5.3-upgrade-17-dev-a61cdab.0+a61cdab",
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-upgrade-16-dev-12b78e3.0+12b78e3",
36
- "@agoric/swingset-vat": "0.33.0-upgrade-16-dev-12b78e3.0+12b78e3",
37
- "@agoric/vow": "0.2.0-upgrade-16-dev-12b78e3.0+12b78e3",
38
- "@agoric/zone": "0.3.0-upgrade-16-dev-12b78e3.0+12b78e3",
39
- "@endo/bundle-source": "^3.2.3",
35
+ "@agoric/swingset-liveslots": "0.10.3-upgrade-17-dev-a61cdab.0+a61cdab",
36
+ "@agoric/swingset-vat": "0.33.0-upgrade-17-dev-a61cdab.0+a61cdab",
37
+ "@agoric/vow": "0.2.0-upgrade-17-dev-a61cdab.0+a61cdab",
38
+ "@agoric/zone": "0.3.0-upgrade-17-dev-a61cdab.0+a61cdab",
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": 89.7
69
+ "atLeast": 91.15
70
70
  },
71
- "gitHead": "12b78e307e22d0dc0c95f40099300e16655781c4"
71
+ "gitHead": "a61cdabb23bd2c846e003dee7326018a7462a929"
72
72
  }
@@ -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,CAmBtB;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;yBA7Fa,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;2BAHpC,YAAY;sCAAZ,YAAY"}
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 { details, Fail } from '@agoric/assert';
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(details`non-object ${specimen} is not a ByteSource`, TypeError);
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
12
+ * @param {VowTools} powers
13
13
  */
14
- export function prepareLoopbackProtocolHandler(zone: import("@agoric/base-zone").Zone, { watch, allVows }: ReturnType<(zone: import("@agoric/base-zone").Zone, powers?: {
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 {import('@agoric/vow').Remote<Port>} port
28
+ * @param {Remote<Port>} port
38
29
  * @param {Endpoint} localAddr
39
- * @param {import('@agoric/vow').Remote<ListenHandler>} listenHandler
30
+ * @param {Remote<ListenHandler>} listenHandler
40
31
  * @param {*} _protocolHandler
41
32
  */
42
- onListenRemove(port: import("@agoric/vow").Remote<Port>, localAddr: Endpoint, listenHandler: import("@agoric/vow").Remote<ListenHandler>, _protocolHandler: any): Promise<void>;
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: import("@agoric/vow").Remote<Required<ConnectionHandler>>, addr0: Endpoint, handler1: import("@agoric/vow").Remote<Required<ConnectionHandler>>, addr1: Endpoint, makeConnection: (opts: ConnectionOpts) => Connection, current?: globalThis.WeakSetStore<Closable> | undefined): Connection[];
55
- export function prepareNetworkProtocol(zone: import("@agoric/base-zone").Zone, powers: ReturnType<(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} [_reason]
55
+ * @param {CloseReason} [reason]
76
56
  * @param {ConnectionHandler} [_connectionHandler]
77
57
  */
78
- onClose(_connection: Connection, _reason?: CloseReason, _connectionHandler?: ConnectionHandler | undefined): Promise<void>;
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} [_reason]
70
+ * @param {CloseReason} [reason]
91
71
  * @param {ConnectionHandler} [_connectionHandler]
92
72
  */
93
- onClose(_connection: Connection, _reason?: CloseReason, _connectionHandler?: ConnectionHandler | undefined): Promise<void>;
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 }: ReturnType<(zone: import("@agoric/base-zone").Zone, powers?: {
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: import("@agoric/vow").Remote<Required<ConnectionHandler>>[];
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
@@ -1 +1 @@
1
- {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["network.js"],"names":[],"mappings":"AAkCA;;;;GAIG;AACH,kCAFW,MAAM,YAahB;AAutCD,mFAAmF;AAEnF;;;;;GAKG;AACH,qDAHW,OAAO,mBAAmB,EAAE,IAAI,sBAChC,UAAU,CAAC;;;;;;;oCAlrCN,GAAG;;CAkrCwC,CAAC;;;;IAmCpD;;;;;OAKG;qBAJQ,GAAC,aACD,QAAQ,cACR,QAAQ,GACN,OAAO,aAAa,EAAE,UAAU,CAAC,kBAAkB,CAAC;;;IAiEjE;;;;;OAKG;yBAJQ,OAAO,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,aAClC,QAAQ,iBACR,OAAO,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,oBAC3C,GAAC;;GA+CnB;AA/5CD;;GAEG;AAEH;;;GAGG;AACH,qCAAsC;AAG/B,0CADK,OAAO,aAWlB;AAyJM,0CARI,OAAO,cAAc,EAAE,IAAI,YAC3B,OAAO,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,SACzD,QAAQ,YACR,OAAO,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,SACzD,QAAQ,kBACR,CAAC,IAAI,EAAE,cAAc,KAAK,UAAU,yEAgD9C;AA+6BM,6CAHI,OAAO,mBAAmB,EAAE,IAAI,UAChC,UAAU,CAAC;;;;;;;oCAtjCN,GAAG;;CAsjCwC,CAAC,qBAM/C,OAAO,aAAa,EAAE,MAAM,CAAC,eAAe,CAAC,KAC3C,QAAQ,CA2BtB;AAOM,+CAFI,OAAO,mBAAmB,EAAE,IAAI;;QAsCnC;;;;WAIG;+BAHQ,UAAU,SACV,KAAK,sBACL,iBAAiB;QAU5B;;;;WAIG;6BAHQ,UAAU,YACV,WAAW;;;;YAftB;;;;eAIG;mCAHQ,UAAU,SACV,KAAK,sBACL,iBAAiB;YAU5B;;;;eAIG;iCAHQ,UAAU,YACV,WAAW;;;;GAyB7B;AAyKM,2CAHI,OAAO,mBAAmB,EAAE,IAAI,aAChC,UAAU,CAAC;;;;;;;oCAl1CN,GAAG;;CAk1CwC,CAAC;cAkB7C,QAAQ;;;;;;GAkDpB;oCA1OW,UAAU,CAAC,OAAO,wBAAwB,CAAC;;WArsC3C,QAAQ,EAAE;cACV,OAAO,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,EAAE;WAC3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;aAC5B,YAAY,CAAC,QAAQ,CAAC;OACtB,CAAC,GAAC,CAAC;OACH,CAAC,GAAC,CAAC;;4BA26CH,UAAU,CAAC,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;8BAx+CyG,YAAY;wCAAZ,YAAY;0BAAZ,YAAY;mCAAZ,YAAY;uCAAZ,YAAY;gCAAZ,YAAY;8BAAZ,YAAY;qCAAZ,YAAY;8BAAZ,YAAY;2BAAZ,YAAY;iCAAZ,YAAY"}
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, Closable, CloseReason, Connection, ConnectionHandler, Endpoint, ListenHandler, Port, Protocol, ProtocolHandler, ProtocolImpl} from './types.js';
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 new Error(`Invalid IBC port name: ${specifiedName}`);
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 {import('@agoric/vow').Remote<Required<ConnectionHandler>>[]} handlers
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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, handlers } = this.state;
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
- current.delete(conns.get(l));
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
- E(this.state.handlers[l]).onClose(
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 {import('@agoric/vow').Remote<Required<ConnectionHandler>>} handler0
190
+ * @param {Remote<Required<ConnectionHandler>>} handler0
180
191
  * @param {Endpoint} addr0
181
- * @param {import('@agoric/vow').Remote<Required<ConnectionHandler>>} handler1
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 {import('@agoric/vow').Remote<Required<ConnectionHandler>>[]} */
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
- current.add(conns.get(l));
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(conns.get(l), addrs[l], addrs[r], handlers[l])
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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, import('@agoric/vow').Remote<Required<ListenHandler>>]>} opts.listening
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 {import('@agoric/vow').Remote<ConnectionHandler>} opts.handler
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 {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
346
- lchandler
347
- ),
363
+ /** @type {Remote<Required<ConnectionHandler>>} */ (lchandler),
348
364
  localAddress,
349
- /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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, import('@agoric/vow').Remote<Required<ListenHandler>>]>} opts.listening
412
- * @param {SetStore<import('@agoric/vow').Remote<Connection>>} opts.openConnections
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 {import('@agoric/vow').Remote<ProtocolHandler>} opts.protocolHandler
416
- * @param {import('@agoric/vow').Remote<ProtocolImpl>} opts.protocolImpl
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 {import('@agoric/vow').Remote<ListenHandler>} listenHandler */
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 {import('@agoric/vow').Remote<Required<ListenHandler>>} */ (
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 {import('@agoric/vow').Remote<Required<ListenHandler>>} */ (
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 {import('@agoric/vow').Remote<ListenHandler>} listenHandler */
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 {import('@agoric/vow').Remote<ConnectionHandler>} [connectionHandler]
525
+ * @param {Remote<ConnectionHandler>} [connectionHandler]
515
526
  */
516
527
  async connect(
517
528
  remotePort,
518
- connectionHandler = /** @type {import('@agoric/vow').Remote<ConnectionHandler>} */ (
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
- { revoked },
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, watchContext) {
568
- const { revoked } = watchContext;
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
- void E(conn).close();
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(conn =>
590
- watch(E(conn).close(), this.facets.sinkWatcher),
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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, import('@agoric/vow').Remote<Required<ListenHandler>>]>} opts.listening
734
- * @param {import('@agoric/vow').Remote<ProtocolHandler>} opts.protocolHandler
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 {import('@agoric/vow').Remote<Required<ProtocolHandler>>} */ (
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 {import('@agoric/vow').Remote<Required<ProtocolHandler>>} */ (
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 {import('@agoric/vow').Remote<Required<ProtocolHandler>>} */ (
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 {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
1012
- lchandler
1013
- ),
1023
+ /** @type {Remote<Required<ConnectionHandler>>} */ (lchandler),
1014
1024
  negotiatedLocalAddress || requestedLocalAddress,
1015
- /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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 {import('@agoric/vow').Remote<ProtocolHandler>} protocolHandler
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, import('@agoric/vow').Remote<Required<ListenHandler>>]>} */
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} [_reason]
1273
+ * @param {CloseReason} [reason]
1265
1274
  * @param {ConnectionHandler} [_connectionHandler]
1266
1275
  */
1267
- async onClose(_connection, _reason, _connectionHandler) {
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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, [import('@agoric/vow').Remote<Port>, import('@agoric/vow').Remote<Required<ListenHandler>>]>} */
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 {import('@agoric/vow').Remote<Required<ListenHandler>>} */ (
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 {import('@agoric/vow').Remote<Required<ListenHandler>>} */ (
1394
- listenHandler
1395
- ),
1402
+ /** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
1396
1403
  ]),
1397
1404
  );
1398
1405
  }
1399
1406
  },
1400
1407
  /**
1401
- * @param {import('@agoric/vow').Remote<Port>} port
1408
+ * @param {Remote<Port>} port
1402
1409
  * @param {Endpoint} localAddr
1403
- * @param {import('@agoric/vow').Remote<ListenHandler>} listenHandler
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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 {AttemptDescription, Bytes, Closable, CloseReason, Connection, ConnectionHandler, Endpoint, ListenHandler, Port, Protocol, ProtocolHandler, ProtocolImpl} from './types.js';
3
- * @import {PromiseVow, Remote, VowKit, VowResolver, VowTools} from '@agoric/vow';
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: ReturnType<(zone: import("@agoric/base-zone").Zone, powers?: {
35
- isRetryableReason?: import("@agoric/vow").IsRetryableReason | undefined;
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
- <T_2>(value: T_2): Promise<Awaited<T_2>>;
48
- <T_3>(value: T_3 | PromiseLike<T_3>): Promise<Awaited<T_3>>;
38
+ <T>(value: T): Promise<Awaited<T>>;
39
+ <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>;
49
40
  };
50
- readonly sendOnly: <T_4>(x: T_4) => import("../../../node_modules/@endo/eventual-send/src/E.js").ESendOnlyCallableOrMethods<import("@endo/eventual-send").RemoteFunctions<T_4>>;
51
- readonly when: <T_5, U = T_5>(x: T_5 | PromiseLike<T_5>, onfulfilled?: ((value: T_5) => import("@endo/eventual-send").ERef<U>) | undefined, onrejected?: ((reason: any) => import("@endo/eventual-send").ERef<U>) | undefined) => Promise<U>;
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';
@@ -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,UAAU,CAAC;;;;;;;oCAnCI,GACzB;;CAkC0D,CAAC;;;;;;;;wEAjGJ,CAAC,0BACxD,qBAEE,kCAEe,CAAC,2BAA4B,qBAAO;;IAgIhD;;;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;;8BA3FkG,YAAY;4BAClH,aAAa;qCADyF,YAAY;4BAClH,aAAa;0BADyF,YAAY;gCAClH,aAAa"}
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 {AttemptDescription, Bytes, Closable, CloseReason, Connection, ConnectionHandler, Endpoint, ListenHandler, Port, Protocol, ProtocolHandler, ProtocolImpl} from './types.js';
14
- * @import {PromiseVow, Remote, VowKit, VowResolver, VowTools} from '@agoric/vow';
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 {ReturnType<import('@agoric/vow').prepareVowTools>} powers
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', {