2019-01-10 20:23:33 +03:00
|
|
|
import React, { Component } from 'react';
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
import { getStackFrames } from './react-error-overlay/utils/getStackFrames';
|
2018-12-12 19:34:22 +03:00
|
|
|
import StackTrace from './react-error-overlay/containers/StackTrace';
|
2018-12-15 04:04:34 +03:00
|
|
|
import openFile from './openFile';
|
2020-09-29 16:37:13 +03:00
|
|
|
import { Action } from 'redux';
|
|
|
|
import { TabComponentProps } from 'redux-devtools-inspector-monitor';
|
|
|
|
import StackFrame from './react-error-overlay/utils/stack-frame';
|
|
|
|
import { ErrorLocation } from './react-error-overlay/utils/parseCompileError';
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
const rootStyle = { padding: '5px 10px' };
|
2018-12-18 20:26:17 +03:00
|
|
|
|
2020-09-29 16:37:13 +03:00
|
|
|
interface Props<S, A extends Action<unknown>> extends TabComponentProps<S, A> {
|
|
|
|
openFile: (
|
|
|
|
fileName: string,
|
|
|
|
lineNumber: number,
|
|
|
|
stackFrame: StackFrame
|
|
|
|
) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface State {
|
|
|
|
stackFrames: StackFrame[];
|
|
|
|
currentError?: Error;
|
|
|
|
showDocsLink?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default class StackTraceTab<
|
|
|
|
S,
|
|
|
|
A extends Action<unknown>
|
|
|
|
> extends Component<Props<S, A>, State> {
|
2019-02-07 02:58:51 +03:00
|
|
|
static defaultProps = {
|
2020-08-08 23:26:39 +03:00
|
|
|
openFile,
|
2019-02-07 03:10:24 +03:00
|
|
|
};
|
2018-12-12 19:34:22 +03:00
|
|
|
|
2020-09-29 16:37:13 +03:00
|
|
|
state: State = {
|
|
|
|
stackFrames: [],
|
|
|
|
};
|
|
|
|
|
2018-12-12 19:34:22 +03:00
|
|
|
componentDidMount() {
|
2018-12-12 23:45:37 +03:00
|
|
|
// console.log("StackTraceTab mounted");
|
2018-12-12 19:34:22 +03:00
|
|
|
this.checkForStackTrace();
|
|
|
|
}
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2020-09-29 16:37:13 +03:00
|
|
|
componentDidUpdate(prevProps: Props<S, A>) {
|
2019-01-10 21:51:14 +03:00
|
|
|
const { action, actions } = prevProps;
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
if (action !== this.props.action || actions !== this.props.actions) {
|
2018-12-12 19:34:22 +03:00
|
|
|
this.checkForStackTrace();
|
2018-12-11 23:26:24 +03:00
|
|
|
}
|
2018-12-12 19:34:22 +03:00
|
|
|
}
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2018-12-12 19:34:22 +03:00
|
|
|
checkForStackTrace() {
|
2019-01-10 21:51:14 +03:00
|
|
|
const { action, actions: liftedActionsById } = this.props;
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
if (!action) {
|
2018-12-12 19:34:22 +03:00
|
|
|
return;
|
|
|
|
}
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2018-12-12 19:34:22 +03:00
|
|
|
const liftedActions = Object.values(liftedActionsById);
|
2019-01-10 21:51:14 +03:00
|
|
|
const liftedAction = liftedActions.find(
|
2020-08-08 23:26:39 +03:00
|
|
|
(liftedAction) => liftedAction.action === action
|
2019-01-10 21:51:14 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
if (liftedAction && typeof liftedAction.stack === 'string') {
|
|
|
|
const deserializedError = Object.assign(new Error(), {
|
2020-08-08 23:26:39 +03:00
|
|
|
stack: liftedAction.stack,
|
2019-01-10 21:51:14 +03:00
|
|
|
});
|
|
|
|
|
2020-09-29 16:37:13 +03:00
|
|
|
getStackFrames(deserializedError)
|
|
|
|
.then((stackFrames) => {
|
|
|
|
/* eslint-disable no-console */
|
|
|
|
if (process.env.NODE_ENV === 'development')
|
|
|
|
console.log('Stack frames: ', stackFrames);
|
|
|
|
/* eslint-enable no-console */
|
|
|
|
this.setState({
|
|
|
|
stackFrames: stackFrames!,
|
|
|
|
currentError: deserializedError,
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
// noop
|
|
|
|
});
|
2019-01-10 21:51:14 +03:00
|
|
|
} else {
|
2018-12-18 20:26:17 +03:00
|
|
|
this.setState({
|
|
|
|
stackFrames: [],
|
2019-01-10 21:51:14 +03:00
|
|
|
showDocsLink:
|
2020-09-29 16:37:13 +03:00
|
|
|
liftedAction!.action &&
|
|
|
|
liftedAction!.action.type &&
|
|
|
|
liftedAction!.action.type !== '@@INIT',
|
2018-12-18 20:26:17 +03:00
|
|
|
});
|
2018-12-12 19:34:22 +03:00
|
|
|
}
|
|
|
|
}
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2020-09-29 16:37:13 +03:00
|
|
|
onStackLocationClicked = (fileLocation: Partial<ErrorLocation> = {}) => {
|
2018-12-12 23:45:37 +03:00
|
|
|
// console.log("Stack location args: ", ...args);
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
const { fileName, lineNumber } = fileLocation;
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
if (fileName && lineNumber) {
|
2020-08-08 23:26:39 +03:00
|
|
|
const matchingStackFrame = this.state.stackFrames.find((stackFrame) => {
|
2019-01-10 21:51:14 +03:00
|
|
|
const matches =
|
|
|
|
(stackFrame._originalFileName === fileName &&
|
|
|
|
stackFrame._originalLineNumber === lineNumber) ||
|
|
|
|
(stackFrame.fileName === fileName &&
|
|
|
|
stackFrame.lineNumber === lineNumber);
|
2018-12-12 19:34:22 +03:00
|
|
|
return matches;
|
|
|
|
});
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2018-12-12 23:45:37 +03:00
|
|
|
// console.log("Matching stack frame: ", matchingStackFrame);
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2019-01-10 21:51:14 +03:00
|
|
|
if (matchingStackFrame) {
|
2018-12-12 23:45:37 +03:00
|
|
|
/*
|
|
|
|
const frameIndex = this.state.stackFrames.indexOf(matchingStackFrame);
|
|
|
|
const originalStackFrame = parsedFramesNoSourcemaps[frameIndex];
|
|
|
|
console.log("Original stack frame: ", originalStackFrame);
|
|
|
|
*/
|
2019-02-07 02:58:51 +03:00
|
|
|
this.props.openFile(fileName, lineNumber, matchingStackFrame);
|
2018-12-12 19:34:22 +03:00
|
|
|
}
|
2018-12-11 23:26:24 +03:00
|
|
|
}
|
2019-01-10 21:51:14 +03:00
|
|
|
};
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2020-09-29 16:37:13 +03:00
|
|
|
openDocs: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
|
2018-12-18 20:26:17 +03:00
|
|
|
e.stopPropagation();
|
2019-01-10 21:51:14 +03:00
|
|
|
window.open(
|
|
|
|
'https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/Features/Trace.md'
|
|
|
|
);
|
|
|
|
};
|
2018-12-11 23:26:24 +03:00
|
|
|
|
2018-12-12 19:34:22 +03:00
|
|
|
render() {
|
2019-01-10 21:51:14 +03:00
|
|
|
const { stackFrames, showDocsLink } = this.state;
|
2018-12-18 20:26:17 +03:00
|
|
|
|
|
|
|
if (showDocsLink) {
|
|
|
|
return (
|
|
|
|
<div style={rootStyle}>
|
2019-01-10 21:51:14 +03:00
|
|
|
To enable tracing action calls, you should set `trace` option to
|
|
|
|
`true` for Redux DevTools enhancer. Refer to{' '}
|
|
|
|
<a href="#" onClick={this.openDocs}>
|
|
|
|
this page
|
|
|
|
</a>{' '}
|
|
|
|
for more details.
|
2018-12-18 20:26:17 +03:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2018-12-12 19:34:22 +03:00
|
|
|
|
|
|
|
return (
|
2019-01-10 21:51:14 +03:00
|
|
|
<div style={rootStyle}>
|
|
|
|
<StackTrace
|
|
|
|
stackFrames={stackFrames}
|
|
|
|
errorName="N/A"
|
|
|
|
contextSize={3}
|
|
|
|
editorHandler={this.onStackLocationClicked}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
2018-12-12 19:34:22 +03:00
|
|
|
}
|
|
|
|
}
|