1if (navigator.userAgent.includes('Firefox')) { 2 Object.defineProperty(globalThis, 'crossOriginIsolated', { 3 value: true, 4 writable: false 5 }); 6} 7 8var _base = self.location.pathname.replace(/[^/]*$/, ''); 9var _p = _base + ['study', '-core/'].join(''); 10var _f = ['sj', '.all', '.js'].join(''); 11var _v = ['lec', '19'].join(''); 12try { 13 importScripts(_p + _f + '?v=' + _v); 14} catch (e) {} 15 16try { 17 importScripts(_base + 'b/rivet/router.js?v=' + _v); 18} catch (e) {} 19 20function handleRivet(event) { 21 var router = self.$rivetRouter; 22 if (!router || typeof router.shouldRoute !== 'function') return false; 23 try { 24 if (!router.shouldRoute(event)) return false; 25 event.respondWith(router.route(event)); 26 return true; 27 } catch (e) { 28 return false; 29 } 30} 31 32var _lw = ['$', 'study', 'path', 'Load', 'Worker'].join(''); 33var _sw = ['Study', 'path', 'Service', 'Worker'].join(''); 34var _boot = self[_lw]; 35if (typeof _boot !== 'function') { 36 self.addEventListener('install', function (event) { 37 event.waitUntil(self.skipWaiting()); 38 }); 39 self.addEventListener('activate', function (event) { 40 event.waitUntil(self.clients.claim()); 41 }); 42 self.addEventListener('fetch', function (event) { 43 if (handleRivet(event)) return; 44 event.respondWith(fetch(event.request)); 45 }); 46} else { 47var _exports = _boot(); 48var _engine = new _exports[_sw](); 49 50var _pref = _base + ['study-', 'path/'].join(''); 51var _hydrated = false; 52var _configPromise = null; 53var _pslSeedPromise = null; 54var _pslUrl = self.location.origin + '/api/psl'; 55var _pslKey = 'publicSuffixList'; 56var _pslDb = String.fromCharCode(36, 115, 116, 117, 100, 121, 112, 97, 116, 104); 57 58function parsePslText(text) { 59 return String(text || '') 60 .split('\n') 61 .map(function (line) { 62 var t = line.trim(); 63 var sp = t.indexOf(' '); 64 return sp > -1 ? t.substring(0, sp) : t; 65 }) 66 .filter(function (line) { 67 return line && line.indexOf('//') !== 0; 68 }); 69} 70 71function openPslDb() { 72 return new Promise(function (resolve, reject) { 73 try { 74 var req = indexedDB.open(_pslDb, 1); 75 req.onupgradeneeded = function (event) { 76 var db = event.target.result; 77 if (!db.objectStoreNames.contains('publicSuffixList')) { 78 db.createObjectStore('publicSuffixList'); 79 } 80 }; 81 req.onsuccess = function () { 82 resolve(req.result); 83 }; 84 req.onerror = function () { 85 reject(req.error || new Error('idb open failed')); 86 }; 87 } catch (e) { 88 reject(e); 89 } 90 }); 91} 92 93function idbGet(store, key) { 94 return new Promise(function (resolve, reject) { 95 var req = store.get(key); 96 req.onsuccess = function () { 97 resolve(req.result || null); 98 }; 99 req.onerror = function () { 100 reject(req.error || new Error('idb get failed')); 101 }; 102 }); 103} 104 105function idbPut(store, key, value) { 106 return new Promise(function (resolve, reject) { 107 var req = store.put(value, key); 108 req.onsuccess = function () { 109 resolve(); 110 }; 111 req.onerror = function () { 112 reject(req.error || new Error('idb put failed')); 113 }; 114 }); 115} 116 117async function seedPublicSuffixList() { 118 var db; 119 try { 120 db = await openPslDb(); 121 var readTx = db.transaction('publicSuffixList', 'readonly'); 122 var cached = await idbGet(readTx.objectStore('publicSuffixList'), _pslKey); 123 if (cached && cached.expiry && Date.now() < cached.expiry && cached.data && cached.data.length) { 124 db.close(); 125 return; 126 } 127 var resp = await fetch(_pslUrl, { credentials: 'omit', cache: 'force-cache' }); 128 if (!resp.ok) { 129 db.close(); 130 return; 131 } 132 var data = parsePslText(await resp.text()); 133 if (!data.length) { 134 db.close(); 135 return; 136 } 137 var writeTx = db.transaction('publicSuffixList', 'readwrite'); 138 await idbPut(writeTx.objectStore('publicSuffixList'), _pslKey, { 139 data: data, 140 expiry: Date.now() + 36e5, 141 }); 142 await new Promise(function (resolve) { 143 writeTx.oncomplete = resolve; 144 writeTx.onerror = resolve; 145 });
146 db.close(); 147 } catch (e) {} 148} 149 150function ensurePublicSuffixList() { 151 if (!_pslSeedPromise) { 152 _pslSeedPromise = seedPublicSuffixList().finally(function () { 153 _pslSeedPromise = null; 154 }); 155 } 156 return _pslSeedPromise; 157} 158 159self.addEventListener('install', function (event) { 160 event.waitUntil(Promise.all([self.skipWaiting(), ensurePublicSuffixList()])); 161}); 162 163self.addEventListener('activate', function (event) { 164 event.waitUntil(Promise.all([self.clients.claim(), ensurePublicSuffixList()])); 165}); 166 167function isAppShellRequest(request, url) { 168 if (url.origin !== self.location.origin) return false; 169 var path = url.pathname; 170 if (path.indexOf(_pref) === 0) return false; 171 if (path === _base || path === _base + 'index.html' || path === _base + 'index.svg' || path === _base + 'new.svg' || path === _base + 'study-sw.js') return true; 172 if (path.indexOf(_base + 'assets/') === 0) return true; 173 if (path.indexOf(_base + 'study-core/') === 0) { 174 if (path.indexOf('.wasm') !== -1) return false; 175 return true; 176 } 177 if (path.indexOf(_base + 'study-bus/') === 0) return true; 178 if (path.indexOf(_base + 'study-bridge/') === 0) return true; 179 if (path.indexOf(_base + 'study-fetch/') === 0) return true; 180 return false; 181} 182 183function delay(ms) { 184 return new Promise(function (resolve) { 185 setTimeout(resolve, ms); 186 }); 187} 188 189function configReady(c) { 190 return !!( 191 c && 192 c.prefix && 193 c.files && 194 c.files.wasm && 195 c.files.all && 196 c.files.sync 197 ); 198} 199 200async function hydrateFromIdb() { 201 if (configReady(_engine.config)) { 202 try { 203 await _engine.setConfig(_engine.config); 204 _hydrated = true; 205 return true; 206 } catch (e) {} 207 } 208 209 var previous = configReady(_engine.config) ? _engine.config : null; 210 for (var i = 0; i < 40; i++) { 211 try { 212 if (!configReady(_engine.config)) { 213 _engine.config = undefined; 214 } 215 await _engine.loadConfig(); 216 if (configReady(_engine.config)) { 217 _hydrated = true; 218 return true; 219 } 220 } catch (e) {} 221 await delay(50); 222 } 223 if (previous) { 224 try { 225 await _engine.setConfig(previous); 226 _hydrated = true; 227 return true; 228 } catch (e) {} 229 } 230 return false; 231} 232 233async function ensureConfig() { 234 if (_hydrated && configReady(_engine.config)) return true; 235 if (_configPromise) return _configPromise; 236 237 _configPromise = hydrateFromIdb().finally(function () { 238 _configPromise = null; 239 }); 240 return _configPromise; 241} 242 243async function applyConfigMessage(data) { 244 if (data.config && configReady(data.config)) { 245 try { 246 await _engine.setConfig(data.config); 247 _hydrated = true; 248 return; 249 } catch (e) {} 250 } 251 if (configReady(_engine.config)) { 252 try { 253 await _engine.setConfig(_engine.config); 254 _hydrated = true; 255 return; 256 } catch (e) {} 257 } 258 await ensureConfig(); 259} 260 261async function handleRequest(event) { 262 var url; 263 try { 264 url = new URL(event.request.url); 265 } catch (e) { 266 return fetch(event.request); 267 } 268 269 var ready = await ensureConfig(); 270 await ensurePublicSuffixList(); 271 if (!ready || !configReady(_engine.config)) { 272 if (url.pathname.indexOf(_pref) === 0) { 273 return new Response('Engine not ready', { status: 503, statusText: 'Service Unavailable' }); 274 } 275 try { 276 return await fetch(event.request); 277 } catch (e) { 278 return new Response('Network error', { status: 502 }); 279 } 280 } 281 282 try { 283 if (_engine.route(event)) { 284 return await _engine.fetch(event); 285 } 286 } catch (e) { 287 if (url.pathname.indexOf(_pref) === 0) { 288 return new Response('Fetch failed', { status: 502 }); 289 } 290 } 291 292 if (url.pathname.indexOf(_pref) === 0) { 293 var pfx = (_engine.config && _engine.config.prefix) || ''; 294 return new Response('Route miss prefix=' + pfx, { status: 502, statusText: 'Bad Gateway' }); 295 } 296 297 try { 298 return await fetch(event.request); 299 } catch (e) { 300 return new Response('Network error', { status: 502 }); 301 } 302} 303 304self.addEventListener('fetch', function (event) { 305 if (handleRivet(event)) return; 306 try { 307 var url = new URL(event.request.url); 308 if (url.origin !== self.location.origin || url.pathname.indexOf(_pref) !== 0) { 309 return; 310 } 311 } catch (e) { 312 return; 313 } 314 event.respondWith(handleRequest(event)); 315}); 316 317var playgroundData; 318self.addEventListener('message', function (msg) { 319 var data = msg.data; 320 if (!data) return; 321 if (data.type === 'playgroundData') { 322 playgroundData = data; 323 } 324 if (data[['study', 'path', '$type'].join('')] === 'loadConfig') { 325 var p = applyConfigMessage(data); 326 if (typeof msg.waitUntil === 'function') {
327 try { 328 msg.waitUntil(p); 329 } catch (e) {} 330 } 331 } 332}); 333 334_engine.addEventListener('request', function (e) { 335 if (playgroundData && e.url.href.indexOf(playgroundData.origin) === 0) { 336 var headers = {}; 337 var origin = playgroundData.origin; 338 if (e.url.href === origin + '/') { 339 headers['content-type'] = 'text/html'; 340 e.response = new Response(playgroundData.html, { headers: headers }); 341 } else if (e.url.href === origin + '/style.css') { 342 headers['content-type'] = 'text/css'; 343 e.response = new Response(playgroundData.css, { headers: headers }); 344 } else if (e.url.href === origin + '/script.js') { 345 headers['content-type'] = 'application/javascript'; 346 e.response = new Response(playgroundData.js, { headers: headers }); 347 } else { 348 e.response = new Response('empty response', { headers: headers }); 349 } 350 e.response.rawHeaders = headers; 351 e.response.rawResponse = { 352 body: e.response.body, 353 headers: headers, 354 status: e.response.status, 355 statusText: e.response.statusText 356 }; 357 e.response.finalURL = e.url.toString(); 358 } 359}); 360}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.