main
js 134 lines 3.9 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import type {LazyComponent} from 'react/src/ReactLazy';
11 import type {ReactContext, ReactConsumerType} from 'shared/ReactTypes';
12
13 import {
14 REACT_CONTEXT_TYPE,
15 REACT_CONSUMER_TYPE,
16 REACT_FORWARD_REF_TYPE,
17 REACT_FRAGMENT_TYPE,
18 REACT_PORTAL_TYPE,
19 REACT_MEMO_TYPE,
20 REACT_PROFILER_TYPE,
21 REACT_STRICT_MODE_TYPE,
22 REACT_SUSPENSE_TYPE,
23 REACT_SUSPENSE_LIST_TYPE,
24 REACT_LAZY_TYPE,
25 REACT_TRACING_MARKER_TYPE,
26 REACT_VIEW_TRANSITION_TYPE,
27 REACT_ACTIVITY_TYPE,
28 } from 'shared/ReactSymbols';
29
30 import {
31 enableTransitionTracing,
32 enableViewTransition,
33 } from './ReactFeatureFlags';
34
35 // Keep in sync with react-reconciler/getComponentNameFromFiber
36 function getWrappedName(
37 outerType: mixed,
38 innerType: any,
39 wrapperName: string,
40 ): string {
41 const displayName = (outerType as any).displayName;
42 if (displayName) {
43 return displayName;
44 }
45 const functionName = innerType.displayName || innerType.name || '';
46 return functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName;
47 }
48
49 // Keep in sync with react-reconciler/getComponentNameFromFiber
50 function getContextName(type: ReactContext<any>) {
51 return type.displayName || 'Context';
52 }
53
54 const REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference');
55
56 // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.
57 export default function getComponentNameFromType(type: mixed): string | null {
58 if (type == null) {
59 // Host root, text node or just invalid type.
60 return null;
61 }
62 if (typeof type === 'function') {
63 if ((type as any).$$typeof === REACT_CLIENT_REFERENCE) {
64 // TODO: Create a convention for naming client references with debug info.
65 return null;
66 }
67 return (type as any).displayName || type.name || null;
68 }
69 if (typeof type === 'string') {
70 return type;
71 }
72 switch (type) {
73 case REACT_FRAGMENT_TYPE:
74 return 'Fragment';
75 case REACT_PROFILER_TYPE:
76 return 'Profiler';
77 case REACT_STRICT_MODE_TYPE:
78 return 'StrictMode';
79 case REACT_SUSPENSE_TYPE:
80 return 'Suspense';
81 case REACT_SUSPENSE_LIST_TYPE:
82 return 'SuspenseList';
83 case REACT_ACTIVITY_TYPE:
84 return 'Activity';
85 case REACT_VIEW_TRANSITION_TYPE:
86 if (enableViewTransition) {
87 return 'ViewTransition';
88 }
89 // Fall through
90 case REACT_TRACING_MARKER_TYPE:
91 if (enableTransitionTracing) {
92 return 'TracingMarker';
93 }
94 }
95 if (typeof type === 'object') {
96 if (__DEV__) {
97 if (typeof (type as any).tag === 'number') {
98 console.error(
99 'Received an unexpected object in getComponentNameFromType(). ' +
100 'This is likely a bug in React. Please file an issue.',
101 );
102 }
103 }
104 switch (type.$$typeof) {
105 case REACT_PORTAL_TYPE:
106 return 'Portal';
107 case REACT_CONTEXT_TYPE:
108 const context: ReactContext<any> = type as any;
109 return getContextName(context);
110 case REACT_CONSUMER_TYPE:
111 const consumer: ReactConsumerType<any> = type as any;
112 return getContextName(consumer._context) + '.Consumer';
113 case REACT_FORWARD_REF_TYPE:
114 return getWrappedName(type, type.render, 'ForwardRef');
115 case REACT_MEMO_TYPE:
116 const outerName = (type as any).displayName || null;
117 if (outerName !== null) {
118 return outerName;
119 }
120 return getComponentNameFromType(type.type) || 'Memo';
121 case REACT_LAZY_TYPE: {
122 const lazyComponent: LazyComponent<any, any> = type as any;
123 const payload = lazyComponent._payload;
124 const init = lazyComponent._init;
125 try {
126 return getComponentNameFromType(init(payload));
127 } catch (x) {
128 return null;
129 }
130 }
131 }
132 }
133 return null;
134 }