From 17b440ea37f6adeba6c4ff1d8ef421e3e2317206 Mon Sep 17 00:00:00 2001 From: Avad3 <65318266+Avad3@users.noreply.github.com> Date: Tue, 30 Jul 2024 22:09:17 -0400 Subject: [PATCH] start bootstrapper --- farm.config.ts | 27 -------------- rollup.config.js | 39 -------------------- rspack.config.js | 6 ++++ server.js | 2 +- src/bootsrapper/index.ts | 70 ++++++++++++++++++++++++++++++++++++ src/scramjet.config.ts | 36 +++++++++---------- src/shared/rewriters/html.ts | 30 +++++++++------- src/shared/rewriters/js.ts | 4 +-- src/shared/rewriters/url.ts | 8 ++--- src/types.d.ts | 32 +++++++++-------- src/worker/fetch.ts | 7 ++-- src/worker/index.ts | 20 +++++++++-- static/index.html | 3 +- static/sw.js | 1 - static/ui.js | 12 +++++-- 15 files changed, 166 insertions(+), 131 deletions(-) delete mode 100644 farm.config.ts delete mode 100644 rollup.config.js create mode 100644 src/bootsrapper/index.ts diff --git a/farm.config.ts b/farm.config.ts deleted file mode 100644 index 715f762..0000000 --- a/farm.config.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { defineConfig } from "@farmfe/core"; -// import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin"; -import { join } from "path"; - -import sj from "scramjet-farm-plugin"; - -export default defineConfig({ - plugins: [sj()], - compilation: { - presetEnv: false, - mode: "development", - sourcemap: false, - input: { - worker: "src/worker/index.ts", - thread: "src/thread/thread.ts", - client: "src/client/index.ts", - config: "src/scramjet.config.ts", - }, - output: { - path: "dist", - format: "cjs", - targetEnv: "browser-esnext", - entryFilename: "scramjet.[entryName].js", - filename: "scramjet.split.[name].js", - }, - }, -}); diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index bd04ffa..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,39 +0,0 @@ -import typescript from "rollup-plugin-typescript2"; -import { join } from "node:path"; -import fs from "node:fs"; -import { fileURLToPath } from "node:url"; - -import { nodeResolve } from "@rollup/plugin-node-resolve"; - -// check if its -const production = !process.env.ROLLUP_WATCH; -console.log(production); -fs.rmSync(join(fileURLToPath(new URL(".", import.meta.url)), "./dist"), { - recursive: true, - force: true, -}); - -const commonPlugins = () => [ - typescript({ - tsconfig: "tsconfig.json", - }), - nodeResolve(), -]; - -export default { - plugins: commonPlugins(), - input: { - client: "./src/client/index.ts", - worker: "./src/worker/index.ts", - config: "./src/scramjet.config.ts", - }, - output: { - entryFileNames: "scramjet.[name].js", - dir: "./dist", - format: "system", - bundle: true, - minify: production, - sourcemap: true, - treeshake: "recommended", - }, -}; diff --git a/rspack.config.js b/rspack.config.js index 3e487cc..51b2b53 100644 --- a/rspack.config.js +++ b/rspack.config.js @@ -16,6 +16,7 @@ export default defineConfig({ client: join(__dirname, "src/client/index.ts"), config: join(__dirname, "src/scramjet.config.ts"), codecs: join(__dirname, "src/codecs/index.ts"), + bootstrapper: join(__dirname, "src/bootsrapper/index.ts") }, resolve: { extensions: [".ts", ".js"], @@ -44,6 +45,11 @@ export default defineConfig({ type: "javascript/auto", }, ], + parser: { + javascript: { + dynamicImportMode: "eager" + } + } }, output: { filename: "scramjet.[name].js", diff --git a/server.js b/server.js index 164ec03..1615ecc 100644 --- a/server.js +++ b/server.js @@ -76,7 +76,7 @@ fastify.register(fastifyStatic, { }); fastify.listen({ port: process.env.PORT || 1337, - host: "0.0.0.0", + // host: "0.0.0.0", }); writeFileSync( diff --git a/src/bootsrapper/index.ts b/src/bootsrapper/index.ts new file mode 100644 index 0000000..061ba03 --- /dev/null +++ b/src/bootsrapper/index.ts @@ -0,0 +1,70 @@ +import IDBMap from "idb-map-entries"; +import { ScramjetConfig } from "../types"; +import { Codec } from "../codecs"; + +export class ScramjetBootstrapper { + config: ScramjetConfig; + private store: IDBMap; + codec: Codec; + + constructor(config: ScramjetConfig) { + const defaultConfig = { + prefix: "/scramjet/", + codec: "plain", + wrapfn: "$scramjet$wrap", + trysetfn: "$scramjet$tryset", + importfn: "$scramjet$import", + rewritefn: "$scramjet$rewrite", + shared: "/scramjet.shared.js", + worker: "/scramjet.worker.js", + thread: "/scramjet.thread.js", + client: "/scramjet.client.js", + codecs: "/scramjet.codecs.js", + } + + this.config = Object.assign({}, defaultConfig, config); + + // rspack won't let me use a dynamic import + fetch(config.codecs).then(async (response) => { + eval(await response.text()); + + self.$scramjet.codec = self.$scramjet.codecs[this.config.codec]; + self.$scramjet.config = this.config; + }); + + console.log(this.config); + this.store = new IDBMap("config", { + prefix: "scramjet" + }); + this.saveConfig(); + } + + registerSw(serviceWorkerPath: string) { + if ("serviceWorker" in navigator) { + navigator.serviceWorker + .register(serviceWorkerPath, { + scope: this.config.prefix + }) + .then((registration) => { + console.log("ServiceWorker registration successful with scope: ", registration.scope); + }) + .catch((err) => { + console.log("ServiceWorker registration failed: ", err); + }); + } + } + + saveConfig() { + this.store.set("config", this.config).then(() => { + console.log("scramjet config saved"); + }); + } + + modifyConfig(config: ScramjetConfig) { + this.config = Object.assign({}, this.config, config); + + this.saveConfig(); + } +} + +window.ScramjetBootstrapper = ScramjetBootstrapper; \ No newline at end of file diff --git a/src/scramjet.config.ts b/src/scramjet.config.ts index 4e47107..d698e81 100644 --- a/src/scramjet.config.ts +++ b/src/scramjet.config.ts @@ -1,18 +1,18 @@ -if (!self.$scramjet) { - //@ts-expect-error really dumb workaround - self.$scramjet = {}; -} -self.$scramjet.config = { - prefix: "/scramjet/", - codec: self.$scramjet.codecs.plain, - wrapfn: "$scramjet$wrap", - trysetfn: "$scramjet$tryset", - importfn: "$scramjet$import", - rewritefn: "$scramjet$rewrite", - config: "/scram/scramjet.config.js", - shared: "/scram/scramjet.shared.js", - worker: "/scram/scramjet.worker.js", - thread: "/scram/scramjet.thread.js", - client: "/scram/scramjet.client.js", - codecs: "/scram/scramjet.codecs.js", -}; +// if (!self.$scramjet) { +// //@ts-expect-error really dumb workaround +// self.$scramjet = {}; +// } +// self.$scramjet.config = { +// prefix: "/scramjet/", +// codec: self.$scramjet.codecs.plain, +// wrapfn: "$scramjet$wrap", +// trysetfn: "$scramjet$tryset", +// importfn: "$scramjet$import", +// rewritefn: "$scramjet$rewrite", +// config: "/scram/scramjet.config.js", +// shared: "/scram/scramjet.shared.js", +// worker: "/scram/scramjet.worker.js", +// thread: "/scram/scramjet.thread.js", +// client: "/scram/scramjet.client.js", +// codecs: "/scram/scramjet.codecs.js", +// }; diff --git a/src/shared/rewriters/html.ts b/src/shared/rewriters/html.ts index 71d8e4d..317524b 100644 --- a/src/shared/rewriters/html.ts +++ b/src/shared/rewriters/html.ts @@ -1,5 +1,5 @@ -import { Parser } from "htmlparser2"; -import { DomHandler, Element } from "domhandler"; +import { ElementType, Parser } from "htmlparser2"; +import { DomHandler, Element, Text } from "domhandler"; import { hasAttrib } from "domutils"; import render from "dom-serializer"; import { encodeUrl } from "./url"; @@ -8,7 +8,7 @@ import { rewriteJs } from "./js"; export function isScramjetFile(src: string) { let bool = false; - ["codecs", "client", "shared", "worker", "config"].forEach((file) => { + ["codecs", "client", "shared", "worker"].forEach((file) => { if (src === self.$scramjet.config[file]) bool = true; }); @@ -96,11 +96,13 @@ function traverseParsedHtml(node, origin?: URL) { node.attribs.type ) && node.children[0] !== undefined + && !(node.attribs["data-scramjet"]) ) { let js = node.children[0].data; const htmlcomment = //g; js = js.replace(htmlcomment, ""); node.children[0].data = rewriteJs(js, origin); + console.log(node.children) } if (node.name === "meta" && hasAttrib(node, "http-equiv")) { if (node.attribs["http-equiv"] === "content-security-policy") { @@ -117,17 +119,19 @@ function traverseParsedHtml(node, origin?: URL) { } if (node.name === "head") { - const scramjetScripts = []; - ["codecs", "config", "shared", "client"].forEach((script) => { - scramjetScripts.push( - new Element("script", { - src: self.$scramjet.config[script], - "data-scramjet": "", - }) - ); - }); + const scripts = []; - node.children.unshift(...scramjetScripts); + const codecs = new Element("script", { src: self.$scramjet.config["codecs"], "data-scramjet": "true" }); + const config = new Element("script", { "data-scramjet": "true" }, [], ElementType.Script); + config.children[0] = new Text(`self.$scramjet.config = ${JSON.stringify(self.$scramjet.config)}; + self.$scramjet.codec = self.$scramjet.codecs[self.$scramjet.config.codec];`); + console.log(config.children[0]); + const shared = new Element("script", { src: self.$scramjet.config["shared"], "data-scramjet": "true" }); + const client = new Element("script", { src: self.$scramjet.config["client"], "data-scramjet": "true" }); + + scripts.push(codecs, config, shared, client); + + node.children.unshift(...scripts); } if (node.childNodes) { diff --git a/src/shared/rewriters/js.ts b/src/shared/rewriters/js.ts index 1cbd579..0a2767e 100644 --- a/src/shared/rewriters/js.ts +++ b/src/shared/rewriters/js.ts @@ -26,13 +26,13 @@ export function rewriteJs(js: string | ArrayBuffer, origin?: URL) { const before = performance.now(); if (typeof js === "string") { js = new TextDecoder().decode( - rewrite_js(js, origin.toString(), self.$scramjet.config) + rewrite_js(js, origin.toString(), self.$scramjet) ); } else { js = rewrite_js_from_arraybuffer( new Uint8Array(js), origin.toString(), - self.$scramjet.config + self.$scramjet ); } const after = performance.now(); diff --git a/src/shared/rewriters/url.ts b/src/shared/rewriters/url.ts index 4b0d5ac..0832d33 100644 --- a/src/shared/rewriters/url.ts +++ b/src/shared/rewriters/url.ts @@ -21,7 +21,7 @@ export function encodeUrl(url: string | URL, origin?: URL) { origin = new URL(new URL(location.href).searchParams.get("origin")); } else origin = new URL( - self.$scramjet.config.codec.decode( + self.$scramjet.codec.decode( location.href.slice( (location.origin + self.$scramjet.config.prefix).length ) @@ -40,7 +40,7 @@ export function encodeUrl(url: string | URL, origin?: URL) { return ( location.origin + self.$scramjet.config.prefix + - self.$scramjet.config.codec.encode(new URL(url, origin).href) + self.$scramjet.codec.encode(new URL(url, origin).href) ); } } @@ -55,13 +55,13 @@ export function decodeUrl(url: string | URL) { URL.canParse(url) && new URL(url).pathname.startsWith(self.$scramjet.config.prefix + "worker") ) { - return new URL(new URL(url).searchParams.get("origin")); + return new URL(new URL(url).searchParams.get("origin")).href; } if (/^(#|about|data|mailto|javascript)/.test(url)) { return url; } else if (canParseUrl(url)) { - return self.$scramjet.config.codec.decode( + return self.$scramjet.codec.decode( url.slice((location.origin + self.$scramjet.config.prefix).length) ); } else { diff --git a/src/types.d.ts b/src/types.d.ts index d6f6f57..f11bfec 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,3 +1,4 @@ +import { ScramjetBootstrapper } from "./bootsrapper/index"; import { encodeUrl, decodeUrl } from "./shared/rewriters/url"; import { rewriteCss } from "./shared/rewriters/css"; import { rewriteHtml, rewriteSrcset } from "./shared/rewriters/html"; @@ -9,6 +10,20 @@ import type { Codec } from "./codecs"; import { BareClient } from "@mercuryworkshop/bare-mux"; import { parseDomain } from "parse-domain"; +interface ScramjetConfig { + prefix: string; + codec: string; + wrapfn: string; + trysetfn: string; + importfn: string; + rewritefn: string; + shared: string; + worker: string; + thread: string; + client: string; + codecs: string; +} + declare global { interface Window { $scramjet: { @@ -31,27 +46,16 @@ declare global { parseDomain: typeof parseDomain; }; }; - config: { - prefix: string; - codec: Codec; - wrapfn: string; - trysetfn: string; - importfn: string; - rewritefn: string; - config: string; - shared: string; - worker: string; - thread: string; - client: string; - codecs: string; - }; + config: ScramjetConfig; codecs: { none: Codec; plain: Codec; base64: Codec; xor: Codec; }; + codec: Codec; }; WASM: string; + ScramjetBootstrapper: typeof ScramjetBootstrapper; } } diff --git a/src/worker/fetch.ts b/src/worker/fetch.ts index 842bc5e..4d2dd3d 100644 --- a/src/worker/fetch.ts +++ b/src/worker/fetch.ts @@ -46,7 +46,7 @@ export async function swfetch( try { const url = new URL(decodeUrl(request.url)); - let headers = new Headers(); + const headers = new Headers(); for (const [key, value] of request.headers.entries()) { headers.set(key, value); } @@ -104,8 +104,7 @@ async function handleResponse( case "script": responseBody = rewriteJs( await response.arrayBuffer(), - url, - self.$scramjet.config.codec.encode + url ); // Disable threading for now, it's causing issues. // responseBody = await this.threadpool.rewriteJs(await responseBody.arrayBuffer(), url.toString()); @@ -166,7 +165,7 @@ async function handleCookies(url: URL, headers: string[]) { let [key, value] = cookieParsed.shift(); if (!value) continue; - value = value.replace('"', ""); + value = value.replace("\"", ""); const hostArg = cookieParsed.find((x) => x[0] === "Domain"); cookieParsed = cookieParsed.filter((x) => x[0] !== "Domain"); diff --git a/src/worker/index.ts b/src/worker/index.ts index 7387372..316a607 100644 --- a/src/worker/index.ts +++ b/src/worker/index.ts @@ -1,3 +1,4 @@ +import IDBMap from "idb-map-entries"; import { FakeServiceWorker } from "./fakesw"; import { swfetch } from "./fetch"; import { ScramjetThreadpool } from "./threadpool"; @@ -18,10 +19,9 @@ export class ScramjetServiceWorker { serviceWorkers: FakeServiceWorker[] = []; - constructor(config = self.$scramjet.config) { + constructor() { + this.loadConfig(); this.client = new self.$scramjet.shared.util.BareClient(); - if (!config.prefix) config.prefix = "/scramjet/"; - this.config = config; this.threadpool = new ScramjetThreadpool(); @@ -46,6 +46,20 @@ export class ScramjetServiceWorker { }); } + loadConfig() { + const store = new IDBMap("config", { + prefix: "scramjet" + }); + + if (store.has("config")) { + store.get("config").then((config) => { + this.config = config; + self.$scramjet.config = config; + self.$scramjet.codec = self.$scramjet.codecs[config.codec] + }); + } + } + async getLocalStorage(): Promise> { let clients = await self.clients.matchAll(); clients = clients.filter( diff --git a/static/index.html b/static/index.html index 1fa4908..0012730 100644 --- a/static/index.html +++ b/static/index.html @@ -32,8 +32,7 @@ - - + diff --git a/static/sw.js b/static/sw.js index 22f6ea8..f557204 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,6 +1,5 @@ importScripts( "/scram/scramjet.codecs.js", - "/scram/scramjet.config.js", "/scram/scramjet.shared.js", "/scram/scramjet.worker.js" ); diff --git a/static/ui.js b/static/ui.js index db8a480..0d8219f 100644 --- a/static/ui.js +++ b/static/ui.js @@ -1,7 +1,13 @@ -navigator.serviceWorker.register("./sw.js").then((reg) => { - reg.update(); +const bootstrapper = new ScramjetBootstrapper({ + codecs: "/scram/scramjet.codecs.js", + worker: "/scram/scramjet.worker.js", + thread: "/scram/scramjet.thread.js", + client: "/scram/scramjet.client.js", + shared: "/scram/scramjet.shared.js", }); +bootstrapper.registerSw("./sw.js"); + navigator.serviceWorker.ready.then((reg) => { for (let i = 0; i < 20; i++) { const thread = new SharedWorker($scramjet.config.thread, { @@ -159,7 +165,7 @@ function App() { - (store.url = e.target.value)} on:keyup=${(e) => e.keyCode == 13 && console.log((this.urlencoded = $scramjet.config.prefix + $scramjet.config.codec.encode(e.target.value)))}> + (store.url = e.target.value)} on:keyup=${(e) => e.keyCode == 13 && console.log((this.urlencoded = $scramjet.config.prefix + $scramjet.codec.encode(e.target.value)))}> `;