diff --git a/Libraries/ReactIOS/YellowBox.js b/Libraries/ReactIOS/YellowBox.js index dbc15dc9e..82507b56f 100644 --- a/Libraries/ReactIOS/YellowBox.js +++ b/Libraries/ReactIOS/YellowBox.js @@ -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; + 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: []}; + const error: any = new Error(); + error.framesToPop = 2; + + _warningMap.set(warning, { + count: 1, + stacktrace: parseErrorStack(error), + symbolicated: false, + }); } - _warningMap.set(warning, warningInfo); _warningEmitter.emit('warning', _warningMap); +} - var error : any = new Error(); - error.framesToPop = 2; +function ensureSymbolicatedWarning(warning: string): void { + const prevWarningInfo = _warningMap.get(warning); + if (!prevWarningInfo || prevWarningInfo.symbolicated) { + return; + } + prevWarningInfo.symbolicated = true; - symbolicateStackTrace(parseErrorStack(error)).then(stack => { - warningInfo = _warningMap.get(warning); - if (warningInfo) { - warningInfo.stacktrace = stack; - - _warningMap.set(warning, warningInfo); - _warningEmitter.emit('warning', _warningMap); + 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); + } } - }, () => { /* Do nothing when can't load source map */ }); + ); } function isWarningIgnored(warning: string): boolean { @@ -182,7 +202,7 @@ const WarningInspector = ({ let stacktraceList; if (stacktraceVisible && stacktrace) { stacktraceList = ( - + {stacktrace.map((frame, ii) => )} ); @@ -203,7 +223,7 @@ const WarningInspector = ({ style={styles.stacktraceButton} underlayColor="transparent"> - {stacktraceVisible ? 'Hide' : 'Show'} stacktrace + {stacktraceVisible ? 'Hide' : 'Show'} Stacktrace @@ -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,