1515 *
1616 */
1717
18- import { firebase } from '@react-native-firebase/app ' ;
18+ import { firebase } from '. ' ;
1919import { isError , once } from '@react-native-firebase/app/lib/common' ;
20+ // @ts -ignore - No declaration file for promise/setimmediate/rejection-tracking
2021import tracking from 'promise/setimmediate/rejection-tracking' ;
2122import StackTrace from 'stacktrace-js' ;
22-
2323export const FATAL_FLAG = 'com.firebase.crashlytics.reactnative.fatal' ;
2424
25- export function createNativeErrorObj ( error , stackFrames , isUnhandledRejection , jsErrorName ) {
26- const nativeObj = { } ;
25+ interface NativeErrorFrame {
26+ src : string ;
27+ line : number ;
28+ col : number ;
29+ fn : string ;
30+ file : string ;
31+ }
32+
33+ interface NativeErrorObj {
34+ message : string ;
35+ isUnhandledRejection : boolean ;
36+ frames : NativeErrorFrame [ ] ;
37+ }
2738
28- nativeObj . message = `${ error . message } ` ;
29- nativeObj . isUnhandledRejection = isUnhandledRejection ;
39+ interface NativeModule {
40+ isCrashlyticsCollectionEnabled : boolean ;
41+ isErrorGenerationOnJSCrashEnabled : boolean ;
42+ isCrashlyticsJavascriptExceptionHandlerChainingEnabled : boolean ;
43+ logPromise ( message : string ) : Promise < void > ;
44+ setAttribute ( name : string , value : string ) : Promise < void > ;
45+ recordErrorPromise ( errorObj : NativeErrorObj ) : Promise < void > ;
46+ crashWithStackPromise ( errorObj : NativeErrorObj ) : Promise < void > ;
47+ }
3048
31- nativeObj . frames = [ ] ;
49+ export function createNativeErrorObj (
50+ error : Error ,
51+ stackFrames : StackTrace . StackFrame [ ] ,
52+ isUnhandledRejection : boolean ,
53+ jsErrorName ?: string ,
54+ ) : NativeErrorObj {
55+ const nativeObj : NativeErrorObj = {
56+ message : `${ error . message } ` ,
57+ isUnhandledRejection,
58+ frames : [ ] ,
59+ } ;
3260
3361 if ( jsErrorName ) {
3462 // Option to fix crashlytics display and alerting. You can add an error name to the recordError function
@@ -42,7 +70,10 @@ export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, j
4270 }
4371
4472 for ( let i = 0 ; i < stackFrames . length ; i ++ ) {
45- const { columnNumber, lineNumber, fileName, functionName, source } = stackFrames [ i ] ;
73+ const frame = stackFrames [ i ] ;
74+ if ( ! frame ) continue ;
75+
76+ const { columnNumber, lineNumber, fileName, functionName, source } = frame ;
4677 let fileNameParsed = '<unknown>' ;
4778 if ( fileName ) {
4879 const subStrLen = fileName . indexOf ( '?' ) ;
@@ -54,7 +85,7 @@ export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, j
5485 }
5586
5687 nativeObj . frames . push ( {
57- src : source ,
88+ src : source || '<unknown>' ,
5889 line : lineNumber || 0 ,
5990 col : columnNumber || 0 ,
6091 fn : functionName || '<unknown>' ,
@@ -65,10 +96,10 @@ export function createNativeErrorObj(error, stackFrames, isUnhandledRejection, j
6596 return nativeObj ;
6697}
6798
68- export const setGlobalErrorHandler = once ( nativeModule => {
99+ export const setGlobalErrorHandler = once ( ( nativeModule : NativeModule ) => {
69100 const originalHandler = ErrorUtils . getGlobalHandler ( ) ;
70101
71- async function handler ( error , fatal ) {
102+ async function handler ( error : unknown , fatal ?: boolean ) {
72103 // If collection is disabled, just forward to the original handler
73104 if ( ! nativeModule . isCrashlyticsCollectionEnabled ) {
74105 return originalHandler ( error , fatal ) ;
@@ -89,7 +120,7 @@ export const setGlobalErrorHandler = once(nativeModule => {
89120 // For that reason we always round up (`.ceil`) and add a second in case of latency
90121 //
91122 // Time is specified as seconds since start of Unix epoch as a baseline, as a string
92- const fatalTime = Math . ceil ( new Date ( ) / 1000 ) + 1 + '' ;
123+ const fatalTime = Math . ceil ( new Date ( ) . getTime ( ) / 1000 ) + 1 + '' ;
93124
94125 // Flag the Crashlytics backend that we have a fatal error, they will transform it
95126 await nativeModule . setAttribute ( FATAL_FLAG , fatalTime ) ;
@@ -107,6 +138,7 @@ export const setGlobalErrorHandler = once(nativeModule => {
107138 // Did not matter if I did named imports above or dynamic require here.
108139 // So temporarily reverting and silencing warnings instead
109140 globalThis . RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = true ;
141+ // @ts -ignore - analytics types not available in crashlytics
110142 await firebase . app ( ) . analytics ( ) . logEvent (
111143 'app_exception' , // 'app_exception' is reserved but we make an exception for JS->fatal transforms
112144 {
@@ -143,8 +175,8 @@ export const setGlobalErrorHandler = once(nativeModule => {
143175 return handler ;
144176} ) ;
145177
146- export const setOnUnhandledPromiseRejectionHandler = once ( nativeModule => {
147- async function onUnhandled ( _id , error ) {
178+ export const setOnUnhandledPromiseRejectionHandler = once ( ( nativeModule : NativeModule ) => {
179+ async function onUnhandled ( _id : number , error : Error ) {
148180 if ( ! __DEV__ ) {
149181 // TODO(salakar): Option to disable
150182 try {
0 commit comments