fix onerror bugs

This commit is contained in:
Spencer Pogorzelski 2023-08-14 14:29:45 -07:00
parent feaac8d6c3
commit 358075f84b
3 changed files with 27 additions and 9 deletions

View file

@ -71,11 +71,21 @@ export class AdriftBareClient extends Client {
let initalCloseHappened = false; let initalCloseHappened = false;
ws.addEventListener("close", (e) => { ws.addEventListener("close", (e) => {
if (!initalCloseHappened) { if (!initalCloseHappened) {
// we can freely mess with the fake readyState here because there is no
// readyStateChange listener for WebSockets
onReadyState(WebSocket.CONNECTING); onReadyState(WebSocket.CONNECTING);
e.stopImmediatePropagation(); e.stopImmediatePropagation();
initalCloseHappened = true; initalCloseHappened = true;
} }
}); });
let initialErrorHappened = false;
ws.addEventListener("error", (e) => {
if (!initialErrorHappened) {
onReadyState(WebSocket.CONNECTING);
e.stopImmediatePropagation();
initialErrorHappened = true;
}
});
let { send, close } = this.connection.wsconnect( let { send, close } = this.connection.wsconnect(
remote, remote,
@ -95,6 +105,7 @@ export class AdriftBareClient extends Client {
); );
}, },
(message: string) => { (message: string) => {
console.log({ message });
ws.dispatchEvent(new ErrorEvent("error", { message })); ws.dispatchEvent(new ErrorEvent("error", { message }));
} }
); );

View file

@ -12,6 +12,7 @@ import {
} from "protocol"; } from "protocol";
type OpenWSMeta = { type OpenWSMeta = {
onopen: () => void;
onclose: (code: number, reason: string, wasClean: boolean) => void; onclose: (code: number, reason: string, wasClean: boolean) => void;
onmessage: (data: any) => void; onmessage: (data: any) => void;
onerror: (message: string) => void; onerror: (message: string) => void;
@ -20,7 +21,7 @@ type OpenWSMeta = {
export class Connection { export class Connection {
requestCallbacks: Record<number, Function> = {}; requestCallbacks: Record<number, Function> = {};
openRequestStreams: Record<number, ReadableStreamDefaultController<any>> = {}; openRequestStreams: Record<number, ReadableStreamDefaultController<any>> = {};
openingSockets: Record<number, { onopen: () => void; rest: OpenWSMeta }> = {}; openingSockets: Record<number, OpenWSMeta> = {};
openSockets: Record<number, OpenWSMeta> = {}; openSockets: Record<number, OpenWSMeta> = {};
counter: number = 0; counter: number = 0;
@ -47,6 +48,7 @@ export class Connection {
const msgText = () => new TextDecoder().decode(data.slice(cursor)); const msgText = () => new TextDecoder().decode(data.slice(cursor));
const msgJSON = () => JSON.parse(msgText()); const msgJSON = () => JSON.parse(msgText());
console.log({ requestType });
switch (requestType) { switch (requestType) {
case S2CRequestTypes.HTTPResponseStart: case S2CRequestTypes.HTTPResponseStart:
const payload = msgJSON(); const payload = msgJSON();
@ -77,10 +79,10 @@ export class Connection {
break; break;
case S2CRequestTypes.WSOpen: case S2CRequestTypes.WSOpen:
const { onopen, rest } = this.openingSockets[requestID]; const socketMeta = this.openingSockets[requestID];
delete this.openingSockets[requestID]; delete this.openingSockets[requestID];
this.openSockets[requestID] = rest; this.openSockets[requestID] = socketMeta;
onopen(); setTimeout(() => socketMeta.onopen());
break; break;
case S2CRequestTypes.WSDataText: { case S2CRequestTypes.WSDataText: {
@ -98,7 +100,8 @@ export class Connection {
} }
case S2CRequestTypes.WSClose: { case S2CRequestTypes.WSClose: {
const socketMeta = this.openSockets[requestID]; const socketMeta =
this.openingSockets[requestID] || this.openSockets[requestID];
if (!socketMeta) return; if (!socketMeta) return;
const payload: WSClosePayload = msgJSON(); const payload: WSClosePayload = msgJSON();
setTimeout(() => setTimeout(() =>
@ -108,16 +111,18 @@ export class Connection {
"wasClean" in payload ? Boolean(payload.wasClean) : false "wasClean" in payload ? Boolean(payload.wasClean) : false
) )
); );
delete this.openingSockets[requestID];
delete this.openSockets[requestID]; delete this.openSockets[requestID];
break; break;
} }
case S2CRequestTypes.WSError: { case S2CRequestTypes.WSError: {
const socketMeta = this.openSockets[requestID]; const socketMeta =
this.openingSockets[requestID] || this.openSockets[requestID];
if (!socketMeta) return; if (!socketMeta) return;
const payload: WSErrorPayload = msgJSON(); const payload: WSErrorPayload = msgJSON();
setTimeout(() => socketMeta.onerror(payload.message)); setTimeout(() => socketMeta.onerror(payload.message));
setTimeout(() => socketMeta.onclose(1006, "", false)); // don't delete socket entries because server will send close after this
break; break;
} }
@ -187,7 +192,9 @@ export class Connection {
// this can't be async, just call onopen when opened // this can't be async, just call onopen when opened
this.openingSockets[seq] = { this.openingSockets[seq] = {
onopen, onopen,
rest: { onmessage, onclose, onerror }, onmessage,
onclose,
onerror,
}; };
return { return {

View file

@ -246,8 +246,8 @@ export class AdriftServer {
const ws = (this.sockets[seq] = new WebSocket(payload.url)); const ws = (this.sockets[seq] = new WebSocket(payload.url));
ws.binaryType = "arraybuffer"; ws.binaryType = "arraybuffer";
ws.onerror = (e) => { ws.onerror = (e) => {
// WSError implies close with code 1006, reason "" and wasClean false
this.sendWSError(seq, { message: e.message }); this.sendWSError(seq, { message: e.message });
// onclose will be called after this with code 1006, reason "" and wasClean false
}; };
ws.onopen = () => { ws.onopen = () => {
this.sendWSOpen(seq); this.sendWSOpen(seq);