Skip to content

Commit

Permalink
fix: less mutate-y
Browse files Browse the repository at this point in the history
  • Loading branch information
erights committed Jun 15, 2023
1 parent 343d4d0 commit 00c807e
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 26 deletions.
2 changes: 2 additions & 0 deletions packages/exo/src/exo-makers.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const initEmpty = () => emptyRecord;
* @returns {(...args: Parameters<I>) => (M & import('@endo/eventual-send').RemotableBrand<{}, M>)}
*/
export const defineExoClass = (tag, interfaceGuard, init, methods, options) => {
harden(methods);
const { finish = undefined } = options || {};
/** @type {WeakMap<M,ClassContext<ReturnType<I>, M>>} */
const contextMap = new WeakMap();
Expand Down Expand Up @@ -133,6 +134,7 @@ export const defineExoClassKit = (
methodsKit,
options,
) => {
harden(methodsKit);
const { finish = undefined } = options || {};
const contextMapKit = objectMap(methodsKit, () => new WeakMap());
const getContextKit = objectMap(
Expand Down
40 changes: 14 additions & 26 deletions packages/exo/src/exo-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,32 +217,19 @@ const bindMethod = (
export const GET_INTERFACE_GUARD = Symbol.for('getInterfaceGuard');

/**
* Mutates `behaviorMethods` argument!
*
* @template {Record<string | symbol, CallableFunction>} T
* @param {T} behaviorMethods
* @param {import('@endo/patterns').InterfaceGuard} interfaceGuard
* @returns {T}
*/
const addGetInterfaceGuardMethod = (behaviorMethods, interfaceGuard) => {
if (!hasOwnPropertyOf(behaviorMethods, GET_INTERFACE_GUARD)) {
// Note that we do not also update the interfaceGuard to describe this
// meta method. Currently, it is a symbol-named method, so we cannot
// anyway.
const getInterfaceGuardMethod = {
[GET_INTERFACE_GUARD]() {
return interfaceGuard;
},
}[GET_INTERFACE_GUARD];
defineProperties(behaviorMethods, {
[GET_INTERFACE_GUARD]: {
value: getInterfaceGuardMethod,
writable: false,
enumerable: false,
configurable: false,
},
});
}
};
const withGetInterfaceGuardMethod = (behaviorMethods, interfaceGuard) =>
harden({
[GET_INTERFACE_GUARD]() {
return interfaceGuard;
},
...behaviorMethods,
});

/**
* @template {Record<string | symbol, CallableFunction>} T
Expand All @@ -260,14 +247,13 @@ export const defendPrototype = (
thisfulMethods = false,
interfaceGuard = undefined,
) => {
// local mutable copy
defineProperties(behaviorMethods, getOwnPropertyDescriptors(behaviorMethods));
const prototype = {};
if (hasOwnPropertyOf(behaviorMethods, 'constructor')) {
// By ignoring any method named "constructor", we can use a
// class.prototype as a behaviorMethods.
const { constructor: _, ...methods } = behaviorMethods;
// @ts-expect-error TS misses that hasOwn check makes this safe
assert(delete behaviorMethods.constructor);
behaviorMethods = methods;
}
let methodGuards;
if (interfaceGuard) {
Expand All @@ -292,8 +278,10 @@ export const defendPrototype = (
Fail`methods ${q(unguarded)} not guarded by ${q(interfaceName)}`;
}
}
// mutates behaviorMethods
addGetInterfaceGuardMethod(behaviorMethods, interfaceGuard);
behaviorMethods = withGetInterfaceGuardMethod(
behaviorMethods,
interfaceGuard,
);
}

for (const prop of ownKeys(behaviorMethods)) {
Expand Down

0 comments on commit 00c807e

Please sign in to comment.