scramjet / src /worker /fakesw.ts
soiz1's picture
Upload 150 files
bee6636 verified
import { type MessageW2R, type MessageR2W } from "../client/swruntime";
export class FakeServiceWorker {
syncToken = 0;
promises: Record<number, (val?: MessageR2W) => void> = {};
messageChannel = new MessageChannel();
connected = false;
constructor(
public handle: MessagePort,
public origin: string
) {
this.messageChannel.port1.addEventListener("message", (event) => {
if ("scramjet$type" in event.data) {
if (event.data.scramjet$type === "init") {
this.connected = true;
} else {
this.handleMessage(event.data);
}
}
});
this.messageChannel.port1.start();
this.handle.postMessage(
{
scramjet$type: "init",
scramjet$port: this.messageChannel.port2,
},
[this.messageChannel.port2]
);
}
handleMessage(data: MessageR2W) {
const cb = this.promises[data.scramjet$token];
if (cb) {
cb(data);
delete this.promises[data.scramjet$token];
}
}
async fetch(request: Request): Promise<Response | false> {
const token = this.syncToken++;
const message: MessageW2R = {
scramjet$type: "fetch",
scramjet$token: token,
scramjet$request: {
url: request.url,
body: request.body,
headers: Array.from(request.headers.entries()),
method: request.method,
mode: request.mode,
destinitation: request.destination,
},
};
const transfer = request.body ? [request.body] : [];
this.handle.postMessage(message, transfer);
const { scramjet$response: r } = (await new Promise((resolve) => {
this.promises[token] = resolve;
})) as MessageR2W;
if (!r) return false;
return new Response(r.body, {
headers: r.headers,
status: r.status,
statusText: r.statusText,
});
}
}