make snapshot.ts function better

This commit is contained in:
Percs 2024-10-10 22:40:10 -05:00
parent a44ee2c48d
commit 37e22c731e
7 changed files with 34 additions and 52 deletions

View file

@ -8,16 +8,6 @@ const pkg = JSON.parse(await readFile('package.json'));
const commonPlugins = () => [
typescript(),
inject(
Object.fromEntries(
['fetch', 'Request', 'Response', 'WebSocket', 'XMLHttpRequest', 'SharedWorker', 'localStorage', 'serviceWorker'].map(
(name) => [
name,
[fileURLToPath(new URL('./src/snapshot.ts', import.meta.url)), name],
]
)
)
),
replace({
'self.BARE_MUX_VERSION': JSON.stringify(
pkg.version

View file

@ -1,6 +1,6 @@
import { BareHeaders, BareTransport, maxRedirects } from './baretypes';
import { WorkerConnection, WorkerMessage } from './connection';
import { WebSocketFields } from './snapshot';
import { nativeFetch } from './snapshot';
import { BareWebSocket } from './websocket';
import { handleFetch, handleWebsocket, sendError } from './workerHandlers';
@ -23,10 +23,6 @@ const wsProtocols = ['ws:', 'wss:'];
const statusEmpty = [101, 204, 205, 304];
const statusRedirect = [301, 302, 303, 307, 308];
export type WebSocketImpl = {
new(...args: ConstructorParameters<typeof WebSocket>): WebSocket;
};
/**
* A Response with additional properties.
*/
@ -183,7 +179,7 @@ export class BareClient {
let urlO = new URL(req.url);
if (urlO.protocol.startsWith('blob:')) {
const response = await fetch(urlO);
const response = await nativeFetch(urlO);
const result: Response & Partial<BareResponse> = new Response(
response.body,
response

View file

@ -1,9 +1,8 @@
import { BareHeaders, TransferrableResponse } from "./baretypes";
import { nativeLocalStorage, nativePostMessage, nativeServiceWorker } from "./snapshot";
type SWClient = { postMessage: typeof MessagePort.prototype.postMessage };
const realPostMessage = MessagePort.prototype.postMessage;
export type WorkerMessage = {
type: "fetch" | "websocket" | "set" | "get" | "ping",
fetch?: {
@ -86,19 +85,18 @@ function testPort(port: MessagePort): Promise<void> {
};
setTimeout(reject, 1500);
});
realPostMessage.call(port, <WorkerRequest>{ message: { type: "ping" }, port: pingChannel.port2 }, [pingChannel.port2]);
nativePostMessage.call(port, <WorkerRequest>{ message: { type: "ping" }, port: pingChannel.port2 }, [pingChannel.port2]);
return pingPromise;
}
function createPort(path: string, registerHandlers: boolean): MessagePort {
const worker = new SharedWorker(path, "bare-mux-worker");
if (registerHandlers) {
// @ts-expect-error we are using snapshot.ts
serviceWorker.addEventListener("message", (event: MessageEvent) => {
nativeServiceWorker.addEventListener("message", (event: MessageEvent) => {
if (event.data.type === "getPort" && event.data.port) {
console.debug("bare-mux: recieved request for port from sw");
const newWorker = new SharedWorker(path, "bare-mux-worker");
realPostMessage.call(event.data.port, newWorker.port, [newWorker.port]);
nativePostMessage.call(event.data.port, newWorker.port, [newWorker.port]);
}
});
}
@ -112,7 +110,7 @@ export function browserSupportsTransferringStreams(): boolean {
const stream = new ReadableStream();
let res: boolean;
try {
realPostMessage.call(chan.port1, stream, [stream]);
nativePostMessage.call(chan.port1, stream, [stream]);
res = true;
} catch (err) {
res = false;
@ -156,11 +154,11 @@ export class WorkerConnection {
if (!workerPath.startsWith("/") && !workerPath.includes("://")) throw new Error("Invalid URL. Must be absolute or start at the root.");
this.port = createPort(workerPath, inInit);
console.debug("bare-mux: setting localStorage bare-mux-path to", workerPath);
localStorage["bare-mux-path"] = workerPath;
nativeLocalStorage["bare-mux-path"] = workerPath;
} else if (SharedWorker) {
// running in a window, was not passed a workerPath
// use sessionStorage for the workerPath
const path = localStorage["bare-mux-path"];
const path = nativeLocalStorage["bare-mux-path"];
console.debug("bare-mux: got localStorage bare-mux-path:", path);
if (!path) throw new Error("Unable to get bare-mux workerPath from localStorage.");
this.port = createPort(path, inInit);
@ -194,7 +192,8 @@ export class WorkerConnection {
}
}
});
this.port.postMessage(<WorkerRequest>{ message: message, port: channel.port2 }, toTransfer);
nativePostMessage.call(this.port, <WorkerRequest>{ message: message, port: channel.port2 }, toTransfer);
return await promise;
}

View file

@ -1,14 +1,9 @@
// The user likely has overwritten all networking functions after importing bare-client
// It is our responsibility to make sure components of Bare-Client are using native networking functions
export const fetch = globalThis.fetch;
export const WebSocket = globalThis.WebSocket;
export const Request = globalThis.Request;
export const Response = globalThis.Response;
export const XMLHttpRequest = globalThis.XMLHttpRequest;
export const SharedWorker = globalThis.SharedWorker;
export const localStorage = globalThis.localStorage;
export const serviceWorker = globalThis.navigator.serviceWorker;
export const nativeFetch = globalThis.fetch;
export const nativeWebSocket = globalThis.WebSocket;
export const nativeSharedWorker = globalThis.SharedWorker;
export const nativeLocalStorage = globalThis.localStorage;
export const nativeServiceWorker = globalThis.navigator.serviceWorker;
export const nativePostMessage = MessagePort.prototype.postMessage;
export const WebSocketFields = {
prototype: {

View file

@ -1,5 +1,5 @@
import type { WorkerConnection } from "./connection";
import { WebSocketFields } from "./snapshot";
import { WebSocketFields, nativePostMessage } from "./snapshot";
import { BareHeaders } from "./baretypes";
export class BareWebSocket extends EventTarget {
@ -79,10 +79,10 @@ export class BareWebSocket extends EventTarget {
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] : []);
nativePostMessage.call(this.channel.port1, { type: "data", data: data }, data instanceof ArrayBuffer ? [data] : []);
}
close(code, reason) {
this.channel.port1.postMessage({ type: "close", closeCode: code, closeReason: reason });
nativePostMessage.call(this.channel.port1, { type: "close", closeCode: code, closeReason: reason });
}
}

View file

@ -1,6 +1,7 @@
import { BareTransport } from "./baretypes";
import { BroadcastMessage, WorkerMessage, WorkerRequest, WorkerResponse } from "./connection"
import { BroadcastMessage, WorkerMessage, WorkerRequest, WorkerResponse } from "./connection";
import { handleFetch, handleWebsocket, sendError } from "./workerHandlers";
import { nativePostMessage } from "./snapshot";
let currentTransport: BareTransport | MessagePort | null = null;
let currentTransportName: string = "";
@ -20,7 +21,7 @@ function handleRemoteClient(message: WorkerMessage, port: MessagePort) {
let transferables: Transferable[] = [port];
if (message.fetch?.body) transferables.push(message.fetch.body);
if (message.websocket?.channel) transferables.push(message.websocket.channel);
remote.postMessage(<WorkerRequest>{ message, port }, transferables);
nativePostMessage.call(remote, <WorkerRequest>{ message, port }, transferables);
}
function handleConnection(port: MessagePort) {
@ -28,7 +29,7 @@ function handleConnection(port: MessagePort) {
const port = event.data.port;
const message: WorkerMessage = event.data.message;
if (message.type === "ping") {
port.postMessage(<WorkerResponse>{ type: "pong" });
nativePostMessage.call(port, (<WorkerResponse>{ type: "pong" }));
} else if (message.type === "set") {
try {
const AsyncFunction = (async function() { }).constructor;
@ -45,7 +46,7 @@ function handleConnection(port: MessagePort) {
}
console.log("set transport to ", currentTransport, currentTransportName);
port.postMessage(<WorkerResponse>{ type: "set" });
nativePostMessage.call(port, <WorkerResponse>{ type: "set" });
} catch (err) {
sendError(port, err, 'set');
}

View file

@ -1,5 +1,6 @@
import { BareTransport } from "./baretypes";
import { browserSupportsTransferringStreams, WorkerMessage, WorkerResponse } from "./connection";
import { nativePostMessage } from "./snapshot";
export function sendError(port: MessagePort, err: Error, name: string) {
console.error(`error while processing '${name}': `, err);
@ -21,27 +22,27 @@ export async function handleFetch(message: WorkerMessage, port: MessagePort, tra
}
if (resp.body instanceof ReadableStream || resp.body instanceof ArrayBuffer) {
port.postMessage(<WorkerResponse>{ type: "fetch", fetch: resp }, [resp.body]);
nativePostMessage.call(port, <WorkerResponse>{ type: "fetch", fetch: resp }, [resp.body]);
} else {
port.postMessage(<WorkerResponse>{ type: "fetch", fetch: resp });
nativePostMessage.call(port, <WorkerResponse>{ type: "fetch", fetch: resp });
}
}
export async function handleWebsocket(message: WorkerMessage, port: MessagePort, transport: BareTransport) {
const onopen = (protocol: string) => {
message.websocket.channel.postMessage({ type: "open", args: [protocol] });
nativePostMessage.call(message.websocket.channel, { type: "open", args: [protocol] });
};
const onclose = (code: number, reason: string) => {
message.websocket.channel.postMessage({ type: "close", args: [code, reason] });
nativePostMessage.call(message.websocket.channel, { type: "close", args: [code, reason] });
};
const onerror = (error: string) => {
message.websocket.channel.postMessage({ type: "error", args: [error] });
nativePostMessage.call(message.websocket.channel, { type: "error", args: [error] });
};
const onmessage = (data: Blob | ArrayBuffer | string) => {
if (data instanceof ArrayBuffer) {
message.websocket.channel.postMessage({ type: "message", args: [data] }, [data]);
nativePostMessage.call(message.websocket.channel, { type: "message", args: [data] }, [data]);
} else {
message.websocket.channel.postMessage({ type: "message", args: [data] });
nativePostMessage.call(message.websocket.channel, { type: "message", args: [data] });
}
}
const [data, close] = transport.connect(
@ -62,5 +63,5 @@ export async function handleWebsocket(message: WorkerMessage, port: MessagePort,
}
}
port.postMessage(<WorkerResponse>{ type: "websocket" });
nativePostMessage.call(port, <WorkerResponse>{ type: "websocket" });
}