yeet
This commit is contained in:
141
node_modules/react-native/Libraries/BugReporting/BugReporting.js
generated
vendored
Normal file
141
node_modules/react-native/Libraries/BugReporting/BugReporting.js
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const RCTDeviceEventEmitter = require('../EventEmitter/RCTDeviceEventEmitter');
|
||||
|
||||
import type EmitterSubscription from '../vendor/emitter/EmitterSubscription';
|
||||
import NativeBugReporting from './NativeBugReporting';
|
||||
import NativeRedBox from '../NativeModules/specs/NativeRedBox';
|
||||
|
||||
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: ?EmitterSubscription = null;
|
||||
static _redboxSubscription: ?EmitterSubscription = null;
|
||||
|
||||
static _maybeInit() {
|
||||
if (!BugReporting._subscription) {
|
||||
BugReporting._subscription = RCTDeviceEventEmitter.addListener(
|
||||
'collectBugExtraData',
|
||||
BugReporting.collectExtraData,
|
||||
null,
|
||||
);
|
||||
defaultExtras();
|
||||
}
|
||||
|
||||
if (!BugReporting._redboxSubscription) {
|
||||
BugReporting._redboxSubscription = RCTDeviceEventEmitter.addListener(
|
||||
'collectRedBoxExtraData',
|
||||
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;
|
20
node_modules/react-native/Libraries/BugReporting/NativeBugReporting.js
generated
vendored
Normal file
20
node_modules/react-native/Libraries/BugReporting/NativeBugReporting.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its 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
|
||||
*/
|
||||
|
||||
import type {TurboModule} from '../TurboModule/RCTExport';
|
||||
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+startReportAProblemFlow: () => void;
|
||||
+setExtraData: (extraData: Object, extraFiles: Object) => void;
|
||||
+setCategoryID: (categoryID: string) => void;
|
||||
}
|
||||
|
||||
export default (TurboModuleRegistry.get<Spec>('BugReporting'): ?Spec);
|
151
node_modules/react-native/Libraries/BugReporting/dumpReactTree.js
generated
vendored
Normal file
151
node_modules/react-native/Libraries/BugReporting/dumpReactTree.js
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
const getReactData = require('getReactData');
|
||||
|
||||
const INDENTATION_SIZE = 2;
|
||||
const MAX_DEPTH = 2;
|
||||
const MAX_STRING_LENGTH = 50;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dump all React Native root views and their content. This function tries
|
||||
* it best to get the content but ultimately relies on implementation details
|
||||
* of React and will fail in future versions.
|
||||
*/
|
||||
function dumpReactTree(): string {
|
||||
try {
|
||||
return getReactTree();
|
||||
} catch (e) {
|
||||
return 'Failed to dump react tree: ' + e;
|
||||
}
|
||||
}
|
||||
|
||||
function getReactTree() {
|
||||
// TODO(sema): Reenable tree dumps using the Fiber tree structure. #15945684
|
||||
return (
|
||||
'React tree dumps have been temporarily disabled while React is ' +
|
||||
'upgraded to Fiber.'
|
||||
);
|
||||
/*
|
||||
let output = '';
|
||||
const rootIds = Object.getOwnPropertyNames(ReactNativeMount._instancesByContainerID);
|
||||
for (const rootId of rootIds) {
|
||||
const instance = ReactNativeMount._instancesByContainerID[rootId];
|
||||
output += `============ Root ID: ${rootId} ============\n`;
|
||||
output += dumpNode(instance, 0);
|
||||
output += `============ End root ID: ${rootId} ============\n`;
|
||||
}
|
||||
return output;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
function dumpNode(node: Object, indentation: number) {
|
||||
const data = getReactData(node);
|
||||
if (data.nodeType === 'Text') {
|
||||
return indent(indentation) + data.text + '\n';
|
||||
} else if (data.nodeType === 'Empty') {
|
||||
return '';
|
||||
}
|
||||
let output = indent(indentation) + `<${data.name}`;
|
||||
if (data.nodeType === 'Composite') {
|
||||
for (const propName of Object.getOwnPropertyNames(data.props || {})) {
|
||||
if (isNormalProp(propName)) {
|
||||
try {
|
||||
const value = convertValue(data.props[propName]);
|
||||
if (value) {
|
||||
output += ` ${propName}=${value}`;
|
||||
}
|
||||
} catch (e) {
|
||||
const message = `[Failed to get property: ${e}]`;
|
||||
output += ` ${propName}=${message}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let childOutput = '';
|
||||
for (const child of data.children || []) {
|
||||
childOutput += dumpNode(child, indentation + 1);
|
||||
}
|
||||
|
||||
if (childOutput) {
|
||||
output += '>\n' + childOutput + indent(indentation) + `</${data.name}>\n`;
|
||||
} else {
|
||||
output += ' />\n';
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
function isNormalProp(name: string): boolean {
|
||||
switch (name) {
|
||||
case 'children':
|
||||
case 'key':
|
||||
case 'ref':
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function convertObject(object: Object, depth: number) {
|
||||
if (depth >= MAX_DEPTH) {
|
||||
return '[...omitted]';
|
||||
}
|
||||
let output = '{';
|
||||
let first = true;
|
||||
for (const key of Object.getOwnPropertyNames(object)) {
|
||||
if (!first) {
|
||||
output += ', ';
|
||||
}
|
||||
output += `${key}: ${convertValue(object[key], depth + 1)}`;
|
||||
first = false;
|
||||
}
|
||||
return output + '}';
|
||||
}
|
||||
|
||||
function convertValue(value, depth = 0): ?string {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return JSON.stringify(possiblyEllipsis(value).replace('\n', '\\n'));
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
return JSON.stringify(value);
|
||||
case 'function':
|
||||
return '[function]';
|
||||
case 'object':
|
||||
return convertObject(value, depth);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function possiblyEllipsis(value: string) {
|
||||
if (value.length > MAX_STRING_LENGTH) {
|
||||
return value.slice(0, MAX_STRING_LENGTH) + '...';
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function indent(size: number) {
|
||||
return ' '.repeat(size * INDENTATION_SIZE);
|
||||
}
|
||||
*/
|
||||
|
||||
module.exports = dumpReactTree;
|
178
node_modules/react-native/Libraries/BugReporting/getReactData.js
generated
vendored
Normal file
178
node_modules/react-native/Libraries/BugReporting/getReactData.js
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Convert a react internal instance to a sanitized data object.
|
||||
*
|
||||
* This is shamelessly stolen from react-devtools:
|
||||
* https://github.com/facebook/react-devtools/blob/master/backend/getData.js
|
||||
*/
|
||||
function getData(element: Object): Object {
|
||||
let children = null;
|
||||
let props = null;
|
||||
let state = null;
|
||||
let context = null;
|
||||
let updater = null;
|
||||
let name = null;
|
||||
let type = null;
|
||||
let text = null;
|
||||
let publicInstance = null;
|
||||
let nodeType = 'Native';
|
||||
// If the parent is a native node without rendered children, but with
|
||||
// multiple string children, then the `element` that gets passed in here is
|
||||
// a plain value -- a string or number.
|
||||
if (typeof element !== 'object') {
|
||||
nodeType = 'Text';
|
||||
text = element + '';
|
||||
} else if (
|
||||
element._currentElement === null ||
|
||||
element._currentElement === false
|
||||
) {
|
||||
nodeType = 'Empty';
|
||||
} else if (element._renderedComponent) {
|
||||
nodeType = 'NativeWrapper';
|
||||
children = [element._renderedComponent];
|
||||
props = element._instance.props;
|
||||
state = element._instance.state;
|
||||
context = element._instance.context;
|
||||
if (context && Object.keys(context).length === 0) {
|
||||
context = null;
|
||||
}
|
||||
} else if (element._renderedChildren) {
|
||||
children = childrenList(element._renderedChildren);
|
||||
} else if (element._currentElement && element._currentElement.props) {
|
||||
// This is a native node without rendered children -- meaning the children
|
||||
// prop is just a string or (in the case of the <option>) a list of
|
||||
// strings & numbers.
|
||||
children = element._currentElement.props.children;
|
||||
}
|
||||
|
||||
if (!props && element._currentElement && element._currentElement.props) {
|
||||
props = element._currentElement.props;
|
||||
}
|
||||
|
||||
// != used deliberately here to catch undefined and null
|
||||
if (element._currentElement != null) {
|
||||
type = element._currentElement.type;
|
||||
if (typeof type === 'string') {
|
||||
name = type;
|
||||
} else if (element.getName) {
|
||||
nodeType = 'Composite';
|
||||
name = element.getName();
|
||||
// 0.14 top-level wrapper
|
||||
// TODO(jared): The backend should just act as if these don't exist.
|
||||
if (
|
||||
element._renderedComponent &&
|
||||
element._currentElement.props ===
|
||||
element._renderedComponent._currentElement
|
||||
) {
|
||||
nodeType = 'Wrapper';
|
||||
}
|
||||
if (name === null) {
|
||||
name = 'No display name';
|
||||
}
|
||||
} else if (element._stringText) {
|
||||
nodeType = 'Text';
|
||||
text = element._stringText;
|
||||
} else {
|
||||
name = type.displayName || type.name || 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
if (element._instance) {
|
||||
const inst = element._instance;
|
||||
updater = {
|
||||
setState: inst.setState && inst.setState.bind(inst),
|
||||
forceUpdate: inst.forceUpdate && inst.forceUpdate.bind(inst),
|
||||
setInProps: inst.forceUpdate && setInProps.bind(null, element),
|
||||
setInState: inst.forceUpdate && setInState.bind(null, inst),
|
||||
setInContext: inst.forceUpdate && setInContext.bind(null, inst),
|
||||
};
|
||||
publicInstance = inst;
|
||||
|
||||
// TODO: React ART currently falls in this bucket, but this doesn't
|
||||
// actually make sense and we should clean this up after stabilizing our
|
||||
// API for backends
|
||||
if (inst._renderedChildren) {
|
||||
children = childrenList(inst._renderedChildren);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
nodeType,
|
||||
type,
|
||||
name,
|
||||
props,
|
||||
state,
|
||||
context,
|
||||
children,
|
||||
text,
|
||||
updater,
|
||||
publicInstance,
|
||||
};
|
||||
}
|
||||
|
||||
function setInProps(internalInst, path: Array<string | number>, value: any) {
|
||||
const element = internalInst._currentElement;
|
||||
internalInst._currentElement = {
|
||||
...element,
|
||||
props: copyWithSet(element.props, path, value),
|
||||
};
|
||||
internalInst._instance.forceUpdate();
|
||||
}
|
||||
|
||||
function setInState(inst, path: Array<string | number>, value: any) {
|
||||
setIn(inst.state, path, value);
|
||||
inst.forceUpdate();
|
||||
}
|
||||
|
||||
function setInContext(inst, path: Array<string | number>, value: any) {
|
||||
setIn(inst.context, path, value);
|
||||
inst.forceUpdate();
|
||||
}
|
||||
|
||||
function setIn(obj: Object, path: Array<string | number>, value: any) {
|
||||
const last = path.pop();
|
||||
const parent = path.reduce((obj_, attr) => (obj_ ? obj_[attr] : null), obj);
|
||||
if (parent) {
|
||||
parent[last] = value;
|
||||
}
|
||||
}
|
||||
|
||||
function childrenList(children) {
|
||||
const res = [];
|
||||
for (const name in children) {
|
||||
res.push(children[name]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function copyWithSetImpl(obj, path, idx, value) {
|
||||
if (idx >= path.length) {
|
||||
return value;
|
||||
}
|
||||
const key = path[idx];
|
||||
const updated = Array.isArray(obj) ? obj.slice() : {...obj};
|
||||
// $FlowFixMe number or string is fine here
|
||||
updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value);
|
||||
return updated;
|
||||
}
|
||||
|
||||
function copyWithSet(
|
||||
obj: Object | Array<any>,
|
||||
path: Array<string | number>,
|
||||
value: any,
|
||||
): Object | Array<any> {
|
||||
return copyWithSetImpl(obj, path, 0, value);
|
||||
}
|
||||
|
||||
module.exports = getData;
|
Reference in New Issue
Block a user