mirror of
https://github.com/MercuryWorkshop/bare-mux.git
synced 2025-05-16 15:40:01 -04:00
websocket support
This commit is contained in:
parent
5355f49957
commit
e2b85c3d99
3 changed files with 298 additions and 19 deletions
|
@ -13,13 +13,20 @@ function tryGetPort(client: SWClient): Promise<MessagePort> {
|
|||
}
|
||||
|
||||
export type WorkerMessage = {
|
||||
type: "fetch" | "set",
|
||||
type: "fetch" | "websocket" | "set",
|
||||
fetch?: {
|
||||
remote: string,
|
||||
method: string,
|
||||
body: ReadableStream | null,
|
||||
headers: BareHeaders,
|
||||
},
|
||||
fetchBody?: ReadableStream,
|
||||
websocket?: {
|
||||
url: string,
|
||||
origin: string,
|
||||
protocols: string[],
|
||||
requestHeaders: BareHeaders,
|
||||
},
|
||||
websocketChannel?: MessagePort,
|
||||
client?: string,
|
||||
};
|
||||
|
||||
|
@ -29,21 +36,32 @@ export type WorkerRequest = {
|
|||
}
|
||||
|
||||
export type WorkerResponse = {
|
||||
type: "fetch" | "set" | "error",
|
||||
type: "fetch" | "websocket" | "set" | "error",
|
||||
fetch?: TransferrableResponse,
|
||||
error?: Error,
|
||||
}
|
||||
|
||||
type BroadcastMessage = {
|
||||
type: "getPath" | "path",
|
||||
path?: string,
|
||||
}
|
||||
|
||||
export class WorkerConnection {
|
||||
channel: BroadcastChannel;
|
||||
port: MessagePort | Promise<MessagePort>;
|
||||
|
||||
constructor(workerPath?: string) {
|
||||
this.channel = new BroadcastChannel("bare-mux");
|
||||
// @ts-expect-error
|
||||
if (self.clients) {
|
||||
// running in a ServiceWorker
|
||||
// ask a window for the worker port
|
||||
// @ts-expect-error
|
||||
const clients: Promise<SWClient[]> = self.clients.matchAll({ type: "window", includeUncontrolled: true });
|
||||
this.port = clients.then(clients => Promise.any(clients.map((x: SWClient) => tryGetPort(x))));
|
||||
} else if (workerPath && SharedWorker) {
|
||||
// running in a window, was passed a workerPath
|
||||
// create the SharedWorker and help other bare-mux clients get the workerPath
|
||||
navigator.serviceWorker.addEventListener("message", event => {
|
||||
if (event.data.type === "getPort" && event.data.port) {
|
||||
const worker = new SharedWorker(workerPath);
|
||||
|
@ -51,18 +69,41 @@ export class WorkerConnection {
|
|||
}
|
||||
});
|
||||
|
||||
this.channel.onmessage = (event: MessageEvent) => {
|
||||
if (event.data.type === "getPath") {
|
||||
this.channel.postMessage(<BroadcastMessage>{ type: "path", path: workerPath });
|
||||
}
|
||||
}
|
||||
|
||||
const worker = new SharedWorker(workerPath, "bare-mux-worker");
|
||||
this.port = worker.port;
|
||||
} else if (SharedWorker) {
|
||||
// running in a window, was not passed a workerPath
|
||||
// ask other bare-mux clients for the workerPath
|
||||
this.port = new Promise(resolve => {
|
||||
this.channel.onmessage = (event: MessageEvent) => {
|
||||
if (event.data.type === "path") {
|
||||
const worker = new SharedWorker(event.data.path, "bare-mux-worker");
|
||||
this.channel.onmessage = (event: MessageEvent) => {
|
||||
if (event.data.type === "getPath") {
|
||||
this.channel.postMessage(<BroadcastMessage>{ type: "path", path: event.data.path });
|
||||
}
|
||||
}
|
||||
resolve(worker.port);
|
||||
}
|
||||
}
|
||||
this.channel.postMessage(<BroadcastMessage>{ type: "getPath" });
|
||||
});
|
||||
} else {
|
||||
throw new Error("workerPath was not passed or SharedWorker does not exist and am not running in a Service Worker.");
|
||||
// SharedWorker does not exist
|
||||
throw new Error("Unable to get a channel to the SharedWorker.");
|
||||
}
|
||||
}
|
||||
|
||||
async sendMessage(message: WorkerMessage): Promise<WorkerResponse> {
|
||||
async sendMessage(message: WorkerMessage, transferable?: Transferable[]): Promise<WorkerResponse> {
|
||||
if (this.port instanceof Promise) this.port = await this.port;
|
||||
let channel = new MessageChannel();
|
||||
let toTransfer: Transferable[] = [channel.port2];
|
||||
if (message.fetch && message.fetch.body) toTransfer.push(message.fetch.body);
|
||||
let toTransfer: Transferable[] = [channel.port2, ...(transferable || [])];
|
||||
|
||||
this.port.postMessage(<WorkerRequest>{ message: message, port: channel.port2 }, toTransfer);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue