88 */
99
1010import 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' ;
1218import type { Fiber } from 'react-reconciler/src/ReactFiber' ;
1319import type { ExpirationTime } from 'react-reconciler/src/ReactFiberExpirationTime' ;
1420
@@ -20,6 +26,8 @@ import {
2026 REACT_CALL_TYPE ,
2127 REACT_RETURN_TYPE ,
2228 REACT_PORTAL_TYPE ,
29+ REACT_PROVIDER_TYPE ,
30+ REACT_CONSUMER_TYPE ,
2331} from 'shared/ReactSymbols' ;
2432import {
2533 FunctionalComponent ,
@@ -29,6 +37,8 @@ import {
2937 CallComponent ,
3038 ReturnComponent ,
3139 Fragment ,
40+ ProviderComponent ,
41+ ConsumerComponent ,
3242} from 'shared/ReactTypeOfWork' ;
3343import emptyObject from 'fbjs/lib/emptyObject' ;
3444import invariant from 'fbjs/lib/invariant' ;
@@ -42,6 +52,8 @@ import {
4252 createFiberFromCall ,
4353 createFiberFromReturn ,
4454 createFiberFromPortal ,
55+ createFiberFromProvider ,
56+ createFiberFromConsumer ,
4557} from './ReactFiber' ;
4658import ReactDebugCurrentFiber from './ReactDebugCurrentFiber' ;
4759
@@ -465,6 +477,52 @@ function ChildReconciler(shouldTrackSideEffects) {
465477 }
466478 }
467479
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+
468526 function createChild (
469527 returnFiber : Fiber ,
470528 newChild : any ,
@@ -537,6 +595,24 @@ function ChildReconciler(shouldTrackSideEffects) {
537595 created . return = returnFiber ;
538596 return created ;
539597 }
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+ }
540616 }
541617
542618 if ( isArray ( newChild ) || getIteratorFn ( newChild ) ) {
@@ -647,6 +723,30 @@ function ChildReconciler(shouldTrackSideEffects) {
647723 return null ;
648724 }
649725 }
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+ }
650750 }
651751
652752 if ( isArray ( newChild ) || getIteratorFn ( newChild ) ) {
@@ -755,6 +855,30 @@ function ChildReconciler(shouldTrackSideEffects) {
755855 expirationTime ,
756856 ) ;
757857 }
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+ }
758882 }
759883
760884 if ( isArray ( newChild ) || getIteratorFn ( newChild ) ) {
@@ -1362,6 +1486,78 @@ function ChildReconciler(shouldTrackSideEffects) {
13621486 return created ;
13631487 }
13641488
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+
13651561 // This API will tag the children with the side-effect of the reconciliation
13661562 // itself. They will be added to the side-effect list as we pass through the
13671563 // children and the parent.
@@ -1430,6 +1626,24 @@ function ChildReconciler(shouldTrackSideEffects) {
14301626 expirationTime ,
14311627 ) ,
14321628 ) ;
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+ ) ;
14331647 }
14341648 }
14351649
0 commit comments