>. Without this assignment its `typeof` guard silently resolves // null and the boot_stall beacon never fires (the frozen-splash class // becomes invisible in Loki). Regression-guarded by // src/__tests__/web/boot_stall_beacon_wiring_test.ts. window.__chippSendError = sendError; // True once the app's own error handling is live. Two signals, in // trust order: // 1. __chippClientErrorsReady -- ErrorBoundary.svelte attached its // window handlers (set in its onMount; ErrorBoundary is the // unconditional top-level wrapper in App.svelte, and its onMount // fires before App.svelte's). This closes the former dead zone // between Svelte's first render and ErrorBoundary attaching: // the old "#app has children" check flipped this off at first // DOM insertion, so a synchronous error thrown mid-mount (e.g. // in a child component's onMount) was reported by NEITHER layer. // 2. __chippBootStage === "app-booted" -- App.svelte finished boot. // // Deliberately NO "#app has children" fallback: index.html and its // main bundle ship as one build (hashed refs), so a bundle that // renders children but never sets either flag cannot pair with this // file -- and keeping the fallback would re-open the mid-mount dead // zone it used to cause. function appHasBooted() { if (window.__chippClientErrorsReady) return true; return window.__chippBootStage === "app-booted"; } // Diagnostics for chunk-load beacons: which asset failed, was it the // boot-blocking entry doc (assets/main-*.js / assets/share-*.js -- // every visitor mid-load is stuck, urgent) or a lazy dynamic-import // route chunk (normal, self-healing deploy churn), and (best-effort) // what HTTP status the browser saw. Mirrors the pure, unit-tested // implementation in web/src/lib/utils/chunk-diagnostics.ts -- kept as // plain ES5 here because this runs before any module can be imported. var ENTRY_CHUNK_RE = /^(?:main|share)-[A-Za-z0-9_-]{8}\.js$/; var ENTRY_CHUNK_LEGACY_RE = /^(?:main|share)\.[a-f0-9]{8}\.js$/; function chunkBasename(pathOrUrl) { var noQuery = String(pathOrUrl || "").split(/[?#]/)[0]; var parts = noQuery.split("/"); return parts[parts.length - 1] || noQuery; } function chunkDiagnostics(assetUrl) { var diag = {}; if (!assetUrl) return diag; var base = chunkBasename(assetUrl); diag.chunkKind = (ENTRY_CHUNK_RE.test(base) || ENTRY_CHUNK_LEGACY_RE.test(base)) ? "entry" : "dynamic"; try { if (typeof performance !== "undefined" && typeof performance.getEntriesByName === "function") { var entries = performance.getEntriesByName(assetUrl); var status = entries[0] && entries[0].responseStatus; if (typeof status === "number" && status > 0) diag.httpStatus = status; } } catch (e) { /* Resource Timing L2 unsupported -- status stays unknown */ } return diag; } // Handle Vite module preload errors ( failures). // iOS Safari fires vite:preloadError but NOT unhandledrejection for // preload failures, so this handler is critical for that browser. // Registering in before the entry module ensures it fires even // if main.ts never boots. window.addEventListener("vite:preloadError", function(event) { event.preventDefault(); var src = (event.payload && event.payload.src) || "unknown"; sendError("ChunkLoadError", "Importing a module script failed: " + src, "chunk_load_error", Object.assign({ event: "vite:preloadError", assetUrl: src }, chunkDiagnostics(src))); tryChunkReload("Module preload"); }); // Handle
Loading