amis-rpc-design/node_modules/react-native/Libraries/BugReporting/BugReporting.js
2023-10-07 19:42:30 +08:00

141 lines
4.2 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
import NativeRedBox from '../NativeModules/specs/NativeRedBox';
import {type EventSubscription} from '../vendor/emitter/EventEmitter';
import NativeBugReporting from './NativeBugReporting';
type ExtraData = {[key: string]: string, ...};
type SourceCallback = () => string;
type DebugData = {
extras: ExtraData,
files: ExtraData,
...
};
function defaultExtras() {
BugReporting.addFileSource('react_hierarchy.txt', () =>
require('./dumpReactTree')(),
);
}
/**
* 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 {
static _extraSources: Map<string, SourceCallback> = new Map();
static _fileSources: Map<string, SourceCallback> = new Map();
static _subscription: ?EventSubscription = null;
static _redboxSubscription: ?EventSubscription = null;
static _maybeInit() {
if (!BugReporting._subscription) {
BugReporting._subscription = RCTDeviceEventEmitter.addListener(
'collectBugExtraData',
// $FlowFixMe[method-unbinding]
BugReporting.collectExtraData,
null,
);
defaultExtras();
}
if (!BugReporting._redboxSubscription) {
BugReporting._redboxSubscription = RCTDeviceEventEmitter.addListener(
'collectRedBoxExtraData',
// $FlowFixMe[method-unbinding]
BugReporting.collectExtraData,
null,
);
}
}
/**
* 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.
*/
static addSource(
key: string,
callback: SourceCallback,
): {remove: () => void, ...} {
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.
*/
static addFileSource(
key: string,
callback: SourceCallback,
): {remove: () => void, ...} {
return this._addSource(key, callback, BugReporting._fileSources);
}
static _addSource(
key: string,
callback: SourceCallback,
source: Map<string, SourceCallback>,
): {remove: () => void, ...} {
BugReporting._maybeInit();
if (source.has(key)) {
console.warn(
`BugReporting.add* called multiple times for same key '${key}'`,
);
}
source.set(key, callback);
return {
remove: () => {
source.delete(key);
},
};
}
/**
* 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`.
*/
static collectExtraData(): DebugData {
const extraData: ExtraData = {};
for (const [key, callback] of BugReporting._extraSources) {
extraData[key] = callback();
}
const fileData: ExtraData = {};
for (const [key, callback] of BugReporting._fileSources) {
fileData[key] = callback();
}
if (NativeBugReporting != null && NativeBugReporting.setExtraData != null) {
NativeBugReporting.setExtraData(extraData, fileData);
}
if (NativeRedBox != null && NativeRedBox.setExtraData != null) {
NativeRedBox.setExtraData(extraData, 'From BugReporting.js');
}
return {extras: extraData, files: fileData};
}
}
module.exports = BugReporting;