cloudflare / cloudflare/capnweb

native Promise accepted by types but not serializable at runtime

Open
#146 2 comments 0 reactions 1 assignee Claimed by @teamchong View on GitHub
Dominant language
TypeScript
Stars
4k
Forks
143
Avg merge
4d 6h
Merged PRs (30d)
7

Description

When passing native promises in a stub call, a `TypeError: Cannot serialize value: [object Promise]` runtime error is thrown. No ts error is given.

~~It is unclear whether native promises are intended to be supported or not, since~~ a comment in `types.d.ts` mentions all promises, even though the current library throws an error on native promises:
https://github.com/cloudflare/capnweb/blob/686da4465b0f42b4f2a30ba93c2b52424a67ba0b/src/types.d.ts#L124-L125

So depending on what is intended, this issue is either:
1. a runtime bug, where it is not actually resolving promises before delivery
2. ~~or a ts typing bug~~

~~Are all promises supposed to be resolved by the library internally? Or does this library only handle `RpcPromise`?~~

*Edit: It was [confirmed here](https://github.com/cloudflare/capnweb/pull/142#issuecomment-4019184849) that it is a missing feature that will be worked on.*

Here is a reproduction of the issue:
```ts
import { RpcPromise, RpcTarget, newMessagePortRpcSession } from "capnweb";

class MyApi extends RpcTarget {
sayHello(): string {
return 'hello'
}

formatMessage(message: string): string {
return `server received: ${message}`;
}

formatObject(obj: Record): string {
let result = 'server received object with keys:\n';
for (const key in obj) {
result += `- ${key}: ${obj[key]}\n`;
}
return result;
}
}

async function main() {
const channel = new MessageChannel();
newMessagePortRpcSession(channel.port1, new MyApi());
const api = newMessagePortRpcSession(channel.port2);

const pipelinedHello: RpcPromise = api.sayHello();

const out1 = api.formatMessage(pipelinedHello);

const out2 = api.formatMessage(api.sayHello());

const out3 = api.formatObject({
greeting: pipelinedHello,
direct: api.sayHello(),
formatted: out2,
static: 'static value',
});

console.log(await out1); // success
console.log(await out2); // success
console.log(await out3); // success

const nativePromise = Promise.resolve(pipelinedHello);

// no ts error given below, but these are actually runtime errors because native Promise values aren't serializable by capnweb
// and aren't automatically resolved like RpcPromise values are.
api.formatMessage(nativePromise); // throws TypeError: Cannot serialize value: [object Promise]

api.formatMessage(Promise.resolve("not actually transportable")); // throws TypeError: Cannot serialize value: [object Promise]

api.formatObject({
validKey: pipelinedHello,
invalidKey: Promise.resolve("not transportable")
}) // throws TypeError: Cannot serialize value: [object Promise]
}

main();
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.