XuqmGroup-RNSDK/packages/bugcollect/src/capture/ErrorCapture.ts

52 行
2.0 KiB
TypeScript

/**
* ErrorCapture — hooks into the RN global error handler and unhandled promise
* rejections to automatically forward errors to BugCollect.captureError.
*/
// React Native exposes ErrorUtils on the global object
declare const ErrorUtils: {
getGlobalHandler(): ((error: Error, isFatal?: boolean) => void) | null
setGlobalHandler(handler: (error: Error, isFatal?: boolean) => void): void
}
// React Native / Hermes exposes onunhandledrejection on globalThis
type UnhandledRejectionHandler = ((event: { reason: unknown }) => void) | null | undefined
let previousErrorHandler: ((error: Error, isFatal?: boolean) => void) | null = null
let previousUnhandledHandler: UnhandledRejectionHandler = null
let started = false
export const ErrorCapture = {
start(onError: (error: unknown, meta?: Record<string, unknown>) => void): void {
if (started) return
started = true
// JS global error handler
previousErrorHandler = typeof ErrorUtils !== 'undefined' ? ErrorUtils.getGlobalHandler() : null
if (typeof ErrorUtils !== 'undefined') {
ErrorUtils.setGlobalHandler((error, isFatal) => {
onError(error, { isFatal: isFatal ?? false })
previousErrorHandler?.(error, isFatal)
})
}
// Unhandled Promise rejection
const g = globalThis as unknown as Record<string, unknown>
previousUnhandledHandler = (g['onunhandledrejection'] as UnhandledRejectionHandler) ?? null
g['onunhandledrejection'] = (event: { reason: unknown }) => {
onError(event.reason, { type: 'unhandledRejection' })
previousUnhandledHandler?.(event)
}
},
stop(): void {
if (!started) return
if (typeof ErrorUtils !== 'undefined') {
ErrorUtils.setGlobalHandler(previousErrorHandler ?? (() => undefined))
}
const g = globalThis as unknown as Record<string, unknown>
g['onunhandledrejection'] = previousUnhandledHandler ?? null
previousErrorHandler = null
previousUnhandledHandler = null
started = false
},
}