diff --git a/desktop/flipper-ui-core/package.json b/desktop/flipper-ui-core/package.json index 541fbcebb..c7ff145fc 100644 --- a/desktop/flipper-ui-core/package.json +++ b/desktop/flipper-ui-core/package.json @@ -48,6 +48,7 @@ "redux-persist": "^6.0.0", "reselect": "^4.1.8", "semver": "^7.5.4", + "stacktrace-js": "2.0.2", "uuid": "^8.3.2" }, "devDependencies": { diff --git a/desktop/flipper-ui-core/src/ui/components/ErrorBoundary.tsx b/desktop/flipper-ui-core/src/ui/components/ErrorBoundary.tsx index 11fea18b6..555eb216d 100644 --- a/desktop/flipper-ui-core/src/ui/components/ErrorBoundary.tsx +++ b/desktop/flipper-ui-core/src/ui/components/ErrorBoundary.tsx @@ -14,6 +14,7 @@ import Button from './Button'; import View from './View'; import styled from '@emotion/styled'; import React from 'react'; +import StackTrace from 'stacktrace-js'; const ErrorBoundaryContainer = styled(View)({ overflow: 'auto', @@ -40,6 +41,7 @@ type ErrorBoundaryProps = { type ErrorBoundaryState = { error: Error | null | undefined; + mappedStack: string | null; }; /** @@ -51,17 +53,26 @@ export default class ErrorBoundary extends Component< > { constructor(props: ErrorBoundaryProps, context: Object) { super(props, context); - this.state = {error: null}; + this.state = {error: null, mappedStack: null}; } componentDidCatch(err: Error, errorInfo: ErrorInfo) { // eslint-disable-next-line flipper/no-console-error-without-context console.error(err, errorInfo.componentStack, 'ErrorBoundary'); this.setState({error: err}); + // eslint-disable-next-line promise/no-promise-in-callback + StackTrace.fromError(err) + .then((frames) => { + const mappedStack = frames.map((frame) => frame.toString()).join('\n'); + this.setState({error: err, mappedStack}); + }) + .catch((e) => { + console.log('[stacktrace-js] failed to extract stack trace', e); + }); } clearError = () => { - this.setState({error: null}); + this.setState({error: null, mappedStack: null}); }; render() { @@ -79,9 +90,11 @@ export default class ErrorBoundary extends Component< return ( {heading} - {this.props.showStack !== false && - 'Look in the console for correct stack traces.'} -
+ {this.props.showStack !== false && ( + + {this.state.mappedStack ?? 'Loading stack trace...'} + + )}
); diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 52f5a990e..71d87b8d9 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -14547,7 +14547,7 @@ stacktrace-gps@^3.0.4: source-map "0.5.6" stackframe "^1.3.4" -stacktrace-js@^2.0.2: +stacktrace-js@2.0.2, stacktrace-js@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==