diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9bbeabd..f49d0a0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,6 +5,11 @@ on: pull_request: workflow_dispatch: +permissions: + contents: read + pages: write + id-token: write + jobs: build: runs-on: ubuntu-latest @@ -41,6 +46,13 @@ jobs: dist/*.js.map - name: build statics run: bash buildstatic.sh + - name: upload pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: "./staticbuild" + - name: deploy to github + id: deployment + uses: actions/deploy-pages@v4 upload: name: Upload release @@ -78,16 +90,3 @@ jobs: body: ${{ github.event.head_commit.message }} artifacts: "scramjet.zip" prerelease: true - deploy: - runs-on: ubuntu-latest - needs: build # Deploy after the build job finishes - permissions: - pages: write - id-token: write - - steps: - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ github.token }} - publish_dir: ./staticbuild diff --git a/eslint.config.mjs b/eslint.config.mjs index 5d5c5c3..acc5a46 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -46,6 +46,7 @@ export default [ "no-unreachable": "warn", "no-undef": "off", "no-empty": "off", + "no-debugger": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/ban-types": "off", diff --git a/rewriter/src/rewrite.rs b/rewriter/src/rewrite.rs index c030c5b..ea233d3 100644 --- a/rewriter/src/rewrite.rs +++ b/rewriter/src/rewrite.rs @@ -419,7 +419,7 @@ fn expression_span(e: &Expression) -> Span { } // js MUST not be able to get a reference to any of these because sbx -const UNSAFE_GLOBALS: [&str; 10] = [ +const UNSAFE_GLOBALS: &[&str] = &[ "window", "self", "globalThis", diff --git a/rspack.config.js b/rspack.config.js index 67c5113..b95436b 100644 --- a/rspack.config.js +++ b/rspack.config.js @@ -10,7 +10,6 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url)); const packagemeta = JSON.parse(await readFile("package.json")); export default defineConfig({ - // change to production when needed mode: "development", entry: { shared: join(__dirname, "src/shared/index.ts"), diff --git a/src/client/dom/serviceworker.ts b/src/client/dom/serviceworker.ts index a31882a..841a600 100644 --- a/src/client/dom/serviceworker.ts +++ b/src/client/dom/serviceworker.ts @@ -7,11 +7,11 @@ import { getOwnPropertyDescriptorHandler } from "../helpers"; export const order = 2; export const enabled = () => config.flags.serviceworkers; -export function disabled(client: ScramjetClient, self: Self) { +export function disabled(_client: ScramjetClient, _self: Self) { Reflect.deleteProperty(Navigator.prototype, "serviceWorker"); } -export default function (client: ScramjetClient, self: Self) { +export default function (client: ScramjetClient, _self: Self) { let registration; client.Proxy("EventTarget.prototype.addEventListener", { @@ -45,7 +45,7 @@ export default function (client: ScramjetClient, self: Self) { }); client.Trap("navigator.serviceWorker.ready", { - get(ctx) { + get(_ctx) { console.log(registration); return new Promise((resolve) => resolve(registration)); @@ -53,7 +53,7 @@ export default function (client: ScramjetClient, self: Self) { }); client.Trap("navigator.serviceWorker.controller", { - get(ctx) { + get(_ctx) { return registration?.active; }, }); diff --git a/src/client/dom/storage.ts b/src/client/dom/storage.ts index 5d9f625..af4bce7 100644 --- a/src/client/dom/storage.ts +++ b/src/client/dom/storage.ts @@ -63,7 +63,9 @@ export default function (client: ScramjetClient, self: typeof window) { ownKeys(target) { return Reflect.ownKeys(target) .filter((f) => typeof f === "string" && f.startsWith(client.url.host)) - .map((f) => f.substring(client.url.host.length + 1)); + .map((f) => + typeof f === "string" ? f.substring(client.url.host.length + 1) : f + ); }, getOwnPropertyDescriptor(target, property) { diff --git a/src/client/global.ts b/src/client/global.ts index d294b7b..e0a9853 100644 --- a/src/client/global.ts +++ b/src/client/global.ts @@ -1,8 +1,8 @@ // import { encodeUrl } from "../shared"; import { ScramjetClient } from "./client"; -import { indirectEval } from "./shared/eval"; // import { config } from "../shared"; import { getOwnPropertyDescriptorHandler } from "./helpers"; +import { indirectEval } from "./shared/eval"; export const UNSAFE_GLOBALS = [ "window", @@ -21,10 +21,13 @@ export function createGlobalProxy( ): typeof globalThis { return new Proxy(self, { get(target, prop) { - const value = Reflect.get(target, prop); - + if (prop === "location") return client.locationProxy; if (typeof prop === "string" && UNSAFE_GLOBALS.includes(prop)) - return client.wrapfn(value); + return client.wrapfn(self[prop]); + if (prop === "$scramjet") return; + if (prop === "eval") return indirectEval.bind(client); + + const value = Reflect.get(target, prop); return value; }, diff --git a/src/client/helpers.ts b/src/client/helpers.ts index ba5fff4..f2b75e5 100644 --- a/src/client/helpers.ts +++ b/src/client/helpers.ts @@ -2,27 +2,26 @@ export function getOwnPropertyDescriptorHandler(target, prop) { const realDescriptor = Reflect.getOwnPropertyDescriptor(target, prop); return realDescriptor; + // const d: PropertyDescriptor = {}; - const d: PropertyDescriptor = {}; + // if (realDescriptor.enumerable !== undefined) + // d.enumerable = realDescriptor.enumerable; + // if (realDescriptor.configurable !== undefined) + // d.configurable = realDescriptor.configurable; + // if (realDescriptor.writable !== undefined) + // d.writable = realDescriptor.writable; - if (realDescriptor.enumerable !== undefined) - d.enumerable = realDescriptor.enumerable; - if (realDescriptor.configurable !== undefined) - d.configurable = realDescriptor.configurable; - if (realDescriptor.writable !== undefined) - d.writable = realDescriptor.writable; + // if (realDescriptor.get) { + // d.get = () => this.get(target, prop); + // } - if (realDescriptor.get) { - d.get = () => this.get(target, prop); - } + // if (realDescriptor.set) { + // d.set = (value) => this.set(target, prop, value); + // } - if (realDescriptor.set) { - d.set = (value) => this.set(target, prop, value); - } + // if (realDescriptor.value) { + // d.value = this.get(target, prop); + // } - if (realDescriptor.value) { - d.value = this.get(target, prop); - } - - return d; + // return d; } diff --git a/src/client/shared/requests/fetch.ts b/src/client/shared/requests/fetch.ts index f6756c0..db056d1 100644 --- a/src/client/shared/requests/fetch.ts +++ b/src/client/shared/requests/fetch.ts @@ -3,9 +3,9 @@ import { isemulatedsw } from "../.."; import { unrewriteUrl } from "../../../shared"; import { ScramjetClient } from "../../client"; -import { rewriteUrl, rewriteHeaders } from "../../../shared"; +import { rewriteUrl } from "../../../shared"; -export default function (client: ScramjetClient, self: typeof globalThis) { +export default function (client: ScramjetClient, _self: typeof globalThis) { client.Proxy("fetch", { apply(ctx) { if (typeof ctx.args[0] === "string" || ctx.args[0] instanceof URL) { diff --git a/src/client/shared/requests/websocket.ts b/src/client/shared/requests/websocket.ts index 5eb9b22..748759c 100644 --- a/src/client/shared/requests/websocket.ts +++ b/src/client/shared/requests/websocket.ts @@ -59,7 +59,7 @@ export default function (client: ScramjetClient, self: typeof globalThis) { fakeWebSocket.dispatchEvent(fakeev); } - barews.addEventListener("open", (ev) => { + barews.addEventListener("open", () => { fakeEventSend(new Event("open")); }); barews.addEventListener("close", (ev) => { @@ -76,7 +76,7 @@ export default function (client: ScramjetClient, self: typeof globalThis) { fakeEventSend(fakeev); }); - barews.addEventListener("error", (ev) => { + barews.addEventListener("error", () => { fakeEventSend(new Event("error")); }); diff --git a/src/client/shared/unproxy.ts b/src/client/shared/unproxy.ts index 9905c2a..991b77c 100644 --- a/src/client/shared/unproxy.ts +++ b/src/client/shared/unproxy.ts @@ -51,17 +51,17 @@ export default function (client: ScramjetClient, self: typeof window) { if (desc.get) { client.RawProxy(desc, "get", { - apply(ctx) { + apply(getCtx) { // value of this in the getter needs to be corrected - unproxy(ctx, client); + unproxy(getCtx, client); }, }); } if (desc.set) { client.RawProxy(desc, "set", { - apply(ctx) { - unproxy(ctx, client); + apply(setCtx) { + unproxy(setCtx, client); }, }); } diff --git a/src/client/shared/wrap.ts b/src/client/shared/wrap.ts index cdc0895..73a305a 100644 --- a/src/client/shared/wrap.ts +++ b/src/client/shared/wrap.ts @@ -47,9 +47,6 @@ export function createWrapFn(client: ScramjetClient, self: typeof globalThis) { } else if (isworker && identifier instanceof self.WorkerGlobalScope) { return client.globalProxy; } - if (identifier == self.eval) { - return indirectEval.bind(client); - } return identifier; }; diff --git a/src/controller/index.ts b/src/controller/index.ts index f35d20e..265e94b 100644 --- a/src/controller/index.ts +++ b/src/controller/index.ts @@ -10,7 +10,6 @@ export class ScramjetController { // sane ish defaults const defaultConfig: Partial = { prefix: "/scramjet/", - globals: { wrapfn: "$scramjet$wrap", trysetfn: "$scramjet$tryset", diff --git a/src/shared/rewriters/html.ts b/src/shared/rewriters/html.ts index bea47ee..2e84a2c 100644 --- a/src/shared/rewriters/html.ts +++ b/src/shared/rewriters/html.ts @@ -137,6 +137,7 @@ export const htmlRules: { // because they can't be fetch'd return unrewriteBlob(value); } + return rewriteUrl(value, meta); }, src: ["video", "audio"], diff --git a/src/shared/rewriters/js.ts b/src/shared/rewriters/js.ts index 2059356..cc48d99 100644 --- a/src/shared/rewriters/js.ts +++ b/src/shared/rewriters/js.ts @@ -26,7 +26,7 @@ export function rewriteJs(js: string | ArrayBuffer, meta: URLMeta) { return rewriteJsNaiive(text); } - const before = performance.now(); + // const before = performance.now(); if (typeof js === "string") { js = new TextDecoder().decode(rewrite_js(js, meta.base.href, $scramjet)); } else { @@ -36,7 +36,7 @@ export function rewriteJs(js: string | ArrayBuffer, meta: URLMeta) { $scramjet ); } - const after = performance.now(); + // const after = performance.now(); // dbg.debug("Rewrite took", Math.floor((after - before) * 10) / 10, "ms"); diff --git a/src/shared/rewriters/url.ts b/src/shared/rewriters/url.ts index 3549059..bb575a7 100644 --- a/src/shared/rewriters/url.ts +++ b/src/shared/rewriters/url.ts @@ -15,12 +15,14 @@ function tryCanParseURL(url: string, origin?: string | URL): URL | null { } export function rewriteBlob(url: string, meta: URLMeta) { - let blob = new URL(url.substring("blob:".length)); + const blob = new URL(url.substring("blob:".length)); + return "blob:" + meta.origin.origin + blob.pathname; } export function unrewriteBlob(url: string) { - let blob = new URL(url.substring("blob:".length)); + const blob = new URL(url.substring("blob:".length)); + return "blob:" + location.origin + blob.pathname; } diff --git a/src/thread/thread.ts b/src/thread/thread.ts deleted file mode 100644 index dc208bc..0000000 --- a/src/thread/thread.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { rewriteJs } from "../shared/rewriters/js"; - -// @ts-ignore -onconnect = (e) => { - const port = e.ports[0]; - - console.log("thread: connected to port", port); - port.postMessage("ready"); - - let syncToken = 0; - port.onmessage = ({ data }) => { - console.log("thread: received message", data); - const [task, ...args] = data; - const token = syncToken++; - - try { - const res = tasks[task](...args); - console.log("thread: task", task, "completed with token", token); - port.postMessage({ - token, - result: res, - }); - } catch (e) { - port.postMessage({ - token, - error: e.message, - }); - } - - port.postMessage("idle"); - }; -}; - -const tasks = { - rewriteJs: taskRewriteJs, -}; - -function taskRewriteJs(js: ArrayBuffer, origin: string): string { - // idk how to get the codec from here - return rewriteJs(js, new URL(origin), () => {}); -} diff --git a/src/worker/fetch.ts b/src/worker/fetch.ts index 0757b67..b2c843f 100644 --- a/src/worker/fetch.ts +++ b/src/worker/fetch.ts @@ -58,7 +58,7 @@ export async function swfetch( dataurl = unrewriteBlob(dataurl); } - let response: Response = await fetch(dataurl, {}); + const response: Response = await fetch(dataurl, {}); let body: BodyType; @@ -286,15 +286,10 @@ async function rewriteBody( } else { return response.body; } - break; case "script": return rewriteJs(await response.arrayBuffer(), meta); - // Disable threading for now, it's causing issues. - // responseBody = await this.threadpool.rewriteJs(await responseBody.arrayBuffer(), url.toString()); - break; case "style": return rewriteCss(await response.text(), meta); - break; case "sharedworker": case "worker": return rewriteWorkers(await response.arrayBuffer(), workertype, meta); diff --git a/src/worker/index.ts b/src/worker/index.ts index 587c214..e15fbb0 100644 --- a/src/worker/index.ts +++ b/src/worker/index.ts @@ -1,6 +1,5 @@ import { FakeServiceWorker } from "./fakesw"; import { swfetch } from "./fetch"; -import { ScramjetThreadpool } from "./threadpool"; import type BareClient from "@mercuryworkshop/bare-mux"; import { ScramjetConfig } from "../types"; import { $scramjet, loadCodecs } from "../scramjet"; @@ -8,7 +7,6 @@ import { $scramjet, loadCodecs } from "../scramjet"; export class ScramjetServiceWorker extends EventTarget { client: BareClient; config: ScramjetConfig; - threadpool: ScramjetThreadpool; syncPool: Record void> = {}; synctoken = 0; @@ -21,8 +19,6 @@ export class ScramjetServiceWorker extends EventTarget { super(); this.client = new $scramjet.shared.util.BareClient(); - this.threadpool = new ScramjetThreadpool(); - addEventListener("message", ({ data }: { data: MessageC2W }) => { if (!("scramjet$type" in data)) return; diff --git a/src/worker/threadpool.ts b/src/worker/threadpool.ts deleted file mode 100644 index 2381cef..0000000 --- a/src/worker/threadpool.ts +++ /dev/null @@ -1,88 +0,0 @@ -type Thread = { - handle: MessagePort; - ready: boolean; - busy: boolean; - syncToken: number; - promises: Map; -}; - -export class ScramjetThreadpool { - threads: Thread[] = []; - constructor() { - self.addEventListener("message", ({ data }) => { - if (data.scramjet$type == "add") { - this.spawn(data.handle); - } - }); - } - - spawn(handle) { - const thread = { - handle, - ready: false, - busy: false, - syncToken: 0, - promises: new Map(), - }; - - this.threads.push(thread); - - thread.handle.onmessage = (e) => { - if (e.data === "ready") { - thread.ready = true; - - return; - } - if (e.data === "idle") { - thread.busy = false; - - return; - } - - const { token, result, error } = e.data; - const { resolve, reject } = thread.promises.get(token); - thread.promises.delete(token); - - if (error) { - reject(error); - } else { - resolve(result); - } - }; - - thread.handle.start(); - } - - pick(): Thread | undefined { - const alive = this.threads.filter((t) => t.ready); - const idle = alive.filter((t) => !t.busy); - - // no threads - if (!alive.length) return; - - // there is a thread, but it's busy - if (!idle.length) return alive[Math.floor(Math.random() * alive.length)]; - - // there's an open thread - return idle[Math.floor(Math.random() * idle.length)]; - } - - run(task: string, args: any[], transferrable: any[]): Promise { - const thread = this.pick(); - if (!thread) throw new Error("No threads available"); - thread.busy = true; - - const token = thread.syncToken++; - - // console.log("runthread: dispatching task", task, "to thread", thread, "of token", token) - return new Promise((resolve, reject) => { - thread.promises.set(token, { resolve, reject }); - - thread.handle.postMessage([task, ...args], transferrable); - }); - } - - async rewriteJs(js: ArrayBuffer, origin: string): Promise { - return await this.run("rewriteJs", [js, origin], [js]); - } -}