From ec0fb8b70ac1b6875c62bc2e83a2fdcc8ae44316 Mon Sep 17 00:00:00 2001 From: velzie Date: Sat, 31 Aug 2024 18:26:17 -0400 Subject: [PATCH] fix data url workers --- rewriter/src/rewrite.rs | 21 +++++---- src/client/dom/origin.ts | 14 ------ src/client/shared/requests/xmlhttprequest.ts | 8 +++- src/client/shared/worker.ts | 26 ++++++----- src/worker/index.ts | 49 +++++++++++++++++--- 5 files changed, 75 insertions(+), 43 deletions(-) diff --git a/rewriter/src/rewrite.rs b/rewriter/src/rewrite.rs index 4b492eb..40f0559 100644 --- a/rewriter/src/rewrite.rs +++ b/rewriter/src/rewrite.rs @@ -85,18 +85,21 @@ impl Rewriter { impl<'a> Visit<'a> for Rewriter { fn visit_identifier_reference(&mut self, it: &IdentifierReference<'a>) { - // self.jschanges.push(JsChange::GenericChange { - // span: it.span, - // text: format!( - // "({}(typeof {} == 'undefined' || {}, (()=>{{ try {{return arguments}} catch(_){{}} }})()))", - // self.wrapfn, it.name, it.name - // ), - // }); - if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) { + if self.config.capture_errors { self.jschanges.push(JsChange::GenericChange { span: it.span, - text: format!("{}({})", self.config.wrapfn, it.name), + text: format!( + "{}({}, typeof arguments != 'undefined' && arguments)", + self.config.wrapfn, it.name + ), }); + } else { + if UNSAFE_GLOBALS.contains(&it.name.to_string().as_str()) { + self.jschanges.push(JsChange::GenericChange { + span: it.span, + text: format!("{}({})", self.config.wrapfn, it.name), + }); + } } } diff --git a/src/client/dom/origin.ts b/src/client/dom/origin.ts index 0245eb7..1a4cb87 100644 --- a/src/client/dom/origin.ts +++ b/src/client/dom/origin.ts @@ -20,20 +20,6 @@ export default function (client: ScramjetClient, self: typeof window) { }, }); - client.Trap("document.baseURI", { - get() { - const base = self.document.querySelector("base"); - if (base) { - return new URL(base.href, client.url).href; - } - - return client.url.href; - }, - set() { - return false; - }, - }); - client.Trap("document.documentURI", { get() { return decodeUrl(self.location.href); diff --git a/src/client/shared/requests/xmlhttprequest.ts b/src/client/shared/requests/xmlhttprequest.ts index 6188d07..70498fd 100644 --- a/src/client/shared/requests/xmlhttprequest.ts +++ b/src/client/shared/requests/xmlhttprequest.ts @@ -1,4 +1,4 @@ -import { encodeUrl, rewriteHeaders } from "../../../shared"; +import { decodeUrl, encodeUrl, rewriteHeaders } from "../../../shared"; export default function (client, self) { client.Proxy("XMLHttpRequest.prototype.open", { @@ -15,4 +15,10 @@ export default function (client, self) { ctx.args = Object.entries(headerObject)[0]; }, }); + + client.Trap("XMLHttpRequest.prototype.responseURL", { + get(ctx) { + return decodeUrl(ctx.get()); + }, + }); } diff --git a/src/client/shared/worker.ts b/src/client/shared/worker.ts index 09ae4b9..9a7c574 100644 --- a/src/client/shared/worker.ts +++ b/src/client/shared/worker.ts @@ -1,4 +1,5 @@ import { encodeUrl, BareMuxConnection } from "../../shared"; +import type { MessageC2W } from "../../worker"; import { ScramjetClient } from "../client"; export default function (client: ScramjetClient, self: typeof globalThis) { @@ -6,26 +7,27 @@ export default function (client: ScramjetClient, self: typeof globalThis) { construct({ args, call }) { if (args[0] instanceof URL) args[0] = args[0].href; if (args[0].startsWith("blob:") || args[0].startsWith("data:")) { - if (args[0].startsWith("blob:")) { - args[0] = - "data:application/javascript;base64," + - btoa(syncfetch(client, args[0])); - } + let data = syncfetch(client, args[0]); + let id = Math.random().toString(8).slice(5); - args[0] = "/scramjet/worker?data=" + args[0]; + args[0] = "/scramjet/worker?id=" + id; if (args[1] && args[1].type === "module") { args[0] += "&type=module"; } args[0] += "&origin=" + encodeURIComponent(client.url.origin); - return; - } + client.serviceWorker.controller?.postMessage({ + scramjet$type: "dataworker", + data, + id, + } as MessageC2W); + } else { + args[0] = encodeUrl(args[0]) + "?dest=worker"; - args[0] = encodeUrl(args[0]) + "?dest=worker"; - - if (args[1] && args[1].type === "module") { - args[0] += "&type=module"; + if (args[1] && args[1].type === "module") { + args[0] += "&type=module"; + } } const worker = call(); diff --git a/src/worker/index.ts b/src/worker/index.ts index 5f01dfa..8078d02 100644 --- a/src/worker/index.ts +++ b/src/worker/index.ts @@ -17,6 +17,11 @@ export class ScramjetServiceWorker { serviceWorkers: FakeServiceWorker[] = []; + dataworkerpromises: Record< + string, + { promise: Promise; resolve: (v: string) => void } + > = {}; + constructor() { this.client = new self.$scramjet.shared.util.BareClient(); @@ -35,8 +40,17 @@ export class ScramjetServiceWorker { return; } - // const resolve = this.syncPool[data.scramjet$token]; - // delete this.syncPool[data.scramjet$token]; + if (data.scramjet$type === "dataworker") { + if (this.dataworkerpromises[data.id]) { + this.dataworkerpromises[data.id].resolve(data.data); + } else { + let resolve: (v: string) => void; + const promise = new Promise((res) => (resolve = res)); + this.dataworkerpromises[data.id] = { promise, resolve }; + resolve(data.data); + } + return; + } }); } @@ -110,16 +124,28 @@ export class ScramjetServiceWorker { async fetch({ request, clientId }: FetchEvent) { if (new URL(request.url).pathname.startsWith("/scramjet/worker")) { - const dataurl = new URL(request.url).searchParams.get("data"); + const id = new URL(request.url).searchParams.get("id"); const type = new URL(request.url).searchParams.get("type"); - const res = await fetch(dataurl); - const ab = await res.arrayBuffer(); const origin = new URL( decodeURIComponent(new URL(request.url).searchParams.get("origin")) ); - const rewritten = rewriteWorkers(ab, type, new URL(origin)); + let promise = this.dataworkerpromises[id]; + if (!promise) { + let resolve: (v: string) => void; + promise = { + promise: new Promise((res) => (resolve = res)), + resolve, + }; + promise.resolve = resolve; + this.dataworkerpromises[id] = promise; + } + + const data = await promise.promise; + delete this.dataworkerpromises[id]; + + const rewritten = rewriteWorkers(data, type, new URL(origin)); return new Response(rewritten, { headers: { @@ -148,12 +174,21 @@ type CookieMessage = { url: string; }; +type DataWorkerMessage = { + scramjet$type: "dataworker"; + data: string; + id: string; +}; + type MessageCommon = { scramjet$type: string; scramjet$token: number; }; -type MessageTypeC2W = RegisterServiceWorkerMessage | CookieMessage; +type MessageTypeC2W = + | RegisterServiceWorkerMessage + | CookieMessage + | DataWorkerMessage; type MessageTypeW2C = CookieMessage; // c2w: client to (service) worker