@petezah-games/scramjet-controller 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controller.api.js +74 -0
- package/dist/controller.api.js.map +1 -0
- package/dist/controller.inject.js +33 -0
- package/dist/controller.inject.js.map +1 -0
- package/dist/controller.sw.js +2 -0
- package/dist/controller.sw.js.map +1 -0
- package/dist/types/index.d.ts +43 -0
- package/dist/types/inject.d.ts +14 -0
- package/dist/types/sw.d.ts +2 -0
- package/dist/types/typesEntry.d.ts +5 -0
- package/package.json +14 -0
- package/src/index.ts +437 -0
- package/src/inject.ts +245 -0
- package/src/sw.ts +159 -0
- package/src/types.d.ts +95 -0
- package/src/typesEntry.ts +6 -0
- package/tsconfig.json +24 -0
- package/tsconfig.types.json +16 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e={805(e,t,r){r.d(t,{C:()=>s});class s{methods;id;sendRaw;counter=0;promiseCallbacks=new Map;constructor(e,t,r){this.methods=e,this.id=t,this.sendRaw=r}recieve(e){if(null==e||"object"!=typeof e)return;let t=e[this.id];if(null==t||"object"!=typeof t)return;let r=t.$type;if("response"===r){let e=t.$token,r=t.$data,s=t.$error,o=this.promiseCallbacks.get(e);if(!o)return;this.promiseCallbacks.delete(e),void 0!==s?o.reject(Error(s)):o.resolve(r)}else if("request"===r){let e=t.$method,r=t.$args;this.methods[e](r).then(e=>{this.sendRaw({[this.id]:{$type:"response",$token:t.$token,$data:e?.[0]}},e?.[1])}).catch(e=>{console.error(e),this.sendRaw({[this.id]:{$type:"response",$token:t.$token,$error:e?.toString()||"Unknown error"}},[])})}}call(e,t,r=[]){let s=this.counter++;return new Promise((o,a)=>{this.promiseCallbacks.set(s,{resolve:o,reject:a}),this.sendRaw({[this.id]:{$type:"request",$method:e,$args:t,$token:s}},r)})}}}},t={};function r(s){var o=t[s];if(void 0!==o)return o.exports;var a=t[s]={exports:{}};return e[s](a,a.exports,r),a.exports}r.d=(e,t)=>{for(var s in t)r.o(t,s)&&!r.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var s={};(()=>{r.d(s,{V:()=>i,w:()=>n});var e=r(805);let t={};addEventListener("message",e=>{if(e.data&&"object"==typeof e.data){if(e.data.$sw$setCookieDone&&"object"==typeof e.data.$sw$setCookieDone){let r=e.data.$sw$setCookieDone,s=t[r.id];s&&(s(),delete t[r.id])}if(e.data.$sw$initRemoteTransport&&"object"==typeof e.data.$sw$initRemoteTransport){let{port:t,prefix:r}=e.data.$sw$initRemoteTransport,s=a.find(e=>new URL(r).pathname.startsWith(e.prefix));if(!s)return void console.error("No relevant controller found for transport init");s.rpc.call("initRemoteTransport",t,[t])}}});class o{prefix;id;rpc;constructor(r,s,o){this.prefix=r,this.id=s,this.rpc=new e.C({sendSetCookie:async({url:e,cookie:r})=>{let s=await self.clients.matchAll(),o=[];for(let a of s){let s=Math.random().toString(36).substring(2,10);a.postMessage({$controller$setCookie:{url:e,cookie:r,id:s}}),o.push(new Promise(e=>{t[s]=e}))}await Promise.race([new Promise(e=>setTimeout(()=>{console.error("timed out waiting for set cookie response (deadlock?)"),e()},1e3)),o])}},"tabchannel-"+s,(e,t)=>{o.postMessage(e,t)}),o.addEventListener("message",e=>{this.rpc.recieve(e.data)}),o.onmessageerror=console.error,this.rpc.call("ready",null)}}let a=[];function i(e){let t=new URL(e.request.url);return void 0!==a.find(e=>t.pathname.startsWith(e.prefix))}async function n(e){try{let t=new URL(e.request.url),r=a.find(e=>t.pathname.startsWith(e.prefix)),s=await clients.get(e.clientId),o=[...e.request.headers],i=await r.rpc.call("request",{rawUrl:e.request.url,destination:e.request.destination,mode:e.request.mode,referrer:e.request.referrer,method:e.request.method,body:e.request.body,cache:e.request.cache,forceCrossOriginIsolated:!1,initialHeaders:o,rawClientUrl:s?s.url:void 0},e.request.body instanceof ReadableStream||e.request.body instanceof ArrayBuffer?[e.request.body]:void 0);return new Response(i.body,{status:i.status,statusText:i.statusText,headers:i.headers})}catch(e){return console.error("Service Worker error:",e),new Response("Internal Service Worker Error: "+e.message,{status:500})}}addEventListener("message",e=>{if(!e.data||"object"!=typeof e.data||!e.data.$controller$init||"object"!=typeof e.data.$controller$init)return;let t=e.data.$controller$init;a.push(new o(t.prefix,t.id,e.ports[0]))})})();var o=s.w,a=s.V;export{o as route,a as shouldRoute};
|
|
2
|
+
//# sourceMappingURL=controller.sw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.sw.js","sources":["webpack://scramjet-root/./packages/rpc/index.ts","webpack://scramjet-root/webpack/runtime/define_property_getters","webpack://scramjet-root/webpack/runtime/has_own_property","webpack://scramjet-root/./packages/controller/src/sw.ts"],"sourcesContent":["type Serverbound = {\n\tmethod1: [{ paramA: string; paramB: number }, boolean];\n\tmethod2: [string, number];\n};\n\ntype Clientbound = {\n\tmethod1: [number];\n\tmethod2: [boolean, string];\n};\n\nexport type RpcDescription = {\n\t[method: string]: [args: any, returnType: any] | [args: any] | [];\n};\n\nexport type MethodsDefinition<Description extends RpcDescription> = {\n\t[Method in keyof Description]: (\n\t\t...args: Description[Method] extends [infer A, ...any[]] ? [A] : []\n\t) => Description[Method] extends [any, infer R]\n\t\t? Promise<[R, Transferable[]]>\n\t\t: Promise<void>;\n};\n\nexport class RpcHelper<\n\tLocal extends RpcDescription,\n\tRemote extends RpcDescription,\n> {\n\tcounter: number = 0;\n\tpromiseCallbacks: Map<\n\t\tnumber,\n\t\t{ resolve: (value: any) => void; reject: (reason?: any) => void }\n\t> = new Map();\n\tconstructor(\n\t\tprivate methods: MethodsDefinition<Local>,\n\t\tprivate id: string,\n\t\tprivate sendRaw: (data: any, transfer: Transferable[]) => void\n\t) {}\n\n\trecieve(data: any) {\n\t\tif (data === undefined || data === null || typeof data !== \"object\") return;\n\t\tconst dt = data[this.id];\n\t\tif (dt === undefined || dt === null || typeof dt !== \"object\") return;\n\n\t\tconst type = dt.$type;\n\n\t\tif (type === \"response\") {\n\t\t\tconst token = dt.$token;\n\t\t\tconst data = dt.$data;\n\t\t\tconst error = dt.$error;\n\t\t\tconst cb = this.promiseCallbacks.get(token);\n\t\t\tif (!cb) return;\n\t\t\tthis.promiseCallbacks.delete(token);\n\t\t\tif (error !== undefined) {\n\t\t\t\tcb.reject(new Error(error));\n\t\t\t} else {\n\t\t\t\tcb.resolve(data);\n\t\t\t}\n\t\t} else if (type === \"request\") {\n\t\t\tconst method = dt.$method as keyof Local;\n\t\t\tconst args = dt.$args as Local[typeof method][0];\n\t\t\t(this.methods[method] as any)(args)\n\t\t\t\t.then((r: any) => {\n\t\t\t\t\tthis.sendRaw(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t[this.id]: {\n\t\t\t\t\t\t\t\t$type: \"response\",\n\t\t\t\t\t\t\t\t$token: dt.$token,\n\t\t\t\t\t\t\t\t$data: r?.[0],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tr?.[1]\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.catch((err: any) => {\n\t\t\t\t\tconsole.error(err);\n\t\t\t\t\tthis.sendRaw(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t[this.id]: {\n\t\t\t\t\t\t\t\t$type: \"response\",\n\t\t\t\t\t\t\t\t$token: dt.$token,\n\t\t\t\t\t\t\t\t$error: err?.toString() || \"Unknown error\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[]\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t}\n\n\tcall<Method extends keyof Remote>(\n\t\tmethod: Method,\n\t\targs: Remote[Method][0],\n\t\ttransfer: Transferable[] = []\n\t): Promise<Remote[Method][1]> {\n\t\tlet token = this.counter++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.promiseCallbacks.set(token, { resolve, reject });\n\t\t\tthis.sendRaw(\n\t\t\t\t{\n\t\t\t\t\t[this.id]: {\n\t\t\t\t\t\t$type: \"request\",\n\t\t\t\t\t\t$method: method,\n\t\t\t\t\t\t$args: args,\n\t\t\t\t\t\t$token: token,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\ttransfer\n\t\t\t);\n\t\t});\n\t}\n}\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","declare var clients: Clients;\nimport { RpcHelper } from \"@mercuryworkshop/rpc\";\nimport type { Controllerbound, SWbound } from \"./types\";\nimport type { RawHeaders } from \"@mercuryworkshop/proxy-transports\";\nimport { ScramjetHeaders } from \"@mercuryworkshop/scramjet\";\n\nfunction makeId(): string {\n\treturn Math.random().toString(36).substring(2, 10);\n}\n\nlet cookieResolvers: Record<string, (value: void) => void> = {};\naddEventListener(\"message\", (e) => {\n\tif (!e.data) return;\n\tif (typeof e.data != \"object\") return;\n\tif (e.data.$sw$setCookieDone && typeof e.data.$sw$setCookieDone == \"object\") {\n\t\tconst done = e.data.$sw$setCookieDone;\n\n\t\tconst resolver = cookieResolvers[done.id];\n\t\tif (resolver) {\n\t\t\tresolver();\n\t\t\tdelete cookieResolvers[done.id];\n\t\t}\n\t}\n\n\tif (\n\t\te.data.$sw$initRemoteTransport &&\n\t\ttypeof e.data.$sw$initRemoteTransport == \"object\"\n\t) {\n\t\tconst { port, prefix } = e.data.$sw$initRemoteTransport;\n\n\t\tconst relevantcontroller = tabs.find((tab) =>\n\t\t\tnew URL(prefix).pathname.startsWith(tab.prefix)\n\t\t);\n\t\tif (!relevantcontroller) {\n\t\t\tconsole.error(\"No relevant controller found for transport init\");\n\t\t\treturn;\n\t\t}\n\t\trelevantcontroller.rpc.call(\"initRemoteTransport\", port, [port]);\n\t}\n});\n\nclass ControllerReference {\n\trpc: RpcHelper<SWbound, Controllerbound>;\n\n\tconstructor(\n\t\tpublic prefix: string,\n\t\tpublic id: string,\n\t\tport: MessagePort\n\t) {\n\t\tthis.rpc = new RpcHelper(\n\t\t\t{\n\t\t\t\tsendSetCookie: async ({ url, cookie }) => {\n\t\t\t\t\tlet clients = await self.clients.matchAll();\n\t\t\t\t\tlet promises = [];\n\n\t\t\t\t\tfor (const client of clients) {\n\t\t\t\t\t\tlet id = makeId();\n\t\t\t\t\t\tclient.postMessage({\n\t\t\t\t\t\t\t$controller$setCookie: {\n\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\tcookie,\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\t\t\t\t\tcookieResolvers[id] = resolve;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait Promise.race([\n\t\t\t\t\t\tnew Promise<void>((resolve) =>\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\"timed out waiting for set cookie response (deadlock?)\"\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t}, 1000)\n\t\t\t\t\t\t),\n\t\t\t\t\t\tpromises,\n\t\t\t\t\t]);\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"tabchannel-\" + id,\n\t\t\t(data, transfer) => {\n\t\t\t\tport.postMessage(data, transfer);\n\t\t\t}\n\t\t);\n\t\tport.addEventListener(\"message\", (e) => {\n\t\t\tthis.rpc.recieve(e.data);\n\t\t});\n\t\tport.onmessageerror = console.error;\n\n\t\tthis.rpc.call(\"ready\", null);\n\t}\n}\n\nconst tabs: ControllerReference[] = [];\n\naddEventListener(\"message\", (e) => {\n\tif (!e.data) return;\n\tif (typeof e.data != \"object\") return;\n\tif (!e.data.$controller$init) return;\n\tif (typeof e.data.$controller$init != \"object\") return;\n\tconst init = e.data.$controller$init;\n\n\ttabs.push(new ControllerReference(init.prefix, init.id, e.ports[0]));\n});\n\nexport function shouldRoute(event: FetchEvent): boolean {\n\tconst url = new URL(event.request.url);\n\tconst tab = tabs.find((tab) => url.pathname.startsWith(tab.prefix));\n\treturn tab !== undefined;\n}\n\nexport async function route(event: FetchEvent): Promise<Response> {\n\ttry {\n\t\tconst url = new URL(event.request.url);\n\t\tconst tab = tabs.find((tab) => url.pathname.startsWith(tab.prefix))!;\n\t\tconst client = await clients.get(event.clientId);\n\n\t\tconst rawheaders: RawHeaders = [...event.request.headers];\n\n\t\tconst response = await tab.rpc.call(\n\t\t\t\"request\",\n\t\t\t{\n\t\t\t\trawUrl: event.request.url,\n\t\t\t\tdestination: event.request.destination,\n\t\t\t\tmode: event.request.mode,\n\t\t\t\treferrer: event.request.referrer,\n\t\t\t\tmethod: event.request.method,\n\t\t\t\tbody: event.request.body,\n\t\t\t\tcache: event.request.cache,\n\t\t\t\tforceCrossOriginIsolated: false,\n\t\t\t\tinitialHeaders: rawheaders,\n\t\t\t\trawClientUrl: client ? client.url : undefined,\n\t\t\t},\n\t\t\tevent.request.body instanceof ReadableStream ||\n\t\t\t\t// @ts-expect-error the types for fetchevent are messed up\n\t\t\t\tevent.request.body instanceof ArrayBuffer\n\t\t\t\t? [event.request.body]\n\t\t\t\t: undefined\n\t\t);\n\n\t\treturn new Response(response.body, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: response.headers,\n\t\t});\n\t} catch (e) {\n\t\tconsole.error(\"Service Worker error:\", e);\n\t\treturn new Response(\n\t\t\t\"Internal Service Worker Error: \" + (e as Error).message,\n\t\t\t{\n\t\t\t\tstatus: 500,\n\t\t\t}\n\t\t);\n\t}\n}\n"],"names":["RpcHelper","Map","methods","id","sendRaw","data","dt","type","token","error","cb","undefined","Error","method","args","r","err","console","transfer","Promise","resolve","reject","e","Object","cookieResolvers","addEventListener","done","resolver","port","prefix","relevantcontroller","tabs","tab","URL","ControllerReference","url","cookie","clients1","self","promises","client","Math","setTimeout","shouldRoute","event","route","clients","rawheaders","response","ReadableStream","ArrayBuffer","Response","init"],"mappings":"kCAsBO,OAAMA,E,kBAIZ,SAAkB,CAAE,AACpB,kBAGI,IAAIC,GAAM,AACd,aACSC,CAAiC,CACjCC,CAAU,CACVC,CAAsD,CAC7D,C,KAHOF,OAAO,CAAPA,E,KACAC,EAAE,CAAFA,E,KACAC,OAAO,CAAPA,CACN,CAEH,QAAQC,CAAS,CAAE,CAClB,GAAIA,MAAAA,GAAuC,AAAgB,UAAhB,OAAOA,EAAmB,OACrE,IAAMC,EAAKD,CAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CACxB,GAAIC,MAAAA,GAAmC,AAAc,UAAd,OAAOA,EAAiB,OAE/D,IAAMC,EAAOD,EAAG,KAAK,CAErB,GAAIC,AAAS,aAATA,EAAqB,CACxB,IAAMC,EAAQF,EAAG,MAAM,CACjBD,EAAOC,EAAG,KAAK,CACfG,EAAQH,EAAG,MAAM,CACjBI,EAAK,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACF,GACrC,GAAI,CAACE,EAAI,OACT,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACF,GACzBC,AAAUE,SAAVF,EACHC,EAAG,MAAM,CAAC,AAAIE,MAAMH,IAEpBC,EAAG,OAAO,CAACL,EAEb,MAAO,GAAIE,AAAS,YAATA,EAAoB,CAC9B,IAAMM,EAASP,EAAG,OAAO,CACnBQ,EAAOR,EAAG,KAAK,CACpB,IAAI,CAAC,OAAO,CAACO,EAAO,CAASC,GAC5B,IAAI,CAAC,AAACC,IACN,IAAI,CAAC,OAAO,CACX,CACC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CACV,MAAO,WACP,OAAQT,EAAG,MAAM,CACjB,MAAOS,GAAG,CAAC,EAAE,AACd,CACD,EACAA,GAAG,CAAC,EAAE,CAER,GACC,KAAK,CAAC,AAACC,IACPC,QAAQ,KAAK,CAACD,GACd,IAAI,CAAC,OAAO,CACX,CACC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CACV,MAAO,WACP,OAAQV,EAAG,MAAM,CACjB,OAAQU,GAAK,YAAc,eAC5B,CACD,EACA,EAAE,CAEJ,EACF,CACD,CAEA,KACCH,CAAc,CACdC,CAAuB,CACvBI,EAA2B,EAAE,CACA,CAC7B,IAAIV,EAAQ,IAAI,CAAC,OAAO,GACxB,OAAO,IAAIW,QAAQ,CAACC,EAASC,KAC5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACb,EAAO,CAAEY,QAAAA,EAASC,OAAAA,CAAO,GACnD,IAAI,CAAC,OAAO,CACX,CACC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CACV,MAAO,UACP,QAASR,EACT,MAAOC,EACP,OAAQN,CACT,CACD,EACAU,EAEF,EACD,CACD,C,6HC7GA,EAAoB,CAAC,CAAG,CAACI,EAAS,KACjC,IAAI,IAAI,KAAO,EACL,EAAoB,CAAC,CAAC,EAAY,IAAQ,CAAC,EAAoB,CAAC,CAACA,EAAS,IACzEC,OAAO,cAAc,CAACD,EAAS,EAAK,CAAE,WAAY,GAAM,IAAK,CAAU,CAAC,EAAI,AAAC,EAGzF,ECNA,EAAoB,CAAC,CAAG,CAAC,EAAK,IAAUC,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,EAAK,G,qDCUlF,IAAIC,EAAyD,CAAC,EAC9DC,iBAAiB,UAAW,AAACH,IAC5B,GAAKA,EAAE,IAAI,EACP,AAAiB,UAAjB,OAAOA,EAAE,IAAI,EACjB,GAAIA,EAAE,IAAI,CAAC,iBAAiB,EAAI,AAAmC,UAAnC,OAAOA,EAAE,IAAI,CAAC,iBAAiB,CAAc,CAC5E,IAAMI,EAAOJ,EAAE,IAAI,CAAC,iBAAiB,CAE/BK,EAAWH,CAAe,CAACE,EAAK,EAAE,CAAC,CACrCC,IACHA,IACA,OAAOH,CAAe,CAACE,EAAK,EAAE,CAAC,CAEjC,CAEA,GACCJ,EAAE,IAAI,CAAC,uBAAuB,EAC9B,AAAyC,UAAzC,OAAOA,EAAE,IAAI,CAAC,uBAAuB,CACpC,CACD,GAAM,CAAEM,KAAAA,CAAI,CAAEC,OAAAA,CAAM,CAAE,CAAGP,EAAE,IAAI,CAAC,uBAAuB,CAEjDQ,EAAqBC,EAAK,IAAI,CAAC,AAACC,GACrC,IAAIC,IAAIJ,GAAQ,QAAQ,CAAC,UAAU,CAACG,EAAI,MAAM,GAE/C,GAAI,CAACF,EAAoB,YACxBb,QAAQ,KAAK,CAAC,mDAGfa,EAAmB,GAAG,CAAC,IAAI,CAAC,sBAAuBF,EAAM,CAACA,EAAK,CAChE,EACD,EAEA,OAAMM,E,SACL,IAAyC,AAEzC,aACQL,CAAc,CACd1B,CAAU,CACjByB,CAAiB,CAChB,C,KAHMC,MAAM,CAANA,E,KACA1B,EAAE,CAAFA,EAGP,IAAI,CAAC,GAAG,CAAG,IAAIH,EAAAA,CAASA,CACvB,CACC,cAAe,MAAO,CAAEmC,IAAAA,CAAG,CAAEC,OAAAA,CAAM,CAAE,IACpC,IAAIC,EAAU,MAAMC,KAAK,OAAO,CAAC,QAAQ,GACrCC,EAAW,EAAE,CAEjB,IAAK,IAAMC,KAAUH,EAAS,CAC7B,IAAIlC,EAjDFsC,KAAK,MAAM,GAAG,QAAQ,CAAC,IAAI,SAAS,CAAC,EAAG,IAkD1CD,EAAO,WAAW,CAAC,CAClB,sBAAuB,CACtBL,IAAAA,EACAC,OAAAA,EACAjC,GAAAA,CACD,CACD,GACAoC,EAAS,IAAI,CACZ,IAAIpB,QAAc,AAACC,IAClBI,CAAe,CAACrB,EAAG,CAAGiB,CACvB,GAEF,CACA,MAAMD,QAAQ,IAAI,CAAC,CAClB,IAAIA,QAAc,AAACC,GAClBsB,WAAW,KACVzB,QAAQ,KAAK,CACZ,yDAEDG,GACD,EAAG,MAEJmB,EACA,CACF,CACD,EACA,cAAgBpC,EAChB,CAACE,EAAMa,KACNU,EAAK,WAAW,CAACvB,EAAMa,EACxB,GAEDU,EAAK,gBAAgB,CAAC,UAAW,AAACN,IACjC,IAAI,CAAC,GAAG,CAAC,OAAO,CAACA,EAAE,IAAI,CACxB,GACAM,EAAK,cAAc,CAAGX,QAAQ,KAAK,CAEnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAS,KACxB,CACD,CAEA,IAAMc,EAA8B,EAAE,CAY/B,SAASY,EAAYC,CAAiB,EAC5C,IAAMT,EAAM,IAAIF,IAAIW,EAAM,OAAO,CAAC,GAAG,EAErC,OAAOZ,AAAQrB,SADHoB,EAAK,IAAI,CAAC,AAACC,GAAQG,EAAI,QAAQ,CAAC,UAAU,CAACH,EAAI,MAAM,EAElE,CAEO,eAAea,EAAMD,CAAiB,EAC5C,GAAI,CACH,IAAMT,EAAM,IAAIF,IAAIW,EAAM,OAAO,CAAC,GAAG,EAC/BZ,EAAMD,EAAK,IAAI,CAAC,AAACC,GAAQG,EAAI,QAAQ,CAAC,UAAU,CAACH,EAAI,MAAM,GAC3DQ,EAAS,MAAMM,QAAQ,GAAG,CAACF,EAAM,QAAQ,EAEzCG,EAAyB,IAAIH,EAAM,OAAO,CAAC,OAAO,CAAC,CAEnDI,EAAW,MAAMhB,EAAI,GAAG,CAAC,IAAI,CAClC,UACA,CACC,OAAQY,EAAM,OAAO,CAAC,GAAG,CACzB,YAAaA,EAAM,OAAO,CAAC,WAAW,CACtC,KAAMA,EAAM,OAAO,CAAC,IAAI,CACxB,SAAUA,EAAM,OAAO,CAAC,QAAQ,CAChC,OAAQA,EAAM,OAAO,CAAC,MAAM,CAC5B,KAAMA,EAAM,OAAO,CAAC,IAAI,CACxB,MAAOA,EAAM,OAAO,CAAC,KAAK,CAC1B,yBAA0B,GAC1B,eAAgBG,EAChB,aAAcP,EAASA,EAAO,GAAG,CAAG7B,MACrC,EACAiC,EAAM,OAAO,CAAC,IAAI,YAAYK,gBAE7BL,EAAM,OAAO,CAAC,IAAI,YAAYM,YAC5B,CAACN,EAAM,OAAO,CAAC,IAAI,CAAC,CACpBjC,QAGJ,OAAO,IAAIwC,SAASH,EAAS,IAAI,CAAE,CAClC,OAAQA,EAAS,MAAM,CACvB,WAAYA,EAAS,UAAU,CAC/B,QAASA,EAAS,OAAO,AAC1B,EACD,CAAE,MAAO1B,EAAG,CAEX,OADAL,QAAQ,KAAK,CAAC,wBAAyBK,GAChC,IAAI6B,SACV,kCAAqC7B,EAAY,OAAO,CACxD,CACC,OAAQ,GACT,EAEF,CACD,CA3DAG,iBAAiB,UAAW,AAACH,IAC5B,GAAI,CAACA,EAAE,IAAI,EACP,AAAiB,UAAjB,OAAOA,EAAE,IAAI,EACb,CAACA,EAAE,IAAI,CAAC,gBAAgB,EACxB,AAAkC,UAAlC,OAAOA,EAAE,IAAI,CAAC,gBAAgB,CAHrB,OAIb,IAAM8B,EAAO9B,EAAE,IAAI,CAAC,gBAAgB,CAEpCS,EAAK,IAAI,CAAC,IAAIG,EAAoBkB,EAAK,MAAM,CAAEA,EAAK,EAAE,CAAE9B,EAAE,KAAK,CAAC,EAAE,EACnE,E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { RpcHelper } from "@mercuryworkshop/rpc";
|
|
2
|
+
import type * as ScramjetGlobal from "@mercuryworkshop/scramjet";
|
|
3
|
+
import { type Controllerbound, type SWbound } from "./types";
|
|
4
|
+
import { type ProxyTransport } from "@mercuryworkshop/proxy-transports";
|
|
5
|
+
type Config = {
|
|
6
|
+
wasmPath: string;
|
|
7
|
+
injectPath: string;
|
|
8
|
+
scramjetPath: string;
|
|
9
|
+
virtualWasmPath: string;
|
|
10
|
+
prefix: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const config: Config;
|
|
13
|
+
type ControllerInit = {
|
|
14
|
+
serviceworker: ServiceWorker;
|
|
15
|
+
transport: ProxyTransport;
|
|
16
|
+
};
|
|
17
|
+
export declare class Controller {
|
|
18
|
+
init: ControllerInit;
|
|
19
|
+
id: string;
|
|
20
|
+
prefix: string;
|
|
21
|
+
frames: Frame[];
|
|
22
|
+
cookieJar: ScramjetGlobal.CookieJar;
|
|
23
|
+
rpc: RpcHelper<Controllerbound, SWbound>;
|
|
24
|
+
private ready;
|
|
25
|
+
private readyResolve;
|
|
26
|
+
isReady: boolean;
|
|
27
|
+
transport: ProxyTransport;
|
|
28
|
+
private methods;
|
|
29
|
+
constructor(init: ControllerInit);
|
|
30
|
+
createFrame(element?: HTMLIFrameElement): Frame;
|
|
31
|
+
wait(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
declare class Frame {
|
|
34
|
+
controller: Controller;
|
|
35
|
+
element: HTMLIFrameElement;
|
|
36
|
+
fetchHandler: ScramjetGlobal.ScramjetFetchHandler;
|
|
37
|
+
id: string;
|
|
38
|
+
prefix: string;
|
|
39
|
+
get context(): ScramjetGlobal.ScramjetContext;
|
|
40
|
+
constructor(controller: Controller, element: HTMLIFrameElement);
|
|
41
|
+
go(url: string): void;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CookieJar, ScramjetConfig } from "@mercuryworkshop/scramjet";
|
|
2
|
+
declare const CookieJar: typeof CookieJar;
|
|
3
|
+
type Config = any;
|
|
4
|
+
type Init = {
|
|
5
|
+
config: Config;
|
|
6
|
+
sjconfig: ScramjetConfig;
|
|
7
|
+
cookies: string;
|
|
8
|
+
prefix: URL;
|
|
9
|
+
yieldGetInjectScripts: (cookieJar: CookieJar, config: Config, sjconfig: ScramjetConfig, prefix: URL) => any;
|
|
10
|
+
codecEncode: (input: string) => string;
|
|
11
|
+
codecDecode: (input: string) => string;
|
|
12
|
+
};
|
|
13
|
+
export declare function load({ config, sjconfig, cookies, prefix, yieldGetInjectScripts, codecEncode, codecDecode, }: Init): void;
|
|
14
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@petezah-games/scramjet-controller",
|
|
3
|
+
"version": "0.0.9",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/controller.api.js",
|
|
6
|
+
"types": "./dist/types/typesEntry.d.ts",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@mercuryworkshop/proxy-transports": "1.0.2",
|
|
9
|
+
"@mercuryworkshop/scramjet": "2.0.2-alpha"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@mercuryworkshop/rpc": "0.0.1"
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { type MethodsDefinition, RpcHelper } from "@mercuryworkshop/rpc";
|
|
2
|
+
import type * as ScramjetGlobal from "@mercuryworkshop/scramjet";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type TransportToController,
|
|
6
|
+
type Controllerbound,
|
|
7
|
+
type ControllerToTransport,
|
|
8
|
+
type SWbound,
|
|
9
|
+
type WebSocketMessage,
|
|
10
|
+
} from "./types";
|
|
11
|
+
import {
|
|
12
|
+
BareCompatibleClient,
|
|
13
|
+
BareResponse,
|
|
14
|
+
type ProxyTransport,
|
|
15
|
+
} from "@mercuryworkshop/proxy-transports";
|
|
16
|
+
import * as $scramjet from '@mercuryworkshop/scramjet';
|
|
17
|
+
|
|
18
|
+
const cookieJar = new $scramjet.CookieJar();
|
|
19
|
+
|
|
20
|
+
type Config = {
|
|
21
|
+
wasmPath: string;
|
|
22
|
+
injectPath: string;
|
|
23
|
+
scramjetPath: string;
|
|
24
|
+
virtualWasmPath: string;
|
|
25
|
+
prefix: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const config: Config = {
|
|
29
|
+
prefix: "/~/sj/",
|
|
30
|
+
virtualWasmPath: "scramjet.wasm.js",
|
|
31
|
+
injectPath: "/controller/controller.inject.js",
|
|
32
|
+
scramjetPath: "/scramjet/scramjet.js",
|
|
33
|
+
wasmPath: "/scramjet/scramjet.wasm",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const cfg = {
|
|
37
|
+
flags: {
|
|
38
|
+
...$scramjet.defaultConfig.flags,
|
|
39
|
+
allowFailedIntercepts: true,
|
|
40
|
+
},
|
|
41
|
+
maskedfiles: ["inject.js", "scramjet.wasm.js"],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const frames: Record<string, Frame> = {};
|
|
45
|
+
|
|
46
|
+
let wasmPayload: string | null = null;
|
|
47
|
+
|
|
48
|
+
function makeId(): string {
|
|
49
|
+
return Math.random().toString(36).substring(2, 10);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const codecEncode = (url: string) => {
|
|
53
|
+
if (!url) return url;
|
|
54
|
+
|
|
55
|
+
return encodeURIComponent(url);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const codecDecode = (url: string) => {
|
|
59
|
+
if (!url) return url;
|
|
60
|
+
|
|
61
|
+
return decodeURIComponent(url);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type ControllerInit = {
|
|
65
|
+
serviceworker: ServiceWorker;
|
|
66
|
+
transport: ProxyTransport;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
let wasmAlreadyFetched = false;
|
|
70
|
+
|
|
71
|
+
async function loadScramjetWasm() {
|
|
72
|
+
if (wasmAlreadyFetched) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let resp = await fetch(config.wasmPath);
|
|
77
|
+
$scramjet.setWasm(await resp.arrayBuffer());
|
|
78
|
+
wasmAlreadyFetched = true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class Controller {
|
|
82
|
+
id: string;
|
|
83
|
+
prefix: string;
|
|
84
|
+
frames: Frame[] = [];
|
|
85
|
+
cookieJar = new $scramjet.CookieJar();
|
|
86
|
+
|
|
87
|
+
rpc: RpcHelper<Controllerbound, SWbound>;
|
|
88
|
+
private ready: Promise<[void, void]>;
|
|
89
|
+
private readyResolve!: () => void;
|
|
90
|
+
public isReady: boolean = false;
|
|
91
|
+
|
|
92
|
+
transport: ProxyTransport;
|
|
93
|
+
|
|
94
|
+
private methods: MethodsDefinition<Controllerbound> = {
|
|
95
|
+
ready: async () => {
|
|
96
|
+
this.readyResolve();
|
|
97
|
+
},
|
|
98
|
+
request: async (data) => {
|
|
99
|
+
try {
|
|
100
|
+
let path = new URL(data.rawUrl).pathname;
|
|
101
|
+
const frame = this.frames.find((f) => path.startsWith(f.prefix));
|
|
102
|
+
if (!frame) throw new Error("No frame found for request");
|
|
103
|
+
|
|
104
|
+
if (path === frame.prefix + config.virtualWasmPath) {
|
|
105
|
+
if (!wasmPayload) {
|
|
106
|
+
const resp = await fetch(config.wasmPath);
|
|
107
|
+
const buf = await resp.arrayBuffer();
|
|
108
|
+
const b64 = btoa(
|
|
109
|
+
new Uint8Array(buf)
|
|
110
|
+
.reduce(
|
|
111
|
+
(data, byte) => (data.push(String.fromCharCode(byte)), data),
|
|
112
|
+
[] as any
|
|
113
|
+
)
|
|
114
|
+
.join("")
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
let payload = "";
|
|
118
|
+
payload +=
|
|
119
|
+
"if ('document' in self && document.currentScript) { document.currentScript.remove(); }\n";
|
|
120
|
+
payload += `self.WASM = '${b64}';`;
|
|
121
|
+
wasmPayload = payload;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return [
|
|
125
|
+
{
|
|
126
|
+
body: wasmPayload,
|
|
127
|
+
status: 200,
|
|
128
|
+
statusText: "OK",
|
|
129
|
+
headers: [["Content-Type", "application/javascript"]],
|
|
130
|
+
},
|
|
131
|
+
[],
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let sjheaders = $scramjet.ScramjetHeaders.fromRawHeaders(
|
|
136
|
+
data.initialHeaders
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const fetchresponse = await frame.fetchHandler.handleFetch({
|
|
140
|
+
initialHeaders: sjheaders,
|
|
141
|
+
rawClientUrl: data.rawClientUrl
|
|
142
|
+
? new URL(data.rawClientUrl)
|
|
143
|
+
: undefined,
|
|
144
|
+
rawUrl: new URL(data.rawUrl),
|
|
145
|
+
destination: data.destination,
|
|
146
|
+
method: data.method,
|
|
147
|
+
mode: data.mode,
|
|
148
|
+
referrer: data.referrer,
|
|
149
|
+
body: data.body,
|
|
150
|
+
cache: data.cache,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return [
|
|
154
|
+
{
|
|
155
|
+
body: fetchresponse.body,
|
|
156
|
+
status: fetchresponse.status,
|
|
157
|
+
statusText: fetchresponse.statusText,
|
|
158
|
+
headers: fetchresponse.headers.toRawHeaders(),
|
|
159
|
+
},
|
|
160
|
+
fetchresponse.body instanceof ReadableStream ||
|
|
161
|
+
fetchresponse.body instanceof ArrayBuffer
|
|
162
|
+
? [fetchresponse.body]
|
|
163
|
+
: [],
|
|
164
|
+
];
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.error("Error in controller request handler:", e);
|
|
167
|
+
throw e;
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
initRemoteTransport: async (port) => {
|
|
171
|
+
const rpc = new RpcHelper<TransportToController, ControllerToTransport>(
|
|
172
|
+
{
|
|
173
|
+
request: async ({ remote, method, body, headers }) => {
|
|
174
|
+
let response = await this.transport.request(
|
|
175
|
+
new URL(remote),
|
|
176
|
+
method,
|
|
177
|
+
body,
|
|
178
|
+
headers,
|
|
179
|
+
undefined
|
|
180
|
+
);
|
|
181
|
+
return [response, [response.body]];
|
|
182
|
+
},
|
|
183
|
+
connect: async ({ url, protocols, requestHeaders, port }) => {
|
|
184
|
+
let resolve: (arg: TransportToController["connect"][1]) => void;
|
|
185
|
+
let promise = new Promise<TransportToController["connect"][1]>(
|
|
186
|
+
(res) => (resolve = res)
|
|
187
|
+
);
|
|
188
|
+
const [send, close] = this.transport.connect(
|
|
189
|
+
new URL(url),
|
|
190
|
+
protocols,
|
|
191
|
+
requestHeaders,
|
|
192
|
+
(protocol, extensions) => {
|
|
193
|
+
resolve({
|
|
194
|
+
result: "success",
|
|
195
|
+
protocol: protocol,
|
|
196
|
+
extensions: extensions,
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
(data) => {
|
|
200
|
+
port.postMessage(
|
|
201
|
+
{
|
|
202
|
+
type: "data",
|
|
203
|
+
data: data,
|
|
204
|
+
} as WebSocketMessage,
|
|
205
|
+
data instanceof ArrayBuffer ? [data] : []
|
|
206
|
+
);
|
|
207
|
+
},
|
|
208
|
+
(close, reason) => {
|
|
209
|
+
port.postMessage({
|
|
210
|
+
type: "close",
|
|
211
|
+
code: close,
|
|
212
|
+
reason: reason,
|
|
213
|
+
} as WebSocketMessage);
|
|
214
|
+
},
|
|
215
|
+
(error) => {
|
|
216
|
+
resolve({
|
|
217
|
+
result: "failure",
|
|
218
|
+
error: error,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
port.onmessageerror = (ev) => {
|
|
223
|
+
console.error(
|
|
224
|
+
"Transport port messageerror (this should never happen!)",
|
|
225
|
+
ev
|
|
226
|
+
);
|
|
227
|
+
};
|
|
228
|
+
port.onmessage = ({ data }: { data: WebSocketMessage }) => {
|
|
229
|
+
if (data.type === "data") {
|
|
230
|
+
send(data.data);
|
|
231
|
+
} else if (data.type === "close") {
|
|
232
|
+
close(data.code, data.reason);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
return [await promise, []];
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
"transport",
|
|
240
|
+
(data, transfer) => port.postMessage(data, transfer)
|
|
241
|
+
);
|
|
242
|
+
port.onmessageerror = (ev) => {
|
|
243
|
+
console.error(
|
|
244
|
+
"Transport port messageerror (this should never happen!)",
|
|
245
|
+
ev
|
|
246
|
+
);
|
|
247
|
+
};
|
|
248
|
+
port.onmessage = (e) => {
|
|
249
|
+
rpc.recieve(e.data);
|
|
250
|
+
};
|
|
251
|
+
rpc.call("ready", undefined, []);
|
|
252
|
+
},
|
|
253
|
+
sendSetCookie: async ({ url, cookie }) => { },
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
constructor(public init: ControllerInit) {
|
|
257
|
+
this.transport = init.transport;
|
|
258
|
+
this.id = makeId();
|
|
259
|
+
this.prefix = config.prefix + this.id + "/";
|
|
260
|
+
|
|
261
|
+
this.ready = Promise.all([
|
|
262
|
+
new Promise<void>((resolve) => {
|
|
263
|
+
this.readyResolve = resolve;
|
|
264
|
+
}),
|
|
265
|
+
loadScramjetWasm(),
|
|
266
|
+
]);
|
|
267
|
+
|
|
268
|
+
let channel = new MessageChannel();
|
|
269
|
+
this.rpc = new RpcHelper<Controllerbound, SWbound>(
|
|
270
|
+
this.methods,
|
|
271
|
+
"tabchannel-" + this.id,
|
|
272
|
+
(data, transfer) => {
|
|
273
|
+
channel.port1.postMessage(data, transfer);
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
channel.port1.addEventListener("message", (e) => {
|
|
277
|
+
this.rpc.recieve(e.data);
|
|
278
|
+
});
|
|
279
|
+
channel.port1.start();
|
|
280
|
+
|
|
281
|
+
init.serviceworker.postMessage(
|
|
282
|
+
{
|
|
283
|
+
$controller$init: {
|
|
284
|
+
prefix: config.prefix + this.id,
|
|
285
|
+
id: this.id,
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
[channel.port2]
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
createFrame(element?: HTMLIFrameElement): Frame {
|
|
293
|
+
if (!this.ready) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
"Controller is not ready! Try awaiting controller.wait()"
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
element ??= document.createElement("iframe");
|
|
299
|
+
const frame = new Frame(this, element);
|
|
300
|
+
this.frames.push(frame);
|
|
301
|
+
return frame;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
wait(): Promise<void> {
|
|
305
|
+
return this.ready;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function yieldGetInjectScripts(
|
|
310
|
+
cookieJar: ScramjetGlobal.CookieJar,
|
|
311
|
+
config: Config,
|
|
312
|
+
sjconfig: ScramjetGlobal.ScramjetConfig,
|
|
313
|
+
prefix: URL
|
|
314
|
+
) {
|
|
315
|
+
let getInjectScripts: ScramjetGlobal.ScramjetInterface["getInjectScripts"] = (
|
|
316
|
+
meta,
|
|
317
|
+
handler,
|
|
318
|
+
script
|
|
319
|
+
) => {
|
|
320
|
+
return [
|
|
321
|
+
script(config.scramjetPath),
|
|
322
|
+
script(config.injectPath),
|
|
323
|
+
script(prefix.href + config.virtualWasmPath),
|
|
324
|
+
script(
|
|
325
|
+
"data:text/javascript;base64," +
|
|
326
|
+
btoa(`
|
|
327
|
+
document.currentScript.remove();
|
|
328
|
+
$scramjetController.load({
|
|
329
|
+
config: ${JSON.stringify(config)},
|
|
330
|
+
sjconfig: ${JSON.stringify(sjconfig)},
|
|
331
|
+
cookies: ${cookieJar.dump()},
|
|
332
|
+
prefix: new URL("${prefix.href}"),
|
|
333
|
+
yieldGetInjectScripts: ${yieldGetInjectScripts.toString()},
|
|
334
|
+
codecEncode: ${codecEncode.toString()},
|
|
335
|
+
codecDecode: ${codecDecode.toString()},
|
|
336
|
+
})
|
|
337
|
+
`)
|
|
338
|
+
),
|
|
339
|
+
];
|
|
340
|
+
};
|
|
341
|
+
return getInjectScripts;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
class Frame {
|
|
345
|
+
fetchHandler: ScramjetGlobal.ScramjetFetchHandler;
|
|
346
|
+
id: string;
|
|
347
|
+
prefix: string;
|
|
348
|
+
|
|
349
|
+
get context(): ScramjetGlobal.ScramjetContext {
|
|
350
|
+
let sjcfg = {
|
|
351
|
+
...$scramjet.defaultConfig,
|
|
352
|
+
...cfg,
|
|
353
|
+
};
|
|
354
|
+
return {
|
|
355
|
+
cookieJar,
|
|
356
|
+
prefix: new URL(this.prefix, location.href),
|
|
357
|
+
config: sjcfg,
|
|
358
|
+
interface: {
|
|
359
|
+
getInjectScripts: yieldGetInjectScripts(
|
|
360
|
+
this.controller.cookieJar,
|
|
361
|
+
config,
|
|
362
|
+
{ ...$scramjet.defaultConfig, ...cfg },
|
|
363
|
+
new URL(this.prefix, location.href)
|
|
364
|
+
),
|
|
365
|
+
getWorkerInjectScripts: (meta, type, script) => {
|
|
366
|
+
let str = "";
|
|
367
|
+
|
|
368
|
+
str += script(config.scramjetPath);
|
|
369
|
+
str += script(this.prefix + config.virtualWasmPath);
|
|
370
|
+
str += `
|
|
371
|
+
(()=>{
|
|
372
|
+
const { ScramjetClient, CookieJar, setWasm } = $scramjet;
|
|
373
|
+
|
|
374
|
+
setWasm(Uint8Array.from(atob(self.WASM), (c) => c.charCodeAt(0)));
|
|
375
|
+
delete self.WASM;
|
|
376
|
+
|
|
377
|
+
const sjconfig = ${JSON.stringify(sjcfg)};
|
|
378
|
+
const prefix = new URL("${this.prefix}", location.href);
|
|
379
|
+
|
|
380
|
+
const context = {
|
|
381
|
+
interface: {
|
|
382
|
+
codecEncode: ${codecEncode.toString()},
|
|
383
|
+
codecDecode: ${codecDecode.toString()},
|
|
384
|
+
},
|
|
385
|
+
prefix,
|
|
386
|
+
config: sjconfig
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
const client = new ScramjetClient(globalThis, {
|
|
390
|
+
context,
|
|
391
|
+
transport: null,
|
|
392
|
+
shouldPassthroughWebsocket: (url) => {
|
|
393
|
+
return url === "wss://anura.pro/";
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
client.hook();
|
|
398
|
+
})();
|
|
399
|
+
`;
|
|
400
|
+
|
|
401
|
+
return str;
|
|
402
|
+
},
|
|
403
|
+
codecEncode,
|
|
404
|
+
codecDecode,
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
constructor(
|
|
410
|
+
public controller: Controller,
|
|
411
|
+
public element: HTMLIFrameElement
|
|
412
|
+
) {
|
|
413
|
+
this.id = makeId();
|
|
414
|
+
this.prefix = this.controller.prefix + this.id + "/";
|
|
415
|
+
|
|
416
|
+
this.fetchHandler = new $scramjet.ScramjetFetchHandler({
|
|
417
|
+
crossOriginIsolated: self.crossOriginIsolated,
|
|
418
|
+
context: this.context,
|
|
419
|
+
transport: controller.transport,
|
|
420
|
+
async sendSetCookie(url, cookie) { },
|
|
421
|
+
async fetchBlobUrl(url) {
|
|
422
|
+
return BareResponse.fromNativeResponse(await fetch(url));
|
|
423
|
+
},
|
|
424
|
+
async fetchDataUrl(url) {
|
|
425
|
+
return BareResponse.fromNativeResponse(await fetch(url));
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
go(url: string) {
|
|
431
|
+
const encoded = $scramjet.rewriteUrl(url, this.context, {
|
|
432
|
+
origin: new URL(location.href),
|
|
433
|
+
base: new URL(location.href),
|
|
434
|
+
});
|
|
435
|
+
this.element.src = encoded;
|
|
436
|
+
}
|
|
437
|
+
}
|