1 |
|
2 | Object.freeze((obj => {
|
3 | const properties = new Set;
|
4 | let currentObj = obj;
|
5 | do {
|
6 | Object.getOwnPropertyNames(currentObj).forEach((item => {
|
7 | "function" == typeof currentObj[item] && properties.add(item);
|
8 | }));
|
9 | } while ((currentObj = Object.getPrototypeOf(currentObj)) !== Object.prototype);
|
10 | return Array.from(properties);
|
11 | })([]));
|
12 |
|
13 | const resolves = new Map;
|
14 |
|
15 | const swMessageError = (accessReq, $error$) => ({
|
16 | $msgId$: accessReq.$msgId$,
|
17 | $error$: $error$
|
18 | });
|
19 |
|
20 | const httpRequestFromWebWorker = req => new Promise((async resolve => {
|
21 | const accessReq = await req.clone().json();
|
22 | const responseData = await (accessReq => new Promise((async resolve => {
|
23 | const clients = await self.clients.matchAll();
|
24 | const client = ((clients, msgId) => {
|
25 | const tabId = msgId.split(".").pop();
|
26 | let client = clients.find((a => a.url.endsWith(`?${tabId}`)));
|
27 | client || (client = [ ...clients ].sort(((a, b) => a.url > b.url ? -1 : a.url < b.url ? 1 : 0))[0]);
|
28 | return client;
|
29 | })([ ...clients ], accessReq.$msgId$);
|
30 | if (client) {
|
31 | const timeout = 12e4;
|
32 | const msgResolve = [ resolve, setTimeout((() => {
|
33 | resolves.delete(accessReq.$msgId$);
|
34 | resolve(swMessageError(accessReq, "Timeout"));
|
35 | }), timeout) ];
|
36 | resolves.set(accessReq.$msgId$, msgResolve);
|
37 | client.postMessage(accessReq);
|
38 | } else {
|
39 | resolve(swMessageError(accessReq, "NoParty"));
|
40 | }
|
41 | })))(accessReq);
|
42 | resolve(response(JSON.stringify(responseData), "application/json"));
|
43 | }));
|
44 |
|
45 | const response = (body, contentType) => new Response(body, {
|
46 | headers: {
|
47 | "content-type": contentType || "text/html",
|
48 | "Cache-Control": "no-store"
|
49 | }
|
50 | });
|
51 |
|
52 | self.oninstall = () => self.skipWaiting();
|
53 |
|
54 | self.onactivate = () => self.clients.claim();
|
55 |
|
56 | self.onmessage = ev => {
|
57 | const accessRsp = ev.data;
|
58 | const r = resolves.get(accessRsp.$msgId$);
|
59 | if (r) {
|
60 | resolves.delete(accessRsp.$msgId$);
|
61 | clearTimeout(r[1]);
|
62 | r[0](accessRsp);
|
63 | }
|
64 | };
|
65 |
|
66 | self.onfetch = ev => {
|
67 | const req = ev.request;
|
68 | const url = new URL(req.url);
|
69 | const pathname = url.pathname;
|
70 | if (pathname.endsWith("sw.html")) {
|
71 | ev.respondWith(response('<!DOCTYPE html><html><head><meta charset="utf-8"><script src="./partytown-sandbox-sw.js?v=0.10.2"><\/script></head></html>'));
|
72 | } else {
|
73 | pathname.endsWith("proxytown") && ev.respondWith(httpRequestFromWebWorker(req));
|
74 | }
|
75 | };
|