mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 09:13:33 +00:00
[EC-598] feat: add ability to throw errors across messenger
This commit is contained in:
@@ -14,6 +14,7 @@ export enum MessageType {
|
||||
CredentialGetResponse,
|
||||
AbortRequest,
|
||||
AbortResponse,
|
||||
ErrorResponse,
|
||||
}
|
||||
|
||||
export type CredentialCreationRequest = {
|
||||
@@ -43,6 +44,11 @@ export type AbortRequest = {
|
||||
abortedRequestId: string;
|
||||
};
|
||||
|
||||
export type ErrorResponse = {
|
||||
type: MessageType.ErrorResponse;
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type AbortResponse = {
|
||||
type: MessageType.AbortResponse;
|
||||
abortedRequestId: string;
|
||||
@@ -54,4 +60,5 @@ export type Message =
|
||||
| CredentialGetRequest
|
||||
| CredentialGetResponse
|
||||
| AbortRequest
|
||||
| AbortResponse;
|
||||
| AbortResponse
|
||||
| ErrorResponse;
|
||||
|
||||
@@ -44,6 +44,17 @@ describe("Messenger", () => {
|
||||
expect(returned).toMatchObject(response);
|
||||
});
|
||||
|
||||
it("should throw error from B when sending request from A that fails", async () => {
|
||||
const request = createRequest();
|
||||
const error = new Error("Test error");
|
||||
const requestPromise = messengerA.request(request);
|
||||
const received = handlerB.recieve();
|
||||
|
||||
received[0].reject(error);
|
||||
|
||||
await expect(requestPromise).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("should deliver abort signal to B when requesting abort", () => {
|
||||
const abortController = new AbortController();
|
||||
messengerA.request(createRequest(), abortController);
|
||||
@@ -53,15 +64,6 @@ describe("Messenger", () => {
|
||||
|
||||
expect(received[0].abortController.signal.aborted).toBe(true);
|
||||
});
|
||||
|
||||
it.skip("should abort request and throw error when abort is requested from A", () => {
|
||||
const abortController = new AbortController();
|
||||
const requestPromise = messengerA.request(createRequest(), abortController);
|
||||
|
||||
abortController.abort();
|
||||
|
||||
expect(requestPromise).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
type TestMessage = Message & { testId: string };
|
||||
@@ -105,6 +107,7 @@ class TestMessageHandler {
|
||||
private recievedMessages: {
|
||||
message: TestMessage;
|
||||
respond: (response: TestMessage) => void;
|
||||
reject: (error: Error) => void;
|
||||
abortController?: AbortController;
|
||||
}[] = [];
|
||||
|
||||
@@ -115,6 +118,7 @@ class TestMessageHandler {
|
||||
message,
|
||||
abortController,
|
||||
respond: (response) => resolve(response),
|
||||
reject: (error) => reject(error),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,15 +49,26 @@ export class Messenger {
|
||||
|
||||
const abortController = new AbortController();
|
||||
this.abortControllers.set(message.metadata.requestId, abortController);
|
||||
const handlerResponse = await this.handler(message, abortController);
|
||||
this.abortControllers.delete(message.metadata.requestId);
|
||||
|
||||
if (handlerResponse === undefined) {
|
||||
return;
|
||||
try {
|
||||
const handlerResponse = await this.handler(message, abortController);
|
||||
|
||||
if (handlerResponse === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const metadata: Metadata = { requestId: message.metadata.requestId };
|
||||
this.channel.postMessage({ ...handlerResponse, metadata });
|
||||
} catch (error) {
|
||||
const metadata: Metadata = { requestId: message.metadata.requestId };
|
||||
this.channel.postMessage({
|
||||
type: MessageType.ErrorResponse,
|
||||
metadata,
|
||||
error: JSON.stringify(error, Object.getOwnPropertyNames(error)),
|
||||
});
|
||||
} finally {
|
||||
this.abortControllers.delete(message.metadata.requestId);
|
||||
}
|
||||
|
||||
const metadata: Metadata = { requestId: message.metadata.requestId };
|
||||
this.channel.postMessage({ ...handlerResponse, metadata });
|
||||
})
|
||||
)
|
||||
.subscribe();
|
||||
@@ -71,7 +82,7 @@ export class Messenger {
|
||||
});
|
||||
}
|
||||
|
||||
request(request: Message, abortController?: AbortController): Promise<Message> {
|
||||
async request(request: Message, abortController?: AbortController): Promise<Message> {
|
||||
const requestId = Date.now().toString();
|
||||
const metadata: Metadata = { requestId };
|
||||
|
||||
@@ -93,8 +104,15 @@ export class Messenger {
|
||||
|
||||
this.channel.postMessage({ ...request, metadata });
|
||||
|
||||
return promise.finally(() =>
|
||||
abortController?.signal.removeEventListener("abort", abortListener)
|
||||
);
|
||||
const response = await promise;
|
||||
abortController?.signal.removeEventListener("abort", abortListener);
|
||||
|
||||
if (response.type === MessageType.ErrorResponse) {
|
||||
const error = new Error();
|
||||
Object.assign(error, JSON.parse(response.error));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user