Skip to content

Commit

Permalink
fix(unwrap): pass through non-Thenables before throwing
Browse files Browse the repository at this point in the history
Closes #518

This makes unwrap a lot more useful in the case when the
calling code may or may not be in a different vat than the supplied
argument.
  • Loading branch information
michaelfig committed Feb 7, 2020
1 parent 4509968 commit 70054c4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
15 changes: 14 additions & 1 deletion packages/eventual-send/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,25 @@ export function makeHandledPromise(Promise) {
// handled. Or, at least, the ability to tell given that the
// promise is already fulfilled.
unwrap(value) {
// This check for Thenable is safe, since in a remote-object
// environment, our comms system will defend against remote
// objects being represented as a tricky local Proxy, otherwise
// it is guaranteed to be local and therefore synchronous enough.
if (Object(value) !== value || !('then' in value)) {
// Not a Thenable, so return it.
// This means that local objects will pass through without error.
return value;
}

// Try to look up the HandledPromise.
ensureMaps();
const pr = presenceToPromise.get(value) || value;

// Find the fulfilled presence for that HandledPromise.
const presence = promiseToPresence.get(pr);
if (!presence) {
throw TypeError(
`Value is not a presence nor a HandledPromise resolved to a presence`,
`Value is a Thenble but not a HandledPromise fulfilled to a presence`,
);
}
return presence;
Expand Down
23 changes: 21 additions & 2 deletions packages/eventual-send/test/test-hp.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,29 @@ test('chained properties', async t => {

test('HandledPromise.unwrap', async t => {
try {
for (const [val, desc] of [
[{}, 'object'],
[true, 'true'],
[false, 'false'],
[undefined, 'undefined'],
[null, 'null'],
]) {
t.equal(HandledPromise.unwrap(val), val, `unwrapped ${desc} is equal`);
}
const t0 = {
then() {},
};
t.throws(
() => HandledPromise.unwrap(t0),
TypeError,
`unwrapped thenable object throws`,
);
const t1 = () => {};
t1.then = () => {};
t.throws(
() => HandledPromise.unwrap({}),
() => HandledPromise.unwrap(t1),
TypeError,
`unwrapped non-presence throws`,
`unwrapped thenable function throws`,
);
const p0 = new Promise(_ => {});
t.throws(
Expand Down

0 comments on commit 70054c4

Please sign in to comment.