@@ -15,7 +15,7 @@ import enqueueTask from 'shared/enqueueTask';
15
15
let actScopeDepth = 0 ;
16
16
let didWarnNoAwaitAct = false ;
17
17
18
- export function act ( callback : ( ) => Thenable < mixed > ) : Thenable < void > {
18
+ export function act < T > ( callback : ( ) = > T | Thenable < T > ) : Thenable < T > {
19
19
if ( __DEV__ ) {
20
20
// `act` calls can be nested, so we track the depth. This represents the
21
21
// number of `act` scopes on the stack.
@@ -41,21 +41,22 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
41
41
typeof result === 'object' &&
42
42
typeof result . then === 'function'
43
43
) {
44
+ const thenableResult : Thenable < T > = (result: any);
44
45
// The callback is an async function (i.e. returned a promise). Wait
45
46
// for it to resolve before exiting the current scope.
46
47
let wasAwaited = false;
47
- const thenable = {
48
+ const thenable: Thenable < T > = {
48
49
then ( resolve , reject ) {
49
50
wasAwaited = true ;
50
- result . then (
51
- ( ) => {
51
+ thenableResult . then (
52
+ returnValue => {
52
53
popActScope ( prevActScopeDepth ) ;
53
54
if ( actScopeDepth === 0 ) {
54
55
// We've exited the outermost act scope. Recursively flush the
55
56
// queue until there's no remaining work.
56
- recursivelyFlushAsyncActWork ( resolve , reject ) ;
57
+ recursivelyFlushAsyncActWork ( returnValue , resolve , reject ) ;
57
58
} else {
58
- resolve ( ) ;
59
+ resolve ( returnValue ) ;
59
60
}
60
61
} ,
61
62
error => {
@@ -88,6 +89,7 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
88
89
}
89
90
return thenable ;
90
91
} else {
92
+ const returnValue : T = ( result : any ) ;
91
93
// The callback is not an async function. Exit the current scope
92
94
// immediately, without awaiting.
93
95
popActScope ( prevActScopeDepth ) ;
@@ -100,26 +102,30 @@ export function act(callback: () => Thenable<mixed>): Thenable<void> {
100
102
}
101
103
// Return a thenable. If the user awaits it, we'll flush again in
102
104
// case additional work was scheduled by a microtask.
103
- return {
105
+ const thenable : Thenable < T > = {
104
106
then ( resolve , reject ) {
105
107
// Confirm we haven't re-entered another `act` scope, in case
106
108
// the user does something weird like await the thenable
107
109
// multiple times.
108
110
if ( ReactCurrentActQueue . current === null ) {
109
111
// Recursively flush the queue until there's no remaining work.
110
112
ReactCurrentActQueue . current = [ ] ;
111
- recursivelyFlushAsyncActWork ( resolve , reject ) ;
113
+ recursivelyFlushAsyncActWork ( returnValue , resolve , reject ) ;
114
+ } else {
115
+ resolve ( returnValue ) ;
112
116
}
113
117
} ,
114
118
} ;
119
+ return thenable ;
115
120
} else {
116
121
// Since we're inside a nested `act` scope, the returned thenable
117
122
// immediately resolves. The outer scope will flush the queue.
118
- return {
123
+ const thenable : Thenable < T > = {
119
124
then ( resolve , reject ) {
120
- resolve ( ) ;
125
+ resolve ( returnValue ) ;
121
126
} ,
122
127
} ;
128
+ return thenable ;
123
129
}
124
130
}
125
131
} else {
@@ -142,7 +148,11 @@ function popActScope(prevActScopeDepth) {
142
148
}
143
149
}
144
150
145
- function recursivelyFlushAsyncActWork ( resolve , reject ) {
151
+ function recursivelyFlushAsyncActWork < T > (
152
+ returnValue: T,
153
+ resolve: T => mixed ,
154
+ reject : mixed => mixed ,
155
+ ) {
146
156
if ( __DEV__ ) {
147
157
const queue = ReactCurrentActQueue . current ;
148
158
if ( queue !== null ) {
@@ -152,17 +162,17 @@ function recursivelyFlushAsyncActWork(resolve, reject) {
152
162
if ( queue . length === 0 ) {
153
163
// No additional work was scheduled. Finish.
154
164
ReactCurrentActQueue . current = null ;
155
- resolve ( ) ;
165
+ resolve ( returnValue ) ;
156
166
} else {
157
167
// Keep flushing work until there's none left.
158
- recursivelyFlushAsyncActWork ( resolve , reject ) ;
168
+ recursivelyFlushAsyncActWork ( returnValue , resolve , reject ) ;
159
169
}
160
170
} ) ;
161
171
} catch ( error ) {
162
172
reject ( error ) ;
163
173
}
164
174
} else {
165
- resolve ( ) ;
175
+ resolve ( returnValue ) ;
166
176
}
167
177
}
168
178
}
0 commit comments