Skip to content

Commit

Permalink
demo guards implying signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed Sep 30, 2023
1 parent 94e2ff6 commit 235e0fe
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 6 deletions.
10 changes: 5 additions & 5 deletions packages/vat-data/src/exo-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,13 @@ export const makeExoUtils = VatData => {
harden(prepareExoClassKit);

/**
* @template {Record<PropertyKey, CallableFunction>} M methods
* @template {InterfaceGuard} I
* @param {Baggage} baggage
* @param {string} kindName
* @param {InterfaceGuard | undefined} interfaceGuard
* @param {M} methods
* @param {DefineKindOptions<{ self: M }>} [options]
* @returns {M & RemotableBrand<{}, M>}
* @param {I | undefined} interfaceGuard
* @param {import('./types.js').GuardedMethods<I>} methods
* @param {DefineKindOptions<{ self: import('./types.js').GuardedMethods<I> }>} [options]
* @returns {import('./types.js').GuardedMethods<I> & RemotableBrand<{}, import('./types.js').GuardedMethods<I>>}
*/
const prepareExo = (
baggage,
Expand Down
41 changes: 40 additions & 1 deletion packages/vat-data/src/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
/* eslint-disable no-use-before-define */
import { expectType } from 'tsd';
import { expectNotType, expectType } from 'tsd';
import type {
KindFacets,
DurableKindHandle,
KindFacet,
FunctionsPlusContext,
} from '@agoric/swingset-liveslots';
import { TypedMatcher } from '@agoric/internal/src/types.js';
import {
defineKind,
defineKindMulti,
makeKindHandle,
defineDurableKind,
partialAssign,
prepareExo,
M,
} from '.';
import { GuardedMethod, TypedMethodGuard } from './types.js';

/*
export const makePaymentMaker = (allegedName: string, brand: unknown) => {
Expand Down Expand Up @@ -158,3 +162,38 @@ const someFacet: KindFacet<typeof someBehavior> = null as any;
// @ts-expect-error
someFacet.gt();
expectType<boolean>(someFacet.gt(1));

const Mnumber = M.number() as TypedMatcher<number>;

{
const numIdentityGuard = M.call(Mnumber).returns(Mnumber) as TypedMethodGuard<
(n: number) => number
>;
const numIdentity: GuardedMethod<typeof numIdentityGuard> = x => x;
expectType<number>(numIdentity(3));
}

{
const baggage = null as any;
const UpCounterI = M.interface('UpCounter', {
// TODO infer the TypedMethodGuard signature from the fluent builder
adjustBy: M.call(Mnumber).returns(Mnumber) as TypedMethodGuard<
(y: number) => number
>,
});
const exo = prepareExo(baggage, 'upCounter', UpCounterI, {
adjustBy(y) {
expectType<number>(y);
expectNotType<any>(y);
return y;
},
});
expectType<(y: number) => number>(exo.adjustBy);

prepareExo(baggage, 'upCounter', UpCounterI, {
// @ts-expect-error invalid return type
adjustBy(y) {
return 'hi';
},
});
}
25 changes: 25 additions & 0 deletions packages/vat-data/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { MatcherType } from '@agoric/internal/src/types.js';
import type { InterfaceGuard } from '@endo/patterns';

type MethodGuardPayload = {
callKind: 'sync' | 'async';
argGuards: ArgGuard[];
optionalArgGuards?: ArgGuard[];
restArgGuard?: unknown;
returnGuard: unknown;
};

declare const methodSignature: unique symbol;
export type TypedMethodGuard<F extends Function> = {
klass: 'methodGuard';
} & MethodGuardPayload & { methodSignature: F };

export type GuardedMethod<G extends MethodGuard> = G extends TypedMethodGuard<
infer F
>
? F
: unknown;

export type GuardedMethods<I extends InterfaceGuard> = {
readonly [P in keyof I['methodGuards']]: GuardedMethod<I['methodGuards'][P]>;
};

0 comments on commit 235e0fe

Please sign in to comment.