@@ -36,6 +36,7 @@ import {
36
36
enableUseHook ,
37
37
enableUseMemoCacheHook ,
38
38
} from 'shared/ReactFeatureFlags' ;
39
+ import { REACT_CONTEXT_TYPE } from 'shared/ReactSymbols' ;
39
40
40
41
import { NoMode , ConcurrentMode , DebugTracingMode } from './ReactTypeOfMode' ;
41
42
import {
@@ -714,68 +715,70 @@ function createFunctionComponentUpdateQueue(): FunctionComponentUpdateQueue {
714
715
}
715
716
716
717
function use < T > (usable: Usable< T > ): T {
717
- if (
718
- usable !== null &&
719
- typeof usable === 'object' &&
720
- typeof usable . then === 'function'
721
- ) {
722
- // This is a thenable.
723
- const thenable : Thenable < T > = ( usable : any ) ;
724
-
725
- // Track the position of the thenable within this fiber.
726
- const index = thenableIndexCounter ;
727
- thenableIndexCounter += 1 ;
728
-
729
- switch ( thenable . status ) {
730
- case 'fulfilled' : {
731
- const fulfilledValue : T = thenable . value ;
732
- return fulfilledValue ;
733
- }
734
- case 'rejected ': {
735
- const rejectedError = thenable . reason ;
736
- throw rejectedError ;
737
- }
738
- default : {
739
- const prevThenableAtIndex : Thenable < T > | null = getPreviouslyUsedThenableAtIndex (
740
- index ,
741
- ) ;
742
- if ( prevThenableAtIndex !== null ) {
743
- switch ( prevThenableAtIndex . status ) {
744
- case 'fulfilled' : {
745
- const fulfilledValue : T = prevThenableAtIndex . value ;
746
- return fulfilledValue ;
747
- }
748
- case 'rejected' : {
749
- const rejectedError : mixed = prevThenableAtIndex . reason ;
750
- throw rejectedError ;
751
- }
752
- default: {
753
- // The thenable still hasn't resolved. Suspend with the same
754
- // thenable as last time to avoid redundant listeners.
755
- throw prevThenableAtIndex ;
718
+ if ( usable !== null && typeof usable === 'object' ) {
719
+ if ( typeof usable . then === 'function' ) {
720
+ // This is a thenable.
721
+ const thenable : Thenable < T > = ( usable : any ) ;
722
+
723
+ // Track the position of the thenable within this fiber.
724
+ const index = thenableIndexCounter ;
725
+ thenableIndexCounter += 1 ;
726
+
727
+ switch ( thenable . status ) {
728
+ case 'fulfilled' : {
729
+ const fulfilledValue : T = thenable . value ;
730
+ return fulfilledValue ;
731
+ }
732
+ case 'rejected ': {
733
+ const rejectedError = thenable . reason ;
734
+ throw rejectedError ;
735
+ }
736
+ default : {
737
+ const prevThenableAtIndex : Thenable < T > | null = getPreviouslyUsedThenableAtIndex (
738
+ index ,
739
+ ) ;
740
+ if ( prevThenableAtIndex !== null ) {
741
+ switch ( prevThenableAtIndex . status ) {
742
+ case 'fulfilled' : {
743
+ const fulfilledValue : T = prevThenableAtIndex . value ;
744
+ return fulfilledValue ;
745
+ }
746
+ case 'rejected' : {
747
+ const rejectedError : mixed = prevThenableAtIndex . reason ;
748
+ throw rejectedError ;
749
+ }
750
+ default: {
751
+ // The thenable still hasn't resolved. Suspend with the same
752
+ // thenable as last time to avoid redundant listeners.
753
+ throw prevThenableAtIndex ;
754
+ }
756
755
}
756
+ } else {
757
+ // This is the first time something has been used at this index.
758
+ // Stash the thenable at the current index so we can reuse it during
759
+ // the next attempt.
760
+ trackUsedThenable ( thenable , index ) ;
761
+
762
+ // Suspend.
763
+ // TODO: Throwing here is an implementation detail that allows us to
764
+ // unwind the call stack. But we shouldn't allow it to leak into
765
+ // userspace. Throw an opaque placeholder value instead of the
766
+ // actual thenable. If it doesn't get captured by the work loop, log
767
+ // a warning, because that means something in userspace must have
768
+ // caught it.
769
+ throw thenable ;
757
770
}
758
- } else {
759
- // This is the first time something has been used at this index.
760
- // Stash the thenable at the current index so we can reuse it during
761
- // the next attempt.
762
- trackUsedThenable ( thenable , index ) ;
763
-
764
- // Suspend.
765
- // TODO: Throwing here is an implementation detail that allows us to
766
- // unwind the call stack. But we shouldn't allow it to leak into
767
- // userspace. Throw an opaque placeholder value instead of the
768
- // actual thenable. If it doesn't get captured by the work loop, log
769
- // a warning, because that means something in userspace must have
770
- // caught it.
771
- throw thenable ;
772
771
}
773
772
}
773
+ } else if (
774
+ usable . $$typeof != null &&
775
+ usable . $$typeof === REACT_CONTEXT_TYPE
776
+ ) {
777
+ const context : ReactContext < T > = ( usable : any ) ;
778
+ return readContext ( context ) ;
774
779
}
775
780
}
776
781
777
- // TODO: Add support for Context
778
-
779
782
// eslint-disable-next-line react-internal/safe-string-coercion
780
783
throw new Error ( 'An unsupported type was passed to use ( ) : ' + String ( usable ) ) ;
781
784
}
0 commit comments