main
js 189 lines 5.03 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 {ReactContext, ReactConsumerType} from 'shared/ReactTypes';
11 import type {Fiber} from './ReactInternalTypes';
12
13 import {
14 disableLegacyMode,
15 enableLegacyHidden,
16 enableViewTransition,
17 } from 'shared/ReactFeatureFlags';
18
19 import {
20 FunctionComponent,
21 ClassComponent,
22 HostRoot,
23 HostPortal,
24 HostComponent,
25 HostHoistable,
26 HostSingleton,
27 HostText,
28 Fragment,
29 Mode,
30 ContextConsumer,
31 ContextProvider,
32 ForwardRef,
33 Profiler,
34 SuspenseComponent,
35 MemoComponent,
36 SimpleMemoComponent,
37 LazyComponent,
38 IncompleteClassComponent,
39 IncompleteFunctionComponent,
40 DehydratedFragment,
41 SuspenseListComponent,
42 ScopeComponent,
43 OffscreenComponent,
44 LegacyHiddenComponent,
45 CacheComponent,
46 TracingMarkerComponent,
47 Throw,
48 ViewTransitionComponent,
49 ActivityComponent,
50 } from 'react-reconciler/src/ReactWorkTags';
51 import getComponentNameFromType from 'shared/getComponentNameFromType';
52 import {REACT_STRICT_MODE_TYPE} from 'shared/ReactSymbols';
53 import type {ReactComponentInfo} from '../../shared/ReactTypes';
54
55 // Keep in sync with shared/getComponentNameFromType
56 function getWrappedName(
57 outerType: mixed,
58 innerType: any,
59 wrapperName: string,
60 ): string {
61 const functionName = innerType.displayName || innerType.name || '';
62 return (
63 (outerType as any).displayName ||
64 (functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName)
65 );
66 }
67
68 // Keep in sync with shared/getComponentNameFromType
69 function getContextName(type: ReactContext<any>) {
70 return type.displayName || 'Context';
71 }
72
73 export function getComponentNameFromOwner(
74 owner: Fiber | ReactComponentInfo,
75 ): string | null {
76 if (typeof owner.tag === 'number') {
77 return getComponentNameFromFiber(owner as any);
78 }
79 if (typeof owner.name === 'string') {
80 return owner.name;
81 }
82 return null;
83 }
84
85 export default function getComponentNameFromFiber(fiber: Fiber): string | null {
86 const {tag, type} = fiber;
87 switch (tag) {
88 case ActivityComponent:
89 return 'Activity';
90 case CacheComponent:
91 return 'Cache';
92 case ContextConsumer:
93 const consumer: ReactConsumerType<any> = type as any;
94 return getContextName(consumer._context) + '.Consumer';
95 case ContextProvider:
96 const context: ReactContext<any> = type as any;
97 return getContextName(context);
98 case DehydratedFragment:
99 return 'DehydratedFragment';
100 case ForwardRef:
101 return getWrappedName(type, type.render, 'ForwardRef');
102 case Fragment:
103 return 'Fragment';
104 case HostHoistable:
105 case HostSingleton:
106 case HostComponent:
107 // Host component type is the display name (e.g. "div", "View")
108 return type;
109 case HostPortal:
110 return 'Portal';
111 case HostRoot:
112 return 'Root';
113 case HostText:
114 return 'Text';
115 case LazyComponent:
116 // Name comes from the type in this case; we don't have a tag.
117 return getComponentNameFromType(type);
118 case Mode:
119 if (type === REACT_STRICT_MODE_TYPE) {
120 // Don't be less specific than shared/getComponentNameFromType
121 return 'StrictMode';
122 }
123 return 'Mode';
124 case OffscreenComponent:
125 if (fiber.return !== null) {
126 return getComponentNameFromFiber(fiber.return);
127 }
128 return null;
129 case Profiler:
130 return 'Profiler';
131 case ScopeComponent:
132 return 'Scope';
133 case SuspenseComponent:
134 return 'Suspense';
135 case SuspenseListComponent:
136 return 'SuspenseList';
137 case TracingMarkerComponent:
138 return 'TracingMarker';
139 case ViewTransitionComponent:
140 if (enableViewTransition) {
141 return 'ViewTransition';
142 }
143 // The display name for these tags come from the user-provided type:
144 // Fallthrough
145 case IncompleteClassComponent:
146 case IncompleteFunctionComponent:
147 if (disableLegacyMode) {
148 break;
149 }
150 // Fallthrough
151 case ClassComponent:
152 case FunctionComponent:
153 case MemoComponent:
154 case SimpleMemoComponent:
155 if (typeof type === 'function') {
156 return (type as any).displayName || type.name || null;
157 }
158 if (typeof type === 'string') {
159 return type;
160 }
161 break;
162 case LegacyHiddenComponent:
163 if (enableLegacyHidden) {
164 return 'LegacyHidden';
165 }
166 break;
167 case Throw: {
168 if (__DEV__) {
169 // For an error in child position we use the name of the inner most parent component.
170 // Whether a Server Component or the parent Fiber.
171 const debugInfo = fiber._debugInfo;
172 if (debugInfo != null) {
173 for (let i = debugInfo.length - 1; i >= 0; i--) {
174 if (typeof debugInfo[i].name === 'string') {
175 return debugInfo[i].name;
176 }
177 }
178 }
179 if (fiber.return === null) {
180 return null;
181 }
182 return getComponentNameFromFiber(fiber.return);
183 }
184 return null;
185 }
186 }
187
188 return null;
189 }