@@ -12,6 +12,7 @@ import type {
1212 PendingThenable ,
1313 FulfilledThenable ,
1414 RejectedThenable ,
15+ ReactIOInfo ,
1516} from 'shared/ReactTypes' ;
1617
1718import type { LazyComponent as LazyComponentType } from 'react/src/ReactLazy' ;
@@ -22,6 +23,8 @@ import {getWorkInProgressRoot} from './ReactFiberWorkLoop';
2223
2324import ReactSharedInternals from 'shared/ReactSharedInternals' ;
2425
26+ import { enableAsyncDebugInfo } from 'shared/ReactFeatureFlags' ;
27+
2528import noop from 'shared/noop' ;
2629
2730opaque type ThenableStateDev = {
@@ -154,6 +157,33 @@ export function trackUsedThenable<T>(
154157 }
155158 }
156159
160+ if (__DEV__ && enableAsyncDebugInfo && thenable . _debugInfo === undefined ) {
161+ // In DEV mode if the thenable that we observed had no debug info, then we add
162+ // an inferred debug info so that we're able to track its potential I/O uniquely.
163+ // We don't know the real start time since the I/O could have started much
164+ // earlier and this could even be a cached Promise. Could be misleading.
165+ const startTime = performance . now ( ) ;
166+ const displayName = thenable . displayName ;
167+ const ioInfo : ReactIOInfo = {
168+ name : typeof displayName === 'string' ? displayName : 'Promise' ,
169+ start : startTime ,
170+ end : startTime ,
171+ value : ( thenable : any ) ,
172+ // We don't know the requesting owner nor stack.
173+ } ;
174+ // We can infer the await owner/stack lazily from where this promise ends up
175+ // used. It can be used in more than one place so we can't assign it here.
176+ thenable . _debugInfo = [ { awaited : ioInfo } ] ;
177+ // Track when we resolved the Promise as the approximate end time.
178+ if ( thenable . status !== 'fulfilled' && thenable . status !== 'rejected' ) {
179+ const trackEndTime = ( ) => {
180+ // $FlowFixMe[cannot-write]
181+ ioInfo . end = performance . now ( ) ;
182+ } ;
183+ thenable . then ( trackEndTime , trackEndTime ) ;
184+ }
185+ }
186+
157187 // We use an expando to track the status and result of a thenable so that we
158188 // can synchronously unwrap the value. Think of this as an extension of the
159189 // Promise API, or a custom interface that is a superset of Thenable.
0 commit comments