@agoric/internal 0.2.2-dev-3fa74c5.0 → 0.2.2-dev-acc2db2.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-acc2db2.0+acc2db2",
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-acc2db2.0+acc2db2",
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": "acc2db25a2c6e50b45848ba9a848c4a71145033e"
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);
@@ -37,7 +37,10 @@ export function makeFakeStorageKit(rootPath: string, rootOptions?: [handleStorag
37
37
  };
38
38
  export function makeMockChainStorageRoot(): {
39
39
  /**
40
- * Defaults to deserializing pass-by-presence objects into Remotable objects.
40
+ * Defaults to deserializing slot references into plain Remotable
41
+ * objects, but if supplied with a different marshaller, it could
42
+ * produce Remotables with e.g. the slog string embedded in the
43
+ * iface.
41
44
  *
42
45
  * @param {string} path
43
46
  * @param {import('./lib-chainStorage.js').Marshaller} marshaller
@@ -53,7 +56,10 @@ export function makeMockChainStorageRoot(): {
53
56
  setValue(value: string): Promise<void>;
54
57
  } & import("@endo/eventual-send").RemotableBrand<{}, {
55
58
  /**
56
- * Defaults to deserializing pass-by-presence objects into Remotable objects.
59
+ * Defaults to deserializing slot references into plain Remotable
60
+ * objects, but if supplied with a different marshaller, it could
61
+ * produce Remotables with e.g. the slog string embedded in the
62
+ * iface.
57
63
  *
58
64
  * @param {string} path
59
65
  * @param {import('./lib-chainStorage.js').Marshaller} marshaller
@@ -1 +1 @@
1
- {"version":3,"file":"storage-test-utils.d.ts","sourceRoot":"","sources":["storage-test-utils.js"],"names":[],"mappings":"AAcO,yCAHI,MAAM,UACN,MAAM,wDAGC;AAElB;;;GAGG;AACH;;;;;EAEG;AAiBW,+CAAU,GAAG,GAAK,GAAG,CAAA;AA+B5B,6CAHI,MAAM,gBACN;;eAAwC,CAAC,CAAC;;;;;;;;;;;;;;;;;;yBAOvC,OAAO,4BAA4B,EAAE,cAAc;;;;EAkDhE;AAIM;IAIH;;;;;;OAMG;oBAHQ,MAAM,eACN,OAAO,uBAAuB,EAAE,UAAU,KACxC,OAAO;;;;;;;;;IALpB;;;;;;OAMG;oBAHQ,MAAM,eACN,OAAO,uBAAuB,EAAE,UAAU,KACxC,OAAO;;;;;;;;GAevB;6BA1Ba,WAAY,yBAAyB,CAAC;mCA2BtC,WAAW,+BAA+B,CAAC"}
1
+ {"version":3,"file":"storage-test-utils.d.ts","sourceRoot":"","sources":["storage-test-utils.js"],"names":[],"mappings":"AAeO,yCAHI,MAAM,UACN,MAAM,wDAGC;AAElB;;;GAGG;AACH;;;;;EAEG;AAsBW,+CAAU,GAAG,GAAK,GAAG,CAAA;AA+B5B,6CAHI,MAAM,gBACN;;eAAwC,CAAC,CAAC;;;;;;;;;;;;;;;;;;yBAOvC,OAAO,4BAA4B,EAAE,cAAc;;;;EAkDhE;AAIM;IAIH;;;;;;;;;OASG;oBAHQ,MAAM,eACN,OAAO,uBAAuB,EAAE,UAAU,KACxC,OAAO;;;;;;;;;IARpB;;;;;;;;;OASG;oBAHQ,MAAM,eACN,OAAO,uBAAuB,EAAE,UAAU,KACxC,OAAO;;;;;;;;GAevB;6BA7Ba,WAAY,yBAAyB,CAAC;mCA8BtC,WAAW,+BAA+B,CAAC"}
@@ -7,12 +7,13 @@ import { bindAllMethods } from './method-tools.js';
7
7
  const { Fail, quote: q } = assert;
8
8
 
9
9
  /**
10
- * A convertSlotToVal function that produces basic Remotables
10
+ * A convertSlotToVal function that produces basic Remotables. Assumes
11
+ * that all slots are Remotables (i.e. none are Promises).
11
12
  *
12
13
  * @param {string} _slotId
13
14
  * @param {string} iface
14
15
  */
15
- export const slotToRemotable = (_slotId, iface = 'Alleged: Remotable') =>
16
+ export const slotToRemotable = (_slotId, iface = 'Remotable') =>
16
17
  Remotable(iface);
17
18
 
18
19
  /**
@@ -31,8 +32,13 @@ export const defaultMarshaller = makeMarshal(undefined, slotToRemotable, {
31
32
  *
32
33
  * This may be useful for display purposes.
33
34
  *
34
- * One limitation: serialized data that contains a particular unusual
35
- * string will be unserialized into a BigInt.
35
+ * Limitations:
36
+ * * it cannot handle Symbols (registered or well-known)
37
+ * * it can handle BigInts, but serialized data that contains a
38
+ * particular unusual string will be unserialized into a BigInt by
39
+ * mistake
40
+ * * it cannot handle Promises, NaN, +/- Infinity, undefined, or
41
+ * other non-JSONable JavaScript values
36
42
  */
37
43
  const makeSlotStringUnserialize = () => {
38
44
  /** @type { (slot: string, iface: string) => any } */
@@ -133,7 +139,10 @@ export const makeMockChainStorageRoot = () => {
133
139
  return Far('mockChainStorage', {
134
140
  ...bindAllMethods(rootNode),
135
141
  /**
136
- * Defaults to deserializing pass-by-presence objects into Remotable objects.
142
+ * Defaults to deserializing slot references into plain Remotable
143
+ * objects, but if supplied with a different marshaller, it could
144
+ * produce Remotables with e.g. the slog string embedded in the
145
+ * iface.
137
146
  *
138
147
  * @param {string} path
139
148
  * @param {import('./lib-chainStorage.js').Marshaller} marshaller
@@ -148,7 +157,7 @@ export const makeMockChainStorageRoot = () => {
148
157
  }
149
158
  assert.typeof(dataStr, 'string');
150
159
  const datum = JSON.parse(dataStr);
151
- return marshaller.unserialize(datum);
160
+ return marshaller.fromCapData(datum);
152
161
  },
153
162
  keys: () => [...data.keys()],
154
163
  });
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
  }