This commit is contained in:
velzie 2024-08-02 23:22:05 -04:00
parent 116d6ce16a
commit 7e8e9990f4
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
4 changed files with 83 additions and 36 deletions

View file

@ -12,7 +12,12 @@ export class ScramjetServiceWorkerRuntime {
port.addEventListener("message", (event) => { port.addEventListener("message", (event) => {
console.log("sw", event.data); console.log("sw", event.data);
if ("scramjet$type" in event.data) { if ("scramjet$type" in event.data) {
handleMessage.call(this, client, event.data); if (event.data.scramjet$type === "init") {
this.recvport = event.data.scramjet$port;
this.recvport.postMessage({ scramjet$type: "init" });
} else {
handleMessage.call(this, client, event.data);
}
} }
}); });
@ -20,7 +25,27 @@ export class ScramjetServiceWorkerRuntime {
}; };
} }
hook() {} hook() {
this.client.global.registration = {
// TODO IMPLEMENT SCOPES
scope: this.client.url.href,
active: {
scriptURL: this.client.url.href,
state: "activated",
onstatechange: null,
onerror: null,
postMessage: () => {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: (_e: Event) => {},
},
unregister: async () => true,
update: async () => {},
installing: null,
waiting: null,
};
}
} }
function handleMessage( function handleMessage(
@ -28,7 +53,6 @@ function handleMessage(
client: ScramjetClient, client: ScramjetClient,
data: MessageW2R data: MessageW2R
) { ) {
if (data.scramjet$port) this.recvport = data.scramjet$port;
const port = this.recvport; const port = this.recvport;
const type = data.scramjet$type; const type = data.scramjet$type;
const token = data.scramjet$token; const token = data.scramjet$token;
@ -54,25 +78,35 @@ function handleMessage(
// TODO: clean up, maybe put into a class // TODO: clean up, maybe put into a class
const fakeFetchEvent: any = new Event("fetch"); const fakeFetchEvent: any = new Event("fetch");
fakeFetchEvent.request = fakeRequest; fakeFetchEvent.request = fakeRequest;
fakeFetchEvent.respondWith = async ( let responded = false;
response: Response | Promise<Response> fakeFetchEvent.respondWith = (response: Response | Promise<Response>) => {
) => { responded = true;
response = await response; (async () => {
const message: MessageR2W = { response = await response;
scramjet$type: "fetch", const message: MessageR2W = {
scramjet$token: token, scramjet$type: "fetch",
scramjet$response: { scramjet$token: token,
body: response.body, scramjet$response: {
headers: Array.from(response.headers.entries()), body: response.body,
status: response.status, headers: Array.from(response.headers.entries()),
statusText: response.statusText, status: response.status,
}, statusText: response.statusText,
}; },
};
port.postMessage(message, [response.body]); dbg.log("sw", "responding", message);
port.postMessage(message, [response.body]);
})();
}; };
handler.proxiedCallback(trustEvent(fakeFetchEvent)); handler.proxiedCallback(trustEvent(fakeFetchEvent));
if (!responded) {
port.postMessage({
scramjet$type: "fetch",
scramjet$token: token,
scramjet$response: false,
});
}
} }
} }
} }
@ -125,4 +159,4 @@ type MessageCommon = {
export type MessageR2W = MessageCommon & MessageTypeR2W; export type MessageR2W = MessageCommon & MessageTypeR2W;
export type MessageW2R = MessageCommon & export type MessageW2R = MessageCommon &
MessageTypeW2R & { scramjet$port: MessagePort | undefined }; MessageTypeW2R & { scramjet$port?: MessagePort };

View file

@ -1,6 +1,6 @@
import { rewriteJs } from "./js"; import { rewriteJs } from "./js";
const clientscripts = ["wasm", "codecs", "shared", "client"]; const clientscripts = ["wasm", "shared", "client"];
export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) { export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) {
const dest = origin.searchParams.get("dest"); const dest = origin.searchParams.get("dest");
const type = origin.searchParams.get("type"); const type = origin.searchParams.get("type");
@ -9,14 +9,20 @@ export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) {
let str = ""; let str = "";
str += `self.$scramjet = {}; self.$scramjet.config = ${JSON.stringify(self.$scramjet.config)};\n`; str += `self.$scramjet = {}; self.$scramjet.config = ${JSON.stringify(self.$scramjet.config)};
`;
str += ""; str += "";
if (type === "module") { if (type === "module") {
str += `import "${self.$scramjet.config["codecs"]}"
self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec];
`;
for (const script of clientscripts) { for (const script of clientscripts) {
console.log("Import", script, self.$scramjet);
str += `import "${self.$scramjet.config[script]}"\n`; str += `import "${self.$scramjet.config[script]}"\n`;
} }
} else { } else {
str += `importScripts("${self.$scramjet.config["codecs"]}");
self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec];
`;
for (const script of clientscripts) { for (const script of clientscripts) {
str += `importScripts("${self.$scramjet.config[script]}");\n`; str += `importScripts("${self.$scramjet.config[script]}");\n`;
} }
@ -27,8 +33,6 @@ export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) {
rewritten = new TextDecoder().decode(rewritten); rewritten = new TextDecoder().decode(rewritten);
} }
str +=
"self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec];\n";
str += rewritten; str += rewritten;
dbg.log("Rewrite", type, dest, str); dbg.log("Rewrite", type, dest, str);

View file

@ -4,7 +4,7 @@ export class FakeServiceWorker {
syncToken = 0; syncToken = 0;
promises: Record<number, (val?: MessageR2W) => void> = {}; promises: Record<number, (val?: MessageR2W) => void> = {};
messageChannel = new MessageChannel(); messageChannel = new MessageChannel();
alreadytransfered = false; connected = false;
constructor( constructor(
public handle: MessagePort, public handle: MessagePort,
@ -12,10 +12,22 @@ export class FakeServiceWorker {
) { ) {
this.messageChannel.port1.addEventListener("message", (event) => { this.messageChannel.port1.addEventListener("message", (event) => {
if ("scramjet$type" in event.data) { if ("scramjet$type" in event.data) {
this.handleMessage(event.data); if (event.data.scramjet$type === "init") {
this.connected = true;
} else {
this.handleMessage(event.data);
}
} }
}); });
this.messageChannel.port1.start(); this.messageChannel.port1.start();
this.handle.postMessage(
{
scramjet$type: "init",
scramjet$port: this.messageChannel.port2,
},
[this.messageChannel.port2]
);
} }
handleMessage(data: MessageR2W) { handleMessage(data: MessageR2W) {
@ -26,13 +38,12 @@ export class FakeServiceWorker {
} }
} }
async fetch(request: Request): Promise<Response> { async fetch(request: Request): Promise<Response | false> {
const token = this.syncToken++; const token = this.syncToken++;
const message: MessageW2R = { const message: MessageW2R = {
scramjet$type: "fetch", scramjet$type: "fetch",
scramjet$token: token, scramjet$token: token,
scramjet$port: !this.alreadytransfered && this.messageChannel.port2,
scramjet$request: { scramjet$request: {
url: request.url, url: request.url,
body: request.body, body: request.body,
@ -43,12 +54,7 @@ export class FakeServiceWorker {
}, },
}; };
const transfer: any = request.body ? [request.body] : []; const transfer = request.body ? [request.body] : [];
if (!this.alreadytransfered) {
this.alreadytransfered = true;
transfer.push(this.messageChannel.port2);
}
this.handle.postMessage(message, transfer); this.handle.postMessage(message, transfer);
@ -56,6 +62,8 @@ export class FakeServiceWorker {
this.promises[token] = resolve; this.promises[token] = resolve;
})) as MessageR2W; })) as MessageR2W;
if (!r) return false;
return new Response(r.body, { return new Response(r.body, {
headers: r.headers, headers: r.headers,
status: r.status, status: r.status,

View file

@ -51,9 +51,10 @@ export async function swfetch(
(w) => w.origin === url.origin (w) => w.origin === url.origin
); );
if (activeWorker) { if (activeWorker && activeWorker.connected) {
// TODO: check scope // TODO: check scope
return await activeWorker.fetch(request); const r = await activeWorker.fetch(request);
if (r) return r;
} }
if (url.origin == new URL(request.url).origin) { if (url.origin == new URL(request.url).origin) {
throw new Error( throw new Error(