Frontend Labs
⋯

public/js/lib/errors.js

// Global error capture, installed at page load (§83): what an error-tracking
// SDK such as Sentry does first, minus the network upload.
export const captured = [];
const listeners = new Set();
export const onCaptured = (fn) => (listeners.add(fn), () => listeners.delete(fn));

function record(kind, detail) {
  captured.unshift({ kind, at: performance.now(), ...detail });
  captured.length = Math.min(captured.length, 30);
  listeners.forEach((fn) => fn(captured));
}

addEventListener("error", (e) =>
  record("error", { message: e.message, where: `${e.filename?.split("/").pop()}:${e.lineno}:${e.colno}`, stack: e.error?.stack }),
);
addEventListener("unhandledrejection", (e) =>
  record("unhandledrejection", { message: String(e.reason?.message ?? e.reason), stack: e.reason?.stack }),
);
// Fired by the browser whenever the page's CSP blocks something.
addEventListener("securitypolicyviolation", (e) =>
  record("csp", { message: `${e.effectiveDirective} blocked ${e.blockedURI || "inline"}`, where: `${e.sourceFile?.split("/").pop() ?? "?"}:${e.lineNumber}` }),
);
// Deprecations and browser interventions, reported by the browser itself.
if ("ReportingObserver" in window) {
  new ReportingObserver((reports) => {
    // csp-violation reports duplicate the event above; they show the other channel.
    for (const r of reports) {
      const b = r.body ?? {};
      record(`report:${r.type}`, { message: b.message ?? `${b.effectiveDirective ?? ""} ${b.blockedURL ?? ""}`.trim() });
    }
  }, { buffered: true }).observe();
}

Generated from SOURCE.md · 8 Oct 2026 16:36