@@ -30,6 +30,24 @@ import {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';
3030const pendingOperations : Map < number , AsyncSequence > =
3131 __DEV__ && enableAsyncDebugInfo ? new Map ( ) : ( null : any ) ;
3232
33+ function resolvePromiseOrAwaitNode (
34+ unresolvedNode : UnresolvedAwaitNode | UnresolvedPromiseNode ,
35+ endTime : number ,
36+ ) : AwaitNode | PromiseNode {
37+ const resolvedNode : AwaitNode | PromiseNode = ( unresolvedNode : any ) ;
38+ resolvedNode . tag = ( ( unresolvedNode . tag === UNRESOLVED_PROMISE_NODE
39+ ? PROMISE_NODE
40+ : AWAIT_NODE ) : any ) ;
41+ // The Promise can be garbage collected after this so we should extract debugInfo first.
42+ const promise = unresolvedNode . debugInfo . deref ( ) ;
43+ resolvedNode . debugInfo =
44+ promise === undefined || promise . _debugInfo === undefined
45+ ? null
46+ : promise . _debugInfo ;
47+ resolvedNode . end = endTime ;
48+ return resolvedNode ;
49+ }
50+
3351// Initialize the tracing of async operations.
3452// We do this globally since the async work can potentially eagerly
3553// start before the first request and once requests start they can interleave.
@@ -129,42 +147,50 @@ export function initAsyncDebugInfo(): void {
129147 }
130148 pendingOperations . set ( asyncId , node ) ;
131149 } ,
150+ before ( asyncId : number ) : void {
151+ const node = pendingOperations . get ( asyncId ) ;
152+ if ( node !== undefined ) {
153+ switch ( node . tag ) {
154+ case IO_NODE : {
155+ // Log the end time when we resolved the I/O. This can happen
156+ // more than once if it's a recurring resource like a connection.
157+ const ioNode : IONode = ( node : any ) ;
158+ ioNode . end = performance . now ( ) ;
159+ break ;
160+ }
161+ case UNRESOLVED_AWAIT_NODE :
162+ case UNRESOLVED_PROMISE_NODE : {
163+ // If we begin before we resolve, that means that this is actually already resolved but
164+ // the promiseResolve hook is called at the end of the execution. This means that it was
165+ // actually already resolved when we started so we just use the start time as the end time.
166+ resolvePromiseOrAwaitNode ( node , node . start ) ;
167+ break ;
168+ }
169+ }
170+ }
171+ } ,
132172 promiseResolve ( asyncId : number ) : void {
133173 const node = pendingOperations . get ( asyncId ) ;
134174 if ( node !== undefined ) {
135175 let resolvedNode : AwaitNode | PromiseNode ;
136176 switch ( node . tag ) {
137- case UNRESOLVED_AWAIT_NODE : {
138- const awaitNode : AwaitNode = ( node : any ) ;
139- awaitNode . tag = AWAIT_NODE ;
140- resolvedNode = awaitNode ;
177+ case UNRESOLVED_AWAIT_NODE :
178+ case UNRESOLVED_PROMISE_NODE : {
179+ resolvedNode = resolvePromiseOrAwaitNode ( node , performance . now ( ) ) ;
141180 break ;
142181 }
143- case UNRESOLVED_PROMISE_NODE : {
144- const promiseNode : PromiseNode = ( node : any ) ;
145- promiseNode . tag = PROMISE_NODE ;
146- resolvedNode = promiseNode ;
182+ case AWAIT_NODE :
183+ case PROMISE_NODE : {
184+ resolvedNode = node ;
185+ // We already resolved this in the begin phase.
147186 break ;
148187 }
149- case IO_NODE :
150- // eslint-disable-next-line react-internal/prod-error-codes
151- throw new Error (
152- 'A Promise should never be an IO_NODE. This is a bug in React.' ,
153- ) ;
154188 default :
155189 // eslint-disable-next-line react-internal/prod-error-codes
156190 throw new Error (
157- 'A Promise should never be resolved twice . This is a bug in React or Node.js .' ,
191+ 'A Promise should never be an IO_NODE . This is a bug in React.' ,
158192 ) ;
159193 }
160- // Log the end time when we resolved the promise.
161- resolvedNode . end = performance . now ( ) ;
162- // The Promise can be garbage collected after this so we should extract debugInfo first.
163- const promise = node . debugInfo . deref ( ) ;
164- resolvedNode . debugInfo =
165- promise === undefined || promise . _debugInfo === undefined
166- ? null
167- : promise . _debugInfo ;
168194 const currentAsyncId = executionAsyncId ( ) ;
169195 if ( asyncId !== currentAsyncId ) {
170196 // If the promise was not resolved by itself, then that means that
0 commit comments