@@ -5,7 +5,7 @@ const { details: X, quote: q, Fail, error: makeError } = assert;
55const { assign, freeze } = Object ;
66
77/**
8- * @import { HandledPromiseConstructor } from './types.js';
8+ * @import { HandledPromiseConstructor, RemotableBrand, Callable, Settler } from './types.js';
99 */
1010
1111const onSend = makeMessageBreakpointTester ( 'ENDO_SEND_BREAKPOINTS' ) ;
@@ -282,15 +282,15 @@ export default makeE;
282282 *
283283 * @template Primary The type of the primary reference.
284284 * @template [Local=DataOnly<Primary>] The local properties of the object.
285- * @typedef {ERef<Local & import('./types.js'). RemotableBrand<Local, Primary>> } FarRef
285+ * @typedef {ERef<Local & RemotableBrand<Local, Primary>> } FarRef
286286 */
287287
288288/**
289289 * `DataOnly<T>` means to return a record type `T2` consisting only of
290290 * properties that are *not* functions.
291291 *
292292 * @template T The type to be filtered.
293- * @typedef {Omit<T, FilteredKeys<T, import('./types.js'). Callable>> } DataOnly
293+ * @typedef {Omit<T, FilteredKeys<T, Callable>> } DataOnly
294294 */
295295
296296/**
@@ -304,24 +304,69 @@ export default makeE;
304304
305305/**
306306 * The awaited return type of a function.
307+ * For the eventual result of an E call, @see {EResult} or @see {ECallableReturn}
307308 *
308309 * @template {(...args: any[]) => any} T
309310 * @typedef {T extends (...args: any[]) => infer R ? Awaited<R> : never } EReturn
310311 */
311312
312313/**
313- * @template {import('./types.js').Callable} T
314+ * An eventual value where remotable objects are recursively mapped to Remote types
315+ *
316+ * @template T
317+ * @typedef {Awaited<T> } EResult
318+ */
319+
320+ /**
321+ * Experimental type mapping remotable objects to Remote types
322+ *
323+ * @template T
314324 * @typedef {(
315- * ReturnType<T> extends PromiseLike<infer U> // if function returns a promise
316- * ? T // return the function
317- * : (...args: Parameters<T>) => Promise<EReturn<T>> // make it return a promise
325+ * 0 extends (1 & T) // If T is any
326+ * ? T // Propagate the any type through the result
327+ * : T extends RemotableBrand<infer L, infer P> // If we have a Remotable
328+ * ? (P | RemotableBrand<L, P>) // map it to its "maybe remote" form (primary behavior or remotable presence)
329+ * : T extends PromiseLike<infer U> // If T is a promise
330+ * ? Promise<EAwaitedResult<Awaited<T>>> // map its resolution
331+ * : T extends (null | undefined | string | number | boolean | symbol | bigint | Callable) // Intersections of these types with objects are not mapped
332+ * ? T // primitives and non-remotable functions are passed-through
333+ * : T extends object //
334+ * ? { [P in keyof T]: EAwaitedResult<T[P]>; } // other objects are considered copy data and properties mapped
335+ * : T // in case anything wasn't covered, fallback to pass-through
336+ * )} EAwaitedResult
337+ */
338+
339+ /**
340+ * The @see {EResult} return type of a remote function.
341+ *
342+ * @template {(...args: any[]) => any} T
343+ * @typedef {(
344+ * 0 extends (1 & T) // If T is any
345+ * ? any // Propagate the any type through the result
346+ * : T extends (...args: any[]) => infer R // Else infer the return type
347+ * ? EResult<R> // In the future, map the eventual result
348+ * : never
349+ * )} ECallableReturn
350+ */
351+
352+ // TODO: Figure out a way to map generic callable return types, or at least better detect them.
353+ // See https://github.com/microsoft/TypeScript/issues/61838. Without that, `E(startGovernedUpgradable)`
354+ // in agoric-sdk doesn't propagate the start function type.
355+ /**
356+ * Maps a callable to its remotely called type
357+ *
358+ * @template {Callable} T
359+ * @typedef {(
360+ * ReturnType<T> extends PromiseLike<infer U> // Check if callable returns a promise
361+ * ? T // Bypass mapping to maintain any generic
362+ * : (...args: Parameters<T>) => Promise<ECallableReturn<T>> // Map it anyway to ensure promise return type
318363 * )} ECallable
319364 */
320365
321366/**
322367 * @template T
323368 * @typedef {{
324- * readonly [P in keyof T]: T[P] extends import('./types.js'). Callable
369+ * readonly [P in keyof T]: T[P] extends Callable
325370 * ? ECallable<T[P]>
326371 * : never;
327372 * }} EMethods
@@ -337,14 +382,14 @@ export default makeE;
337382 */
338383
339384/**
340- * @template {import('./types.js'). Callable} T
385+ * @template {Callable} T
341386 * @typedef {(...args: Parameters<T>) => Promise<void> } ESendOnlyCallable
342387 */
343388
344389/**
345390 * @template T
346391 * @typedef {{
347- * readonly [P in keyof T]: T[P] extends import('./types.js'). Callable
392+ * readonly [P in keyof T]: T[P] extends Callable
348393 * ? ESendOnlyCallable<T[P]>
349394 * : never;
350395 * }} ESendOnlyMethods
@@ -353,18 +398,22 @@ export default makeE;
353398/**
354399 * @template T
355400 * @typedef {(
356- * T extends import('./types.js'). Callable
401+ * T extends Callable
357402 * ? ESendOnlyCallable<T> & ESendOnlyMethods<Required<T>>
358- * : ESendOnlyMethods<Required<T>>
403+ * : 0 extends (1 & T)
404+ * ? never
405+ * : ESendOnlyMethods<Required<T>>
359406 * )} ESendOnlyCallableOrMethods
360407 */
361408
362409/**
363410 * @template T
364411 * @typedef {(
365- * T extends import('./types.js'). Callable
412+ * T extends Callable
366413 * ? ECallable<T> & EMethods<Required<T>>
367- * : EMethods<Required<T>>
414+ * : 0 extends (1 & T)
415+ * ? never
416+ * : EMethods<Required<T>>
368417 * )} ECallableOrMethods
369418 */
370419
@@ -389,9 +438,9 @@ export default makeE;
389438 *
390439 * @template T
391440 * @typedef {(
392- * T extends import('./types.js'). Callable
441+ * T extends Callable
393442 * ? (...args: Parameters<T>) => ReturnType<T> // a root callable, no methods
394- * : Pick<T, FilteredKeys<T, import('./types.js'). Callable>> // any callable methods
443+ * : Pick<T, FilteredKeys<T, Callable>> // any callable methods
395444 * )} PickCallable
396445 */
397446
@@ -400,25 +449,21 @@ export default makeE;
400449 *
401450 * @template T
402451 * @typedef {(
403- * T extends import('./types.js').RemotableBrand<infer L, infer R> // if a given T is some remote interface R
404- * ? PickCallable<R> // then return the callable properties of R
405- * : Awaited<T> extends import('./types.js').RemotableBrand<infer L, infer R> // otherwise, if the final resolution of T is some remote interface R
406- * ? PickCallable<R> // then return the callable properties of R
407- * : T extends PromiseLike<infer U> // otherwise, if T is a promise
408- * ? Awaited<T> // then return resolved value T
409- * : T // otherwise, return T
452+ * T extends RemotableBrand<infer L, infer R> // if a given T is some remote interface R
453+ * ? PickCallable<R> // then return the callable properties of R
454+ * : T extends PromiseLike<infer U> // otherwise, if T is a promise
455+ * ? RemoteFunctions<U> // recurse on the resolved value of T
456+ * : T // otherwise, return T
410457 * )} RemoteFunctions
411458 */
412459
413460/**
414461 * @template T
415462 * @typedef {(
416- * T extends import('./types.js').RemotableBrand<infer L, infer R>
417- * ? L
418- * : Awaited<T> extends import('./types.js').RemotableBrand<infer L, infer R>
463+ * T extends RemotableBrand<infer L, infer R>
419464 * ? L
420465 * : T extends PromiseLike<infer U>
421- * ? Awaited<T >
466+ * ? LocalRecord<U >
422467 * : T
423468 * )} LocalRecord
424469 */
@@ -427,7 +472,7 @@ export default makeE;
427472 * @template [R = unknown]
428473 * @typedef {{
429474 * promise: Promise<R>;
430- * settler: import('./types.js'). Settler<R>;
475+ * settler: Settler<R>;
431476 * }} EPromiseKit
432477 */
433478
@@ -438,11 +483,11 @@ export default makeE;
438483 *
439484 * @template T
440485 * @typedef {(
441- * T extends import('./types.js'). Callable
486+ * T extends Callable
442487 * ? (...args: Parameters<T>) => ERef<Awaited<EOnly<ReturnType<T>>>>
443- * : T extends Record<PropertyKey, import('./types.js'). Callable>
488+ * : T extends Record<PropertyKey, Callable>
444489 * ? {
445- * [K in keyof T]: T[K] extends import('./types.js'). Callable
490+ * [K in keyof T]: T[K] extends Callable
446491 * ? (...args: Parameters<T[K]>) => ERef<Awaited<EOnly<ReturnType<T[K]>>>>
447492 * : T[K];
448493 * }
0 commit comments