Skip to content

Commit

Permalink
feat(vowTools): add asVow helper
Browse files Browse the repository at this point in the history
- adds asVow() helper function that coerces the result of a function to a Vow
- see comment from @mhofman for inspiration: #9454 (comment)
  • Loading branch information
0xpatrickdev committed Jun 25, 2024
1 parent 3aa5d66 commit b6b5f5f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 4 deletions.
6 changes: 4 additions & 2 deletions packages/vow/src/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { makeWhen } from './when.js';
import { prepareVowKit } from './vow.js';
import { prepareWatch } from './watch.js';
import { prepareWatchUtils } from './watch-utils.js';
import { makeAsVow } from './vow-utils.js';

/** @import {Zone} from '@agoric/base-zone' */
/** @import {IsRetryableReason} from './types.js' */
/** @import {IsRetryableReason, Vow} from './types.js' */

/**
* @param {Zone} zone
Expand All @@ -20,6 +21,7 @@ export const prepareVowTools = (zone, powers = {}) => {
const watch = prepareWatch(zone, makeVowKit, isRetryableReason);
const makeWatchUtils = prepareWatchUtils(zone, watch, makeVowKit);
const watchUtils = makeWatchUtils();
const asVow = makeAsVow(makeVowKit);

/**
* Vow-tolerant implementation of Promise.all.
Expand All @@ -28,7 +30,7 @@ export const prepareVowTools = (zone, powers = {}) => {
*/
const allVows = vows => watchUtils.all(vows);

return harden({ when, watch, makeVowKit, allVows });
return harden({ when, watch, makeVowKit, allVows, asVow });
};
harden(prepareVowTools);

Expand Down
27 changes: 25 additions & 2 deletions packages/vow/src/vow-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { isPassable } from '@endo/pass-style';
import { M, matches } from '@endo/patterns';

/**
* @import {PassableCap} from '@endo/pass-style'
* @import {VowPayload, Vow} from './types.js'
* @import {PassableCap} from '@endo/pass-style';
* @import {VowPayload, Vow} from './types.js';
* @import {MakeVowKit} from './vow.js';
*/

export { basicE };
Expand Down Expand Up @@ -73,3 +74,25 @@ export const toPassableCap = k => {
return vowV0;
};
harden(toPassableCap);

/** @param {MakeVowKit} makeVowKit */
export const makeAsVow = makeVowKit => {
/**
* Helper function that coerces the result of a function to a Vow. Helpful
* for scenarios like a synchronously thrown error.
* @template {any} T
* @param {(...args: any[]) => Vow<Awaited<T>> | Awaited<T>} fn
* @returns {Vow<Awaited<T>>}
*/
const asVow = fn => {
const kit = makeVowKit();
try {
kit.resolver.resolve(fn());
} catch (e) {
kit.resolver.reject(e);
}
return kit.vow;
};
return harden(asVow);
};
harden(makeAsVow);
1 change: 1 addition & 0 deletions packages/vow/src/vow.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ export const prepareVowKit = zone => {

return makeVowKit;
};
/** @typedef {ReturnType<typeof prepareVowKit>} MakeVowKit */

harden(prepareVowKit);
32 changes: 32 additions & 0 deletions packages/vow/test/asVow.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @ts-check
import test from 'ava';

import { makeHeapZone } from '@agoric/base-zone/heap.js';

import { prepareVowTools } from '../src/tools.js';
import { isVow } from '../src/vow-utils.js';

test('asVow takes a function that throws/returns synchronously and returns a vow', async t => {
const zone = makeHeapZone();
const { watch, when, asVow } = prepareVowTools(zone);

const fnThatThrows = () => {
throw Error('fail');
};

const vowWithRejection = asVow(fnThatThrows);
t.true(isVow(vowWithRejection));
await t.throwsAsync(when(vowWithRejection), { message: 'fail' }, 'failure ');

const isWatchAble = watch(asVow(fnThatThrows));
t.true(isVow(vowWithRejection));
await t.throwsAsync(when(isWatchAble), { message: 'fail' }, 'failure ');

const fnThatReturns = () => {
return 'early return';
};
const vowWithReturn = asVow(fnThatReturns);
t.true(isVow(vowWithReturn));
t.is(await when(vowWithReturn), 'early return');
t.is(await when(watch(vowWithReturn)), 'early return');
});

0 comments on commit b6b5f5f

Please sign in to comment.