RN: Lazily Symbolicate Warnings
Summary: Currently, every warning triggers a packager request to symbolicate the stack trace. If there happens to be a lot of warnings or if the packager or device are pretty busy (or low powered), this can cause a significant delay in responsiveness (and development velocity). This fixes the issue by only symbolicating warnings when users inspect them. Reviewed By: sahrens Differential Revision: D3448032 fbshipit-source-id: d6154f336ed34c15f99170da013ae3ff1f1ef075
This commit is contained in:
parent
1731598428
commit
f60e80d89d
|
@ -16,8 +16,9 @@ const EventEmitter = require('EventEmitter');
|
|||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const symbolicateStackTrace = require('symbolicateStackTrace');
|
||||
const infoLog = require('infoLog');
|
||||
const parseErrorStack = require('parseErrorStack');
|
||||
const symbolicateStackTrace = require('symbolicateStackTrace');
|
||||
|
||||
import type EmitterSubscription from 'EmitterSubscription';
|
||||
import type {StackFrame} from 'parseErrorStack';
|
||||
|
@ -25,6 +26,7 @@ import type {StackFrame} from 'parseErrorStack';
|
|||
type WarningInfo = {
|
||||
count: number;
|
||||
stacktrace: Array<StackFrame>;
|
||||
symbolicated: boolean;
|
||||
};
|
||||
|
||||
const _warningEmitter = new EventEmitter();
|
||||
|
@ -77,7 +79,7 @@ if (__DEV__) {
|
|||
* @return {string} the replaced string
|
||||
*/
|
||||
function sprintf(format, ...args) {
|
||||
var index = 0;
|
||||
let index = 0;
|
||||
return format.replace(/%s/g, match => args[index++]);
|
||||
}
|
||||
|
||||
|
@ -91,28 +93,46 @@ function updateWarningMap(format, ...args): void {
|
|||
...args.slice(argCount).map(stringifySafe),
|
||||
].join(' ');
|
||||
|
||||
var warningInfo = _warningMap.get(warning);
|
||||
const warningInfo = _warningMap.get(warning);
|
||||
if (warningInfo) {
|
||||
warningInfo.count += 1;
|
||||
} else {
|
||||
warningInfo = {count: 1, stacktrace: []};
|
||||
}
|
||||
|
||||
_warningMap.set(warning, warningInfo);
|
||||
_warningEmitter.emit('warning', _warningMap);
|
||||
|
||||
var error : any = new Error();
|
||||
const error: any = new Error();
|
||||
error.framesToPop = 2;
|
||||
|
||||
symbolicateStackTrace(parseErrorStack(error)).then(stack => {
|
||||
warningInfo = _warningMap.get(warning);
|
||||
if (warningInfo) {
|
||||
warningInfo.stacktrace = stack;
|
||||
_warningMap.set(warning, {
|
||||
count: 1,
|
||||
stacktrace: parseErrorStack(error),
|
||||
symbolicated: false,
|
||||
});
|
||||
}
|
||||
|
||||
_warningMap.set(warning, warningInfo);
|
||||
_warningEmitter.emit('warning', _warningMap);
|
||||
}
|
||||
}, () => { /* Do nothing when can't load source map */ });
|
||||
|
||||
function ensureSymbolicatedWarning(warning: string): void {
|
||||
const prevWarningInfo = _warningMap.get(warning);
|
||||
if (!prevWarningInfo || prevWarningInfo.symbolicated) {
|
||||
return;
|
||||
}
|
||||
prevWarningInfo.symbolicated = true;
|
||||
|
||||
symbolicateStackTrace(prevWarningInfo.stacktrace).then(
|
||||
stack => {
|
||||
const nextWarningInfo = _warningMap.get(warning);
|
||||
if (nextWarningInfo) {
|
||||
nextWarningInfo.stacktrace = stack;
|
||||
_warningEmitter.emit('warning', _warningMap);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
const nextWarningInfo = _warningMap.get(warning);
|
||||
if (nextWarningInfo) {
|
||||
infoLog('Failed to symbolicate warning, "%s":', warning, error);
|
||||
_warningEmitter.emit('warning', _warningMap);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function isWarningIgnored(warning: string): boolean {
|
||||
|
@ -182,7 +202,7 @@ const WarningInspector = ({
|
|||
let stacktraceList;
|
||||
if (stacktraceVisible && stacktrace) {
|
||||
stacktraceList = (
|
||||
<View>
|
||||
<View style={styles.stacktraceList}>
|
||||
{stacktrace.map((frame, ii) => <StackRow frame={frame} key={ii} />)}
|
||||
</View>
|
||||
);
|
||||
|
@ -203,7 +223,7 @@ const WarningInspector = ({
|
|||
style={styles.stacktraceButton}
|
||||
underlayColor="transparent">
|
||||
<Text style={styles.inspectorButtonText}>
|
||||
{stacktraceVisible ? 'Hide' : 'Show'} stacktrace
|
||||
{stacktraceVisible ? 'Hide' : 'Show'} Stacktrace
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
|
@ -280,6 +300,13 @@ class YellowBox extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const {inspecting} = this.state;
|
||||
if (inspecting != null) {
|
||||
ensureSymbolicatedWarning(inspecting);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._listener) {
|
||||
this._listener.remove();
|
||||
|
@ -355,9 +382,6 @@ var styles = StyleSheet.create({
|
|||
backgroundColor: backgroundColor(0.95),
|
||||
flex: 1,
|
||||
},
|
||||
inspectorContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
inspectorButtons: {
|
||||
flexDirection: 'row',
|
||||
position: 'absolute',
|
||||
|
@ -374,6 +398,9 @@ var styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
padding: 5,
|
||||
},
|
||||
stacktraceList: {
|
||||
paddingBottom: 5,
|
||||
},
|
||||
inspectorButtonText: {
|
||||
color: textColor,
|
||||
fontSize: 14,
|
||||
|
|
Loading…
Reference in New Issue