Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 5x 133x 133x 6x 127x 127x 127x 127x 133x 133x 5x 69x 131x 131x 1x 130x | /**
* Filter providers by guard matching at an invocation point.
*/
import { GET_INTERFACE_GUARD } from '@endo/exo';
import { matches } from '@endo/patterns';
import type { InterfaceGuard } from '@endo/patterns';
import { getInterfaceMethodGuards, getMethodPayload } from './guard.ts';
import type { Section } from './types.ts';
/**
* Check whether an interface guard covers the invocation point (method, args).
*
* @param guard - The interface guard to test.
* @param method - The method name being invoked.
* @param args - The arguments to the method invocation.
* @returns True if the guard accepts the invocation.
*/
export const guardCoversPoint = (
guard: InterfaceGuard,
method: string,
args: unknown[],
): boolean => {
const methodGuards = getInterfaceMethodGuards(guard);
if (!(method in methodGuards)) {
return false;
}
const methodGuard = methodGuards[method];
Iif (!methodGuard) {
return false;
}
const { argGuards, optionalArgGuards, restArgGuard } =
getMethodPayload(methodGuard);
const optionals = optionalArgGuards ?? [];
const maxFixedArgs = argGuards.length + optionals.length;
return (
args.length >= argGuards.length &&
(restArgGuard !== undefined || args.length <= maxFixedArgs) &&
args
.slice(0, argGuards.length)
.every((arg, i) => matches(arg, argGuards[i])) &&
args
.slice(argGuards.length, maxFixedArgs)
.every((arg, i) => matches(arg, optionals[i])) &&
(restArgGuard === undefined ||
args.slice(maxFixedArgs).every((arg) => matches(arg, restArgGuard)))
);
};
/**
* Get the matching providers at an invocation point.
*
* Returns the providers whose guards accept the given method + args.
*
* @param providers - The providers to filter.
* @param method - The method name being invoked.
* @param args - The arguments to the method invocation.
* @returns The providers whose guards accept the invocation.
*/
export const getMatchingProviders = <T extends { exo: Section }>(
providers: readonly T[],
method: string,
args: unknown[],
): T[] => {
return providers.filter(({ exo }) => {
const interfaceGuard = exo[GET_INTERFACE_GUARD]?.();
if (!interfaceGuard) {
return false;
}
return guardCoversPoint(interfaceGuard, method, args);
});
};
|