[ReactNative] differentiate fatal and soft exceptions
This commit is contained in:
parent
484f63b1db
commit
81ad810186
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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--;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue