greatly simplify createwebsocket

This commit is contained in:
velzie 2024-09-07 16:29:32 -04:00
parent ea21f222be
commit abec64ef97
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
3 changed files with 69 additions and 146 deletions

View file

@ -26,7 +26,6 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-inject": "^5.0.5",
"@rollup/plugin-replace": "^5.0.5", "@rollup/plugin-replace": "^5.0.5",
"rollup": "^4.9.6", "rollup": "^4.9.6",

View file

@ -121,10 +121,9 @@ export class BareClient {
createWebSocket( createWebSocket(
remote: string | URL, remote: string | URL,
protocols: string | string[] | undefined = [], protocols: string | string[] | undefined = [],
webSocketImpl?: WebSocketImpl, __deprecated_donotuse_websocket?: any,
requestHeaders?: BareHeaders, requestHeaders?: BareHeaders,
arrayBufferImpl?: ArrayBuffer, ): BareWebSocket {
): WebSocket {
try { try {
remote = new URL(remote); remote = new URL(remote);
} catch (err) { } catch (err) {
@ -148,7 +147,6 @@ export class BareClient {
`Failed to construct 'WebSocket': The subprotocol '${proto}' is invalid.` `Failed to construct 'WebSocket': The subprotocol '${proto}' is invalid.`
); );
arrayBufferImpl = arrayBufferImpl || (webSocketImpl || WebSocket).constructor.constructor("return ArrayBuffer")().prototype;
requestHeaders = requestHeaders || {}; requestHeaders = requestHeaders || {};
requestHeaders['Host'] = (new URL(remote)).host; requestHeaders['Host'] = (new URL(remote)).host;
// requestHeaders['Origin'] = origin; // requestHeaders['Origin'] = origin;
@ -158,9 +156,9 @@ export class BareClient {
// requestHeaders['User-Agent'] = navigator.userAgent; // requestHeaders['User-Agent'] = navigator.userAgent;
requestHeaders['Connection'] = 'Upgrade'; requestHeaders['Connection'] = 'Upgrade';
const socket = new BareWebSocket(remote, protocols, this.worker, requestHeaders, arrayBufferImpl) const socket = new BareWebSocket(remote, protocols, this.worker, requestHeaders);
return socket as unknown as WebSocket; return socket;
} }
async fetch( async fetch(

View file

@ -3,150 +3,76 @@ import { WebSocketFields } from "./snapshot";
import { BareHeaders } from "./baretypes"; import { BareHeaders } from "./baretypes";
export class BareWebSocket extends EventTarget { export class BareWebSocket extends EventTarget {
url: string; url: string;
protocols: string | string[] | undefined = [];
readyState: number = WebSocketFields.CONNECTING;
binaryType = "blob";
//legacy event handlers channel: MessageChannel;
onopen = null; constructor(
onerror = null; remote: string | URL,
onmessage = null; public protocols: string | string[] | undefined = [],
onclose = null; worker: WorkerConnection,
requestHeaders?: BareHeaders,
channel: MessageChannel; ) {
constructor( super();
remote: string | URL, this.url = remote.toString();
protocols: string | string[] | undefined = [], this.protocols = protocols;
worker: WorkerConnection,
requestHeaders?: BareHeaders,
arrayBufferImpl?: ArrayBuffer,
) {
super();
this.url = remote.toString();
this.protocols = protocols;
const onopen = (protocol: string) => {
this.readyState = WebSocketFields.OPEN;
this.protocols = protocol;
(this as any).meta = { const onopen = (protocol: string) => {
headers: { this.protocols = protocol;
"sec-websocket-protocol": protocol,
}
};
const event = new Event("open")
this.dispatchEvent(event);
if (this.onopen) {
this.onopen(event);
}
};
const onmessage = async (payload) => {
if (typeof payload === "string") {
} else if ("byteLength" in payload) {
if (this.binaryType === "blob") {
payload = new Blob([payload]);
} else {
Object.setPrototypeOf(payload, arrayBufferImpl);
}
} else if ("arrayBuffer" in payload) {
if (this.binaryType === "arraybuffer") {
payload = await payload.arrayBuffer()
Object.setPrototypeOf(payload, arrayBufferImpl);
}
}
const event = new MessageEvent("message", {data: payload }); const event = new Event("open")
this.dispatchEvent(event); this.dispatchEvent(event);
if (this.onmessage) { };
this.onmessage(event);
}
};
const onclose = (code: number, reason: string) => {
this.readyState = WebSocketFields.CLOSED;
const event = new CloseEvent("close", { code, reason })
this.dispatchEvent(event);
if (this.onclose) {
this.onclose(event);
}
};
const onerror = () => {
this.readyState = WebSocketFields.CLOSED;
const event = new Event("error");
this.dispatchEvent(event);
if (this.onerror) {
this.onerror(event);
};
};
this.channel = new MessageChannel();
this.channel.port1.onmessage = event => {
if (event.data.type === "open") {
onopen(event.data.args[0]);
} else if (event.data.type === "message") {
onmessage(event.data.args[0]);
} else if (event.data.type === "close") {
onclose(event.data.args[0], event.data.args[1]);
} else if (event.data.type === "error") {
onerror(/* event.data.args[0] */);
}
}
worker.sendMessage({
type: "websocket",
websocket: {
url: remote.toString(),
origin: origin,
//@ts-expect-error
protocols: protocols,
requestHeaders: requestHeaders,
channel: this.channel.port2,
},
}, [this.channel.port2])
}
send(...args) {
if (this.readyState === WebSocketFields.CONNECTING) {
throw new DOMException(
"Failed to execute 'send' on 'WebSocket': Still in CONNECTING state."
);
}
let data = args[0]; const onmessage = async (payload) => {
if (data.buffer) data = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength); const event = new MessageEvent("message", { data: payload });
this.dispatchEvent(event);
};
this.channel.port1.postMessage({ type: "data", data: data }, data instanceof ArrayBuffer ? [data] : []); const onclose = (code: number, reason: string) => {
} const event = new CloseEvent("close", { code, reason })
this.dispatchEvent(event);
close(code, reason) { };
this.readyState = WebSocketFields.CLOSING;
this.channel.port1.postMessage({ type: "close", closeCode: code, closeReason: reason }); const onerror = () => {
} const event = new Event("error");
this.dispatchEvent(event);
get bufferedAmount() { };
return 0;
} this.channel = new MessageChannel();
get protocol() {
if (Array.isArray(this.protocols)) { this.channel.port1.onmessage = event => {
return this.protocols[0] || ""; if (event.data.type === "open") {
} else { onopen(event.data.args[0]);
return this.protocols || ""; } else if (event.data.type === "message") {
onmessage(event.data.args[0]);
} else if (event.data.type === "close") {
onclose(event.data.args[0], event.data.args[1]);
} else if (event.data.type === "error") {
onerror(/* event.data.args[0] */);
} }
} }
get extensions() {
return ""; worker.sendMessage({
} type: "websocket",
websocket: {
url: remote.toString(),
origin: origin,
//@ts-expect-error
protocols: protocols,
requestHeaders: requestHeaders,
channel: this.channel.port2,
},
}, [this.channel.port2])
}
send(...args) {
let data = args[0];
if (data.buffer) data = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
this.channel.port1.postMessage({ type: "data", data: data }, data instanceof ArrayBuffer ? [data] : []);
}
close(code, reason) {
this.channel.port1.postMessage({ type: "close", closeCode: code, closeReason: reason });
}
} }
//@ts-expect-error have to do this
BareWebSocket.prototype.CONNECTING = WebSocketFields.CONNECTING;
//@ts-expect-error have to do this
BareWebSocket.prototype.OPEN = WebSocketFields.OPEN;
//@ts-expect-error have to do this
BareWebSocket.prototype.CLOSING = WebSocketFields.CLOSING;
//@ts-expect-error have to do this
BareWebSocket.prototype.CLOSED = WebSocketFields.CLOSED;