Update files

This commit is contained in:
Mohamed Boudra
2026-02-10 10:50:54 +07:00
parent 7a21a5cce1
commit 7001928f4f
33 changed files with 3490 additions and 304 deletions
@@ -158,6 +158,49 @@ describe("EncryptedChannel", () => {
expect(sentData.length).toBeGreaterThan(plaintext.length + 20);
});
it("does not throw uncaught when handshake hello retry send fails", async () => {
vi.useFakeTimers();
try {
const daemonKeyPair = await generateKeyPair();
const daemonPubKeyB64 = await exportPublicKey(daemonKeyPair.publicKey);
const transport: Transport = {
send: vi.fn(),
close: vi.fn(),
onmessage: null,
onclose: null,
onerror: null,
};
let sendAttempts = 0;
(transport.send as ReturnType<typeof vi.fn>).mockImplementation(() => {
sendAttempts += 1;
if (sendAttempts >= 2) {
throw new Error("WebSocket not open (readyState=2)");
}
});
const onerror = vi.fn();
await createClientChannel(transport, daemonPubKeyB64, { onerror });
expect(() => {
vi.advanceTimersByTime(1000);
}).not.toThrow();
expect(onerror).toHaveBeenCalledTimes(1);
expect(onerror.mock.calls[0][0]).toBeInstanceOf(Error);
expect((onerror.mock.calls[0][0] as Error).message).toContain(
"WebSocket not open"
);
// Close the transport to stop retry timer.
transport.onclose?.(1000, "closed");
vi.runOnlyPendingTimers();
} finally {
vi.useRealTimers();
}
});
it("fails handshake on invalid hello", async () => {
const [daemonTransport] = createMockTransportPair();
+17 -2
View File
@@ -85,6 +85,21 @@ export async function createClientChannel(
const helloText = JSON.stringify(hello);
let retry: ReturnType<typeof setInterval> | null = null;
const emitSendError = (error: unknown) => {
const err = error instanceof Error ? error : new Error(String(error));
events.onerror?.(err);
};
const sendHello = () => {
try {
transport.send(helloText);
return true;
} catch (error) {
// This can happen during daemon restarts while the socket transitions
// through CLOSING/CLOSED states. Report it but do not throw from timers.
emitSendError(error);
return false;
}
};
const clearRetry = () => {
if (retry) {
clearInterval(retry);
@@ -95,13 +110,13 @@ export async function createClientChannel(
channel.onTransitionToOpen(() => clearRetry());
channel.onClose(() => clearRetry());
transport.send(helloText);
sendHello();
retry = setInterval(() => {
if (channel.isOpen()) {
clearRetry();
return;
}
transport.send(helloText);
sendHello();
}, HANDSHAKE_RETRY_MS);
// Avoid keeping Node processes alive (e.g. tests) if the handshake is stuck.
(retry as unknown as { unref?: () => void }).unref?.();