1// Similar interface to the one used in expo modules. 2type CodedError = Error & { code?: string }; 3 4let isErrorHandlingEnabled = true; 5let wasHit = false; // whether the original error handler was called 6 7const unavailableErrorPossibleSolutions = `Some possible solutions: 8- Make sure that the method is available on the current platform. 9- Make sure you're using the newest available version of this development client. 10- Make sure you're running a compatible version of your JavaScript code. 11- If you've installed a new library recently, you may need to make a new development client build.`; 12 13const moduleIsMissingPossibleSolutions = `Some possible solutions: 14- Make sure you're using the newest available version of this development client. 15- Make sure you're running a compatible version of your JavaScript code. 16- If you've installed a new library recently, you may need to make a new development client build.`; 17 18function customizeUnavailableMessage(error: CodedError) { 19 error.message += '\n\n' + unavailableErrorPossibleSolutions; 20} 21 22function customizeModuleIsMissingMessage(error: Error) { 23 error.message = `Your JavaScript code tried to access a native module that doesn't exist in this development client. 24 25${moduleIsMissingPossibleSolutions}`; 26} 27 28function customizeError(error: Error | CodedError) { 29 if ('code' in error) { 30 // It's a CodedError from expo modules 31 switch (error.code) { 32 case 'ERR_UNAVAILABLE': { 33 customizeUnavailableMessage(error); 34 break; 35 } 36 } 37 } else if ( 38 error.message.includes('Native module cannot be null') || // RN 0.64 and below message 39 error.message.includes('`new NativeEventEmitter()` requires a non-null argument.') // RN 0.65+ message 40 ) { 41 customizeModuleIsMissingMessage(error); 42 } 43} 44 45function errorHandler(originalHandler, error, isFatal) { 46 if (error instanceof Error) { 47 // Suppresses `"main" has not been registered` error only if it was caused by a different error. 48 // Otherwise, we want to show it, cause the user may forget to call `AppRegistry.registerComponent`. 49 if (wasHit && error.message?.includes('has not been registered. This can happen if')) { 50 return; 51 } 52 customizeError(error); 53 } 54 55 wasHit = true; 56 originalHandler(error, isFatal); 57} 58 59export function createErrorHandler(originalHandler) { 60 return (error, isFatal) => { 61 if (isErrorHandlingEnabled) { 62 errorHandler(originalHandler, error, isFatal); 63 return; 64 } 65 66 originalHandler(error, isFatal); 67 }; 68} 69 70export function disableErrorHandling() { 71 isErrorHandlingEnabled = false; 72} 73