@@ -15,7 +15,7 @@ import enqueueTask from 'shared/enqueueTask';
1515let actScopeDepth = 0 ;
1616let didWarnNoAwaitAct = false ;
1717
18- export function act ( callback : ( ) => Thenable < mixed > ) : Thenable < void > {
18+ export function act < T > ( callback : ( ) = > T | Thenable < T > ) : Thenable < T > {
1919 if ( __DEV__ ) {
2020 // `act` calls can be nested, so we track the depth. This represents the
2121 // number of `act` scopes on the stack.
@@ -41,21 +41,22 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
4141 typeof result === 'object' &&
4242 typeof result . then === 'function'
4343 ) {
44+ const thenableResult : Thenable < T > = (result: any);
4445 // The callback is an async function (i.e. returned a promise). Wait
4546 // for it to resolve before exiting the current scope.
4647 let wasAwaited = false;
47- const thenable = {
48+ const thenable: Thenable < T > = {
4849 then ( resolve , reject ) {
4950 wasAwaited = true ;
50- result . then (
51- ( ) => {
51+ thenableResult . then (
52+ returnValue => {
5253 popActScope ( prevActScopeDepth ) ;
5354 if ( actScopeDepth === 0 ) {
5455 // We've exited the outermost act scope. Recursively flush the
5556 // queue until there's no remaining work.
56- recursivelyFlushAsyncActWork ( resolve , reject ) ;
57+ recursivelyFlushAsyncActWork ( returnValue , resolve , reject ) ;
5758 } else {
58- resolve ( ) ;
59+ resolve ( returnValue ) ;
5960 }
6061 } ,
6162 error => {
@@ -88,6 +89,7 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
8889 }
8990 return thenable ;
9091 } else {
92+ const returnValue : T = ( result : any ) ;
9193 // The callback is not an async function. Exit the current scope
9294 // immediately, without awaiting.
9395 popActScope ( prevActScopeDepth ) ;
@@ -100,26 +102,30 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
100102 }
101103 // Return a thenable. If the user awaits it, we'll flush again in
102104 // case additional work was scheduled by a microtask.
103- return {
105+ const thenable : Thenable < T > = {
104106 then ( resolve , reject ) {
105107 // Confirm we haven't re-entered another `act` scope, in case
106108 // the user does something weird like await the thenable
107109 // multiple times.
108110 if ( ReactCurrentActQueue . current === null ) {
109111 // Recursively flush the queue until there's no remaining work.
110112 ReactCurrentActQueue . current = [ ] ;
111- recursivelyFlushAsyncActWork ( resolve , reject ) ;
113+ recursivelyFlushAsyncActWork ( returnValue , resolve , reject ) ;
114+ } else {
115+ resolve ( returnValue ) ;
112116 }
113117 } ,
114118 } ;
119+ return thenable ;
115120 } else {
116121 // Since we're inside a nested `act` scope, the returned thenable
117122 // immediately resolves. The outer scope will flush the queue.
118- return {
123+ const thenable : Thenable < T > = {
119124 then ( resolve , reject ) {
120- resolve ( ) ;
125+ resolve ( returnValue ) ;
121126 } ,
122127 } ;
128+ return thenable ;
123129 }
124130 }
125131 } else {
@@ -142,7 +148,11 @@ function popActScope(prevActScopeDepth) {
142148 }
143149}
144150
145- function recursivelyFlushAsyncActWork ( resolve , reject ) {
151+ function recursivelyFlushAsyncActWork < T > (
152+ returnValue: T,
153+ resolve: T => mixed ,
154+ reject : mixed => mixed ,
155+ ) {
146156 if ( __DEV__ ) {
147157 const queue = ReactCurrentActQueue . current ;
148158 if ( queue !== null ) {
@@ -152,17 +162,17 @@ function recursivelyFlushAsyncActWork(resolve, reject) {
152162 if ( queue . length === 0 ) {
153163 // No additional work was scheduled. Finish.
154164 ReactCurrentActQueue . current = null ;
155- resolve ( ) ;
165+ resolve ( returnValue ) ;
156166 } else {
157167 // Keep flushing work until there's none left.
158- recursivelyFlushAsyncActWork ( resolve , reject ) ;
168+ recursivelyFlushAsyncActWork ( returnValue , resolve , reject ) ;
159169 }
160170 } ) ;
161171 } catch ( error ) {
162172 reject ( error ) ;
163173 }
164174 } else {
165- resolve ( ) ;
175+ resolve ( returnValue ) ;
166176 }
167177 }
168178}
0 commit comments