diff --git a/packages/chrome/public/controller.sw.js b/packages/chrome/public/controller.sw.js index 4416f36e..6992dd12 100644 --- a/packages/chrome/public/controller.sw.js +++ b/packages/chrome/public/controller.sw.js @@ -1,360 +1,2 @@ -var $scramjetController; -(() => { - var __webpack_modules__ = { - "./packages/scramjet/packages/rpc/index.ts"( - __unused_rspack_module, - __webpack_exports__, - __webpack_require__ - ) { - __webpack_require__.r(__webpack_exports__); - __webpack_require__.d(__webpack_exports__, { - RpcHelper: () => RpcHelper, - }); - class RpcHelper { - methods; - id; - sendRaw; - counter = 0; - promiseCallbacks = new Map(); - constructor(methods, id, sendRaw) { - this.methods = methods; - this.id = id; - this.sendRaw = sendRaw; - } - recieve(data) { - if (data === undefined || data === null || typeof data !== "object") - return; - const dt = data[this.id]; - if (dt === undefined || dt === null || typeof dt !== "object") return; - const type = dt.$type; - if (type === "response") { - const token = dt.$token; - const data = dt.$data; - const error = dt.$error; - const cb = this.promiseCallbacks.get(token); - if (!cb) return; - this.promiseCallbacks.delete(token); - if (error !== undefined) { - cb.reject(new Error(error)); - } else { - cb.resolve(data); - } - } else if (type === "request") { - const method = dt.$method; - const args = dt.$args; - this.methods[method](args) - .then((r) => { - this.sendRaw( - { - [this.id]: { - $type: "response", - $token: dt.$token, - $data: r?.[0], - }, - }, - r?.[1] - ); - }) - .catch((err) => { - console.error(err); - this.sendRaw( - { - [this.id]: { - $type: "response", - $token: dt.$token, - $error: err?.toString() || "Unknown error", - }, - }, - [] - ); - }); - } - } - call(method, args, transfer = []) { - const token = this.counter++; - return new Promise((resolve, reject) => { - this.promiseCallbacks.set(token, { - resolve, - reject, - }); - this.sendRaw( - { - [this.id]: { - $type: "request", - $method: method, - $args: args, - $token: token, - }, - }, - transfer - ); - }); - } - } - }, - }; - // The module cache - var __webpack_module_cache__ = {}; - - // The require function - function __webpack_require__(moduleId) { - // Check if module is in cache - var cachedModule = __webpack_module_cache__[moduleId]; - if (cachedModule !== undefined) { - return cachedModule.exports; - } - // Create a new module (and put it into the cache) - var module = (__webpack_module_cache__[moduleId] = { - exports: {}, - }); - // Execute the module function - __webpack_modules__[moduleId](module, module.exports, __webpack_require__); - - // Return the exports of the module - return module.exports; - } - - // webpack/runtime/define_property_getters - (() => { - __webpack_require__.d = (exports, definition) => { - for (var key in definition) { - if ( - __webpack_require__.o(definition, key) && - !__webpack_require__.o(exports, key) - ) { - Object.defineProperty(exports, key, { - enumerable: true, - get: definition[key], - }); - } - } - }; - })(); - // webpack/runtime/has_own_property - (() => { - __webpack_require__.o = (obj, prop) => - Object.prototype.hasOwnProperty.call(obj, prop); - })(); - // webpack/runtime/make_namespace_object - (() => { - // define __esModule on exports - __webpack_require__.r = (exports) => { - if (typeof Symbol !== "undefined" && Symbol.toStringTag) { - Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); - } - Object.defineProperty(exports, "__esModule", { value: true }); - }; - })(); - var __webpack_exports__ = {}; - // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. - (() => { - __webpack_require__.r(__webpack_exports__); - __webpack_require__.d(__webpack_exports__, { - route: () => route, - shouldRoute: () => shouldRoute, - }); - /* import */ var _mercuryworkshop_rpc__rspack_import_0 = - __webpack_require__("./packages/scramjet/packages/rpc/index.ts"); - - function makeId() { - return Math.random().toString(36).substring(2, 10); - } - const cookieResolvers = {}; - addEventListener("message", (e) => { - if (!e.data) return; - if (typeof e.data != "object") return; - if ( - e.data.$sw$setCookieDone && - typeof e.data.$sw$setCookieDone == "object" - ) { - const done = e.data.$sw$setCookieDone; - const resolver = cookieResolvers[done.id]; - if (resolver) { - resolver(); - delete cookieResolvers[done.id]; - } - } - if ( - e.data.$sw$initRemoteTransport && - typeof e.data.$sw$initRemoteTransport == "object" - ) { - const { port, prefix } = e.data.$sw$initRemoteTransport; - const relevantcontroller = tabs.find((tab) => - new URL(prefix).pathname.startsWith(tab.prefix) - ); - if (!relevantcontroller) { - console.error("No relevant controller found for transport init"); - return; - } - relevantcontroller.rpc.call("initRemoteTransport", port, [port]); - } - }); - class ControllerReference { - prefix; - id; - rpc; - constructor(prefix, id, port) { - this.prefix = prefix; - this.id = id; - this.rpc = new _mercuryworkshop_rpc__rspack_import_0.RpcHelper( - { - sendSetCookie: async ({ cookies, options }) => { - const clients1 = await self.clients.matchAll(); - const ids = []; - const promises = []; - // Navigation fetches (document/iframe) deliver cookies via the inject - // script's embedded cookieJar dump — the destination page doesn't have - // inject.ts loaded yet to ack, so awaiting would deadlock. Broadcast - // so any already-loaded clients can update their jars, but don't wait. - const isNavigation = - options?.destination === "document" || - options?.destination === "iframe"; - for (const client of clients1) { - const id = makeId(); - ids.push(id); - client.postMessage({ - $controller$setCookie: { - cookies, - options, - id, - }, - }); - if (!isNavigation) { - promises.push( - new Promise((resolve) => { - // Resolve with the id so we know which client replied. - cookieResolvers[id] = () => resolve(id); - }) - ); - } - } - // Wait for the first client to acknowledge the cookie sync. - // Using Promise.any (not Promise.all) so that extra SW clients created by - // window.open (e.g. test popup windows) don't cause timeouts — only the - // main controller client needs to respond. - if (promises.length > 0) { - let timeoutId; - let responded = false; - const timeoutPromise = new Promise((resolve) => { - timeoutId = setTimeout(() => { - if (!responded) { - const pending = ids.filter( - (id) => cookieResolvers[id] !== undefined - ); - console.error( - "timed out waiting for set cookie response (deadlock?): " + - `cookies=${cookies.length} clients=${clients1.length} ` + - `pending=${pending.length}/${ids.length} ` + - `clientUrls=${clients1.map((c) => c.url).join(",")}` - ); - } - resolve(); - }, 1000); - }); - try { - await Promise.race([ - timeoutPromise, - Promise.any(promises) - .then(() => { - responded = true; - }) - .catch(() => {}), - ]); - } finally { - // Clear the timeout so it doesn't fire spuriously after the - // race has already been won by Promise.any. - if (timeoutId !== undefined) clearTimeout(timeoutId); - // Clean up any pending resolvers so clients that never - // responded don't leak entries in cookieResolvers. - for (const id of ids) { - delete cookieResolvers[id]; - } - } - } - }, - }, - "tabchannel-" + id, - (data, transfer) => { - port.postMessage(data, transfer); - } - ); - port.onmessage = (e) => { - this.rpc.recieve(e.data); - }; - port.onmessageerror = console.error; - this.rpc.call("ready", undefined); - } - } - const tabs = []; - addEventListener("message", (e) => { - if (!e.data) return; - if (typeof e.data != "object") return; - if (!e.data.$controller$init) return; - if (typeof e.data.$controller$init != "object") return; - const init = e.data.$controller$init; - const existing = tabs.findIndex((t) => t.id === init.id); - if (existing !== -1) { - tabs.splice(existing, 1); - } - tabs.push(new ControllerReference(init.prefix, init.id, e.ports[0])); - }); - function shouldRoute(event) { - const url = new URL(event.request.url); - const tab = tabs.find((tab) => url.pathname.startsWith(tab.prefix)); - return tab !== undefined; - } - async function route(event) { - try { - const url = new URL(event.request.url); - const tab = tabs.find((tab) => url.pathname.startsWith(tab.prefix)); - const client = await clients.get(event.clientId); - const rawheaders = [...event.request.headers]; - const response = await tab.rpc.call( - "request", - { - rawUrl: event.request.url, - rawReferrer: event.request.referrer, - destination: event.request.destination, - mode: event.request.mode, - referrer: event.request.referrer, - method: event.request.method, - body: event.request.body, - cache: event.request.cache, - forceCrossOriginIsolated: false, - initialHeaders: rawheaders, - rawClientUrl: client ? client.url : undefined, - clientId: event.clientId || event.resultingClientId, - }, - event.request.body instanceof ReadableStream || // @ts-expect-error the types for fetchevent are messed up - event.request.body instanceof ArrayBuffer - ? [event.request.body] - : undefined - ); - return new Response(response.body, { - status: response.status, - statusText: response.statusText, - headers: response.headers, - }); - } catch (e) { - console.error("Service Worker error:", e); - return new Response("Internal Service Worker Error: " + e.message, { - status: 500, - }); - } - } - // the only way to know if a service worker has suddenly died is if this code runs again - // notify all clients to send over their messageports again - setTimeout(async () => { - console.log("service worker activated, notifying clients to revive"); - for (const client of await clients.matchAll()) { - client.postMessage({ - $controller$swrevive: {}, - }); - } - // short delay is apparently needed - }, 100); - })(); - - $scramjetController = __webpack_exports__; -})(); -//# sourceMappingURL=controller.sw.js.map +var $scramjetController;(()=>{var e={805(e,t,r){r.d(t,{C:()=>o});class o{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,o=t.$error,s=this.promiseCallbacks.get(e);if(!s)return;this.promiseCallbacks.delete(e),void 0!==o?s.reject(Error(o)):s.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 o=this.counter++;return new Promise((s,i)=>{this.promiseCallbacks.set(o,{resolve:s,reject:i}),this.sendRaw({[this.id]:{$type:"request",$method:e,$args:t,$token:o}},r)})}}}},t={};function r(o){var s=t[o];if(void 0!==s)return s.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,r),i.exports}r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};(()=>{r.r(o),r.d(o,{route:()=>a,shouldRoute:()=>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,o=t[r.id];o&&(o(),delete t[r.id])}if(e.data.$sw$initRemoteTransport&&"object"==typeof e.data.$sw$initRemoteTransport){let{port:t,prefix:r}=e.data.$sw$initRemoteTransport,o=i.find(e=>new URL(r).pathname.startsWith(e.prefix));if(!o)return void console.error("No relevant controller found for transport init");o.rpc.call("initRemoteTransport",t,[t])}}});class s{prefix;id;rpc;constructor(r,o,s){this.prefix=r,this.id=o,this.rpc=new e.C({sendSetCookie:async({cookies:e,options:r})=>{let o=await self.clients.matchAll(),s=[],i=[],n=r?.destination==="document"||r?.destination==="iframe";for(let a of o){let o=Math.random().toString(36).substring(2,10);s.push(o),a.postMessage({$controller$setCookie:{cookies:e,options:r,id:o}}),n||i.push(new Promise(e=>{t[o]=()=>e(o)}))}if(i.length>0){let r,n=!1,a=new Promise(i=>{r=setTimeout(()=>{if(!n){let r=s.filter(e=>void 0!==t[e]);console.error(`timed out waiting for set cookie response (deadlock?): cookies=${e.length} clients=${o.length} pending=${r.length}/${s.length} clientUrls=${o.map(e=>e.url).join(",")}`)}i()},1e3)});try{await Promise.race([a,Promise.any(i).then(()=>{n=!0}).catch(()=>{})])}finally{for(let e of(void 0!==r&&clearTimeout(r),s))delete t[e]}}}},"tabchannel-"+o,(e,t)=>{s.postMessage(e,t)}),s.onmessage=e=>{this.rpc.recieve(e.data)},s.onmessageerror=console.error,this.rpc.call("ready",void 0)}}let i=[];function n(e){let t=new URL(e.request.url);return void 0!==i.find(e=>t.pathname.startsWith(e.prefix))}async function a(e){try{let t=new URL(e.request.url),r=i.find(e=>t.pathname.startsWith(e.prefix)),o=await clients.get(e.clientId),s=[...e.request.headers],n=await r.rpc.call("request",{rawUrl:e.request.url,rawReferrer:e.request.referrer,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:s,rawClientUrl:o?o.url:void 0,clientId:e.clientId||e.resultingClientId},e.request.body instanceof ReadableStream||e.request.body instanceof ArrayBuffer?[e.request.body]:void 0);return new Response(n.body,{status:n.status,statusText:n.statusText,headers:n.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,r=i.findIndex(e=>e.id===t.id);-1!==r&&i.splice(r,1),i.push(new s(t.prefix,t.id,e.ports[0]))}),addEventListener("install",()=>{self.skipWaiting()}),addEventListener("activate",e=>{e.waitUntil(clients.claim())}),setTimeout(async()=>{for(let e of(console.log("service worker activated, notifying clients to revive"),await clients.matchAll()))e.postMessage({$controller$swrevive:{}})},100)})(),$scramjetController=o})(); +//# sourceMappingURL=controller.sw.js.map \ No newline at end of file diff --git a/packages/chrome/public/localcontrollersw.js b/packages/chrome/public/localcontrollersw.js index d603bb09..9c271751 100644 --- a/packages/chrome/public/localcontrollersw.js +++ b/packages/chrome/public/localcontrollersw.js @@ -4,14 +4,4 @@ addEventListener("fetch", (event) => { if ($scramjetController.shouldRoute(event)) { event.respondWith($scramjetController.route(event)); } -}); - -self.addEventListener("install", () => { - self.skipWaiting(); -}); - -self.addEventListener("activate", (e) => { - e.waitUntil(self.clients.claim()); -}); - -console.log("sw initialized"); +}); \ No newline at end of file diff --git a/packages/sandbox/controller.sw.js b/packages/sandbox/controller.sw.js index 4416f36e..6992dd12 100644 --- a/packages/sandbox/controller.sw.js +++ b/packages/sandbox/controller.sw.js @@ -1,360 +1,2 @@ -var $scramjetController; -(() => { - var __webpack_modules__ = { - "./packages/scramjet/packages/rpc/index.ts"( - __unused_rspack_module, - __webpack_exports__, - __webpack_require__ - ) { - __webpack_require__.r(__webpack_exports__); - __webpack_require__.d(__webpack_exports__, { - RpcHelper: () => RpcHelper, - }); - class RpcHelper { - methods; - id; - sendRaw; - counter = 0; - promiseCallbacks = new Map(); - constructor(methods, id, sendRaw) { - this.methods = methods; - this.id = id; - this.sendRaw = sendRaw; - } - recieve(data) { - if (data === undefined || data === null || typeof data !== "object") - return; - const dt = data[this.id]; - if (dt === undefined || dt === null || typeof dt !== "object") return; - const type = dt.$type; - if (type === "response") { - const token = dt.$token; - const data = dt.$data; - const error = dt.$error; - const cb = this.promiseCallbacks.get(token); - if (!cb) return; - this.promiseCallbacks.delete(token); - if (error !== undefined) { - cb.reject(new Error(error)); - } else { - cb.resolve(data); - } - } else if (type === "request") { - const method = dt.$method; - const args = dt.$args; - this.methods[method](args) - .then((r) => { - this.sendRaw( - { - [this.id]: { - $type: "response", - $token: dt.$token, - $data: r?.[0], - }, - }, - r?.[1] - ); - }) - .catch((err) => { - console.error(err); - this.sendRaw( - { - [this.id]: { - $type: "response", - $token: dt.$token, - $error: err?.toString() || "Unknown error", - }, - }, - [] - ); - }); - } - } - call(method, args, transfer = []) { - const token = this.counter++; - return new Promise((resolve, reject) => { - this.promiseCallbacks.set(token, { - resolve, - reject, - }); - this.sendRaw( - { - [this.id]: { - $type: "request", - $method: method, - $args: args, - $token: token, - }, - }, - transfer - ); - }); - } - } - }, - }; - // The module cache - var __webpack_module_cache__ = {}; - - // The require function - function __webpack_require__(moduleId) { - // Check if module is in cache - var cachedModule = __webpack_module_cache__[moduleId]; - if (cachedModule !== undefined) { - return cachedModule.exports; - } - // Create a new module (and put it into the cache) - var module = (__webpack_module_cache__[moduleId] = { - exports: {}, - }); - // Execute the module function - __webpack_modules__[moduleId](module, module.exports, __webpack_require__); - - // Return the exports of the module - return module.exports; - } - - // webpack/runtime/define_property_getters - (() => { - __webpack_require__.d = (exports, definition) => { - for (var key in definition) { - if ( - __webpack_require__.o(definition, key) && - !__webpack_require__.o(exports, key) - ) { - Object.defineProperty(exports, key, { - enumerable: true, - get: definition[key], - }); - } - } - }; - })(); - // webpack/runtime/has_own_property - (() => { - __webpack_require__.o = (obj, prop) => - Object.prototype.hasOwnProperty.call(obj, prop); - })(); - // webpack/runtime/make_namespace_object - (() => { - // define __esModule on exports - __webpack_require__.r = (exports) => { - if (typeof Symbol !== "undefined" && Symbol.toStringTag) { - Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); - } - Object.defineProperty(exports, "__esModule", { value: true }); - }; - })(); - var __webpack_exports__ = {}; - // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. - (() => { - __webpack_require__.r(__webpack_exports__); - __webpack_require__.d(__webpack_exports__, { - route: () => route, - shouldRoute: () => shouldRoute, - }); - /* import */ var _mercuryworkshop_rpc__rspack_import_0 = - __webpack_require__("./packages/scramjet/packages/rpc/index.ts"); - - function makeId() { - return Math.random().toString(36).substring(2, 10); - } - const cookieResolvers = {}; - addEventListener("message", (e) => { - if (!e.data) return; - if (typeof e.data != "object") return; - if ( - e.data.$sw$setCookieDone && - typeof e.data.$sw$setCookieDone == "object" - ) { - const done = e.data.$sw$setCookieDone; - const resolver = cookieResolvers[done.id]; - if (resolver) { - resolver(); - delete cookieResolvers[done.id]; - } - } - if ( - e.data.$sw$initRemoteTransport && - typeof e.data.$sw$initRemoteTransport == "object" - ) { - const { port, prefix } = e.data.$sw$initRemoteTransport; - const relevantcontroller = tabs.find((tab) => - new URL(prefix).pathname.startsWith(tab.prefix) - ); - if (!relevantcontroller) { - console.error("No relevant controller found for transport init"); - return; - } - relevantcontroller.rpc.call("initRemoteTransport", port, [port]); - } - }); - class ControllerReference { - prefix; - id; - rpc; - constructor(prefix, id, port) { - this.prefix = prefix; - this.id = id; - this.rpc = new _mercuryworkshop_rpc__rspack_import_0.RpcHelper( - { - sendSetCookie: async ({ cookies, options }) => { - const clients1 = await self.clients.matchAll(); - const ids = []; - const promises = []; - // Navigation fetches (document/iframe) deliver cookies via the inject - // script's embedded cookieJar dump — the destination page doesn't have - // inject.ts loaded yet to ack, so awaiting would deadlock. Broadcast - // so any already-loaded clients can update their jars, but don't wait. - const isNavigation = - options?.destination === "document" || - options?.destination === "iframe"; - for (const client of clients1) { - const id = makeId(); - ids.push(id); - client.postMessage({ - $controller$setCookie: { - cookies, - options, - id, - }, - }); - if (!isNavigation) { - promises.push( - new Promise((resolve) => { - // Resolve with the id so we know which client replied. - cookieResolvers[id] = () => resolve(id); - }) - ); - } - } - // Wait for the first client to acknowledge the cookie sync. - // Using Promise.any (not Promise.all) so that extra SW clients created by - // window.open (e.g. test popup windows) don't cause timeouts — only the - // main controller client needs to respond. - if (promises.length > 0) { - let timeoutId; - let responded = false; - const timeoutPromise = new Promise((resolve) => { - timeoutId = setTimeout(() => { - if (!responded) { - const pending = ids.filter( - (id) => cookieResolvers[id] !== undefined - ); - console.error( - "timed out waiting for set cookie response (deadlock?): " + - `cookies=${cookies.length} clients=${clients1.length} ` + - `pending=${pending.length}/${ids.length} ` + - `clientUrls=${clients1.map((c) => c.url).join(",")}` - ); - } - resolve(); - }, 1000); - }); - try { - await Promise.race([ - timeoutPromise, - Promise.any(promises) - .then(() => { - responded = true; - }) - .catch(() => {}), - ]); - } finally { - // Clear the timeout so it doesn't fire spuriously after the - // race has already been won by Promise.any. - if (timeoutId !== undefined) clearTimeout(timeoutId); - // Clean up any pending resolvers so clients that never - // responded don't leak entries in cookieResolvers. - for (const id of ids) { - delete cookieResolvers[id]; - } - } - } - }, - }, - "tabchannel-" + id, - (data, transfer) => { - port.postMessage(data, transfer); - } - ); - port.onmessage = (e) => { - this.rpc.recieve(e.data); - }; - port.onmessageerror = console.error; - this.rpc.call("ready", undefined); - } - } - const tabs = []; - addEventListener("message", (e) => { - if (!e.data) return; - if (typeof e.data != "object") return; - if (!e.data.$controller$init) return; - if (typeof e.data.$controller$init != "object") return; - const init = e.data.$controller$init; - const existing = tabs.findIndex((t) => t.id === init.id); - if (existing !== -1) { - tabs.splice(existing, 1); - } - tabs.push(new ControllerReference(init.prefix, init.id, e.ports[0])); - }); - function shouldRoute(event) { - const url = new URL(event.request.url); - const tab = tabs.find((tab) => url.pathname.startsWith(tab.prefix)); - return tab !== undefined; - } - async function route(event) { - try { - const url = new URL(event.request.url); - const tab = tabs.find((tab) => url.pathname.startsWith(tab.prefix)); - const client = await clients.get(event.clientId); - const rawheaders = [...event.request.headers]; - const response = await tab.rpc.call( - "request", - { - rawUrl: event.request.url, - rawReferrer: event.request.referrer, - destination: event.request.destination, - mode: event.request.mode, - referrer: event.request.referrer, - method: event.request.method, - body: event.request.body, - cache: event.request.cache, - forceCrossOriginIsolated: false, - initialHeaders: rawheaders, - rawClientUrl: client ? client.url : undefined, - clientId: event.clientId || event.resultingClientId, - }, - event.request.body instanceof ReadableStream || // @ts-expect-error the types for fetchevent are messed up - event.request.body instanceof ArrayBuffer - ? [event.request.body] - : undefined - ); - return new Response(response.body, { - status: response.status, - statusText: response.statusText, - headers: response.headers, - }); - } catch (e) { - console.error("Service Worker error:", e); - return new Response("Internal Service Worker Error: " + e.message, { - status: 500, - }); - } - } - // the only way to know if a service worker has suddenly died is if this code runs again - // notify all clients to send over their messageports again - setTimeout(async () => { - console.log("service worker activated, notifying clients to revive"); - for (const client of await clients.matchAll()) { - client.postMessage({ - $controller$swrevive: {}, - }); - } - // short delay is apparently needed - }, 100); - })(); - - $scramjetController = __webpack_exports__; -})(); -//# sourceMappingURL=controller.sw.js.map +var $scramjetController;(()=>{var e={805(e,t,r){r.d(t,{C:()=>o});class o{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,o=t.$error,s=this.promiseCallbacks.get(e);if(!s)return;this.promiseCallbacks.delete(e),void 0!==o?s.reject(Error(o)):s.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 o=this.counter++;return new Promise((s,i)=>{this.promiseCallbacks.set(o,{resolve:s,reject:i}),this.sendRaw({[this.id]:{$type:"request",$method:e,$args:t,$token:o}},r)})}}}},t={};function r(o){var s=t[o];if(void 0!==s)return s.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,r),i.exports}r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};(()=>{r.r(o),r.d(o,{route:()=>a,shouldRoute:()=>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,o=t[r.id];o&&(o(),delete t[r.id])}if(e.data.$sw$initRemoteTransport&&"object"==typeof e.data.$sw$initRemoteTransport){let{port:t,prefix:r}=e.data.$sw$initRemoteTransport,o=i.find(e=>new URL(r).pathname.startsWith(e.prefix));if(!o)return void console.error("No relevant controller found for transport init");o.rpc.call("initRemoteTransport",t,[t])}}});class s{prefix;id;rpc;constructor(r,o,s){this.prefix=r,this.id=o,this.rpc=new e.C({sendSetCookie:async({cookies:e,options:r})=>{let o=await self.clients.matchAll(),s=[],i=[],n=r?.destination==="document"||r?.destination==="iframe";for(let a of o){let o=Math.random().toString(36).substring(2,10);s.push(o),a.postMessage({$controller$setCookie:{cookies:e,options:r,id:o}}),n||i.push(new Promise(e=>{t[o]=()=>e(o)}))}if(i.length>0){let r,n=!1,a=new Promise(i=>{r=setTimeout(()=>{if(!n){let r=s.filter(e=>void 0!==t[e]);console.error(`timed out waiting for set cookie response (deadlock?): cookies=${e.length} clients=${o.length} pending=${r.length}/${s.length} clientUrls=${o.map(e=>e.url).join(",")}`)}i()},1e3)});try{await Promise.race([a,Promise.any(i).then(()=>{n=!0}).catch(()=>{})])}finally{for(let e of(void 0!==r&&clearTimeout(r),s))delete t[e]}}}},"tabchannel-"+o,(e,t)=>{s.postMessage(e,t)}),s.onmessage=e=>{this.rpc.recieve(e.data)},s.onmessageerror=console.error,this.rpc.call("ready",void 0)}}let i=[];function n(e){let t=new URL(e.request.url);return void 0!==i.find(e=>t.pathname.startsWith(e.prefix))}async function a(e){try{let t=new URL(e.request.url),r=i.find(e=>t.pathname.startsWith(e.prefix)),o=await clients.get(e.clientId),s=[...e.request.headers],n=await r.rpc.call("request",{rawUrl:e.request.url,rawReferrer:e.request.referrer,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:s,rawClientUrl:o?o.url:void 0,clientId:e.clientId||e.resultingClientId},e.request.body instanceof ReadableStream||e.request.body instanceof ArrayBuffer?[e.request.body]:void 0);return new Response(n.body,{status:n.status,statusText:n.statusText,headers:n.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,r=i.findIndex(e=>e.id===t.id);-1!==r&&i.splice(r,1),i.push(new s(t.prefix,t.id,e.ports[0]))}),addEventListener("install",()=>{self.skipWaiting()}),addEventListener("activate",e=>{e.waitUntil(clients.claim())}),setTimeout(async()=>{for(let e of(console.log("service worker activated, notifying clients to revive"),await clients.matchAll()))e.postMessage({$controller$swrevive:{}})},100)})(),$scramjetController=o})(); +//# sourceMappingURL=controller.sw.js.map \ No newline at end of file diff --git a/packages/sandbox/sw.js b/packages/sandbox/sw.js index d603bb09..0f088f71 100644 --- a/packages/sandbox/sw.js +++ b/packages/sandbox/sw.js @@ -6,12 +6,4 @@ addEventListener("fetch", (event) => { } }); -self.addEventListener("install", () => { - self.skipWaiting(); -}); - -self.addEventListener("activate", (e) => { - e.waitUntil(self.clients.claim()); -}); - console.log("sw initialized"); diff --git a/packages/scramjet/packages/bootstrap/package.json b/packages/scramjet/packages/bootstrap/package.json index 69828064..27fe6207 100644 --- a/packages/scramjet/packages/bootstrap/package.json +++ b/packages/scramjet/packages/bootstrap/package.json @@ -6,7 +6,7 @@ "main": "./dist/bootstrap-server.js", "types": "./dist/types/server.d.ts", "dependencies": { - "server": "link:@mercuryworkshop/wisp-js/server", + "@mercuryworkshop/wisp-js": "catalog:", "tar": "^7.5.1" }, "devDependencies": { diff --git a/packages/scramjet/packages/controller/package.json b/packages/scramjet/packages/controller/package.json index 55280bdf..197a452e 100644 --- a/packages/scramjet/packages/controller/package.json +++ b/packages/scramjet/packages/controller/package.json @@ -11,6 +11,7 @@ "@mercuryworkshop/scramjet": "workspace:*" }, "devDependencies": { + "@types/serviceworker": "^0.0.197", "@mercuryworkshop/rpc": "workspace:*" } } diff --git a/packages/scramjet/packages/controller/src/index.ts b/packages/scramjet/packages/controller/src/index.ts index 544e13b0..91d4f0ca 100644 --- a/packages/scramjet/packages/controller/src/index.ts +++ b/packages/scramjet/packages/controller/src/index.ts @@ -766,6 +766,18 @@ export class Frame { element[CONTROLLERFRAME] = this; } + back() { + this.element.contentWindow?.history.back(); + } + + forward() { + this.element.contentWindow?.history.forward(); + } + + reload() { + this.element.contentWindow?.location.reload(); + } + go(url: string) { const encoded = $scramjet.rewriteUrl(url, this.context, { //@ts-expect-error diff --git a/packages/scramjet/packages/controller/src/sw.ts b/packages/scramjet/packages/controller/src/sw.ts index ea533ad6..60ff6c9d 100644 --- a/packages/scramjet/packages/controller/src/sw.ts +++ b/packages/scramjet/packages/controller/src/sw.ts @@ -1,8 +1,8 @@ -declare let clients: Clients; +/// +/// import { RpcHelper } from "@mercuryworkshop/rpc"; import type { Controllerbound, SWbound } from "./types"; import type { RawHeaders } from "@mercuryworkshop/proxy-transports"; -import { ScramjetHeaders } from "@mercuryworkshop/scramjet"; function makeId(): string { return Math.random().toString(36).substring(2, 10); @@ -210,6 +210,14 @@ export async function route(event: FetchEvent): Promise { } } +addEventListener("install", () => { + self.skipWaiting(); +}); + +addEventListener("activate", (event: ExtendableEvent) => { + event.waitUntil(clients.claim()); +}); + // the only way to know if a service worker has suddenly died is if this code runs again // notify all clients to send over their messageports again setTimeout(async () => { diff --git a/packages/scramjet/packages/controller/tsconfig.json b/packages/scramjet/packages/controller/tsconfig.json index 2bc7fc96..b0e20585 100644 --- a/packages/scramjet/packages/controller/tsconfig.json +++ b/packages/scramjet/packages/controller/tsconfig.json @@ -3,7 +3,7 @@ "target": "ES2022", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ES2022", "webworker", "DOM", "DOM.Iterable"], + "lib": ["ES2022", "WebWorker", "DOM", "DOM.Iterable"], "types": [], "skipLibCheck": true, /* Bundler mode */ diff --git a/packages/scramjet/packages/demo/src/pages/BrowserView.tsx b/packages/scramjet/packages/demo/src/pages/BrowserView.tsx index 6a7b5b59..78087ab2 100644 --- a/packages/scramjet/packages/demo/src/pages/BrowserView.tsx +++ b/packages/scramjet/packages/demo/src/pages/BrowserView.tsx @@ -33,13 +33,13 @@ export const Omnibox: Component = function (cx) { >
diff --git a/packages/scramjet/packages/demo/src/store.ts b/packages/scramjet/packages/demo/src/store.ts index 9438105a..fb10a3d2 100644 --- a/packages/scramjet/packages/demo/src/store.ts +++ b/packages/scramjet/packages/demo/src/store.ts @@ -6,8 +6,8 @@ export const AVAILABLE_TRANSPORTS: ReadonlyArray<{ value: AvailableTransports; label: string; }> = [ - { value: "libcurl", label: "libcurl" }, - { value: "epoxy", label: "epoxy" }, + { value: "libcurl", label: "Libcurl" }, + { value: "epoxy", label: "Epoxy" }, ]; const DEFAULT_WISP_URL = import.meta.env.VITE_WISP_URL; const DEFAULT_TRANSPORT: AvailableTransports = "libcurl"; diff --git a/packages/scramjet/pnpm-lock.yaml b/packages/scramjet/pnpm-lock.yaml index bfd09e49..9e017c9f 100644 --- a/packages/scramjet/pnpm-lock.yaml +++ b/packages/scramjet/pnpm-lock.yaml @@ -68,9 +68,9 @@ importers: packages/bootstrap: dependencies: - server: - specifier: link:@mercuryworkshop/wisp-js/server - version: link:@mercuryworkshop/wisp-js/server + '@mercuryworkshop/wisp-js': + specifier: 'catalog:' + version: 0.4.1 tar: specifier: ^7.5.1 version: 7.5.1 @@ -103,6 +103,9 @@ importers: '@mercuryworkshop/rpc': specifier: workspace:* version: link:../rpc + '@types/serviceworker': + specifier: ^0.0.197 + version: 0.0.197 packages/core: dependencies: @@ -1168,6 +1171,9 @@ packages: '@types/serviceworker@0.0.160': resolution: {integrity: sha512-ZfHcjggZ7g+I8K1OndpSJCJmXAzTDGmnDzXhBioM2j+9H9ZeCEa1bDlDRI69Ike+3gPUgaUt6VxfMrBN2ItSRg==} + '@types/serviceworker@0.0.197': + resolution: {integrity: sha512-PaeOFYHcR2c7guBn9M4Y5H1++snluHYzZ6DzzRCUf6kue2FFfpTjF82aZq31DJ2c/Qyb3KGf5ROQH/fOU8NdxQ==} + '@types/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} @@ -5099,6 +5105,8 @@ snapshots: '@types/serviceworker@0.0.160': {} + '@types/serviceworker@0.0.197': {} + '@types/sockjs@0.3.36': dependencies: '@types/node': 24.9.1 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c80b418..502a9908 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -369,9 +369,9 @@ importers: packages/scramjet/packages/bootstrap: dependencies: - server: - specifier: link:@mercuryworkshop/wisp-js/server - version: link:@mercuryworkshop/wisp-js/server + '@mercuryworkshop/wisp-js': + specifier: 'catalog:' + version: 0.4.1 tar: specifier: ^7.5.1 version: 7.5.1 @@ -404,6 +404,9 @@ importers: '@mercuryworkshop/rpc': specifier: workspace:* version: link:../rpc + '@types/serviceworker': + specifier: ^0.0.197 + version: 0.0.197 packages/scramjet/packages/core: dependencies: @@ -2597,6 +2600,9 @@ packages: '@types/serviceworker@0.0.160': resolution: {integrity: sha512-ZfHcjggZ7g+I8K1OndpSJCJmXAzTDGmnDzXhBioM2j+9H9ZeCEa1bDlDRI69Ike+3gPUgaUt6VxfMrBN2ItSRg==} + '@types/serviceworker@0.0.197': + resolution: {integrity: sha512-PaeOFYHcR2c7guBn9M4Y5H1++snluHYzZ6DzzRCUf6kue2FFfpTjF82aZq31DJ2c/Qyb3KGf5ROQH/fOU8NdxQ==} + '@types/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} @@ -9171,6 +9177,8 @@ snapshots: '@types/serviceworker@0.0.160': {} + '@types/serviceworker@0.0.197': {} + '@types/sockjs@0.3.36': dependencies: '@types/node': 25.5.0