import { Thenable } from 'react-reconciler' ; import { reconciler } from '../reconciler' ; import { ReactSharedInternals , enqueueTask , __DEV__ , warningWithoutStack } from './forks' ; const { batchedUpdates , flushPassiveEffects , IsThisRendererActing } = reconciler as any ; const { IsSomeRendererActing } = ReactSharedInternals ; const isSchedulerMocked = false ; const flushWork = ( ) => { let didFlushWork = false ; while ( flushPassiveEffects ( ) ) { didFlushWork = true ; } return didFlushWork ; } ; function flushWorkAndMicroTasks ( onDone ) { try { flushWork ( ) ; enqueueTask ( ( ) => { if ( flushWork ( ) ) { flushWorkAndMicroTasks ( onDone ) ; } else { onDone ( ) ; } } ) ; } catch ( err ) { onDone ( err ) ; } } let actingUpdatesScopeDepth = 0 ; let didWarnAboutUsingActInProd = false ; export function act ( callback ) { if ( ! __DEV__ ) { if ( didWarnAboutUsingActInProd === false ) { didWarnAboutUsingActInProd = true ; console . error ( 'act(...) is not supported in production builds of React, and might not behave as expected.' ) ; } } const previousActingUpdatesScopeDepth = actingUpdatesScopeDepth ; actingUpdatesScopeDepth += 1 ; const previousIsSomeRendererActing = IsSomeRendererActing . current ; const previousIsThisRendererActing = IsThisRendererActing . current ; IsSomeRendererActing . current = true ; IsThisRendererActing . current = true ; function onDone ( ) { actingUpdatesScopeDepth -= 1 ; IsSomeRendererActing . current = previousIsSomeRendererActing ; IsThisRendererActing . current = previousIsThisRendererActing ; if ( __DEV__ ) { if ( actingUpdatesScopeDepth > previousActingUpdatesScopeDepth ) { warningWithoutStack ( null , 'You seem to have overlapping act() calls, this is not supported. ' + 'Be sure to await previous act() calls before making a new one. ' ) ; } } } let result ; try { result = batchedUpdates ( callback ) ; } catch ( error ) { onDone ( ) ; throw error ; } if ( result !== null && typeof result === 'object' && typeof result . then === 'function' ) { let called = false ; if ( __DEV__ ) { if ( typeof Promise !== 'undefined' ) { Promise . resolve ( ) . then ( ( ) => { } ) . then ( ( ) => { if ( called === false ) { warningWithoutStack ( null , 'You called act(async () => ...) without await. ' + 'This could lead to unexpected testing behaviour, interleaving multiple act ' + 'calls and mixing their scopes. You should - await act(async () => ...);' ) ; } } ) ; } } return { then ( resolve , reject ) { called = true ; result . then ( ( ) => { if ( actingUpdatesScopeDepth > 1 || ( isSchedulerMocked === true && previousIsSomeRendererActing === true ) ) { onDone ( ) ; resolve ( ) ; return ; } flushWorkAndMicroTasks ( ( err ? ) => { onDone ( ) ; if ( err ) { reject ( err ) ; } else { resolve ( ) ; } } ) ; } , err => { onDone ( ) ; reject ( err ) ; } ) ; } , } ; } if ( __DEV__ ) { warningWithoutStack ( result === undefined , 'The callback passed to act(...) function ' + 'must return undefined, or a Promise. You returned %s' , result ) ; } try { if ( actingUpdatesScopeDepth === 1 && ( isSchedulerMocked === false || previousIsSomeRendererActing === false ) ) { flushWork ( ) ; } onDone ( ) ; } catch ( err ) { onDone ( ) ; throw err ; } return { then ( resolve ) { if ( __DEV__ ) { warningWithoutStack ( false , 'Do not await the result of calling act(...) with sync logic, it is not a Promise.' ) ; } resolve ( ) ; } , } ; }