UNPKG

reactotron-react-native

Version:

A development tool to explore, inspect, and diagnose your React Native apps.

130 lines (121 loc) 4.7 kB
"use strict"; /** * Provides a global error handler to report errors.. */ import { assertHasLoggerPlugin } from "reactotron-core-client"; import _LogBox // eslint-disable-next-line import/default, import/namespace from "react-native/Libraries/LogBox/LogBox"; // eslint-disable-next-line import/namespace const LogBox = _LogBox; // a few functions to help source map errors -- these seem to be not available immediately // so we're lazy loading. let parseErrorStack; let symbolicateStackTrace; // defaults const PLUGIN_DEFAULTS = { veto: null }; const objectifyError = error => { const objectifiedError = {}; Object.getOwnPropertyNames(error).forEach(key => { objectifiedError[key] = error[key]; }); return objectifiedError; }; // const reactNativeFrameFinder = frame => contains('/node_modules/react-native/', frame.fileName) /** * Track global errors and send them to Reactotron logger. */ const trackGlobalErrors = options => reactotron => { // make sure we have the logger plugin assertHasLoggerPlugin(reactotron); const client = reactotron; // setup configuration const config = Object.assign({}, PLUGIN_DEFAULTS, options || {}); // manually fire an error function reportError(error) { try { if (!parseErrorStack) { const parseErrorStackModule = require("react-native/Libraries/Core/Devtools/parseErrorStack"); // Handle both CommonJS (module.exports) and ESM (export default) formats parseErrorStack = typeof parseErrorStackModule === "function" ? parseErrorStackModule : parseErrorStackModule.default; } if (!symbolicateStackTrace) { const symbolicateStackTraceModule = require("react-native/Libraries/Core/Devtools/symbolicateStackTrace"); // Handle both CommonJS (module.exports) and ESM (export default) formats symbolicateStackTrace = typeof symbolicateStackTraceModule === "function" ? symbolicateStackTraceModule : symbolicateStackTraceModule.default; } } catch (e) { client.error('Unable to load "react-native/Libraries/Core/Devtools/parseErrorStack" or "react-native/Libraries/Core/Devtools/symbolicateStackTrace"', []); client.debug(objectifyError(e)); return; } if (!parseErrorStack || !symbolicateStackTrace) { client.error("parseErrorStack or symbolicateStackTrace is not available", []); client.debug({ parseErrorStackAvailable: !!parseErrorStack, symbolicateStackTraceAvailable: !!symbolicateStackTrace }); return; } if (typeof parseErrorStack !== "function") { client.error("parseErrorStack is not a function", []); client.debug({ parseErrorStackType: typeof parseErrorStack, parseErrorStack }); return; } if (typeof symbolicateStackTrace !== "function") { client.error("symbolicateStackTrace is not a function", []); client.debug({ symbolicateStackTraceType: typeof symbolicateStackTrace, symbolicateStackTrace }); return; } let parsedStacktrace; try { // parseErrorStack arg type is wrong, it's expecting an array, a string, or a hermes error data, https://github.com/facebook/react-native/blob/v0.72.1/packages/react-native/Libraries/Core/Devtools/parseErrorStack.js#L41 parsedStacktrace = parseErrorStack(error.stack); } catch (e) { client.error("Unable to parse stack trace from error object", []); client.debug(objectifyError(e)); return; } symbolicateStackTrace(parsedStacktrace).then(symbolicatedStackTrace => { let prettyStackFrames = symbolicatedStackTrace.stack.map(stackFrame => ({ fileName: stackFrame.file, functionName: stackFrame.methodName, lineNumber: stackFrame.lineNumber })); // does the dev want us to keep each frame? if (config.veto) { prettyStackFrames = prettyStackFrames.filter(frame => config?.veto(frame)); } client.error(error.message, prettyStackFrames); // TODO: Fix this. }).catch(e => { client.error("Unable to symbolicate stack trace from error object", []); client.debug(objectifyError(e)); }); } // the reactotron plugin interface return { onConnect: () => { LogBox.addException = new Proxy(LogBox.addException, { apply: function (target, thisArg, argumentsList) { const error = argumentsList[0]; reportError(error); return target.apply(thisArg, argumentsList); } }); }, // attach these functions to the Reactotron features: { reportError } }; }; export default trackGlobalErrors; //# sourceMappingURL=trackGlobalErrors.js.map