@@ -36,6 +36,7 @@ import {
3636 enableUseHook ,
3737 enableUseMemoCacheHook ,
3838} from 'shared/ReactFeatureFlags' ;
39+ import { REACT_CONTEXT_TYPE } from 'shared/ReactSymbols' ;
3940
4041import { NoMode , ConcurrentMode , DebugTracingMode } from './ReactTypeOfMode' ;
4142import {
@@ -714,68 +715,70 @@ function createFunctionComponentUpdateQueue(): FunctionComponentUpdateQueue {
714715}
715716
716717function 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+ }
756755 }
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 ;
757770 }
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 ;
772771 }
773772 }
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 ) ;
774779 }
775780 }
776781
777- // TODO: Add support for Context
778-
779782 // eslint-disable-next-line react-internal/safe-string-coercion
780783 throw new Error ( 'An unsupported type was passed to use ( ) : ' + String ( usable ) ) ;
781784}
0 commit comments