diff --git a/Libraries/Core/ExceptionsManager.js b/Libraries/Core/ExceptionsManager.js index 9d6767d51f380d..68a6214a15b7a1 100644 --- a/Libraries/Core/ExceptionsManager.js +++ b/Libraries/Core/ExceptionsManager.js @@ -12,9 +12,12 @@ import type {ExtendedError} from './Devtools/parseErrorStack'; +// NOTE: Deprecated in favor of driving this from the symbolication endpoint +// instead. +// See Metro config option `symbolicator.customizeFrame`. const INTERNAL_CALLSITES_REGEX = new RegExp( [ - '/Libraries/Renderer/oss/ReactNativeRenderer-dev\\.js$', + '/Libraries/Renderer/implementations/.+\\.js$', '/Libraries/BatchedBridge/MessageQueue\\.js$', ].join('|'), ); @@ -50,11 +53,15 @@ function reportException(e: ExtendedError, isFatal: boolean) { symbolicateStackTrace(stack) .then(prettyStack => { if (prettyStack) { - const stackWithoutInternalCallsites = prettyStack.filter( - frame => + const stackWithoutInternalCallsites = prettyStack.filter(frame => { + if (typeof frame.collapse === 'boolean') { + return !frame.collapse; + } + return ( frame.file && - frame.file.match(INTERNAL_CALLSITES_REGEX) === null, - ); + frame.file.match(INTERNAL_CALLSITES_REGEX) === null + ); + }); NativeExceptionsManager.updateExceptionMessage( message, stackWithoutInternalCallsites, diff --git a/Libraries/Core/NativeExceptionsManager.js b/Libraries/Core/NativeExceptionsManager.js index f79f2643914b1c..525d020d06960f 100644 --- a/Libraries/Core/NativeExceptionsManager.js +++ b/Libraries/Core/NativeExceptionsManager.js @@ -18,6 +18,7 @@ export type StackFrame = {| file: string, lineNumber: number, methodName: string, + collapse?: boolean, |}; export type ExceptionData = { diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h index 4630310673aeb7..21d5174c475538 100644 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +++ b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h @@ -912,6 +912,7 @@ namespace JS { NSString *file() const; double lineNumber() const; NSString *methodName() const; + folly::Optional collapse() const; StackFrame(NSDictionary *const v) : _v(v) {} private: @@ -2649,6 +2650,11 @@ inline NSString *JS::NativeExceptionsManager::StackFrame::methodName() const id const p = _v[@"methodName"]; return RCTBridgingToString(p); } +inline folly::Optional JS::NativeExceptionsManager::StackFrame::collapse() const +{ + id const p = _v[@"collapse"]; + return RCTBridgingToOptionalBool(p); +} inline NSString *JS::NativeExceptionsManager::ExceptionData::message() const { diff --git a/template/metro.config.js b/template/metro.config.js index 13a964217f20a0..ed2a70d13f89de 100644 --- a/template/metro.config.js +++ b/template/metro.config.js @@ -5,7 +5,22 @@ * @format */ +const INTERNAL_CALLSITES_REGEX = new RegExp( + [ + '/Libraries/Renderer/implementations/.+\\.js$', + '/Libraries/BatchedBridge/MessageQueue\\.js$', + ].join('|'), +); + module.exports = { + symbolicator: { + customizeFrame: frame => { + const collapse = Boolean( + frame.file && INTERNAL_CALLSITES_REGEX.test(frame.file), + ); + return {collapse}; + }, + }, transformer: { getTransformOptions: async () => ({ transform: {