2016-04-20 15:07:43 +00:00
|
|
|
/**
|
2018-09-11 22:27:47 +00:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2016-04-20 15:07:43 +00:00
|
|
|
*
|
2018-02-17 02:24:55 +00:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2016-04-20 15:07:43 +00:00
|
|
|
*
|
2018-05-11 02:06:46 +00:00
|
|
|
* @format
|
2016-04-20 15:07:43 +00:00
|
|
|
* @flow
|
|
|
|
*/
|
2018-05-11 02:06:46 +00:00
|
|
|
|
2016-04-20 15:07:43 +00:00
|
|
|
'use strict';
|
|
|
|
|
2016-04-22 18:23:21 +00:00
|
|
|
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
2016-05-16 14:13:20 +00:00
|
|
|
const Map = require('Map');
|
2016-05-17 19:42:17 +00:00
|
|
|
const infoLog = require('infoLog');
|
2016-04-22 18:23:21 +00:00
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
import type EmitterSubscription from 'EmitterSubscription';
|
2016-04-20 15:07:43 +00:00
|
|
|
|
2018-05-11 02:06:46 +00:00
|
|
|
type ExtraData = {[key: string]: string};
|
2016-04-20 15:07:43 +00:00
|
|
|
type SourceCallback = () => string;
|
2018-05-11 02:06:46 +00:00
|
|
|
type DebugData = {extras: ExtraData, files: ExtraData};
|
2016-04-20 15:07:43 +00:00
|
|
|
|
2016-05-18 21:23:40 +00:00
|
|
|
function defaultExtras() {
|
2018-05-11 02:06:46 +00:00
|
|
|
BugReporting.addFileSource('react_hierarchy.txt', () =>
|
|
|
|
require('dumpReactTree')(),
|
|
|
|
);
|
2016-05-18 21:23:40 +00:00
|
|
|
}
|
|
|
|
|
2016-04-20 15:07:43 +00:00
|
|
|
/**
|
|
|
|
* A simple class for collecting bug report data. Components can add sources that will be queried when a bug report
|
|
|
|
* is created via `collectExtraData`. For example, a list component might add a source that provides the list of rows
|
|
|
|
* that are currently visible on screen. Components should also remember to call `remove()` on the object that is
|
|
|
|
* returned by `addSource` when they are unmounted.
|
|
|
|
*/
|
|
|
|
class BugReporting {
|
2016-05-16 14:13:20 +00:00
|
|
|
static _extraSources: Map<string, SourceCallback> = new Map();
|
|
|
|
static _fileSources: Map<string, SourceCallback> = new Map();
|
2016-05-16 11:04:37 +00:00
|
|
|
static _subscription: ?EmitterSubscription = null;
|
2017-12-14 18:38:34 +00:00
|
|
|
static _redboxSubscription: ?EmitterSubscription = null;
|
2016-04-20 15:07:43 +00:00
|
|
|
|
2016-05-18 21:23:40 +00:00
|
|
|
static _maybeInit() {
|
2016-04-22 18:23:21 +00:00
|
|
|
if (!BugReporting._subscription) {
|
2018-05-11 02:06:46 +00:00
|
|
|
BugReporting._subscription = RCTDeviceEventEmitter.addListener(
|
|
|
|
'collectBugExtraData',
|
|
|
|
BugReporting.collectExtraData,
|
|
|
|
null,
|
|
|
|
);
|
2016-05-18 21:23:40 +00:00
|
|
|
defaultExtras();
|
2016-04-22 18:23:21 +00:00
|
|
|
}
|
2017-12-14 18:38:34 +00:00
|
|
|
|
|
|
|
if (!BugReporting._redboxSubscription) {
|
2018-05-11 02:06:46 +00:00
|
|
|
BugReporting._redboxSubscription = RCTDeviceEventEmitter.addListener(
|
|
|
|
'collectRedBoxExtraData',
|
|
|
|
BugReporting.collectExtraData,
|
|
|
|
null,
|
|
|
|
);
|
2017-12-14 18:38:34 +00:00
|
|
|
}
|
2016-04-20 15:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps a string key to a simple callback that should return a string payload to be attached
|
|
|
|
* to a bug report. Source callbacks are called when `collectExtraData` is called.
|
|
|
|
*
|
|
|
|
* Returns an object to remove the source when the component unmounts.
|
|
|
|
*
|
|
|
|
* Conflicts trample with a warning.
|
|
|
|
*/
|
2018-05-11 02:06:46 +00:00
|
|
|
static addSource(
|
|
|
|
key: string,
|
|
|
|
callback: SourceCallback,
|
|
|
|
): {remove: () => void} {
|
2016-05-16 14:13:20 +00:00
|
|
|
return this._addSource(key, callback, BugReporting._extraSources);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps a string key to a simple callback that should return a string payload to be attached
|
|
|
|
* to a bug report. Source callbacks are called when `collectExtraData` is called.
|
|
|
|
*
|
|
|
|
* Returns an object to remove the source when the component unmounts.
|
|
|
|
*
|
|
|
|
* Conflicts trample with a warning.
|
|
|
|
*/
|
2018-05-11 02:06:46 +00:00
|
|
|
static addFileSource(
|
|
|
|
key: string,
|
|
|
|
callback: SourceCallback,
|
|
|
|
): {remove: () => void} {
|
2016-05-16 14:13:20 +00:00
|
|
|
return this._addSource(key, callback, BugReporting._fileSources);
|
|
|
|
}
|
|
|
|
|
2018-05-11 02:06:46 +00:00
|
|
|
static _addSource(
|
|
|
|
key: string,
|
|
|
|
callback: SourceCallback,
|
|
|
|
source: Map<string, SourceCallback>,
|
|
|
|
): {remove: () => void} {
|
2016-05-18 21:23:40 +00:00
|
|
|
BugReporting._maybeInit();
|
2016-05-16 14:13:20 +00:00
|
|
|
if (source.has(key)) {
|
2018-05-11 02:06:46 +00:00
|
|
|
console.warn(
|
|
|
|
`BugReporting.add* called multiple times for same key '${key}'`,
|
|
|
|
);
|
2016-04-20 15:07:43 +00:00
|
|
|
}
|
2016-05-16 14:13:20 +00:00
|
|
|
source.set(key, callback);
|
2018-05-11 02:06:46 +00:00
|
|
|
return {
|
|
|
|
remove: () => {
|
|
|
|
source.delete(key);
|
|
|
|
},
|
|
|
|
};
|
2016-04-20 15:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This can be called from a native bug reporting flow, or from JS code.
|
|
|
|
*
|
|
|
|
* If available, this will call `NativeModules.BugReporting.setExtraData(extraData)`
|
|
|
|
* after collecting `extraData`.
|
|
|
|
*/
|
2016-05-16 14:13:20 +00:00
|
|
|
static collectExtraData(): DebugData {
|
2016-04-20 15:07:43 +00:00
|
|
|
const extraData: ExtraData = {};
|
2016-05-16 14:13:20 +00:00
|
|
|
for (const [key, callback] of BugReporting._extraSources) {
|
2016-04-20 15:07:43 +00:00
|
|
|
extraData[key] = callback();
|
|
|
|
}
|
2016-05-16 14:13:20 +00:00
|
|
|
const fileData: ExtraData = {};
|
|
|
|
for (const [key, callback] of BugReporting._fileSources) {
|
|
|
|
fileData[key] = callback();
|
|
|
|
}
|
2016-05-17 19:42:17 +00:00
|
|
|
infoLog('BugReporting extraData:', extraData);
|
2016-05-19 19:49:53 +00:00
|
|
|
const BugReportingNativeModule = require('NativeModules').BugReporting;
|
2016-04-20 15:07:43 +00:00
|
|
|
BugReportingNativeModule &&
|
|
|
|
BugReportingNativeModule.setExtraData &&
|
2016-05-16 14:13:20 +00:00
|
|
|
BugReportingNativeModule.setExtraData(extraData, fileData);
|
|
|
|
|
2017-12-14 18:38:34 +00:00
|
|
|
const RedBoxNativeModule = require('NativeModules').RedBox;
|
|
|
|
RedBoxNativeModule &&
|
|
|
|
RedBoxNativeModule.setExtraData &&
|
|
|
|
RedBoxNativeModule.setExtraData(extraData, 'From BugReporting.js');
|
|
|
|
|
2018-05-11 02:06:46 +00:00
|
|
|
return {extras: extraData, files: fileData};
|
2016-04-20 15:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = BugReporting;
|