1(() => { 2 try { 3 const config = window.GraphekMonitorErrors; 4 5 if (!config) { 6 return; 7 } 8 9 const sent = new Set(); 10 11 // Eine Seite mit Fehler in einer Schleife soll den Endpunkt nicht mit 12 // Meldungen eindecken. Fünf verschiedene je Seitenaufruf genügen zur 13 // Diagnose. 14 let remaining = 5; 15 let sending = false; 16 const optionalHosts = new Set([ 17 'www.google-analytics.com', 18 'www.googletagmanager.com', 19 'pagead2.googlesyndication.com', 20 'googleads.g.doubleclick.net', 21 ]); 22 23 const boundedText = (value) => { 24 const prefix = value.slice(0, 500); 25 // Eine mitten in Zugangsdaten gekürzte URL sähe wie ein Hostname aus. 26 return value.length > 500 ? prefix.replace(/https?:\/\/[^\s<>"')]*$/i, '(URL)') : prefix; 27 }; 28 29 const safeText = (value) => { 30 try { 31 if (typeof value === 'string') return boundedText(value); 32 if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value).slice(0, 500); 33 if (value instanceof Error) { 34 const descriptor = Object.getOwnPropertyDescriptor(value, 'message'); 35 return typeof descriptor?.value === 'string' ? boundedText(descriptor.value) : ''; 36 } 37 } catch { 38 // Fremde Objekte können selbst bei einer Typprüfung werfen. 39 } 40 return ''; 41 }; 42 43 const ignored = (message, file) => { 44 if (/^(?:chrome|moz)-extension:\/\//i.test(file)) return true; 45 if (!/\bERR_BLOCKED_BY_CLIENT\b/.test(message)) return false; 46 const urls = message.match(/https?:\/\/[^\s<>"')]+/gi) || []; 47 if (file) urls.push(file); 48 if (urls.length === 0) return false; 49 return urls.every((value) => { 50 try { 51 const url = new URL(value, window.location.href); 52 return (url.protocol === 'http:' || url.protocol === 'https:') && optionalHosts.has(url.hostname.toLowerCase()); 53 } catch { 54 return false; 55 } 56 }); 57 }; 58 59 const cleanText = (message) => message 60 .replace(/\r?\n\s*at\s[\s\S]*$/, '') 61 .replace(/\s*Stack trace:[\s\S]*$/i, '') 62 .replace(/https?:\/\/[^\s<>"')]+/gi, (value) => { 63 try { 64 const url = new URL(value); 65 return `${url.origin}${url.pathname}`; 66 } catch { 67 return '(URL)'; 68 } 69 }).trim().slice(0, 500); 70 71 const send = (message, file, line) => { 72 if (sending) return; 73 message = safeText(message); 74 file = typeof file === 'string' ? boundedText(file) : ''; 75 if (ignored(message, file)) return; 76 message = cleanText(message); 77 if (file) { 78 try { 79 const url = new URL(file, window.location.href); 80 file = url.protocol === 'http:' || url.protocol === 'https:' ? `${url.origin}${url.pathname}`.slice(0, 500) : ''; 81 } catch { 82 file = ''; 83 } 84 } 85 line = typeof line === 'number' && Number.isFinite(line) ? Math.max(0, Math.floor(line)) : 0; 86 if (!message || message.toLowerCase() === 'script error.') return; 87 const key = `${message}|${file}|${line}`; 88 89 if (sent.has(key) || remaining <= 0) { 90 return; 91 } 92 93 sent.add(key); 94 remaining -= 1; 95 96 sending = true; 97 try { 98 fetch(config.endpoint, { 99 method: 'POST', 100 credentials: 'same-origin', 101 keepalive: true, 102 headers: { 103 'Content-Type': 'application/json', 104 'X-WP-Nonce': config.nonce, 105 }, 106 body: JSON.stringify({ 107 message, 108 file, 109 line, 110 request_path: window.location.pathname, 111 }), 112 }).catch(() => {}); 113 } catch { 114 // Auch ein ersetztes fetch darf den Seitenaufruf nicht beschädigen. 115 } finally { 116 sending = false;
117 } 118 }; 119 120 window.addEventListener('error', (event) => { 121 try { 122 if (event instanceof ErrorEvent) send(event.message, event.filename, event.lineno); 123 } catch { 124 // Die Erfassung bleibt für den Besucher unsichtbar. 125 } 126 }); 127 128 window.addEventListener('unhandledrejection', (event) => { 129 try { 130 send(safeText(event.reason), '', 0); 131 } catch { 132 // Ein fremder Reason-Getter darf nicht selbst einen Fehler auslösen. 133 } 134 }); 135 136 try { 137 const original = window.console?.error; 138 if (typeof original === 'function') { 139 window.console.error = function (...args) { 140 const result = Reflect.apply(original, this, args); 141 try { 142 if (!sending) send(args.slice(0, 8).map(safeText).filter(Boolean).join(' '), '', 0); 143 } catch { 144 // Keine Objekte serialisieren; die Originalausgabe bleibt erhalten. 145 } 146 return result; 147 }; 148 } 149 } catch { 150 // Nicht jede Website erlaubt das Ersetzen ihrer Konsolenfunktion. 151 } 152 } catch { 153 // Auch die Initialisierung darf fremde Skripte nicht unterbrechen. 154 } 155})();
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.