8
8
*/
9
9
10
10
import type { ReactElement } from 'shared/ReactElementType' ;
11
- import type { ReactCall , ReactPortal , ReactReturn } from 'shared/ReactTypes' ;
11
+ import type {
12
+ ReactCall ,
13
+ ReactPortal ,
14
+ ReactReturn ,
15
+ ReactProvider ,
16
+ ReactConsumer ,
17
+ } from 'shared/ReactTypes' ;
12
18
import type { Fiber } from 'react-reconciler/src/ReactFiber' ;
13
19
import type { ExpirationTime } from 'react-reconciler/src/ReactFiberExpirationTime' ;
14
20
@@ -20,6 +26,8 @@ import {
20
26
REACT_CALL_TYPE ,
21
27
REACT_RETURN_TYPE ,
22
28
REACT_PORTAL_TYPE ,
29
+ REACT_PROVIDER_TYPE ,
30
+ REACT_CONSUMER_TYPE ,
23
31
} from 'shared/ReactSymbols' ;
24
32
import {
25
33
FunctionalComponent ,
@@ -29,6 +37,8 @@ import {
29
37
CallComponent ,
30
38
ReturnComponent ,
31
39
Fragment ,
40
+ ProviderComponent ,
41
+ ConsumerComponent ,
32
42
} from 'shared/ReactTypeOfWork' ;
33
43
import emptyObject from 'fbjs/lib/emptyObject' ;
34
44
import invariant from 'fbjs/lib/invariant' ;
@@ -42,6 +52,8 @@ import {
42
52
createFiberFromCall ,
43
53
createFiberFromReturn ,
44
54
createFiberFromPortal ,
55
+ createFiberFromProvider ,
56
+ createFiberFromConsumer ,
45
57
} from './ReactFiber' ;
46
58
import ReactDebugCurrentFiber from './ReactDebugCurrentFiber' ;
47
59
@@ -465,6 +477,52 @@ function ChildReconciler(shouldTrackSideEffects) {
465
477
}
466
478
}
467
479
480
+ function updateProviderComponent (
481
+ returnFiber : Fiber ,
482
+ current : Fiber | null ,
483
+ provider : ReactProvider < any > ,
484
+ expirationTime : ExpirationTime ,
485
+ ) {
486
+ if ( current !== null && current . type === provider . context ) {
487
+ // Move based on index
488
+ const existing = useFiber ( current , provider , expirationTime ) ;
489
+ existing . return = returnFiber ;
490
+ return existing ;
491
+ } else {
492
+ // Insert
493
+ const created = createFiberFromProvider (
494
+ provider ,
495
+ returnFiber . internalContextTag ,
496
+ expirationTime ,
497
+ ) ;
498
+ created . return = returnFiber ;
499
+ return created ;
500
+ }
501
+ }
502
+
503
+ function updateConsumerComponent (
504
+ returnFiber : Fiber ,
505
+ current : Fiber | null ,
506
+ consumer : ReactConsumer < any > ,
507
+ expirationTime : ExpirationTime ,
508
+ ) {
509
+ if ( current !== null && current . type === consumer . context ) {
510
+ // Move based on index
511
+ const existing = useFiber ( current , consumer , expirationTime ) ;
512
+ existing . return = returnFiber ;
513
+ return existing ;
514
+ } else {
515
+ // Insert
516
+ const created = createFiberFromConsumer (
517
+ consumer ,
518
+ returnFiber . internalContextTag ,
519
+ expirationTime ,
520
+ ) ;
521
+ created . return = returnFiber ;
522
+ return created ;
523
+ }
524
+ }
525
+
468
526
function createChild (
469
527
returnFiber : Fiber ,
470
528
newChild : any ,
@@ -537,6 +595,24 @@ function ChildReconciler(shouldTrackSideEffects) {
537
595
created . return = returnFiber ;
538
596
return created ;
539
597
}
598
+ case REACT_PROVIDER_TYPE : {
599
+ const created = createFiberFromProvider (
600
+ newChild ,
601
+ returnFiber . internalContextTag ,
602
+ expirationTime ,
603
+ ) ;
604
+ created . return = returnFiber ;
605
+ return created ;
606
+ }
607
+ case REACT_CONSUMER_TYPE : {
608
+ const created = createFiberFromConsumer (
609
+ newChild ,
610
+ returnFiber . internalContextTag ,
611
+ expirationTime ,
612
+ ) ;
613
+ created . return = returnFiber ;
614
+ return created ;
615
+ }
540
616
}
541
617
542
618
if ( isArray ( newChild ) || getIteratorFn ( newChild ) ) {
@@ -647,6 +723,30 @@ function ChildReconciler(shouldTrackSideEffects) {
647
723
return null ;
648
724
}
649
725
}
726
+ case REACT_PROVIDER_TYPE : {
727
+ if ( newChild . key === key ) {
728
+ return updateProviderComponent (
729
+ returnFiber ,
730
+ oldFiber ,
731
+ newChild ,
732
+ expirationTime ,
733
+ ) ;
734
+ } else {
735
+ return null ;
736
+ }
737
+ }
738
+ case REACT_CONSUMER_TYPE : {
739
+ if ( newChild . key === key ) {
740
+ return updateConsumerComponent (
741
+ returnFiber ,
742
+ oldFiber ,
743
+ newChild ,
744
+ expirationTime ,
745
+ ) ;
746
+ } else {
747
+ return null ;
748
+ }
749
+ }
650
750
}
651
751
652
752
if ( isArray ( newChild ) || getIteratorFn ( newChild ) ) {
@@ -755,6 +855,30 @@ function ChildReconciler(shouldTrackSideEffects) {
755
855
expirationTime ,
756
856
) ;
757
857
}
858
+ case REACT_PROVIDER_TYPE : {
859
+ const matchedFiber =
860
+ existingChildren . get (
861
+ newChild . key === null ? newIdx : newChild . key ,
862
+ ) || null ;
863
+ return updateProviderComponent (
864
+ returnFiber ,
865
+ matchedFiber ,
866
+ newChild ,
867
+ expirationTime ,
868
+ ) ;
869
+ }
870
+ case REACT_CONSUMER_TYPE : {
871
+ const matchedFiber =
872
+ existingChildren . get (
873
+ newChild . key === null ? newIdx : newChild . key ,
874
+ ) || null ;
875
+ return updateConsumerComponent (
876
+ returnFiber ,
877
+ matchedFiber ,
878
+ newChild ,
879
+ expirationTime ,
880
+ ) ;
881
+ }
758
882
}
759
883
760
884
if ( isArray ( newChild ) || getIteratorFn ( newChild ) ) {
@@ -1362,6 +1486,78 @@ function ChildReconciler(shouldTrackSideEffects) {
1362
1486
return created ;
1363
1487
}
1364
1488
1489
+ function reconcileSingleProvider (
1490
+ returnFiber : Fiber ,
1491
+ currentFirstChild : Fiber | null ,
1492
+ provider : ReactProvider < any > ,
1493
+ expirationTime : ExpirationTime ,
1494
+ ) : Fiber {
1495
+ const key = provider . key ;
1496
+ let child = currentFirstChild ;
1497
+ while ( child !== null ) {
1498
+ // TODO: If key === null and child.key === null, then this only applies to
1499
+ // the first item in the list.
1500
+ if ( child . key === key && child . type === provider . context ) {
1501
+ if ( child . tag === ProviderComponent ) {
1502
+ deleteRemainingChildren ( returnFiber , child . sibling ) ;
1503
+ const existing = useFiber ( child , provider , expirationTime ) ;
1504
+ existing . return = returnFiber ;
1505
+ return existing ;
1506
+ } else {
1507
+ deleteRemainingChildren ( returnFiber , child ) ;
1508
+ break ;
1509
+ }
1510
+ } else {
1511
+ deleteChild ( returnFiber , child ) ;
1512
+ }
1513
+ child = child . sibling ;
1514
+ }
1515
+
1516
+ const created = createFiberFromProvider (
1517
+ provider ,
1518
+ returnFiber . internalContextTag ,
1519
+ expirationTime ,
1520
+ ) ;
1521
+ created . return = returnFiber ;
1522
+ return created ;
1523
+ }
1524
+
1525
+ function reconcileSingleConsumer (
1526
+ returnFiber : Fiber ,
1527
+ currentFirstChild : Fiber | null ,
1528
+ consumer : ReactConsumer < any > ,
1529
+ expirationTime : ExpirationTime ,
1530
+ ) : Fiber {
1531
+ const key = consumer . key ;
1532
+ let child = currentFirstChild ;
1533
+ while ( child !== null ) {
1534
+ // TODO: If key === null and child.key === null, then this only applies to
1535
+ // the first item in the list.
1536
+ if ( child . key === key && child . type === consumer . context ) {
1537
+ if ( child . tag === ConsumerComponent ) {
1538
+ deleteRemainingChildren ( returnFiber , child . sibling ) ;
1539
+ const existing = useFiber ( child , consumer , expirationTime ) ;
1540
+ existing . return = returnFiber ;
1541
+ return existing ;
1542
+ } else {
1543
+ deleteRemainingChildren ( returnFiber , child ) ;
1544
+ break ;
1545
+ }
1546
+ } else {
1547
+ deleteChild ( returnFiber , child ) ;
1548
+ }
1549
+ child = child . sibling ;
1550
+ }
1551
+
1552
+ const created = createFiberFromConsumer (
1553
+ consumer ,
1554
+ returnFiber . internalContextTag ,
1555
+ expirationTime ,
1556
+ ) ;
1557
+ created . return = returnFiber ;
1558
+ return created ;
1559
+ }
1560
+
1365
1561
// This API will tag the children with the side-effect of the reconciliation
1366
1562
// itself. They will be added to the side-effect list as we pass through the
1367
1563
// children and the parent.
@@ -1430,6 +1626,24 @@ function ChildReconciler(shouldTrackSideEffects) {
1430
1626
expirationTime ,
1431
1627
) ,
1432
1628
) ;
1629
+ case REACT_PROVIDER_TYPE :
1630
+ return placeSingleChild (
1631
+ reconcileSingleProvider (
1632
+ returnFiber ,
1633
+ currentFirstChild ,
1634
+ newChild ,
1635
+ expirationTime ,
1636
+ ) ,
1637
+ ) ;
1638
+ case REACT_CONSUMER_TYPE :
1639
+ return placeSingleChild (
1640
+ reconcileSingleConsumer (
1641
+ returnFiber ,
1642
+ currentFirstChild ,
1643
+ newChild ,
1644
+ expirationTime ,
1645
+ ) ,
1646
+ ) ;
1433
1647
}
1434
1648
}
1435
1649
0 commit comments