Skip to content

Commit

Permalink
Merge pull request #1859 from endojs/mfig-unbreak-callWhen
Browse files Browse the repository at this point in the history
fix(exo): update `M.callWhen` broken by `M.raw()`
  • Loading branch information
michaelfig authored Nov 10, 2023
2 parents e4d9de9 + 015696d commit 3dbeff7
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
40 changes: 32 additions & 8 deletions packages/exo/src/exo-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ const defendSyncMethod = (method, methodGuardPayload, label) => {
return syncMethod;
};

/**
* @param {MethodGuardPayload} methodGuardPayload
*/
const desync = methodGuardPayload => {
const {
argGuards,
Expand Down Expand Up @@ -210,22 +213,43 @@ const desync = methodGuardPayload => {
};
};

/**
* @param {(...args: unknown[]) => any} method
* @param {MethodGuardPayload} methodGuardPayload
* @param {string} label
*/
const defendAsyncMethod = (method, methodGuardPayload, label) => {
const { returnGuard } = methodGuardPayload;
const isRawReturn = isRawGuard(returnGuard);

const { awaitIndexes, rawMethodGuardPayload } = desync(methodGuardPayload);
const matchConfig = buildMatchConfig(rawMethodGuardPayload);

const { asyncMethod } = {
// Note purposeful use of `this` and concise method syntax
asyncMethod(...args) {
const awaitList = awaitIndexes.map(i => args[i]);
const awaitList = [];
for (const i of awaitIndexes) {
if (i >= args.length) {
break;
}
awaitList.push(args[i]);
}
const p = Promise.all(awaitList);
const syncArgs = [...args];
const resultP = E.when(p, awaitedArgs => {
for (let j = 0; j < awaitIndexes.length; j += 1) {
syncArgs[awaitIndexes[j]] = awaitedArgs[j];
}
const realArgs = defendSyncArgs(syncArgs, rawMethodGuardPayload, label);
return apply(method, this, realArgs);
});
const resultP = E.when(
p,
/** @param {any[]} awaitedArgs */ awaitedArgs => {
for (let j = 0; j < awaitedArgs.length; j += 1) {
syncArgs[awaitIndexes[j]] = awaitedArgs[j];
}
const realArgs = defendSyncArgs(syncArgs, matchConfig, label);
return apply(method, this, realArgs);
},
);
if (isRawReturn) {
return resultP;
}
return E.when(resultP, result => {
mustMatch(harden(result), returnGuard, `${label}: result`);
return result;
Expand Down
13 changes: 13 additions & 0 deletions packages/exo/test/test-heap-classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ test('what happens with extra arguments', t => {
exo.foo('an extra arg');
});

const OptionalArrayI = M.interface('OptionalArray', {
foo: M.callWhen().optional(M.arrayOf(M.any())).returns(),
});

test('callWhen-guarded method called without optional array argument', async t => {
const exo = makeExo('WithNoOption', OptionalArrayI, {
async foo(arr) {
t.is(arr, undefined);
},
});
await t.notThrowsAsync(() => exo.foo());
});

const UpCounterI = M.interface('UpCounter', {
incr: M.call()
// TODO M.number() should not be needed to get a better error message
Expand Down

0 comments on commit 3dbeff7

Please sign in to comment.