import { IFiber , ITask , ITaskCallback } from './type' ; const queue = [ ] ; const threshold = 5 ; const transitions = [ ] ; let deadline = 0 ; export const startTransition = cb => { transitions . push ( cb ) && translate ( ) ; } ; export const schedule = ( callback ) : void => { queue . push ( { callback } as any ) ; startTransition ( flush ) ; } ; const task = ( pending ) => { const cb = ( ) => transitions . splice ( 0 , 1 ) . forEach ( c => c ( ) ) ; if ( ! pending && typeof Promise !== 'undefined' ) { return ( ) => queueMicrotask ( cb ) ; } if ( typeof MessageChannel !== 'undefined' ) { const { port1 , port2 } = new MessageChannel ( ) ; port1 . onmessage = cb ; return ( ) => port2 . postMessage ( null ) ; } return ( ) => setTimeout ( cb ) ; } ; let translate = task ( false ) ; const flush = ( ) : void => { deadline = getTime ( ) + threshold ; let job = peek ( queue ) ; while ( job && ! shouldYield ( ) ) { const { callback } = job as any ; job . callback = null ; const next = callback ( ) ; if ( next ) { job . callback = next as any ; } else { queue . shift ( ) ; } job = peek ( queue ) ; } job && startTransition ( flush ) ; } ; export const shouldYield = ( ) : boolean => { const pending = getTime ( ) >= deadline ; translate = task ( pending ) ; return pending ; } ; export const getTime = ( ) => performance . now ( ) ; const peek = ( queue ) => queue [ 0 ] ;