mirror of
https://github.com/MercuryWorkshop/bare-mux.git
synced 2025-05-15 15:10:02 -04:00
add getTransport, add retrying to the sw messageport promise
This commit is contained in:
parent
c540450b66
commit
dc9f4a7e39
6 changed files with 43 additions and 19 deletions
|
@ -5,6 +5,7 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
|
"watch": "rollup -cw",
|
||||||
"prepare": "npm run build"
|
"prepare": "npm run build"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|
|
@ -44,7 +44,7 @@ const configs = [
|
||||||
format: 'umd',
|
format: 'umd',
|
||||||
name: 'BareMux',
|
name: 'BareMux',
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
exports: 'auto',
|
exports: 'named',
|
||||||
},
|
},
|
||||||
plugins: commonPlugins(),
|
plugins: commonPlugins(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -107,10 +107,14 @@ export class BareMuxConnection {
|
||||||
this.worker = new WorkerConnection(workerPath);
|
this.worker = new WorkerConnection(workerPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getTransport(): Promise<string> {
|
||||||
|
return (await this.worker.sendMessage({ type: "get" })).name;
|
||||||
|
}
|
||||||
|
|
||||||
async setTransport(path: string, options: any[]) {
|
async setTransport(path: string, options: any[]) {
|
||||||
await this.setManualTransport(`
|
await this.setManualTransport(`
|
||||||
const { default: BareTransport } = await import("${path}");
|
const { default: BareTransport } = await import("${path}");
|
||||||
return new BareTransport(${options.map(x => JSON.stringify(x)).join(", ")});
|
return [new BareTransport(${options.map(x => JSON.stringify(x)).join(", ")}), "${path}"];
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,8 @@ import { BareHeaders, TransferrableResponse } from "./baretypes";
|
||||||
|
|
||||||
type SWClient = { postMessage: typeof MessagePort.prototype.postMessage };
|
type SWClient = { postMessage: typeof MessagePort.prototype.postMessage };
|
||||||
|
|
||||||
function tryGetPort(client: SWClient): Promise<MessagePort> {
|
|
||||||
let channel = new MessageChannel();
|
|
||||||
return new Promise(resolve => {
|
|
||||||
client.postMessage({ type: "getPort", port: channel.port2 }, [channel.port2]);
|
|
||||||
channel.port1.onmessage = event => {
|
|
||||||
resolve(event.data)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export type WorkerMessage = {
|
export type WorkerMessage = {
|
||||||
type: "fetch" | "websocket" | "set",
|
type: "fetch" | "websocket" | "set" | "get",
|
||||||
fetch?: {
|
fetch?: {
|
||||||
remote: string,
|
remote: string,
|
||||||
method: string,
|
method: string,
|
||||||
|
@ -36,8 +26,9 @@ export type WorkerRequest = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WorkerResponse = {
|
export type WorkerResponse = {
|
||||||
type: "fetch" | "websocket" | "set" | "error",
|
type: "fetch" | "websocket" | "set" | "get" | "error",
|
||||||
fetch?: TransferrableResponse,
|
fetch?: TransferrableResponse,
|
||||||
|
name?: string,
|
||||||
error?: Error,
|
error?: Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +37,28 @@ type BroadcastMessage = {
|
||||||
path?: string,
|
path?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function searchForPort(): Promise<MessagePort> {
|
||||||
|
// @ts-expect-error
|
||||||
|
const clients: SWClient[] = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
|
||||||
|
const promise: Promise<MessagePort> = Promise.race([...clients.map((x: SWClient) => tryGetPort(x)), new Promise((_, reject) => setTimeout(reject, 1000, new Error("")))]) as Promise<MessagePort>;
|
||||||
|
try {
|
||||||
|
return await promise;
|
||||||
|
} catch {
|
||||||
|
console.warn("bare-mux: failed to get a bare-mux SharedWorker MessagePort within 1s, retrying");
|
||||||
|
return await searchForPort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryGetPort(client: SWClient): Promise<MessagePort> {
|
||||||
|
let channel = new MessageChannel();
|
||||||
|
return new Promise(resolve => {
|
||||||
|
client.postMessage({ type: "getPort", port: channel.port2 }, [channel.port2]);
|
||||||
|
channel.port1.onmessage = event => {
|
||||||
|
resolve(event.data)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createPort(path: string, channel: BroadcastChannel): MessagePort {
|
function createPort(path: string, channel: BroadcastChannel): MessagePort {
|
||||||
const worker = new SharedWorker(path, "bare-mux-worker");
|
const worker = new SharedWorker(path, "bare-mux-worker");
|
||||||
// uv removes navigator.serviceWorker so this errors
|
// uv removes navigator.serviceWorker so this errors
|
||||||
|
@ -77,12 +90,12 @@ export class WorkerConnection {
|
||||||
if (self.clients) {
|
if (self.clients) {
|
||||||
// running in a ServiceWorker
|
// running in a ServiceWorker
|
||||||
// ask a window for the worker port
|
// ask a window for the worker port
|
||||||
// @ts-expect-error
|
this.port = searchForPort();
|
||||||
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) {
|
} else if (workerPath && SharedWorker) {
|
||||||
// running in a window, was passed a workerPath
|
// running in a window, was passed a workerPath
|
||||||
// create the SharedWorker and help other bare-mux clients get the workerPath
|
// create the SharedWorker and help other bare-mux clients get the workerPath
|
||||||
|
|
||||||
|
if (!workerPath.startsWith("/") && !workerPath.includes("://")) throw new Error("Invalid URL. Must be absolute or start at the root.");
|
||||||
this.port = createPort(workerPath, this.channel);
|
this.port = createPort(workerPath, this.channel);
|
||||||
} else if (SharedWorker) {
|
} else if (SharedWorker) {
|
||||||
// running in a window, was not passed a workerPath
|
// running in a window, was not passed a workerPath
|
||||||
|
|
|
@ -6,6 +6,7 @@ export const WebSocket = globalThis.WebSocket;
|
||||||
export const Request = globalThis.Request;
|
export const Request = globalThis.Request;
|
||||||
export const Response = globalThis.Response;
|
export const Response = globalThis.Response;
|
||||||
export const XMLHttpRequest = globalThis.XMLHttpRequest;
|
export const XMLHttpRequest = globalThis.XMLHttpRequest;
|
||||||
|
export const SharedWorker = globalThis.SharedWorker;
|
||||||
|
|
||||||
export const WebSocketFields = {
|
export const WebSocketFields = {
|
||||||
prototype: {
|
prototype: {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { BareTransport } from "./baretypes";
|
||||||
import { WorkerMessage, WorkerResponse } from "./connection"
|
import { WorkerMessage, WorkerResponse } from "./connection"
|
||||||
|
|
||||||
let currentTransport: BareTransport | null = null;
|
let currentTransport: BareTransport | null = null;
|
||||||
|
let currentTransportName: string = "";
|
||||||
|
|
||||||
function noClients(): Error {
|
function noClients(): Error {
|
||||||
// @ts-expect-error mdn error constructor: new Error(message, options)
|
// @ts-expect-error mdn error constructor: new Error(message, options)
|
||||||
|
@ -21,13 +22,17 @@ function handleConnection(port: MessagePort) {
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
const func = new AsyncFunction(message.client);
|
const func = new AsyncFunction(message.client);
|
||||||
currentTransport = await func();
|
const [newTransport, name] = await func();
|
||||||
console.log("set transport to ", currentTransport);
|
currentTransport = newTransport;
|
||||||
|
currentTransportName = name;
|
||||||
|
console.log("set transport to ", currentTransport, name);
|
||||||
|
|
||||||
port.postMessage(<WorkerResponse>{ type: "set" });
|
port.postMessage(<WorkerResponse>{ type: "set" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
port.postMessage(<WorkerResponse>{ type: "error", error: err });
|
port.postMessage(<WorkerResponse>{ type: "error", error: err });
|
||||||
}
|
}
|
||||||
|
} else if (message.type === "get") {
|
||||||
|
port.postMessage(<WorkerResponse>{ type: "get", name: currentTransportName });
|
||||||
} else if (message.type === "fetch") {
|
} else if (message.type === "fetch") {
|
||||||
try {
|
try {
|
||||||
if (!currentTransport) throw noClients();
|
if (!currentTransport) throw noClients();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue