1/** 2 * Deduped script loader â prevents parallel duplicate <script src> loads (race â false onerror). 3 */ 4(function (global) { 5 'use strict'; 6 7 var inflight = Object.create(null); 8 var loaded = Object.create(null); 9 10 function scriptTypeAttr(opts) { 11 return opts && opts.type === 'module' ? 'module' : ''; 12 } 13 14 function findExistingScript(src, typeAttr) { 15 var existing = document.querySelector('script[src="' + src + '"]'); 16 if (!existing) return null; 17 var existingType = existing.getAttribute('type') || ''; 18 if (existingType === typeAttr) return existing; 19 return null; 20 } 21 22 function loadScriptOnce(src, opts) { 23 opts = opts || {}; 24 var markKey = opts.markKey || 'spaLoaded'; 25 var typeAttr = scriptTypeAttr(opts); 26 27 if (!src) return Promise.resolve(); 28 var loadKey = typeAttr ? src + '|' + typeAttr : src; 29 if (loaded[loadKey]) return Promise.resolve(); 30 if (inflight[loadKey]) return inflight[loadKey]; 31 32 inflight[loadKey] = new Promise(function (resolve, reject) { 33 var existing = findExistingScript(src, typeAttr); 34 if (existing) { 35 if (existing.dataset[markKey] === '1') { 36 loaded[loadKey] = true; 37 resolve(); 38 return; 39 } 40 if (existing.dataset[markKey] === 'error') { 41 reject(new Error('Failed to load ' + src)); 42 return; 43 } 44 function onLoad() { 45 existing.dataset[markKey] = '1'; 46 loaded[loadKey] = true; 47 resolve(); 48 } 49 function onError() { 50 existing.dataset[markKey] = 'error'; 51 reject(new Error('Failed to load ' + src)); 52 } 53 existing.addEventListener('load', onLoad, { once: true }); 54 existing.addEventListener('error', onError, { once: true }); 55 global.setTimeout(function () { 56 if (existing.dataset[markKey] === '1' || existing.dataset[markKey] === 'error') { 57 return; 58 } 59 onLoad(); 60 }, 0); 61 return; 62 } 63 64 var script = document.createElement('script'); 65 script.src = src; 66 script.async = false; 67 if (typeAttr) script.type = typeAttr; 68 script.onload = function () { 69 script.dataset[markKey] = '1'; 70 loaded[loadKey] = true; 71 delete inflight[loadKey]; 72 resolve(); 73 }; 74 script.onerror = function () { 75 script.dataset[markKey] = 'error'; 76 delete inflight[loadKey]; 77 reject(new Error('Failed to load ' + src)); 78 }; 79 (opts.parent || document.body).appendChild(script); 80 }); 81 82 return inflight[loadKey].catch(function (err) { 83 delete inflight[loadKey]; 84 throw err; 85 }); 86 } 87 88 function forgetScript(src, opts) { 89 opts = opts || {}; 90 var typeAttr = scriptTypeAttr(opts); 91 var loadKey = typeAttr ? src + '|' + typeAttr : src; 92 delete loaded[loadKey]; 93 delete inflight[loadKey]; 94 } 95 96 global.PupwifeScriptLoad = { 97 once: loadScriptOnce, 98 forget: forgetScript 99 }; 100})(typeof window !== 'undefined' ? window : this);
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.