[DevTools] chore: extract getInternalReactConstants (#35986)
The test is quite naive, but worth having as additional check for changes in this logic.
Ruslan Lesiutin committed
Mar 20, 2026 at 14:17 UTC
8b2e903a7447d370eb77bb117bc4c0ae240ce831
2 files changed
+518
-490
packages/react-devtools-shared/src/backend/fiber/renderer.js
+1
-490
@@ -46,8 +46,6 @@ import {
46
} from 'react-devtools-shared/src/frontend/types';
47
import {
48
deletePathInObject,
49
- getDisplayName,
50
- getWrappedDisplayName,
49
getInObject,
50
getUID,
51
renamePathInObject,
@@ -57,7 +55,6 @@ import {
55
import {
56
formatConsoleArgumentsToSingleString,
57
formatDurationToMicrosecondsGranularity,
60
- gt,
58
gte,
59
serializeToString,
60
} from 'react-devtools-shared/src/backend/utils';
@@ -109,14 +106,6 @@ import {
106
STRICT_MODE_SYMBOL_STRING,
107
PROFILER_NUMBER,
108
PROFILER_SYMBOL_STRING,
112
- REACT_MEMO_CACHE_SENTINEL,
113
- SCOPE_NUMBER,
114
- SCOPE_SYMBOL_STRING,
115
- FORWARD_REF_NUMBER,
116
- FORWARD_REF_SYMBOL_STRING,
117
- MEMO_NUMBER,
118
- MEMO_SYMBOL_STRING,
119
- SERVER_CONTEXT_SYMBOL_STRING,
109
LAZY_SYMBOL_STRING,
110
REACT_OPTIMISTIC_KEY,
111
} from '../shared/ReactSymbols';
@@ -144,6 +133,7 @@ import {
133
getChangedHooksIndices,
134
getChangedKeys,
135
} from './shared/DevToolsFiberChangeDetection';
136
+import {getInternalReactConstants} from './shared/DevToolsFiberInternalReactConstants';
137
import {
138
ioExistsInSuspenseAncestor,
139
getAwaitInSuspendedByFromIO,
@@ -179,7 +169,6 @@ import type {
169
RendererInterface,
170
SerializedElement,
171
SerializedAsyncInfo,
182
- WorkTagMap,
172
CurrentDispatcherRef,
173
LegacyDispatcherRef,
174
ProfilingSettings,
@@ -284,18 +273,6 @@ function createSuspenseNode(
273
});
274
}
275
287
-type getDisplayNameForFiberType = (fiber: Fiber) => string | null;
288
-type getTypeSymbolType = (type: any) => symbol | string | number;
289
-
290
-type ReactPriorityLevelsType = {
291
- ImmediatePriority: number,
292
- UserBlockingPriority: number,
293
- NormalPriority: number,
294
- LowPriority: number,
295
- IdlePriority: number,
296
- NoPriority: number,
297
-};
298
-
276
export function getDispatcherRef(renderer: {
277
+currentDispatcherRef?: LegacyDispatcherRef | CurrentDispatcherRef,
278
...
@@ -321,472 +298,6 @@ export function getDispatcherRef(renderer: {
298
return (injectedRef: any);
299
}
300
324
-export function getInternalReactConstants(version: string): {
325
- getDisplayNameForFiber: getDisplayNameForFiberType,
326
- getTypeSymbol: getTypeSymbolType,
327
- ReactPriorityLevels: ReactPriorityLevelsType,
328
- ReactTypeOfWork: WorkTagMap,
329
- StrictModeBits: number,
330
- SuspenseyImagesMode: number,
331
-} {
332
- // **********************************************************
333
- // The section below is copied from files in React repo.
334
- // Keep it in sync, and add version guards if it changes.
335
- //
336
- // Technically these priority levels are invalid for versions before 16.9,
337
- // but 16.9 is the first version to report priority level to DevTools,
338
- // so we can avoid checking for earlier versions and support pre-16.9 canary releases in the process.
339
- let ReactPriorityLevels: ReactPriorityLevelsType = {
340
- ImmediatePriority: 99,
341
- UserBlockingPriority: 98,
342
- NormalPriority: 97,
343
- LowPriority: 96,
344
- IdlePriority: 95,
345
- NoPriority: 90,
346
- };
347
-
348
- if (gt(version, '17.0.2')) {
349
- ReactPriorityLevels = {
350
- ImmediatePriority: 1,
351
- UserBlockingPriority: 2,
352
- NormalPriority: 3,
353
- LowPriority: 4,
354
- IdlePriority: 5,
355
- NoPriority: 0,
356
- };
357
- }
358
-
359
- let StrictModeBits = 0;
360
- if (gte(version, '18.0.0-alpha')) {
361
- // 18+
362
- StrictModeBits = 0b011000;
363
- } else if (gte(version, '16.9.0')) {
364
- // 16.9 - 17
365
- StrictModeBits = 0b1;
366
- } else if (gte(version, '16.3.0')) {
367
- // 16.3 - 16.8
368
- StrictModeBits = 0b10;
369
- }
370
-
371
- const SuspenseyImagesMode = 0b0100000;
372
-
373
- let ReactTypeOfWork: WorkTagMap = ((null: any): WorkTagMap);
374
-
375
- // **********************************************************
376
- // The section below is copied from files in React repo.
377
- // Keep it in sync, and add version guards if it changes.
378
- //
379
- // TODO Update the gt() check below to be gte() whichever the next version number is.
380
- // Currently the version in Git is 17.0.2 (but that version has not been/may not end up being released).
381
- if (gt(version, '17.0.1')) {
382
- ReactTypeOfWork = {
383
- CacheComponent: 24, // Experimental
384
- ClassComponent: 1,
385
- ContextConsumer: 9,
386
- ContextProvider: 10,
387
- CoroutineComponent: -1, // Removed
388
- CoroutineHandlerPhase: -1, // Removed
389
- DehydratedSuspenseComponent: 18, // Behind a flag
390
- ForwardRef: 11,
391
- Fragment: 7,
392
- FunctionComponent: 0,
393
- HostComponent: 5,
394
- HostPortal: 4,
395
- HostRoot: 3,
396
- HostHoistable: 26, // In reality, 18.2+. But doesn't hurt to include it here
397
- HostSingleton: 27, // Same as above
398
- HostText: 6,
399
- IncompleteClassComponent: 17,
400
- IncompleteFunctionComponent: 28,
401
- IndeterminateComponent: 2, // removed in 19.0.0
402
- LazyComponent: 16,
403
- LegacyHiddenComponent: 23, // Does not exist in 18+ OSS but exists in fb builds
404
- MemoComponent: 14,
405
- Mode: 8,
406
- OffscreenComponent: 22, // Experimental in 17. Stable in 18+
407
- Profiler: 12,
408
- ScopeComponent: 21, // Experimental
409
- SimpleMemoComponent: 15,
410
- SuspenseComponent: 13,
411
- SuspenseListComponent: 19, // Experimental
412
- TracingMarkerComponent: 25, // Experimental - This is technically in 18 but we don't
413
- // want to fork again so we're adding it here instead
414
- YieldComponent: -1, // Removed
415
- Throw: 29,
416
- ViewTransitionComponent: 30, // Experimental
417
- ActivityComponent: 31,
418
- };
419
- } else if (gte(version, '17.0.0-alpha')) {
420
- ReactTypeOfWork = {
421
- CacheComponent: -1, // Doesn't exist yet
422
- ClassComponent: 1,
423
- ContextConsumer: 9,
424
- ContextProvider: 10,
425
- CoroutineComponent: -1, // Removed
426
- CoroutineHandlerPhase: -1, // Removed
427
- DehydratedSuspenseComponent: 18, // Behind a flag
428
- ForwardRef: 11,
429
- Fragment: 7,
430
- FunctionComponent: 0,
431
- HostComponent: 5,
432
- HostPortal: 4,
433
- HostRoot: 3,
434
- HostHoistable: -1, // Doesn't exist yet
435
- HostSingleton: -1, // Doesn't exist yet
436
- HostText: 6,
437
- IncompleteClassComponent: 17,
438
- IncompleteFunctionComponent: -1, // Doesn't exist yet
439
- IndeterminateComponent: 2,
440
- LazyComponent: 16,
441
- LegacyHiddenComponent: 24,
442
- MemoComponent: 14,
443
- Mode: 8,
444
- OffscreenComponent: 23, // Experimental
445
- Profiler: 12,
446
- ScopeComponent: 21, // Experimental
447
- SimpleMemoComponent: 15,
448
- SuspenseComponent: 13,
449
- SuspenseListComponent: 19, // Experimental
450
- TracingMarkerComponent: -1, // Doesn't exist yet
451
- YieldComponent: -1, // Removed
452
- Throw: -1, // Doesn't exist yet
453
- ViewTransitionComponent: -1, // Doesn't exist yet
454
- ActivityComponent: -1, // Doesn't exist yet
455
- };
456
- } else if (gte(version, '16.6.0-beta.0')) {
457
- ReactTypeOfWork = {
458
- CacheComponent: -1, // Doesn't exist yet
459
- ClassComponent: 1,
460
- ContextConsumer: 9,
461
- ContextProvider: 10,
462
- CoroutineComponent: -1, // Removed
463
- CoroutineHandlerPhase: -1, // Removed
464
- DehydratedSuspenseComponent: 18, // Behind a flag
465
- ForwardRef: 11,
466
- Fragment: 7,
467
- FunctionComponent: 0,
468
- HostComponent: 5,
469
- HostPortal: 4,
470
- HostRoot: 3,
471
- HostHoistable: -1, // Doesn't exist yet
472
- HostSingleton: -1, // Doesn't exist yet
473
- HostText: 6,
474
- IncompleteClassComponent: 17,
475
- IncompleteFunctionComponent: -1, // Doesn't exist yet
476
- IndeterminateComponent: 2,
477
- LazyComponent: 16,
478
- LegacyHiddenComponent: -1,
479
- MemoComponent: 14,
480
- Mode: 8,
481
- OffscreenComponent: -1, // Experimental
482
- Profiler: 12,
483
- ScopeComponent: -1, // Experimental
484
- SimpleMemoComponent: 15,
485
- SuspenseComponent: 13,
486
- SuspenseListComponent: 19, // Experimental
487
- TracingMarkerComponent: -1, // Doesn't exist yet
488
- YieldComponent: -1, // Removed
489
- Throw: -1, // Doesn't exist yet
490
- ViewTransitionComponent: -1, // Doesn't exist yet
491
- ActivityComponent: -1, // Doesn't exist yet
492
- };
493
- } else if (gte(version, '16.4.3-alpha')) {
494
- ReactTypeOfWork = {
495
- CacheComponent: -1, // Doesn't exist yet
496
- ClassComponent: 2,
497
- ContextConsumer: 11,
498
- ContextProvider: 12,
499
- CoroutineComponent: -1, // Removed
500
- CoroutineHandlerPhase: -1, // Removed
501
- DehydratedSuspenseComponent: -1, // Doesn't exist yet
502
- ForwardRef: 13,
503
- Fragment: 9,
504
- FunctionComponent: 0,
505
- HostComponent: 7,
506
- HostPortal: 6,
507
- HostRoot: 5,
508
- HostHoistable: -1, // Doesn't exist yet
509
- HostSingleton: -1, // Doesn't exist yet
510
- HostText: 8,
511
- IncompleteClassComponent: -1, // Doesn't exist yet
512
- IncompleteFunctionComponent: -1, // Doesn't exist yet
513
- IndeterminateComponent: 4,
514
- LazyComponent: -1, // Doesn't exist yet
515
- LegacyHiddenComponent: -1,
516
- MemoComponent: -1, // Doesn't exist yet
517
- Mode: 10,
518
- OffscreenComponent: -1, // Experimental
519
- Profiler: 15,
520
- ScopeComponent: -1, // Experimental
521
- SimpleMemoComponent: -1, // Doesn't exist yet
522
- SuspenseComponent: 16,
523
- SuspenseListComponent: -1, // Doesn't exist yet
524
- TracingMarkerComponent: -1, // Doesn't exist yet
525
- YieldComponent: -1, // Removed
526
- Throw: -1, // Doesn't exist yet
527
- ViewTransitionComponent: -1, // Doesn't exist yet
528
- ActivityComponent: -1, // Doesn't exist yet
529
- };
530
- } else {
531
- ReactTypeOfWork = {
532
- CacheComponent: -1, // Doesn't exist yet
533
- ClassComponent: 2,
534
- ContextConsumer: 12,
535
- ContextProvider: 13,
536
- CoroutineComponent: 7,
537
- CoroutineHandlerPhase: 8,
538
- DehydratedSuspenseComponent: -1, // Doesn't exist yet
539
- ForwardRef: 14,
540
- Fragment: 10,
541
- FunctionComponent: 1,
542
- HostComponent: 5,
543
- HostPortal: 4,
544
- HostRoot: 3,
545
- HostHoistable: -1, // Doesn't exist yet
546
- HostSingleton: -1, // Doesn't exist yet
547
- HostText: 6,
548
- IncompleteClassComponent: -1, // Doesn't exist yet
549
- IncompleteFunctionComponent: -1, // Doesn't exist yet
550
- IndeterminateComponent: 0,
551
- LazyComponent: -1, // Doesn't exist yet
552
- LegacyHiddenComponent: -1,
553
- MemoComponent: -1, // Doesn't exist yet
554
- Mode: 11,
555
- OffscreenComponent: -1, // Experimental
556
- Profiler: 15,
557
- ScopeComponent: -1, // Experimental
558
- SimpleMemoComponent: -1, // Doesn't exist yet
559
- SuspenseComponent: 16,
560
- SuspenseListComponent: -1, // Doesn't exist yet
561
- TracingMarkerComponent: -1, // Doesn't exist yet
562
- YieldComponent: 9,
563
- Throw: -1, // Doesn't exist yet
564
- ViewTransitionComponent: -1, // Doesn't exist yet
565
- ActivityComponent: -1, // Doesn't exist yet
566
- };
567
- }
568
- // **********************************************************
569
- // End of copied code.
570
- // **********************************************************
571
-
572
- function getTypeSymbol(type: any): symbol | string | number {
573
- const symbolOrNumber =
574
- typeof type === 'object' && type !== null ? type.$$typeof : type;
575
-
576
- return typeof symbolOrNumber === 'symbol'
577
- ? symbolOrNumber.toString()
578
- : symbolOrNumber;
579
- }
580
-
581
- const {
582
- CacheComponent,
583
- ClassComponent,
584
- IncompleteClassComponent,
585
- IncompleteFunctionComponent,
586
- FunctionComponent,
587
- IndeterminateComponent,
588
- ForwardRef,
589
- HostRoot,
590
- HostHoistable,
591
- HostSingleton,
592
- HostComponent,
593
- HostPortal,
594
- HostText,
595
- Fragment,
596
- LazyComponent,
597
- LegacyHiddenComponent,
598
- MemoComponent,
599
- OffscreenComponent,
600
- Profiler,
601
- ScopeComponent,
602
- SimpleMemoComponent,
603
- SuspenseComponent,
604
- SuspenseListComponent,
605
- TracingMarkerComponent,
606
- Throw,
607
- ViewTransitionComponent,
608
- ActivityComponent,
609
- } = ReactTypeOfWork;
610
-
611
- function resolveFiberType(type: any): $FlowFixMe {
612
- const typeSymbol = getTypeSymbol(type);
613
- switch (typeSymbol) {
614
- case MEMO_NUMBER:
615
- case MEMO_SYMBOL_STRING:
616
- // recursively resolving memo type in case of memo(forwardRef(Component))
617
- return resolveFiberType(type.type);
618
- case FORWARD_REF_NUMBER:
619
- case FORWARD_REF_SYMBOL_STRING:
620
- return type.render;
621
- default:
622
- return type;
623
- }
624
- }
625
-
626
- // NOTICE Keep in sync with shouldFilterFiber() and other get*ForFiber methods
627
- function getDisplayNameForFiber(
628
- fiber: Fiber,
629
- shouldSkipForgetCheck: boolean = false,
630
- ): string | null {
631
- const {elementType, type, tag} = fiber;
632
-
633
- let resolvedType = type;
634
- if (typeof type === 'object' && type !== null) {
635
- resolvedType = resolveFiberType(type);
636
- }
637
-
638
- let resolvedContext: any = null;
639
- if (
640
- !shouldSkipForgetCheck &&
641
- // $FlowFixMe[incompatible-type] fiber.updateQueue is mixed
642
- (fiber.updateQueue?.memoCache != null ||
643
- (Array.isArray(fiber.memoizedState?.memoizedState) &&
644
- fiber.memoizedState.memoizedState[0]?.[REACT_MEMO_CACHE_SENTINEL]) ||
645
- fiber.memoizedState?.memoizedState?.[REACT_MEMO_CACHE_SENTINEL])
646
- ) {
647
- const displayNameWithoutForgetWrapper = getDisplayNameForFiber(
648
- fiber,
649
- true,
650
- );
651
- if (displayNameWithoutForgetWrapper == null) {
652
- return null;
653
- }
654
-
655
- return `Forget(${displayNameWithoutForgetWrapper})`;
656
- }
657
-
658
- switch (tag) {
659
- case ActivityComponent:
660
- return 'Activity';
661
- case CacheComponent:
662
- return 'Cache';
663
- case ClassComponent:
664
- case IncompleteClassComponent:
665
- case IncompleteFunctionComponent:
666
- case FunctionComponent:
667
- case IndeterminateComponent:
668
- return getDisplayName(resolvedType);
669
- case ForwardRef:
670
- return getWrappedDisplayName(
671
- elementType,
672
- resolvedType,
673
- 'ForwardRef',
674
- 'Anonymous',
675
- );
676
- case HostRoot:
677
- const fiberRoot = fiber.stateNode;
678
- if (fiberRoot != null && fiberRoot._debugRootType !== null) {
679
- return fiberRoot._debugRootType;
680
- }
681
- return null;
682
- case HostComponent:
683
- case HostSingleton:
684
- case HostHoistable:
685
- return type;
686
- case HostPortal:
687
- case HostText:
688
- return null;
689
- case Fragment:
690
- return 'Fragment';
691
- case LazyComponent:
692
- // This display name will not be user visible.
693
- // Once a Lazy component loads its inner component, React replaces the tag and type.
694
- // This display name will only show up in console logs when DevTools DEBUG mode is on.
695
- return 'Lazy';
696
- case MemoComponent:
697
- case SimpleMemoComponent:
698
- // Display name in React does not use `Memo` as a wrapper but fallback name.
699
- return getWrappedDisplayName(
700
- elementType,
701
- resolvedType,
702
- 'Memo',
703
- 'Anonymous',
704
- );
705
- case SuspenseComponent:
706
- return 'Suspense';
707
- case LegacyHiddenComponent:
708
- return 'LegacyHidden';
709
- case OffscreenComponent:
710
- return 'Offscreen';
711
- case ScopeComponent:
712
- return 'Scope';
713
- case SuspenseListComponent:
714
- return 'SuspenseList';
715
- case Profiler:
716
- return 'Profiler';
717
- case TracingMarkerComponent:
718
- return 'TracingMarker';
719
- case ViewTransitionComponent:
720
- return 'ViewTransition';
721
- case Throw:
722
- // This should really never be visible.
723
- return 'Error';
724
- default:
725
- const typeSymbol = getTypeSymbol(type);
726
-
727
- switch (typeSymbol) {
728
- case CONCURRENT_MODE_NUMBER:
729
- case CONCURRENT_MODE_SYMBOL_STRING:
730
- case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
731
- return null;
732
- case PROVIDER_NUMBER:
733
- case PROVIDER_SYMBOL_STRING:
734
- // 16.3.0 exposed the context object as "context"
735
- // PR #12501 changed it to "_context" for 16.3.1+
736
- // NOTE Keep in sync with inspectElementRaw()
737
- resolvedContext = fiber.type._context || fiber.type.context;
738
- return `${resolvedContext.displayName || 'Context'}.Provider`;
739
- case CONTEXT_NUMBER:
740
- case CONTEXT_SYMBOL_STRING:
741
- case SERVER_CONTEXT_SYMBOL_STRING:
742
- if (
743
- fiber.type._context === undefined &&
744
- fiber.type.Provider === fiber.type
745
- ) {
746
- // In 19+, Context.Provider === Context, so this is a provider.
747
- resolvedContext = fiber.type;
748
- return `${resolvedContext.displayName || 'Context'}.Provider`;
749
- }
750
-
751
- // 16.3-16.5 read from "type" because the Consumer is the actual context object.
752
- // 16.6+ should read from "type._context" because Consumer can be different (in DEV).
753
- // NOTE Keep in sync with inspectElementRaw()
754
- resolvedContext = fiber.type._context || fiber.type;
755
-
756
- // NOTE: TraceUpdatesBackendManager depends on the name ending in '.Consumer'
757
- // If you change the name, figure out a more resilient way to detect it.
758
- return `${resolvedContext.displayName || 'Context'}.Consumer`;
759
- case CONSUMER_SYMBOL_STRING:
760
- // 19+
761
- resolvedContext = fiber.type._context;
762
- return `${resolvedContext.displayName || 'Context'}.Consumer`;
763
- case STRICT_MODE_NUMBER:
764
- case STRICT_MODE_SYMBOL_STRING:
765
- return null;
766
- case PROFILER_NUMBER:
767
- case PROFILER_SYMBOL_STRING:
768
- return `Profiler(${fiber.memoizedProps.id})`;
769
- case SCOPE_NUMBER:
770
- case SCOPE_SYMBOL_STRING:
771
- return 'Scope';
772
- default:
773
- // Unknown element type.
774
- // This may mean a new element type that has not yet been added to DevTools.
775
- return null;
776
- }
777
- }
778
- }
779
-
780
- return {
781
- getDisplayNameForFiber,
782
- getTypeSymbol,
783
- ReactPriorityLevels,
784
- ReactTypeOfWork,
785
- StrictModeBits,
786
- SuspenseyImagesMode,
787
- };
788
-}
789
-
301
// All environment names we've seen so far. This lets us create a list of filters to apply.
302
// This should ideally include env of filtered Components too so that you can add those as
303
// filters at the same time as removing some other filter.
packages/react-devtools-shared/src/backend/fiber/shared/DevToolsFiberInternalReactConstants.js
new
+517
@@ -0,0 +1,517 @@
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 {Fiber} from 'react-reconciler/src/ReactInternalTypes';
11
+import type {WorkTagMap} from 'react-devtools-shared/src/backend/types';
12
+
13
+import {
14
+ getDisplayName,
15
+ getWrappedDisplayName,
16
+} from 'react-devtools-shared/src/utils';
17
+import {gt, gte} from 'react-devtools-shared/src/backend/utils';
18
+import {
19
+ CONCURRENT_MODE_NUMBER,
20
+ CONCURRENT_MODE_SYMBOL_STRING,
21
+ DEPRECATED_ASYNC_MODE_SYMBOL_STRING,
22
+ PROVIDER_NUMBER,
23
+ PROVIDER_SYMBOL_STRING,
24
+ CONTEXT_NUMBER,
25
+ CONTEXT_SYMBOL_STRING,
26
+ CONSUMER_SYMBOL_STRING,
27
+ STRICT_MODE_NUMBER,
28
+ STRICT_MODE_SYMBOL_STRING,
29
+ PROFILER_NUMBER,
30
+ PROFILER_SYMBOL_STRING,
31
+ REACT_MEMO_CACHE_SENTINEL,
32
+ SCOPE_NUMBER,
33
+ SCOPE_SYMBOL_STRING,
34
+ FORWARD_REF_NUMBER,
35
+ FORWARD_REF_SYMBOL_STRING,
36
+ MEMO_NUMBER,
37
+ MEMO_SYMBOL_STRING,
38
+ SERVER_CONTEXT_SYMBOL_STRING,
39
+} from 'react-devtools-shared/src/backend/shared/ReactSymbols';
40
+
41
+export type getDisplayNameForFiberType = (fiber: Fiber) => string | null;
42
+export type getTypeSymbolType = (type: any) => symbol | string | number;
43
+
44
+export type ReactPriorityLevelsType = {
45
+ ImmediatePriority: number,
46
+ UserBlockingPriority: number,
47
+ NormalPriority: number,
48
+ LowPriority: number,
49
+ IdlePriority: number,
50
+ NoPriority: number,
51
+};
52
+
53
+export function getInternalReactConstants(version: string): {
54
+ getDisplayNameForFiber: getDisplayNameForFiberType,
55
+ getTypeSymbol: getTypeSymbolType,
56
+ ReactPriorityLevels: ReactPriorityLevelsType,
57
+ ReactTypeOfWork: WorkTagMap,
58
+ StrictModeBits: number,
59
+ SuspenseyImagesMode: number,
60
+} {
61
+ // **********************************************************
62
+ // The section below is copied from files in React repo.
63
+ // Keep it in sync, and add version guards if it changes.
64
+ //
65
+ // Technically these priority levels are invalid for versions before 16.9,
66
+ // but 16.9 is the first version to report priority level to DevTools,
67
+ // so we can avoid checking for earlier versions and support pre-16.9 canary releases in the process.
68
+ let ReactPriorityLevels: ReactPriorityLevelsType = {
69
+ ImmediatePriority: 99,
70
+ UserBlockingPriority: 98,
71
+ NormalPriority: 97,
72
+ LowPriority: 96,
73
+ IdlePriority: 95,
74
+ NoPriority: 90,
75
+ };
76
+
77
+ if (gt(version, '17.0.2')) {
78
+ ReactPriorityLevels = {
79
+ ImmediatePriority: 1,
80
+ UserBlockingPriority: 2,
81
+ NormalPriority: 3,
82
+ LowPriority: 4,
83
+ IdlePriority: 5,
84
+ NoPriority: 0,
85
+ };
86
+ }
87
+
88
+ let StrictModeBits = 0;
89
+ if (gte(version, '18.0.0-alpha')) {
90
+ // 18+
91
+ StrictModeBits = 0b011000;
92
+ } else if (gte(version, '16.9.0')) {
93
+ // 16.9 - 17
94
+ StrictModeBits = 0b1;
95
+ } else if (gte(version, '16.3.0')) {
96
+ // 16.3 - 16.8
97
+ StrictModeBits = 0b10;
98
+ }
99
+
100
+ const SuspenseyImagesMode = 0b0100000;
101
+
102
+ let ReactTypeOfWork: WorkTagMap = ((null: any): WorkTagMap);
103
+
104
+ // **********************************************************
105
+ // The section below is copied from files in React repo.
106
+ // Keep it in sync, and add version guards if it changes.
107
+ //
108
+ // TODO Update the gt() check below to be gte() whichever the next version number is.
109
+ // Currently the version in Git is 17.0.2 (but that version has not been/may not end up being released).
110
+ if (gt(version, '17.0.1')) {
111
+ ReactTypeOfWork = {
112
+ CacheComponent: 24, // Experimental
113
+ ClassComponent: 1,
114
+ ContextConsumer: 9,
115
+ ContextProvider: 10,
116
+ CoroutineComponent: -1, // Removed
117
+ CoroutineHandlerPhase: -1, // Removed
118
+ DehydratedSuspenseComponent: 18, // Behind a flag
119
+ ForwardRef: 11,
120
+ Fragment: 7,
121
+ FunctionComponent: 0,
122
+ HostComponent: 5,
123
+ HostPortal: 4,
124
+ HostRoot: 3,
125
+ HostHoistable: 26, // In reality, 18.2+. But doesn't hurt to include it here
126
+ HostSingleton: 27, // Same as above
127
+ HostText: 6,
128
+ IncompleteClassComponent: 17,
129
+ IncompleteFunctionComponent: 28,
130
+ IndeterminateComponent: 2, // removed in 19.0.0
131
+ LazyComponent: 16,
132
+ LegacyHiddenComponent: 23, // Does not exist in 18+ OSS but exists in fb builds
133
+ MemoComponent: 14,
134
+ Mode: 8,
135
+ OffscreenComponent: 22, // Experimental in 17. Stable in 18+
136
+ Profiler: 12,
137
+ ScopeComponent: 21, // Experimental
138
+ SimpleMemoComponent: 15,
139
+ SuspenseComponent: 13,
140
+ SuspenseListComponent: 19, // Experimental
141
+ TracingMarkerComponent: 25, // Experimental - This is technically in 18 but we don't
142
+ // want to fork again so we're adding it here instead
143
+ YieldComponent: -1, // Removed
144
+ Throw: 29,
145
+ ViewTransitionComponent: 30, // Experimental
146
+ ActivityComponent: 31,
147
+ };
148
+ } else if (gte(version, '17.0.0-alpha')) {
149
+ ReactTypeOfWork = {
150
+ CacheComponent: -1, // Doesn't exist yet
151
+ ClassComponent: 1,
152
+ ContextConsumer: 9,
153
+ ContextProvider: 10,
154
+ CoroutineComponent: -1, // Removed
155
+ CoroutineHandlerPhase: -1, // Removed
156
+ DehydratedSuspenseComponent: 18, // Behind a flag
157
+ ForwardRef: 11,
158
+ Fragment: 7,
159
+ FunctionComponent: 0,
160
+ HostComponent: 5,
161
+ HostPortal: 4,
162
+ HostRoot: 3,
163
+ HostHoistable: -1, // Doesn't exist yet
164
+ HostSingleton: -1, // Doesn't exist yet
165
+ HostText: 6,
166
+ IncompleteClassComponent: 17,
167
+ IncompleteFunctionComponent: -1, // Doesn't exist yet
168
+ IndeterminateComponent: 2,
169
+ LazyComponent: 16,
170
+ LegacyHiddenComponent: 24,
171
+ MemoComponent: 14,
172
+ Mode: 8,
173
+ OffscreenComponent: 23, // Experimental
174
+ Profiler: 12,
175
+ ScopeComponent: 21, // Experimental
176
+ SimpleMemoComponent: 15,
177
+ SuspenseComponent: 13,
178
+ SuspenseListComponent: 19, // Experimental
179
+ TracingMarkerComponent: -1, // Doesn't exist yet
180
+ YieldComponent: -1, // Removed
181
+ Throw: -1, // Doesn't exist yet
182
+ ViewTransitionComponent: -1, // Doesn't exist yet
183
+ ActivityComponent: -1, // Doesn't exist yet
184
+ };
185
+ } else if (gte(version, '16.6.0-beta.0')) {
186
+ ReactTypeOfWork = {
187
+ CacheComponent: -1, // Doesn't exist yet
188
+ ClassComponent: 1,
189
+ ContextConsumer: 9,
190
+ ContextProvider: 10,
191
+ CoroutineComponent: -1, // Removed
192
+ CoroutineHandlerPhase: -1, // Removed
193
+ DehydratedSuspenseComponent: 18, // Behind a flag
194
+ ForwardRef: 11,
195
+ Fragment: 7,
196
+ FunctionComponent: 0,
197
+ HostComponent: 5,
198
+ HostPortal: 4,
199
+ HostRoot: 3,
200
+ HostHoistable: -1, // Doesn't exist yet
201
+ HostSingleton: -1, // Doesn't exist yet
202
+ HostText: 6,
203
+ IncompleteClassComponent: 17,
204
+ IncompleteFunctionComponent: -1, // Doesn't exist yet
205
+ IndeterminateComponent: 2,
206
+ LazyComponent: 16,
207
+ LegacyHiddenComponent: -1,
208
+ MemoComponent: 14,
209
+ Mode: 8,
210
+ OffscreenComponent: -1, // Experimental
211
+ Profiler: 12,
212
+ ScopeComponent: -1, // Experimental
213
+ SimpleMemoComponent: 15,
214
+ SuspenseComponent: 13,
215
+ SuspenseListComponent: 19, // Experimental
216
+ TracingMarkerComponent: -1, // Doesn't exist yet
217
+ YieldComponent: -1, // Removed
218
+ Throw: -1, // Doesn't exist yet
219
+ ViewTransitionComponent: -1, // Doesn't exist yet
220
+ ActivityComponent: -1, // Doesn't exist yet
221
+ };
222
+ } else if (gte(version, '16.4.3-alpha')) {
223
+ ReactTypeOfWork = {
224
+ CacheComponent: -1, // Doesn't exist yet
225
+ ClassComponent: 2,
226
+ ContextConsumer: 11,
227
+ ContextProvider: 12,
228
+ CoroutineComponent: -1, // Removed
229
+ CoroutineHandlerPhase: -1, // Removed
230
+ DehydratedSuspenseComponent: -1, // Doesn't exist yet
231
+ ForwardRef: 13,
232
+ Fragment: 9,
233
+ FunctionComponent: 0,
234
+ HostComponent: 7,
235
+ HostPortal: 6,
236
+ HostRoot: 5,
237
+ HostHoistable: -1, // Doesn't exist yet
238
+ HostSingleton: -1, // Doesn't exist yet
239
+ HostText: 8,
240
+ IncompleteClassComponent: -1, // Doesn't exist yet
241
+ IncompleteFunctionComponent: -1, // Doesn't exist yet
242
+ IndeterminateComponent: 4,
243
+ LazyComponent: -1, // Doesn't exist yet
244
+ LegacyHiddenComponent: -1,
245
+ MemoComponent: -1, // Doesn't exist yet
246
+ Mode: 10,
247
+ OffscreenComponent: -1, // Experimental
248
+ Profiler: 15,
249
+ ScopeComponent: -1, // Experimental
250
+ SimpleMemoComponent: -1, // Doesn't exist yet
251
+ SuspenseComponent: 16,
252
+ SuspenseListComponent: -1, // Doesn't exist yet
253
+ TracingMarkerComponent: -1, // Doesn't exist yet
254
+ YieldComponent: -1, // Removed
255
+ Throw: -1, // Doesn't exist yet
256
+ ViewTransitionComponent: -1, // Doesn't exist yet
257
+ ActivityComponent: -1, // Doesn't exist yet
258
+ };
259
+ } else {
260
+ ReactTypeOfWork = {
261
+ CacheComponent: -1, // Doesn't exist yet
262
+ ClassComponent: 2,
263
+ ContextConsumer: 12,
264
+ ContextProvider: 13,
265
+ CoroutineComponent: 7,
266
+ CoroutineHandlerPhase: 8,
267
+ DehydratedSuspenseComponent: -1, // Doesn't exist yet
268
+ ForwardRef: 14,
269
+ Fragment: 10,
270
+ FunctionComponent: 1,
271
+ HostComponent: 5,
272
+ HostPortal: 4,
273
+ HostRoot: 3,
274
+ HostHoistable: -1, // Doesn't exist yet
275
+ HostSingleton: -1, // Doesn't exist yet
276
+ HostText: 6,
277
+ IncompleteClassComponent: -1, // Doesn't exist yet
278
+ IncompleteFunctionComponent: -1, // Doesn't exist yet
279
+ IndeterminateComponent: 0,
280
+ LazyComponent: -1, // Doesn't exist yet
281
+ LegacyHiddenComponent: -1,
282
+ MemoComponent: -1, // Doesn't exist yet
283
+ Mode: 11,
284
+ OffscreenComponent: -1, // Experimental
285
+ Profiler: 15,
286
+ ScopeComponent: -1, // Experimental
287
+ SimpleMemoComponent: -1, // Doesn't exist yet
288
+ SuspenseComponent: 16,
289
+ SuspenseListComponent: -1, // Doesn't exist yet
290
+ TracingMarkerComponent: -1, // Doesn't exist yet
291
+ YieldComponent: 9,
292
+ Throw: -1, // Doesn't exist yet
293
+ ViewTransitionComponent: -1, // Doesn't exist yet
294
+ ActivityComponent: -1, // Doesn't exist yet
295
+ };
296
+ }
297
+ // **********************************************************
298
+ // End of copied code.
299
+ // **********************************************************
300
+
301
+ function getTypeSymbol(type: any): symbol | string | number {
302
+ const symbolOrNumber =
303
+ typeof type === 'object' && type !== null ? type.$$typeof : type;
304
+
305
+ return typeof symbolOrNumber === 'symbol'
306
+ ? symbolOrNumber.toString()
307
+ : symbolOrNumber;
308
+ }
309
+
310
+ const {
311
+ CacheComponent,
312
+ ClassComponent,
313
+ IncompleteClassComponent,
314
+ IncompleteFunctionComponent,
315
+ FunctionComponent,
316
+ IndeterminateComponent,
317
+ ForwardRef,
318
+ HostRoot,
319
+ HostHoistable,
320
+ HostSingleton,
321
+ HostComponent,
322
+ HostPortal,
323
+ HostText,
324
+ Fragment,
325
+ LazyComponent,
326
+ LegacyHiddenComponent,
327
+ MemoComponent,
328
+ OffscreenComponent,
329
+ Profiler,
330
+ ScopeComponent,
331
+ SimpleMemoComponent,
332
+ SuspenseComponent,
333
+ SuspenseListComponent,
334
+ TracingMarkerComponent,
335
+ Throw,
336
+ ViewTransitionComponent,
337
+ ActivityComponent,
338
+ } = ReactTypeOfWork;
339
+
340
+ function resolveFiberType(type: any): $FlowFixMe {
341
+ const typeSymbol = getTypeSymbol(type);
342
+ switch (typeSymbol) {
343
+ case MEMO_NUMBER:
344
+ case MEMO_SYMBOL_STRING:
345
+ // recursively resolving memo type in case of memo(forwardRef(Component))
346
+ return resolveFiberType(type.type);
347
+ case FORWARD_REF_NUMBER:
348
+ case FORWARD_REF_SYMBOL_STRING:
349
+ return type.render;
350
+ default:
351
+ return type;
352
+ }
353
+ }
354
+
355
+ // NOTICE Keep in sync with shouldFilterFiber() and other get*ForFiber methods
356
+ function getDisplayNameForFiber(
357
+ fiber: Fiber,
358
+ shouldSkipForgetCheck: boolean = false,
359
+ ): string | null {
360
+ const {elementType, type, tag} = fiber;
361
+
362
+ let resolvedType = type;
363
+ if (typeof type === 'object' && type !== null) {
364
+ resolvedType = resolveFiberType(type);
365
+ }
366
+
367
+ let resolvedContext: any = null;
368
+ if (
369
+ !shouldSkipForgetCheck &&
370
+ // $FlowFixMe[incompatible-type] fiber.updateQueue is mixed
371
+ (fiber.updateQueue?.memoCache != null ||
372
+ (Array.isArray(fiber.memoizedState?.memoizedState) &&
373
+ fiber.memoizedState.memoizedState[0]?.[REACT_MEMO_CACHE_SENTINEL]) ||
374
+ fiber.memoizedState?.memoizedState?.[REACT_MEMO_CACHE_SENTINEL])
375
+ ) {
376
+ const displayNameWithoutForgetWrapper = getDisplayNameForFiber(
377
+ fiber,
378
+ true,
379
+ );
380
+ if (displayNameWithoutForgetWrapper == null) {
381
+ return null;
382
+ }
383
+
384
+ return `Forget(${displayNameWithoutForgetWrapper})`;
385
+ }
386
+
387
+ switch (tag) {
388
+ case ActivityComponent:
389
+ return 'Activity';
390
+ case CacheComponent:
391
+ return 'Cache';
392
+ case ClassComponent:
393
+ case IncompleteClassComponent:
394
+ case IncompleteFunctionComponent:
395
+ case FunctionComponent:
396
+ case IndeterminateComponent:
397
+ return getDisplayName(resolvedType);
398
+ case ForwardRef:
399
+ return getWrappedDisplayName(
400
+ elementType,
401
+ resolvedType,
402
+ 'ForwardRef',
403
+ 'Anonymous',
404
+ );
405
+ case HostRoot:
406
+ const fiberRoot = fiber.stateNode;
407
+ if (fiberRoot != null && fiberRoot._debugRootType !== null) {
408
+ return fiberRoot._debugRootType;
409
+ }
410
+ return null;
411
+ case HostComponent:
412
+ case HostSingleton:
413
+ case HostHoistable:
414
+ return type;
415
+ case HostPortal:
416
+ case HostText:
417
+ return null;
418
+ case Fragment:
419
+ return 'Fragment';
420
+ case LazyComponent:
421
+ // This display name will not be user visible.
422
+ // Once a Lazy component loads its inner component, React replaces the tag and type.
423
+ // This display name will only show up in console logs when DevTools DEBUG mode is on.
424
+ return 'Lazy';
425
+ case MemoComponent:
426
+ case SimpleMemoComponent:
427
+ // Display name in React does not use `Memo` as a wrapper but fallback name.
428
+ return getWrappedDisplayName(
429
+ elementType,
430
+ resolvedType,
431
+ 'Memo',
432
+ 'Anonymous',
433
+ );
434
+ case SuspenseComponent:
435
+ return 'Suspense';
436
+ case LegacyHiddenComponent:
437
+ return 'LegacyHidden';
438
+ case OffscreenComponent:
439
+ return 'Offscreen';
440
+ case ScopeComponent:
441
+ return 'Scope';
442
+ case SuspenseListComponent:
443
+ return 'SuspenseList';
444
+ case Profiler:
445
+ return 'Profiler';
446
+ case TracingMarkerComponent:
447
+ return 'TracingMarker';
448
+ case ViewTransitionComponent:
449
+ return 'ViewTransition';
450
+ case Throw:
451
+ // This should really never be visible.
452
+ return 'Error';
453
+ default:
454
+ const typeSymbol = getTypeSymbol(type);
455
+
456
+ switch (typeSymbol) {
457
+ case CONCURRENT_MODE_NUMBER:
458
+ case CONCURRENT_MODE_SYMBOL_STRING:
459
+ case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
460
+ return null;
461
+ case PROVIDER_NUMBER:
462
+ case PROVIDER_SYMBOL_STRING:
463
+ // 16.3.0 exposed the context object as "context"
464
+ // PR #12501 changed it to "_context" for 16.3.1+
465
+ // NOTE Keep in sync with inspectElementRaw()
466
+ resolvedContext = fiber.type._context || fiber.type.context;
467
+ return `${resolvedContext.displayName || 'Context'}.Provider`;
468
+ case CONTEXT_NUMBER:
469
+ case CONTEXT_SYMBOL_STRING:
470
+ case SERVER_CONTEXT_SYMBOL_STRING:
471
+ if (
472
+ fiber.type._context === undefined &&
473
+ fiber.type.Provider === fiber.type
474
+ ) {
475
+ // In 19+, Context.Provider === Context, so this is a provider.
476
+ resolvedContext = fiber.type;
477
+ return `${resolvedContext.displayName || 'Context'}.Provider`;
478
+ }
479
+
480
+ // 16.3-16.5 read from "type" because the Consumer is the actual context object.
481
+ // 16.6+ should read from "type._context" because Consumer can be different (in DEV).
482
+ // NOTE Keep in sync with inspectElementRaw()
483
+ resolvedContext = fiber.type._context || fiber.type;
484
+
485
+ // NOTE: TraceUpdatesBackendManager depends on the name ending in '.Consumer'
486
+ // If you change the name, figure out a more resilient way to detect it.
487
+ return `${resolvedContext.displayName || 'Context'}.Consumer`;
488
+ case CONSUMER_SYMBOL_STRING:
489
+ // 19+
490
+ resolvedContext = fiber.type._context;
491
+ return `${resolvedContext.displayName || 'Context'}.Consumer`;
492
+ case STRICT_MODE_NUMBER:
493
+ case STRICT_MODE_SYMBOL_STRING:
494
+ return null;
495
+ case PROFILER_NUMBER:
496
+ case PROFILER_SYMBOL_STRING:
497
+ return `Profiler(${fiber.memoizedProps.id})`;
498
+ case SCOPE_NUMBER:
499
+ case SCOPE_SYMBOL_STRING:
500
+ return 'Scope';
501
+ default:
502
+ // Unknown element type.
503
+ // This may mean a new element type that has not yet been added to DevTools.
504
+ return null;
505
+ }
506
+ }
507
+ }
508
+
509
+ return {
510
+ getDisplayNameForFiber,
511
+ getTypeSymbol,
512
+ ReactPriorityLevels,
513
+ ReactTypeOfWork,
514
+ StrictModeBits,
515
+ SuspenseyImagesMode,
516
+ };
517
+}