1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-31 08:43:54 +00:00

feat: support all responses

This commit is contained in:
Andreas Coroiu
2025-10-31 15:04:43 +01:00
parent d387979f19
commit fa4a264011
3 changed files with 71 additions and 11 deletions

View File

@@ -20,16 +20,17 @@ describe("Batching proxies", () => {
});
});
// Not sure what await itself should do yet
// it("should allow awaiting the proxy itself", async () => {
// const reference = {
// referenceId: 2,
// objectType: "AwaitableObject",
// };
// const proxy = RpcObjectReference(channel, reference);
// const awaited = await proxy;
// expect(awaited).toBe(proxy);
// });
it("awaiting the proxy returns the proxy itself", async () => {
const reference = {
referenceId: 1,
objectType: "TestObject",
};
const proxy = RpcObjectReference(channel, reference);
const awaited = await proxy;
expect(awaited).toBe(proxy);
});
it("returns a pending object reference proxy when accesing a property", async () => {
const reference = { referenceId: 1, objectType: "TestObject" };
@@ -133,6 +134,50 @@ describe("Batching proxies", () => {
],
} satisfies Command);
});
it("returns value when receiving a value response", async () => {
const reference = { referenceId: 1, objectType: "TestObject" };
const proxy = RpcObjectReference(channel, reference) as any;
channel.responses.push({ status: "success", result: { type: "value", value: 42 } });
const result = await proxy.prop;
expect(result).toBe(42);
});
it("returns reference when receiving a reference response", async () => {
const reference = { referenceId: 1, objectType: "TestObject" };
const proxy = RpcObjectReference(channel, reference) as any;
channel.responses.push({ status: "success", result: { type: "reference", referenceId: 2 } });
const result = await proxy.prop;
expect(result[ProxyInfo].referenceId).toBe(2);
});
it("throws error when receiving an error response", async () => {
class TestError extends Error {
constructor(
message: string,
public someProperty: string,
) {
super(message);
}
}
const reference = { referenceId: 1, objectType: "TestObject" };
const proxy = RpcObjectReference(channel, reference) as any;
const error = new TestError("Something went wrong", "someValue");
channel.responses.push({ status: "error", error });
// Note: We are getting the actual error instance here because our
// channel is a local mock. In a real RPC scenario, the error would be
// serialized and deserialized, losing its prototype and properties.
await expect(proxy.prop).rejects.toThrow(error);
});
});
class RpcChannel implements RpcRequestChannel {

View File

@@ -65,7 +65,14 @@ function proxyHandler(
return (target as any)[ProxyInfo];
}
if (property === "then") {
if (property === "then" && commands.length === 0) {
// This means we awaited a RpcObjectReference which resolves to itself
// We don't support transfering references to Promises themselves, we'll
// automatically await them before returning
return undefined;
}
if (property === "then" && commands.length > 0) {
return BatchCommandExecutor(channel, reference.referenceId, commands);
}

View File

@@ -0,0 +1,8 @@
/**
* RpcError represents an error that occurs during RPC communication.
*/
export class RpcError extends Error {
constructor(message: string) {
super(message);
}
}