8
*/
9
10
import type {ReactElement} from 'shared/ReactElementType';
11
-import type {ReactPortal, Thenable, ReactContext} from 'shared/ReactTypes';
11
+import type {
12
+ ReactPortal,
13
+ Thenable,
14
+ ReactContext,
15
+ ReactDebugInfo,
16
+} from 'shared/ReactTypes';
17
import type {Fiber} from './ReactInternalTypes';
18
import type {Lanes} from './ReactFiberLane';
19
import type {ThenableState} from './ReactFiberThenable';
55
let thenableState: ThenableState | null = null;
56
let thenableIndexCounter: number = 0;
57
58
+function mergeDebugInfo(
59
+ outer: ReactDebugInfo | null,
60
+ inner: ReactDebugInfo | null | void,
61
+): ReactDebugInfo | null {
62
+ if (!__DEV__) {
63
+ return null;
64
+ }
65
+ if (inner == null) {
66
+ return outer;
67
+ } else if (outer === null) {
68
+ return inner;
69
+ } else {
70
+ // If we have two debugInfo, we need to create a new one. This makes the array no longer
71
+ // live so we'll miss any future updates if we received more so ideally we should always
72
+ // do this after both have fully resolved/unsuspended.
73
+ return outer.concat(inner);
74
+ }
75
+}
76
+
77
let didWarnAboutMaps;
78
let didWarnAboutGenerators;
79
let didWarnAboutStringRefs;
411
current: Fiber | null,
412
textContent: string,
413
lanes: Lanes,
414
+ debugInfo: ReactDebugInfo | null,
415
) {
416
if (current === null || current.tag !== HostText) {
417
// Insert
418
const created = createFiberFromText(textContent, returnFiber.mode, lanes);
419
created.return = returnFiber;
420
+ if (__DEV__) {
421
+ created._debugInfo = debugInfo;
422
+ }
423
return created;
424
} else {
425
// Update
426
const existing = useFiber(current, textContent);
427
existing.return = returnFiber;
428
+ if (__DEV__) {
429
+ existing._debugInfo = debugInfo;
430
+ }
431
return existing;
432
}
433
}
437
current: Fiber | null,
438
element: ReactElement,
439
lanes: Lanes,
440
+ debugInfo: ReactDebugInfo | null,
441
): Fiber {
442
const elementType = element.type;
443
if (elementType === REACT_FRAGMENT_TYPE) {
447
element.props.children,
448
lanes,
449
element.key,
450
+ debugInfo,
451
);
452
}
453
if (current !== null) {
472
existing.return = returnFiber;
473
if (__DEV__) {
474
existing._debugOwner = element._owner;
475
+ existing._debugInfo = debugInfo;
476
}
477
return existing;
478
}
481
const created = createFiberFromElement(element, returnFiber.mode, lanes);
482
created.ref = coerceRef(returnFiber, current, element);
483
created.return = returnFiber;
484
+ if (__DEV__) {
485
+ created._debugInfo = debugInfo;
486
+ }
487
return created;
488
}
489
492
current: Fiber | null,
493
portal: ReactPortal,
494
lanes: Lanes,
495
+ debugInfo: ReactDebugInfo | null,
496
): Fiber {
497
if (
498
current === null ||
503
// Insert
504
const created = createFiberFromPortal(portal, returnFiber.mode, lanes);
505
created.return = returnFiber;
506
+ if (__DEV__) {
507
+ created._debugInfo = debugInfo;
508
+ }
509
return created;
510
} else {
511
// Update
512
const existing = useFiber(current, portal.children || []);
513
existing.return = returnFiber;
514
+ if (__DEV__) {
515
+ existing._debugInfo = debugInfo;
516
+ }
517
return existing;
518
}
519
}
524
fragment: Iterable<React$Node>,
525
lanes: Lanes,
526
key: null | string,
527
+ debugInfo: null | ReactDebugInfo,
528
): Fiber {
529
if (current === null || current.tag !== Fragment) {
530
// Insert
535
key,
536
);
537
created.return = returnFiber;
538
+ if (__DEV__) {
539
+ created._debugInfo = debugInfo;
540
+ }
541
return created;
542
} else {
543
// Update
544
const existing = useFiber(current, fragment);
545
existing.return = returnFiber;
546
+ if (__DEV__) {
547
+ existing._debugInfo = debugInfo;
548
+ }
549
return existing;
550
}
551
}
554
returnFiber: Fiber,
555
newChild: any,
556
lanes: Lanes,
557
+ debugInfo: ReactDebugInfo | null,
558
): Fiber | null {
559
if (
560
(typeof newChild === 'string' && newChild !== '') ||
569
lanes,
570
);
571
created.return = returnFiber;
572
+ if (__DEV__) {
573
+ created._debugInfo = debugInfo;
574
+ }
575
return created;
576
}
577
585
);
586
created.ref = coerceRef(returnFiber, null, newChild);
587
created.return = returnFiber;
588
+ if (__DEV__) {
589
+ created._debugInfo = mergeDebugInfo(debugInfo, newChild._debugInfo);
590
+ }
591
return created;
592
}
593
case REACT_PORTAL_TYPE: {
597
lanes,
598
);
599
created.return = returnFiber;
600
+ if (__DEV__) {
601
+ created._debugInfo = debugInfo;
602
+ }
603
return created;
604
}
605
case REACT_LAZY_TYPE: {
606
const payload = newChild._payload;
607
const init = newChild._init;
547
- return createChild(returnFiber, init(payload), lanes);
608
+ return createChild(
609
+ returnFiber,
610
+ init(payload),
611
+ lanes,
612
+ mergeDebugInfo(debugInfo, newChild._debugInfo), // call merge after init
613
+ );
614
}
615
}
616
622
null,
623
);
624
created.return = returnFiber;
625
+ if (__DEV__) {
626
+ created._debugInfo = mergeDebugInfo(debugInfo, newChild._debugInfo);
627
+ }
628
return created;
629
}
630
633
// Unwrap the inner value and recursively call this function again.
634
if (typeof newChild.then === 'function') {
635
const thenable: Thenable<any> = (newChild: any);
567
- return createChild(returnFiber, unwrapThenable(thenable), lanes);
636
+ return createChild(
637
+ returnFiber,
638
+ unwrapThenable(thenable),
639
+ lanes,
640
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
641
+ );
642
}
643
644
if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
647
returnFiber,
648
readContextDuringReconcilation(returnFiber, context, lanes),
649
lanes,
650
+ debugInfo,
651
);
652
}
653
668
oldFiber: Fiber | null,
669
newChild: any,
670
lanes: Lanes,
671
+ debugInfo: null | ReactDebugInfo,
672
): Fiber | null {
673
// Update the fiber if the keys match, otherwise return null.
674
const key = oldFiber !== null ? oldFiber.key : null;
683
if (key !== null) {
684
return null;
685
}
610
- return updateTextNode(returnFiber, oldFiber, '' + newChild, lanes);
686
+ return updateTextNode(
687
+ returnFiber,
688
+ oldFiber,
689
+ '' + newChild,
690
+ lanes,
691
+ debugInfo,
692
+ );
693
}
694
695
if (typeof newChild === 'object' && newChild !== null) {
696
switch (newChild.$$typeof) {
697
case REACT_ELEMENT_TYPE: {
698
if (newChild.key === key) {
617
- return updateElement(returnFiber, oldFiber, newChild, lanes);
699
+ return updateElement(
700
+ returnFiber,
701
+ oldFiber,
702
+ newChild,
703
+ lanes,
704
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
705
+ );
706
} else {
707
return null;
708
}
709
}
710
case REACT_PORTAL_TYPE: {
711
if (newChild.key === key) {
624
- return updatePortal(returnFiber, oldFiber, newChild, lanes);
712
+ return updatePortal(
713
+ returnFiber,
714
+ oldFiber,
715
+ newChild,
716
+ lanes,
717
+ debugInfo,
718
+ );
719
} else {
720
return null;
721
}
723
case REACT_LAZY_TYPE: {
724
const payload = newChild._payload;
725
const init = newChild._init;
632
- return updateSlot(returnFiber, oldFiber, init(payload), lanes);
726
+ return updateSlot(
727
+ returnFiber,
728
+ oldFiber,
729
+ init(payload),
730
+ lanes,
731
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
732
+ );
733
}
734
}
735
738
return null;
739
}
740
641
- return updateFragment(returnFiber, oldFiber, newChild, lanes, null);
741
+ return updateFragment(
742
+ returnFiber,
743
+ oldFiber,
744
+ newChild,
745
+ lanes,
746
+ null,
747
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
748
+ );
749
}
750
751
// Usable node types
758
oldFiber,
759
unwrapThenable(thenable),
760
lanes,
761
+ debugInfo,
762
);
763
}
764
769
oldFiber,
770
readContextDuringReconcilation(returnFiber, context, lanes),
771
lanes,
772
+ debugInfo,
773
);
774
}
775
791
newIdx: number,
792
newChild: any,
793
lanes: Lanes,
794
+ debugInfo: ReactDebugInfo | null,
795
): Fiber | null {
796
if (
797
(typeof newChild === 'string' && newChild !== '') ||
800
// Text nodes don't have keys, so we neither have to check the old nor
801
// new node for the key. If both are text nodes, they match.
802
const matchedFiber = existingChildren.get(newIdx) || null;
693
- return updateTextNode(returnFiber, matchedFiber, '' + newChild, lanes);
803
+ return updateTextNode(
804
+ returnFiber,
805
+ matchedFiber,
806
+ '' + newChild,
807
+ lanes,
808
+ debugInfo,
809
+ );
810
}
811
812
if (typeof newChild === 'object' && newChild !== null) {
816
existingChildren.get(
817
newChild.key === null ? newIdx : newChild.key,
818
) || null;
703
- return updateElement(returnFiber, matchedFiber, newChild, lanes);
819
+ return updateElement(
820
+ returnFiber,
821
+ matchedFiber,
822
+ newChild,
823
+ lanes,
824
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
825
+ );
826
}
827
case REACT_PORTAL_TYPE: {
828
const matchedFiber =
829
existingChildren.get(
830
newChild.key === null ? newIdx : newChild.key,
831
) || null;
710
- return updatePortal(returnFiber, matchedFiber, newChild, lanes);
832
+ return updatePortal(
833
+ returnFiber,
834
+ matchedFiber,
835
+ newChild,
836
+ lanes,
837
+ debugInfo,
838
+ );
839
}
840
case REACT_LAZY_TYPE:
841
const payload = newChild._payload;
846
newIdx,
847
init(payload),
848
lanes,
849
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
850
);
851
}
852
853
if (isArray(newChild) || getIteratorFn(newChild)) {
854
const matchedFiber = existingChildren.get(newIdx) || null;
726
- return updateFragment(returnFiber, matchedFiber, newChild, lanes, null);
855
+ return updateFragment(
856
+ returnFiber,
857
+ matchedFiber,
858
+ newChild,
859
+ lanes,
860
+ null,
861
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
862
+ );
863
}
864
865
// Usable node types
873
newIdx,
874
unwrapThenable(thenable),
875
lanes,
876
+ debugInfo,
877
);
878
}
879
885
newIdx,
886
readContextDuringReconcilation(returnFiber, context, lanes),
887
lanes,
888
+ debugInfo,
889
);
890
}
891
956
currentFirstChild: Fiber | null,
957
newChildren: Array<any>,
958
lanes: Lanes,
959
+ debugInfo: ReactDebugInfo | null,
960
): Fiber | null {
961
// This algorithm can't optimize by searching from both ends since we
962
// don't have backpointers on fibers. I'm trying to see how far we can get
1005
oldFiber,
1006
newChildren[newIdx],
1007
lanes,
1008
+ debugInfo,
1009
);
1010
if (newFiber === null) {
1011
// TODO: This breaks on empty slots like null children. That's
1053
// If we don't have any more existing children we can choose a fast path
1054
// since the rest will all be insertions.
1055
for (; newIdx < newChildren.length; newIdx++) {
916
- const newFiber = createChild(returnFiber, newChildren[newIdx], lanes);
1056
+ const newFiber = createChild(
1057
+ returnFiber,
1058
+ newChildren[newIdx],
1059
+ lanes,
1060
+ debugInfo,
1061
+ );
1062
if (newFiber === null) {
1063
continue;
1064
}
1089
newIdx,
1090
newChildren[newIdx],
1091
lanes,
1092
+ debugInfo,
1093
);
1094
if (newFiber !== null) {
1095
if (shouldTrackSideEffects) {
1131
currentFirstChild: Fiber | null,
1132
newChildrenIterable: Iterable<mixed>,
1133
lanes: Lanes,
1134
+ debugInfo: ReactDebugInfo | null,
1135
): Fiber | null {
1136
// This is the same implementation as reconcileChildrenArray(),
1137
// but using the iterator instead.
1215
} else {
1216
nextOldFiber = oldFiber.sibling;
1217
}
1071
- const newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes);
1218
+ const newFiber = updateSlot(
1219
+ returnFiber,
1220
+ oldFiber,
1221
+ step.value,
1222
+ lanes,
1223
+ debugInfo,
1224
+ );
1225
if (newFiber === null) {
1226
// TODO: This breaks on empty slots like null children. That's
1227
// unfortunate because it triggers the slow path all the time. We need
1268
// If we don't have any more existing children we can choose a fast path
1269
// since the rest will all be insertions.
1270
for (; !step.done; newIdx++, step = newChildren.next()) {
1118
- const newFiber = createChild(returnFiber, step.value, lanes);
1271
+ const newFiber = createChild(returnFiber, step.value, lanes, debugInfo);
1272
if (newFiber === null) {
1273
continue;
1274
}
1299
newIdx,
1300
step.value,
1301
lanes,
1302
+ debugInfo,
1303
);
1304
if (newFiber !== null) {
1305
if (shouldTrackSideEffects) {
1365
currentFirstChild: Fiber | null,
1366
element: ReactElement,
1367
lanes: Lanes,
1368
+ debugInfo: ReactDebugInfo | null,
1369
): Fiber {
1370
const key = element.key;
1371
let child = currentFirstChild;
1381
existing.return = returnFiber;
1382
if (__DEV__) {
1383
existing._debugOwner = element._owner;
1384
+ existing._debugInfo = debugInfo;
1385
}
1386
return existing;
1387
}
1407
existing.return = returnFiber;
1408
if (__DEV__) {
1409
existing._debugOwner = element._owner;
1410
+ existing._debugInfo = debugInfo;
1411
}
1412
return existing;
1413
}
1429
element.key,
1430
);
1431
created.return = returnFiber;
1432
+ if (__DEV__) {
1433
+ created._debugInfo = debugInfo;
1434
+ }
1435
return created;
1436
} else {
1437
const created = createFiberFromElement(element, returnFiber.mode, lanes);
1438
created.ref = coerceRef(returnFiber, currentFirstChild, element);
1439
created.return = returnFiber;
1440
+ if (__DEV__) {
1441
+ created._debugInfo = debugInfo;
1442
+ }
1443
return created;
1444
}
1445
}
1449
currentFirstChild: Fiber | null,
1450
portal: ReactPortal,
1451
lanes: Lanes,
1452
+ debugInfo: ReactDebugInfo | null,
1453
): Fiber {
1454
const key = portal.key;
1455
let child = currentFirstChild;
1489
currentFirstChild: Fiber | null,
1490
newChild: any,
1491
lanes: Lanes,
1492
+ debugInfo: ReactDebugInfo | null,
1493
): Fiber | null {
1494
// This function is not recursive.
1495
// If the top level item is an array, we treat it as a set of children,
1519
currentFirstChild,
1520
newChild,
1521
lanes,
1522
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
1523
),
1524
);
1525
case REACT_PORTAL_TYPE:
1529
currentFirstChild,
1530
newChild,
1531
lanes,
1532
+ debugInfo,
1533
),
1534
);
1535
case REACT_LAZY_TYPE:
1536
const payload = newChild._payload;
1537
const init = newChild._init;
1371
- // TODO: This function is supposed to be non-recursive.
1372
- return reconcileChildFibers(
1538
+ return reconcileChildFibersImpl(
1539
returnFiber,
1540
currentFirstChild,
1541
init(payload),
1542
lanes,
1543
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
1544
);
1545
}
1546
1550
currentFirstChild,
1551
newChild,
1552
lanes,
1553
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
1554
);
1555
}
1556
1560
currentFirstChild,
1561
newChild,
1562
lanes,
1563
+ mergeDebugInfo(debugInfo, newChild._debugInfo),
1564
);
1565
}
1566
1587
currentFirstChild,
1588
unwrapThenable(thenable),
1589
lanes,
1590
+ mergeDebugInfo(debugInfo, thenable._debugInfo),
1591
);
1592
}
1593
1598
currentFirstChild,
1599
readContextDuringReconcilation(returnFiber, context, lanes),
1600
lanes,
1601
+ debugInfo,
1602
);
1603
}
1604
1643
currentFirstChild,
1644
newChild,
1645
lanes,
1646
+ null, // debugInfo
1647
);
1648
thenableState = null;
1649
// Don't bother to reset `thenableIndexCounter` to 0 because it always gets