@samitouri / QOS-React-2 / commits / aefb97e6bb

DevTools: Add root and renderer version to inspected props panel (#18963)

* DevTools: Add root and renderer version to inspected props panel * Removed redundant .length check

Brian Vaughn committed May 21, 2020 at 14:40 UTC aefb97e6bb2874e48a08cb87366bc4ca3aa99a7d
10 files changed +111 -18
packages/react-devtools-shared/src/backend/legacy/renderer.js
+4
@@ -802,6 +802,10 @@ export function attach(
802
803 // Location of component in source coude.
804 source,
805 +
806 + rootType: null,
807 + rendererPackageName: null,
808 + rendererVersion: null,
809 };
810 }
811
packages/react-devtools-shared/src/backend/renderer.js
+14
@@ -2278,6 +2278,16 @@ export function attach(
2278 }
2279 }
2280
2281 + let rootType = null;
2282 + let current = fiber;
2283 + while (current.return !== null) {
2284 + current = current.return;
2285 + }
2286 + const fiberRoot = current.stateNode;
2287 + if (fiberRoot != null && fiberRoot._debugRootType !== null) {
2288 + rootType = fiberRoot._debugRootType;
2289 + }
2290 +
2291 return {
2292 id,
2293
@@ -2318,6 +2328,10 @@ export function attach(
2328
2329 // Location of component in source coude.
2330 source: _debugSource || null,
2331 +
2332 + rootType,
2333 + rendererPackageName: renderer.rendererPackageName,
2334 + rendererVersion: renderer.version,
2335 };
2336 }
2337
packages/react-devtools-shared/src/backend/types.js
+9 -1
@@ -87,6 +87,7 @@ export type ReactProviderType<T> = {
87 export type ReactRenderer = {
88 findFiberByHostInstance: (hostInstance: NativeType) => ?Fiber,
89 version: string,
90 + rendererPackageName: string,
91 bundleType: BundleType,
92 // 16.9+
93 overrideHookState?: ?(
@@ -207,10 +208,17 @@ export type InspectedElement = {|
208 // List of owners
209 owners: Array<Owner> | null,
210
210 - // Location of component in source coude.
211 + // Location of component in source code.
212 source: Source | null,
213
214 type: ElementType,
215 +
216 + // Meta information about the root this element belongs to.
217 + rootType: string | null,
218 +
219 + // Meta information about the renderer that created this element.
220 + rendererPackageName: string | null,
221 + rendererVersion: string | null,
222 |};
223
224 export const InspectElementFullDataType = 'full-data';
packages/react-devtools-shared/src/devtools/views/Components/Badge.js
+4 -4
@@ -26,12 +26,12 @@ export default function Badge({
26 type,
27 children,
28 }: Props) {
29 - let totalBadgeCount = 0;
30 -
31 - if (hocDisplayNames !== null) {
32 - totalBadgeCount += hocDisplayNames.length;
29 + if (hocDisplayNames === null) {
30 + return null;
31 }
32
33 + const totalBadgeCount = hocDisplayNames.length;
34 +
35 return (
36 <Fragment>
37 <div className={`${styles.Badge} ${className || ''}`}>{children}</div>
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js
+6
@@ -208,6 +208,9 @@ function InspectedElementContextController({children}: Props) {
208 context,
209 hooks,
210 props,
211 + rendererPackageName,
212 + rendererVersion,
213 + rootType,
214 state,
215 key,
216 } = ((data.value: any): InspectedElementBackend);
@@ -220,6 +223,9 @@ function InspectedElementContextController({children}: Props) {
223 hasLegacyContext,
224 id,
225 key,
226 + rendererPackageName,
227 + rendererVersion,
228 + rootType,
229 source,
230 type,
231 owners:
packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.css
+7
@@ -153,3 +153,10 @@
153 .ContextMenuIcon {
154 margin-right: 0.5rem;
155 }
156 +
157 +.OwnersMetaField {
158 + padding-left: 1.25rem;
159 + white-space: nowrap;
160 + overflow: hidden;
161 + text-overflow: ellipsis;
162 +}
\ No newline at end of file
packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js
+30 -13
@@ -45,7 +45,7 @@ import type {
45 InspectedElementContextType,
46 StoreAsGlobal,
47 } from './InspectedElementContext';
48 -import type {Element, InspectedElement} from './types';
48 +import type {Element, InspectedElement, Owner} from './types';
49 import type {ElementType} from 'react-devtools-shared/src/types';
50
51 export type Props = {||};
@@ -291,11 +291,13 @@ function InspectedElementView({
291 hooks,
292 owners,
293 props,
294 + rendererPackageName,
295 + rendererVersion,
296 + rootType,
297 source,
298 state,
299 } = inspectedElement;
300
298 - const {ownerID} = useContext(TreeStateContext);
301 const bridge = useContext(BridgeContext);
302 const store = useContext(StoreContext);
303
@@ -374,6 +376,14 @@ function InspectedElementView({
376 };
377 }
378
379 + const rendererLabel =
380 + rendererPackageName !== null && rendererVersion !== null
381 + ? `${rendererPackageName}@${rendererVersion}`
382 + : null;
383 + const showOwnersList = owners !== null && owners.length > 0;
384 + const showRenderedBy =
385 + showOwnersList || rendererLabel !== null || rootType !== null;
386 +
387 return (
388 <Fragment>
389 <div className={styles.InspectedElement}>
@@ -415,19 +425,26 @@ function InspectedElementView({
425
426 <NativeStyleEditor />
427
418 - {ownerID === null && owners !== null && owners.length > 0 && (
428 + {showRenderedBy && (
429 <div className={styles.Owners}>
430 <div className={styles.OwnersHeader}>rendered by</div>
421 - {owners.map(owner => (
422 - <OwnerView
423 - key={owner.id}
424 - displayName={owner.displayName || 'Anonymous'}
425 - hocDisplayNames={owner.hocDisplayNames}
426 - id={owner.id}
427 - isInStore={store.containsElement(owner.id)}
428 - type={owner.type}
429 - />
430 - ))}
431 + {showOwnersList &&
432 + ((owners: any): Array<Owner>).map(owner => (
433 + <OwnerView
434 + key={owner.id}
435 + displayName={owner.displayName || 'Anonymous'}
436 + hocDisplayNames={owner.hocDisplayNames}
437 + id={owner.id}
438 + isInStore={store.containsElement(owner.id)}
439 + type={owner.type}
440 + />
441 + ))}
442 + {rootType !== null && (
443 + <div className={styles.OwnersMetaField}>{rootType}</div>
444 + )}
445 + {rendererLabel !== null && (
446 + <div className={styles.OwnersMetaField}>{rendererLabel}</div>
447 + )}
448 </div>
449 )}
450
packages/react-devtools-shared/src/devtools/views/Components/types.js
+7
@@ -88,6 +88,13 @@ export type InspectedElement = {|
88 source: Source | null,
89
90 type: ElementType,
91 +
92 + // Meta information about the root this element belongs to.
93 + rootType: string | null,
94 +
95 + // Meta information about the renderer that created this element.
96 + rendererPackageName: string | null,
97 + rendererVersion: string | null,
98 |};
99
100 // TODO: Add profiling type
packages/react-reconciler/src/ReactFiberRoot.new.js
+15
@@ -24,6 +24,7 @@ import {
24 } from 'shared/ReactFeatureFlags';
25 import {unstable_getThreadID} from 'scheduler/tracing';
26 import {initializeUpdateQueue} from './ReactUpdateQueue.new';
27 +import {LegacyRoot, BlockingRoot, ConcurrentRoot} from './ReactRootTags';
28
29 function FiberRootNode(containerInfo, tag, hydrate) {
30 this.tag = tag;
@@ -60,6 +61,20 @@ function FiberRootNode(containerInfo, tag, hydrate) {
61 if (enableSuspenseCallback) {
62 this.hydrationCallbacks = null;
63 }
64 +
65 + if (__DEV__) {
66 + switch (tag) {
67 + case BlockingRoot:
68 + this._debugRootType = 'createBlockingRoot()';
69 + break;
70 + case ConcurrentRoot:
71 + this._debugRootType = 'createRoot()';
72 + break;
73 + case LegacyRoot:
74 + this._debugRootType = 'createLegacyRoot()';
75 + break;
76 + }
77 + }
78 }
79
80 export function createFiberRoot(
packages/react-reconciler/src/ReactFiberRoot.old.js
+15
@@ -22,6 +22,7 @@ import {unstable_getThreadID} from 'scheduler/tracing';
22 import {NoPriority} from './SchedulerWithReactIntegration.old';
23 import {initializeUpdateQueue} from './ReactUpdateQueue.old';
24 import {clearPendingUpdates as clearPendingMutableSourceUpdates} from './ReactMutableSource.old';
25 +import {LegacyRoot, BlockingRoot, ConcurrentRoot} from './ReactRootTags';
26
27 function FiberRootNode(containerInfo, tag, hydrate) {
28 this.tag = tag;
@@ -54,6 +55,20 @@ function FiberRootNode(containerInfo, tag, hydrate) {
55 if (enableSuspenseCallback) {
56 this.hydrationCallbacks = null;
57 }
58 +
59 + if (__DEV__) {
60 + switch (tag) {
61 + case BlockingRoot:
62 + this._debugRootType = 'createBlockingRoot()';
63 + break;
64 + case ConcurrentRoot:
65 + this._debugRootType = 'createRoot()';
66 + break;
67 + case LegacyRoot:
68 + this._debugRootType = 'createLegacyRoot()';
69 + break;
70 + }
71 + }
72 }
73
74 export function createFiberRoot(