Skip to content

Commit

Permalink
Merge pull request #1831 from endojs/mfig-interface-optout
Browse files Browse the repository at this point in the history
feat: support `M.raw()` in method guards
  • Loading branch information
michaelfig committed Oct 29, 2023
2 parents 126d1b0 + a0b3a5c commit 746974b
Show file tree
Hide file tree
Showing 10 changed files with 457 additions and 136 deletions.
2 changes: 1 addition & 1 deletion packages/exo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ export {
makeExo,
} from './src/exo-makers.js';

export { GET_INTERFACE_GUARD } from './src/exo-tools.js';
export { GET_INTERFACE_GUARD } from './src/get-interface.js';
50 changes: 34 additions & 16 deletions packages/exo/src/exo-makers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ const DEBUG = getEnvironmentOption('DEBUG', '');
// Turn on to give each exo instance its own toStringTag value.
const LABEL_INSTANCES = DEBUG.split(',').includes('label-instances');

/**
* @template {{}} T
* @param {T} proto
* @param {number} instanceCount
* @returns {T}
*/
const makeSelf = (proto, instanceCount) => {
const self = create(proto);
if (LABEL_INSTANCES) {
Expand Down Expand Up @@ -82,6 +88,21 @@ export const initEmpty = () => emptyRecord;
* @property {ReceiveRevoker} [receiveRevoker]
*/

/**
* @template {Methods} M
* @typedef {M & import('@endo/eventual-send').RemotableBrand<{}, M>} Farable
*/

/**
* @template {Methods} M
* @typedef {Farable<M & import('./get-interface.js').GetInterfaceGuard<M>>} Guarded
*/

/**
* @template {Record<FacetName, Methods>} F
* @typedef {{ [K in keyof F]: Guarded<F[K]> }} GuardedKit
*/

/**
* @template {(...args: any[]) => any} I init function
* @template {Methods} M methods
Expand All @@ -90,9 +111,9 @@ export const initEmpty = () => emptyRecord;
* [K in keyof M]: import("@endo/patterns").MethodGuard
* }> | undefined} interfaceGuard
* @param {I} init
* @param {M & ThisType<{ self: M, state: ReturnType<I> }>} methods
* @param {M & ThisType<{ self: Guarded<M>, state: ReturnType<I> }>} methods
* @param {FarClassOptions<ClassContext<ReturnType<I>, M>>} [options]
* @returns {(...args: Parameters<I>) => (M & import('@endo/eventual-send').RemotableBrand<{}, M>)}
* @returns {(...args: Parameters<I>) => Guarded<M>}
*/
export const defineExoClass = (
tag,
Expand Down Expand Up @@ -120,7 +141,6 @@ export const defineExoClass = (
// Be careful not to freeze the state record
const state = seal(init(...args));
instanceCount += 1;
/** @type {M} */
const self = makeSelf(proto, instanceCount);

// Be careful not to freeze the state record
Expand All @@ -130,9 +150,7 @@ export const defineExoClass = (
if (finish) {
finish(context);
}
return /** @type {M & import('@endo/eventual-send').RemotableBrand<{}, M>} */ (
self
);
return self;
};

if (receiveRevoker) {
Expand All @@ -149,13 +167,13 @@ harden(defineExoClass);
* @template {(...args: any[]) => any} I init function
* @template {Record<FacetName, Methods>} F facet methods
* @param {string} tag
* @param {{ [K in keyof F]: import("@endo/patterns").InterfaceGuard<{
* [M in keyof F[K]]: import("@endo/patterns").MethodGuard;
* }> } | undefined} interfaceGuardKit
* @param {{ [K in keyof F]:
* InterfaceGuard<{[M in keyof F[K]]: MethodGuard; }>
* } | undefined} interfaceGuardKit
* @param {I} init
* @param {F & ThisType<{ facets: F, state: ReturnType<I> }> } methodsKit
* @param {FarClassOptions<KitContext<ReturnType<I>,F>>} [options]
* @returns {(...args: Parameters<I>) => F}
* @param {F & { [K in keyof F]: ThisType<{ facets: GuardedKit<F>, state: ReturnType<I> }> }} methodsKit
* @param {FarClassOptions<KitContext<ReturnType<I>, GuardedKit<F>>>} [options]
* @returns {(...args: Parameters<I>) => GuardedKit<F>}
*/
export const defineExoClassKit = (
tag,
Expand Down Expand Up @@ -186,8 +204,8 @@ export const defineExoClassKit = (
// Be careful not to freeze the state record
const state = seal(init(...args));
// Don't freeze context until we add facets
/** @type {KitContext<ReturnType<I>,F>} */
const context = { state, facets: {} };
/** @type {{ state: ReturnType<I>, facets: unknown }} */
const context = { state, facets: null };
instanceCount += 1;
const facets = objectMap(prototypeKit, (proto, facetName) => {
const self = makeSelf(proto, instanceCount);
Expand All @@ -200,7 +218,7 @@ export const defineExoClassKit = (
if (finish) {
finish(context);
}
return context.facets;
return /** @type {GuardedKit<F>} */ (context.facets);
};

if (receiveRevoker) {
Expand All @@ -222,7 +240,7 @@ harden(defineExoClassKit);
* }> | undefined} interfaceGuard CAVEAT: static typing does not yet support `callWhen` transformation
* @param {T} methods
* @param {FarClassOptions<ClassContext<{},T>>} [options]
* @returns {T & import('@endo/eventual-send').RemotableBrand<{}, T>}
* @returns {Guarded<T>}
*/
export const makeExo = (tag, interfaceGuard, methods, options = undefined) => {
const makeInstance = defineExoClass(
Expand Down
Loading

0 comments on commit 746974b

Please sign in to comment.