@agoric/internal 0.2.2-dev-3fa74c5.0 → 0.2.2-dev-9cebd87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/internal",
3
- "version": "0.2.2-dev-3fa74c5.0+3fa74c5",
3
+ "version": "0.2.2-dev-9cebd87.0+9cebd87",
4
4
  "description": "Externally unsupported utilities internal to agoric-sdk",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -20,7 +20,7 @@
20
20
  "lint:types": "tsc -p jsconfig.json"
21
21
  },
22
22
  "dependencies": {
23
- "@agoric/zone": "0.1.1-dev-3fa74c5.0+3fa74c5",
23
+ "@agoric/zone": "0.1.1-dev-9cebd87.0+9cebd87",
24
24
  "@endo/far": "^0.2.18",
25
25
  "@endo/marshal": "^0.8.5",
26
26
  "@endo/patterns": "^0.2.2",
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "3fa74c5bb9675c4ed967cd9c7961ab4692a49cf7"
45
+ "gitHead": "9cebd8777a46b726467f50cba084d2fd0e496c2a"
46
46
  }
package/src/callback.d.ts CHANGED
@@ -4,7 +4,32 @@ export function makeSyncFunctionCallback<I extends (...args: unknown[]) => any,
4
4
  export function makeFunctionCallback<I extends (...args: unknown[]) => any, T extends import("@endo/far").ERef<(...args: [...B, ...Parameters<I>]) => ReturnType<I>> = import("@endo/far").ERef<I>, B extends unknown[] = []>(target: T, ...bound: B): import("./types").Callback<I>;
5
5
  export function makeSyncMethodCallback<I extends (...args: unknown[]) => any, P extends PropertyKey, T extends { [x in P]: (...args: [...B, ...Parameters<I>]) => ReturnType<I>; } = { [x_1 in P]: I; }, B extends unknown[] = []>(target: T, methodName: P, ...bound: B): import("./types").SyncCallback<I>;
6
6
  export function makeMethodCallback<I extends (...args: unknown[]) => any, P extends PropertyKey, T extends import("@endo/far").ERef<{ [x in P]: (...args: [...B, ...Parameters<I>]) => ReturnType<I>; }> = import("@endo/far").ERef<{ [x_1 in P]: I; }>, B extends unknown[] = []>(target: T, methodName: P, ...bound: B): import("./types").Callback<I>;
7
- export function isCallback(callback: any): callback is any;
7
+ export function isCallback(callback: any): callback is import("./types").Callback<any>;
8
+ export function prepareAttenuator<M extends PropertyKey>(zone: import('@agoric/zone').Zone, methodNames: M[], { interfaceGuard, tag }?: {
9
+ interfaceGuard?: InterfaceGuard | undefined;
10
+ tag?: string | undefined;
11
+ }): (args_0: {
12
+ target?: any;
13
+ isSync?: boolean | undefined;
14
+ overrides?: { [K in M]?: import("./types").Callback<any> | null | undefined; } | undefined;
15
+ }) => { [K_1 in M]: (this: any, ...args: unknown[]) => any; } & import("@endo/eventual-send").RemotableBrand<{}, { [K_1 in M]: (this: any, ...args: unknown[]) => any; }>;
16
+ export function prepareGuardedAttenuator(zone: import('@agoric/zone').Zone, interfaceGuard: InterfaceGuard, opts?: {
17
+ tag?: string | undefined;
18
+ } | undefined): (args_0: {
19
+ target?: any;
20
+ isSync?: boolean | undefined;
21
+ overrides?: {
22
+ [x: string]: import("./types").Callback<any> | null | undefined;
23
+ [x: symbol]: import("./types").Callback<any> | null | undefined;
24
+ } | undefined;
25
+ }) => {
26
+ [x: string]: (this: any, ...args: unknown[]) => any;
27
+ [x: symbol]: (this: any, ...args: unknown[]) => any;
28
+ } & import("@endo/eventual-send").RemotableBrand<{}, {
29
+ [x: string]: (this: any, ...args: unknown[]) => any;
30
+ [x: symbol]: (this: any, ...args: unknown[]) => any;
31
+ }>;
8
32
  export type Callback<I extends (...args: unknown[]) => any> = import('./types').Callback<I>;
9
33
  export type SyncCallback<I extends (...args: unknown[]) => any> = import('./types').SyncCallback<I>;
34
+ export type Farable<T> = import('@endo/eventual-send').RemotableBrand<{}, T> & T;
10
35
  //# sourceMappingURL=callback.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["callback.js"],"names":[],"mappings":"AAwBO,6CALiB,OAAO,EAAE,KAAK,GAAG,sFAWxC;AAUM,0CALiB,OAAO,EAAE,KAAK,GAAG,oGAWxC;AAYM,6DAPiB,OAAO,EAAE,KAAK,GAAG,2JAaxC;AAeM,yDATiB,OAAO,EAAE,KAAK,GAAG,2MAexC;AAiBM,2DAXiB,OAAO,EAAE,KAAK,GAAG,iOAoBxC;AAiBM,uDAXiB,OAAO,EAAE,KAAK,GAAG,iRAmBxC;AAOM,qCAHI,GAAG,mBAeb;yCApJuB,OAAO,EAAE,KAAK,GAAG,IAC5B,OAAO,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;6CAIlB,OAAO,EAAE,KAAK,GAAG,IAC5B,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["callback.js"],"names":[],"mappings":"AAkDO,6CALiB,OAAO,EAAE,KAAK,GAAG,sFAWxC;AAWM,0CALiB,OAAO,EAAE,KAAK,GAAG,oGAWxC;AAaM,6DAPiB,OAAO,EAAE,KAAK,GAAG,2JAaxC;AAeM,yDATiB,OAAO,EAAE,KAAK,GAAG,2MAexC;AAiBM,2DAXiB,OAAO,EAAE,KAAK,GAAG,iOAoBxC;AAiBM,uDAXiB,OAAO,EAAE,KAAK,GAAG,iRAmBxC;AAOM,qCAHI,GAAG,+CAeb;AAcM,+DAPI,OAAO,cAAc,EAAE,IAAI;IAGL,cAAc;IAEtB,GAAG;;aAkEb,GAAG;;;2BA1DI,GAAG,WAAW,OAAO,EAAE,KAAK,GAAG,4EAA/B,GAAG,WAAW,OAAO,EAAE,KAAK,GAAG,KA8FpD;AAWM,+CALI,OAAO,cAAc,EAAE,IAAI,kBAC3B,cAAc;;;aA3CV,GAAG;;;;;;;wBA1DI,GAAG,WAAW,OAAO,EAAE,KAAK,GAAG;wBAA/B,GAAG,WAAW,OAAO,EAAE,KAAK,GAAG;;wBAA/B,GAAG,WAAW,OAAO,EAAE,KAAK,GAAG;wBAA/B,GAAG,WAAW,OAAO,EAAE,KAAK,GAAG;GA6GpD;yCAzSuB,OAAO,EAAE,KAAK,GAAG,IAC5B,OAAO,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;6CAIlB,OAAO,EAAE,KAAK,GAAG,IAC5B,OAAO,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;yBAGpB,OAAO,qBAAqB,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC"}
package/src/callback.js CHANGED
@@ -2,7 +2,15 @@
2
2
  import { E } from '@endo/far';
3
3
  import { isObject, isPassableSymbol } from '@endo/marshal';
4
4
 
5
- const { Fail } = assert;
5
+ const { Fail, quote: q } = assert;
6
+
7
+ const { fromEntries } = Object;
8
+
9
+ const { ownKeys: rawOwnKeys } = Reflect;
10
+ const ownKeys =
11
+ /** @type {<T extends PropertyKey>(obj: {[K in T]?: unknown}) => T[]} */ (
12
+ rawOwnKeys
13
+ );
6
14
 
7
15
  /**
8
16
  * @template {(...args: unknown[]) => any} I
@@ -14,6 +22,24 @@ const { Fail } = assert;
14
22
  * @typedef {import('./types').SyncCallback<I>} SyncCallback
15
23
  */
16
24
 
25
+ /** @template T @typedef {import('@endo/eventual-send').RemotableBrand<{}, T> & T} Farable */
26
+
27
+ /**
28
+ * @param {unknown} key
29
+ * @returns {key is PropertyKey} FIXME: should be just `PropertyKey` but TS
30
+ * complains it can't be used as an index type.
31
+ */
32
+ const isPropertyKey = key => {
33
+ switch (typeof key) {
34
+ case 'string':
35
+ case 'number':
36
+ case 'symbol':
37
+ return true;
38
+ default:
39
+ return false;
40
+ }
41
+ };
42
+
17
43
  /**
18
44
  * Synchronously call a callback.
19
45
  *
@@ -29,6 +55,7 @@ export const callSync = (callback, ...args) => {
29
55
  }
30
56
  return target[methodName](...bound, ...args);
31
57
  };
58
+ harden(callSync);
32
59
 
33
60
  /**
34
61
  * Eventual send to a callback.
@@ -45,6 +72,7 @@ export const callE = (callback, ...args) => {
45
72
  }
46
73
  return E(target)[methodName](...bound, ...args);
47
74
  };
75
+ harden(callE);
48
76
 
49
77
  /**
50
78
  * Create a callback from a near function.
@@ -60,7 +88,7 @@ export const makeSyncFunctionCallback = (target, ...bound) => {
60
88
  typeof target === 'function' ||
61
89
  Fail`sync function callback target must be a function: ${target}`;
62
90
  /** @type {unknown} */
63
- const cb = harden({ target, bound });
91
+ const cb = harden({ target, bound, isSync: true });
64
92
  return /** @type {SyncCallback<I>} */ (cb);
65
93
  };
66
94
  harden(makeSyncFunctionCallback);
@@ -107,7 +135,7 @@ export const makeSyncMethodCallback = (target, methodName, ...bound) => {
107
135
  isPassableSymbol(methodName) ||
108
136
  Fail`method name must be a string or passable symbol: ${methodName}`;
109
137
  /** @type {unknown} */
110
- const cb = harden({ target, methodName, bound });
138
+ const cb = harden({ target, methodName, bound, isSync: true });
111
139
  return /** @type {SyncCallback<I>} */ (cb);
112
140
  };
113
141
  harden(makeSyncMethodCallback);
@@ -139,7 +167,7 @@ harden(makeMethodCallback);
139
167
 
140
168
  /**
141
169
  * @param {any} callback
142
- * @returns {callback is Callback}
170
+ * @returns {callback is Callback<any>}
143
171
  */
144
172
  export const isCallback = callback => {
145
173
  if (!isObject(callback)) {
@@ -155,3 +183,132 @@ export const isCallback = callback => {
155
183
  );
156
184
  };
157
185
  harden(isCallback);
186
+
187
+ /**
188
+ * Prepare an attenuator class whose methods can be redirected via callbacks.
189
+ *
190
+ * @template {PropertyKey} M
191
+ * @param {import('@agoric/zone').Zone} zone The zone in which to allocate attenuators.
192
+ * @param {M[]} methodNames Methods to forward.
193
+ * @param {object} opts
194
+ * @param {InterfaceGuard} [opts.interfaceGuard] An interface guard for the
195
+ * new attenuator.
196
+ * @param {string} [opts.tag] A tag for the new attenuator exoClass.
197
+ */
198
+ export const prepareAttenuator = (
199
+ zone,
200
+ methodNames,
201
+ { interfaceGuard, tag = 'Attenuator' } = {},
202
+ ) => {
203
+ /**
204
+ * @typedef {(this: any, ...args: unknown[]) => any} Method
205
+ * @typedef {{ [K in M]: Method }} Methods
206
+ * @typedef {{ [K in M]?: Callback<any> | null}} Overrides
207
+ */
208
+ const methods = fromEntries(
209
+ methodNames.map(key => {
210
+ // Only allow the `PropertyKey` type for the target method key.
211
+ if (!isPropertyKey(key)) {
212
+ throw Fail`key ${q(key)} is not a PropertyKey`;
213
+ }
214
+
215
+ const m = /** @type {Methods} */ ({
216
+ // Explicitly use concise method syntax to preserve `this` but prevent
217
+ // constructor behavior.
218
+ /** @type {Method} */
219
+ [key](...args) {
220
+ // Support both synchronous and async callbacks.
221
+ const cb = this.state.cbs[key];
222
+ if (!cb) {
223
+ const err = assert.error(
224
+ `unimplemented ${q(tag)} method ${q(key)}`,
225
+ );
226
+ if (this.state.isSync) {
227
+ throw err;
228
+ }
229
+ return Promise.reject(err);
230
+ }
231
+ if (cb.isSync) {
232
+ return callSync(cb, ...args);
233
+ }
234
+ return callE(cb, ...args);
235
+ },
236
+ })[key];
237
+ return /** @type {const} */ ([key, m]);
238
+ }),
239
+ );
240
+
241
+ const methodKeys = /** @type {M[]} */ (ownKeys(methods));
242
+
243
+ /**
244
+ * Create an exo object whose behavior is composed from a default target
245
+ * and/or individual method override callbacks.
246
+ *
247
+ * @param {object} opts
248
+ * @param {unknown} [opts.target] The target for any methods that
249
+ * weren't specified in `opts.overrides`.
250
+ * @param {boolean} [opts.isSync=false] Whether the target should be treated
251
+ * as synchronously available.
252
+ * @param {Overrides} [opts.overrides] Set individual
253
+ * callbacks for methods (whose names must be defined in the
254
+ * `prepareAttenuator` or `prepareGuardedAttenuator` call). Nullish overrides
255
+ * mean to throw.
256
+ */
257
+ const makeAttenuator = zone.exoClass(
258
+ tag,
259
+ interfaceGuard,
260
+ /**
261
+ * @param {object} opts
262
+ * @param {any} [opts.target]
263
+ * @param {boolean} [opts.isSync=false]
264
+ * @param {Overrides} [opts.overrides]
265
+ */
266
+ ({
267
+ target = null,
268
+ isSync = false,
269
+ overrides = /** @type {Overrides} */ ({}),
270
+ }) => {
271
+ const cbs = /** @type {Overrides} */ ({});
272
+
273
+ const remaining = new Set(methodKeys);
274
+ for (const key of ownKeys(overrides)) {
275
+ remaining.has(key) ||
276
+ Fail`${q(tag)} overrides[${q(key)}] not allowed by methodNames`;
277
+
278
+ remaining.delete(key);
279
+ const cb = overrides[key];
280
+ if (cb != null) {
281
+ isCallback(cb) ||
282
+ Fail`${q(tag)} overrides[${q(key)}] is not a callback; got ${cb}`;
283
+ }
284
+ cbs[key] = cb;
285
+ }
286
+ for (const key of remaining) {
287
+ if (isSync) {
288
+ cbs[key] = makeSyncMethodCallback(target, key);
289
+ } else {
290
+ cbs[key] = makeMethodCallback(target, key);
291
+ }
292
+ }
293
+ return harden({ cbs, isSync });
294
+ },
295
+ /** @type {Methods} */ (methods),
296
+ );
297
+ return makeAttenuator;
298
+ };
299
+ harden(prepareAttenuator);
300
+
301
+ /**
302
+ * Prepare an attenuator whose methodNames are derived from the interfaceGuard.
303
+ *
304
+ * @param {import('@agoric/zone').Zone} zone
305
+ * @param {InterfaceGuard} interfaceGuard
306
+ * @param {object} [opts]
307
+ * @param {string} [opts.tag]
308
+ */
309
+ export const prepareGuardedAttenuator = (zone, interfaceGuard, opts = {}) => {
310
+ const { methodGuards } = interfaceGuard;
311
+ const methodNames = ownKeys(methodGuards);
312
+ return prepareAttenuator(zone, methodNames, { ...opts, interfaceGuard });
313
+ };
314
+ harden(prepareGuardedAttenuator);
package/src/types.d.ts CHANGED
@@ -7,10 +7,14 @@ export declare class Callback<I extends (...args: unknown[]) => any> {
7
7
  public methodName?: PropertyKey;
8
8
 
9
9
  public bound: unknown[];
10
+
11
+ public isSync: boolean;
10
12
  }
11
13
 
12
14
  export declare class SyncCallback<
13
15
  I extends (...args: unknown[]) => any,
14
16
  > extends Callback<I> {
15
17
  private syncIface: I;
18
+
19
+ public isSync: true;
16
20
  }