Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cuddly-lions-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"capnweb": patch
---

Fixed serialization of async functions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ function newWebSocketRpcSession(
: Disposable;
```

### HTTP server using Hono

If your app is built on [Hono](https://hono.dev/) (on any runtime it supports), check out [`@hono/capnweb`](https://github.com/honojs/middleware/tree/main/packages/capnweb).

### MessagePort

Cap'n Web can also talk over MessagePorts. This can be used in a browser to talk to Web Workers, iframes, etc.
Expand Down
37 changes: 37 additions & 0 deletions __tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ describe("local stub", () => {
expect(await stub(3)).toBe(8);
});

it("supports wrapping an async function", async () => {
let stub = new RpcStub(async (i :number) => { return i + 5; });
expect(await stub(3)).toBe(8);
});

it("supports wrapping an arbitrary object", async () => {
let stub = new RpcStub({abc: "hello"});
expect(await stub.abc).toBe("hello");
Expand All @@ -246,6 +251,27 @@ describe("local stub", () => {
expect(await outerStub.inner.square(4)).toBe(16);
});

it("supports wrapping an object with nested functions", async () => {
let outerObject = { square: (x: number) => x * x, value: 42 };
let outerStub = new RpcStub(outerObject);

expect(await outerStub.value).toBe(42);
expect(await outerStub.square(4)).toBe(16);
});

it("supports wrapping an object with nested async functions", async () => {
async function asyncSqare(x: number) {
await Promise.resolve();
return x * x;
}

let outerObject = { square: asyncSqare, value: 42 };
let outerStub = new RpcStub(outerObject);

expect(await outerStub.value).toBe(42);
expect(await outerStub.square(4)).toBe(16);
});

it("supports wrapping an RpcTarget with nested stubs", async () => {
class TargetWithStubs extends RpcTarget {
getValue() { return 42; }
Expand Down Expand Up @@ -646,6 +672,17 @@ describe("basic rpc", () => {

expect(await stub.jsonify({x: 123, $remove$toJSON: () => "bad"})).toBe('{"x":123}');
});

it("supports passing async functinos", async () => {
await using harness = new TestHarness(new TestTarget());

async function square(i: number) {
await Promise.resolve();
return i * i;
}

expect(await harness.stub.callFunction(square, 3)).toStrictEqual({result: 9});
});
});

describe("capability-passing", () => {
Expand Down
4 changes: 4 additions & 0 deletions __tests__/test-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class TestTarget extends RpcTarget {
return { result: self.square(i) };
}

async callFunction(func: RpcStub<(i: number) => number>, i: number) {
return { result: await func(i) };
}

throwError() {
throwErrorImpl();
}
Expand Down
Loading
Loading