[ReactNative] differentiate fatal and soft exceptions

This commit is contained in:
Spencer Ahrens 2015-05-13 10:56:09 -07:00 committed by Christopher Chedeau
parent 484f63b1db
commit 81ad810186
6 changed files with 57 additions and 15 deletions

View File

@ -25,12 +25,23 @@ type Exception = {
message: string; message: string;
} }
function reportException(e: Exception, stack?: any) { function reportException(e: Exception, isFatal: bool, stack?: any) {
if (RCTExceptionsManager) { if (RCTExceptionsManager) {
if (!stack) { if (!stack) {
stack = parseErrorStack(e); stack = parseErrorStack(e);
} }
RCTExceptionsManager.reportUnhandledException(e.message, stack); if (!RCTExceptionsManager.reportFatalException ||
!RCTExceptionsManager.reportSoftException) {
// Backwards compatibility - no differentiation
// TODO(#7049989): deprecate reportUnhandledException on Android
RCTExceptionsManager.reportUnhandledException(e.message, stack);
} else {
if (isFatal) {
RCTExceptionsManager.reportFatalException(e.message, stack);
} else {
RCTExceptionsManager.reportSoftException(e.message, stack);
}
}
if (__DEV__) { if (__DEV__) {
(sourceMapPromise = sourceMapPromise || loadSourceMap()) (sourceMapPromise = sourceMapPromise || loadSourceMap())
.then(map => { .then(map => {
@ -44,7 +55,7 @@ function reportException(e: Exception, stack?: any) {
} }
} }
function handleException(e: Exception) { function handleException(e: Exception, isFatal: boolean) {
var stack = parseErrorStack(e); var stack = parseErrorStack(e);
var msg = var msg =
'Error: ' + e.message + 'Error: ' + e.message +
@ -57,7 +68,7 @@ function handleException(e: Exception) {
} else { } else {
console.error(msg); console.error(msg);
} }
reportException(e, stack); reportException(e, isFatal, stack);
} }
/** /**
@ -78,7 +89,7 @@ function installConsoleErrorReporter() {
var str = Array.prototype.map.call(arguments, stringifySafe).join(', '); var str = Array.prototype.map.call(arguments, stringifySafe).join(', ');
var error: any = new Error('console.error: ' + str); var error: any = new Error('console.error: ' + str);
error.framesToPop = 1; error.framesToPop = 1;
reportException(error); reportException(error, /* isFatal */ false);
}; };
if (console.reportErrorsAsExceptions === undefined) { if (console.reportErrorsAsExceptions === undefined) {
console.reportErrorsAsExceptions = true; // Individual apps can disable this console.reportErrorsAsExceptions = true; // Individual apps can disable this

View File

@ -66,9 +66,9 @@ function setupDocumentShim() {
GLOBAL.MutationObserver = undefined; GLOBAL.MutationObserver = undefined;
} }
function handleErrorWithRedBox(e) { function handleErrorWithRedBox(e, isFatal) {
try { try {
require('ExceptionsManager').handleException(e); require('ExceptionsManager').handleException(e, isFatal);
} catch(ee) { } catch(ee) {
console.log('Failed to print error: ', ee.message); console.log('Failed to print error: ', ee.message);
} }

View File

@ -81,6 +81,14 @@ var REQUEST_PARAMSS = 2;
var RESPONSE_CBIDS = 3; var RESPONSE_CBIDS = 3;
var RESPONSE_RETURN_VALUES = 4; var RESPONSE_RETURN_VALUES = 4;
var applyWithErrorReporter = function(fun: Function, context: ?any, args: ?any) {
try {
return fun.apply(context, args);
} catch (e) {
ErrorUtils.reportFatalError(e);
}
};
/** /**
* Utility to catch errors and prevent having to bind, or execute a bound * Utility to catch errors and prevent having to bind, or execute a bound
* function, while catching errors in a process and returning a resulting * function, while catching errors in a process and returning a resulting
@ -97,10 +105,10 @@ var RESPONSE_RETURN_VALUES = 4;
*/ */
var guardReturn = function(operation, operationArguments, getReturnValue, context) { var guardReturn = function(operation, operationArguments, getReturnValue, context) {
if (operation) { if (operation) {
ErrorUtils.applyWithGuard(operation, context, operationArguments); applyWithErrorReporter(operation, context, operationArguments);
} }
if (getReturnValue) { if (getReturnValue) {
return ErrorUtils.applyWithGuard(getReturnValue, context, null); return applyWithErrorReporter(getReturnValue, context, null);
} }
return null; return null;
}; };

View File

@ -13,7 +13,9 @@
@protocol RCTExceptionsManagerDelegate <NSObject> @protocol RCTExceptionsManagerDelegate <NSObject>
- (void)unhandledJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack; - (void)handleSoftJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack;
- (void)handleFatalJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack;
- (void)updateJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack;
@end @end

View File

@ -36,11 +36,23 @@ RCT_EXPORT_MODULE()
return [self initWithDelegate:nil]; return [self initWithDelegate:nil];
} }
RCT_EXPORT_METHOD(reportUnhandledException:(NSString *)message RCT_EXPORT_METHOD(reportSoftException:(NSString *)message
stack:(NSArray *)stack)
{
// TODO(#7070533): report a soft error to the server
if (_delegate) {
[_delegate handleSoftJSExceptionWithMessage:message stack:stack];
return;
}
[[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack];
}
RCT_EXPORT_METHOD(reportFatalException:(NSString *)message
stack:(NSArray *)stack) stack:(NSArray *)stack)
{ {
if (_delegate) { if (_delegate) {
[_delegate unhandledJSExceptionWithMessage:message stack:stack]; [_delegate handleFatalJSExceptionWithMessage:message stack:stack];
return; return;
} }
@ -78,11 +90,17 @@ RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
stack:(NSArray *)stack) stack:(NSArray *)stack)
{ {
if (_delegate) { if (_delegate) {
[_delegate unhandledJSExceptionWithMessage:message stack:stack]; [_delegate updateJSExceptionWithMessage:message stack:stack];
return; return;
} }
[[RCTRedBox sharedInstance] updateErrorMessage:message withStack:stack]; [[RCTRedBox sharedInstance] updateErrorMessage:message withStack:stack];
} }
// Deprecated. Use reportFatalException directly instead.
RCT_EXPORT_METHOD(reportUnhandledException:(NSString *)message
stack:(NSArray *)stack)
{
[self reportFatalException:message stack:stack];
}
@end @end

View File

@ -22,14 +22,17 @@
ErrorUtils._globalHandler = fun; ErrorUtils._globalHandler = fun;
}, },
reportError: function(error) { reportError: function(error) {
Error._globalHandler && ErrorUtils._globalHandler(error); ErrorUtils._globalHandler && ErrorUtils._globalHandler(error);
},
reportFatalError: function(error) {
ErrorUtils._globalHandler && ErrorUtils._globalHandler(error, true);
}, },
applyWithGuard: function(fun, context, args) { applyWithGuard: function(fun, context, args) {
try { try {
ErrorUtils._inGuard++; ErrorUtils._inGuard++;
return fun.apply(context, args); return fun.apply(context, args);
} catch (e) { } catch (e) {
ErrorUtils._globalHandler && ErrorUtils._globalHandler(e); ErrorUtils.reportError(e);
} finally { } finally {
ErrorUtils._inGuard--; ErrorUtils._inGuard--;
} }