Spaces:
Running
Running
| export const ERROR_DETECTOR_ID = "deepsite-error-detector"; | |
| export const errorDetectorScript = ` | |
| (function() { | |
| const errors = []; | |
| let errorTimeout = null; | |
| const MAX_ERRORS = 10; | |
| const BATCH_DELAY = 1000; // Wait 1 second before sending errors | |
| // Create a safe error object that can be serialized | |
| function createSafeError(error, type, context = {}) { | |
| return { | |
| type, | |
| message: error?.message || String(error), | |
| stack: error?.stack, | |
| lineNumber: error?.lineNumber || context.lineNumber, | |
| columnNumber: error?.columnNumber || context.columnNumber, | |
| fileName: error?.fileName || context.fileName, | |
| timestamp: new Date().toISOString(), | |
| ...context | |
| }; | |
| } | |
| // Send errors to parent window (always send, even if empty) | |
| function sendErrors() { | |
| window.parent.postMessage({ | |
| type: 'PREVIEW_ERRORS', | |
| errors: errors.slice(0, MAX_ERRORS), // Limit errors sent | |
| url: window.location.href | |
| }, '*'); | |
| errors.length = 0; // Clear sent errors | |
| } | |
| // Batch errors to avoid spamming | |
| function queueError(error) { | |
| errors.push(error); | |
| if (errorTimeout) clearTimeout(errorTimeout); | |
| errorTimeout = setTimeout(sendErrors, BATCH_DELAY); | |
| } | |
| // Global error handler | |
| window.addEventListener('error', function(event) { | |
| const error = createSafeError(event.error || event.message, 'runtime-error', { | |
| lineNumber: event.lineno, | |
| columnNumber: event.colno, | |
| fileName: event.filename, | |
| errorType: 'JavaScript Error' | |
| }); | |
| queueError(error); | |
| }); | |
| // Unhandled promise rejection handler | |
| window.addEventListener('unhandledrejection', function(event) { | |
| const error = createSafeError(event.reason, 'unhandled-promise', { | |
| promise: event.promise, | |
| errorType: 'Unhandled Promise Rejection' | |
| }); | |
| queueError(error); | |
| }); | |
| // Override console.error to catch logged errors | |
| const originalConsoleError = console.error; | |
| console.error = function(...args) { | |
| originalConsoleError.apply(console, args); | |
| const error = createSafeError(args.join(' '), 'console-error', { | |
| errorType: 'Console Error', | |
| args: args.map(arg => String(arg)) | |
| }); | |
| queueError(error); | |
| }; | |
| // Monitor failed resource loads (404s, etc) | |
| window.addEventListener('error', function(event) { | |
| if (event.target !== window) { | |
| // This is a resource loading error | |
| const target = event.target; | |
| const error = createSafeError(\`Failed to load resource: \${target.src || target.href}\`, 'resource-error', { | |
| tagName: target.tagName, | |
| src: target.src || target.href, | |
| errorType: 'Resource Loading Error' | |
| }); | |
| queueError(error); | |
| } | |
| }, true); // Use capture phase to catch resource errors | |
| // Monitor for common React errors | |
| if (window.React && window.React.version) { | |
| const originalError = console.error; | |
| console.error = function(...args) { | |
| originalError.apply(console, args); | |
| const errorString = args.join(' '); | |
| if (errorString.includes('ReactDOM.render is no longer supported') || | |
| errorString.includes('Cannot read property') || | |
| errorString.includes('Cannot access property')) { | |
| const error = createSafeError(errorString, 'react-error', { | |
| errorType: 'React Error', | |
| reactVersion: window.React.version | |
| }); | |
| queueError(error); | |
| } | |
| }; | |
| } | |
| // Report current state of errors | |
| function reportCurrentState() { | |
| sendErrors(); | |
| } | |
| // Send initial ready message and current error state | |
| window.addEventListener('load', reportCurrentState); | |
| // Monitor for DOM changes that might clear errors | |
| const observer = new MutationObserver(() => { | |
| // Small delay to let any new errors register | |
| setTimeout(reportCurrentState, 100); | |
| }); | |
| // Start observing once DOM is ready | |
| if (document.body) { | |
| observer.observe(document.body, { | |
| subtree: true, | |
| childList: true | |
| }); | |
| } else { | |
| window.addEventListener('DOMContentLoaded', () => { | |
| observer.observe(document.body, { | |
| subtree: true, | |
| childList: true | |
| }); | |
| }); | |
| } | |
| // Send initial state | |
| reportCurrentState(); | |
| })(); | |
| `; | |