diff --git a/src/client/swruntime.ts b/src/client/swruntime.ts index aa4c64e..b983ecb 100644 --- a/src/client/swruntime.ts +++ b/src/client/swruntime.ts @@ -12,7 +12,12 @@ export class ScramjetServiceWorkerRuntime { port.addEventListener("message", (event) => { console.log("sw", 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( @@ -28,7 +53,6 @@ function handleMessage( client: ScramjetClient, data: MessageW2R ) { - if (data.scramjet$port) this.recvport = data.scramjet$port; const port = this.recvport; const type = data.scramjet$type; const token = data.scramjet$token; @@ -54,25 +78,35 @@ function handleMessage( // TODO: clean up, maybe put into a class const fakeFetchEvent: any = new Event("fetch"); fakeFetchEvent.request = fakeRequest; - fakeFetchEvent.respondWith = async ( - response: Response | Promise - ) => { - response = await response; - const message: MessageR2W = { - scramjet$type: "fetch", - scramjet$token: token, - scramjet$response: { - body: response.body, - headers: Array.from(response.headers.entries()), - status: response.status, - statusText: response.statusText, - }, - }; + let responded = false; + fakeFetchEvent.respondWith = (response: Response | Promise) => { + responded = true; + (async () => { + response = await response; + const message: MessageR2W = { + scramjet$type: "fetch", + scramjet$token: token, + scramjet$response: { + body: response.body, + headers: Array.from(response.headers.entries()), + 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)); + 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 MessageW2R = MessageCommon & - MessageTypeW2R & { scramjet$port: MessagePort | undefined }; + MessageTypeW2R & { scramjet$port?: MessagePort }; diff --git a/src/shared/rewriters/worker.ts b/src/shared/rewriters/worker.ts index 763a240..6bb10e3 100644 --- a/src/shared/rewriters/worker.ts +++ b/src/shared/rewriters/worker.ts @@ -1,6 +1,6 @@ import { rewriteJs } from "./js"; -const clientscripts = ["wasm", "codecs", "shared", "client"]; +const clientscripts = ["wasm", "shared", "client"]; export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) { const dest = origin.searchParams.get("dest"); const type = origin.searchParams.get("type"); @@ -9,14 +9,20 @@ export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) { 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 += ""; if (type === "module") { + str += `import "${self.$scramjet.config["codecs"]}" +self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec]; +`; for (const script of clientscripts) { - console.log("Import", script, self.$scramjet); str += `import "${self.$scramjet.config[script]}"\n`; } } else { + str += `importScripts("${self.$scramjet.config["codecs"]}"); +self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec]; +`; for (const script of clientscripts) { str += `importScripts("${self.$scramjet.config[script]}");\n`; } @@ -27,8 +33,6 @@ export function rewriteWorkers(js: string | ArrayBuffer, origin?: URL) { rewritten = new TextDecoder().decode(rewritten); } - str += - "self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec];\n"; str += rewritten; dbg.log("Rewrite", type, dest, str); diff --git a/src/worker/fakesw.ts b/src/worker/fakesw.ts index 236848d..1246066 100644 --- a/src/worker/fakesw.ts +++ b/src/worker/fakesw.ts @@ -4,7 +4,7 @@ export class FakeServiceWorker { syncToken = 0; promises: Record void> = {}; messageChannel = new MessageChannel(); - alreadytransfered = false; + connected = false; constructor( public handle: MessagePort, @@ -12,10 +12,22 @@ export class FakeServiceWorker { ) { this.messageChannel.port1.addEventListener("message", (event) => { 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.handle.postMessage( + { + scramjet$type: "init", + scramjet$port: this.messageChannel.port2, + }, + [this.messageChannel.port2] + ); } handleMessage(data: MessageR2W) { @@ -26,13 +38,12 @@ export class FakeServiceWorker { } } - async fetch(request: Request): Promise { + async fetch(request: Request): Promise { const token = this.syncToken++; const message: MessageW2R = { scramjet$type: "fetch", scramjet$token: token, - scramjet$port: !this.alreadytransfered && this.messageChannel.port2, scramjet$request: { url: request.url, body: request.body, @@ -43,12 +54,7 @@ export class FakeServiceWorker { }, }; - const transfer: any = request.body ? [request.body] : []; - - if (!this.alreadytransfered) { - this.alreadytransfered = true; - transfer.push(this.messageChannel.port2); - } + const transfer = request.body ? [request.body] : []; this.handle.postMessage(message, transfer); @@ -56,6 +62,8 @@ export class FakeServiceWorker { this.promises[token] = resolve; })) as MessageR2W; + if (!r) return false; + return new Response(r.body, { headers: r.headers, status: r.status, diff --git a/src/worker/fetch.ts b/src/worker/fetch.ts index c696f91..14d0e78 100644 --- a/src/worker/fetch.ts +++ b/src/worker/fetch.ts @@ -51,9 +51,10 @@ export async function swfetch( (w) => w.origin === url.origin ); - if (activeWorker) { + if (activeWorker && activeWorker.connected) { // 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) { throw new Error(