import { Disposable } from './dispose' ; export interface IdleDeadline { readonly didTimeout : boolean ; timeRemaining ( ) : DOMHighResTimeStamp ; } export type DisposableCallback = ( ) => void ; /**
 * this run the callback when CPU is idle. Will fallback to setTimeout if
 * the browser doesn't support requestIdleCallback
 */ export let runWhenIdle ; declare function requestIdleCallback ( callback , options ? ) ; declare function cancelIdleCallback ( handle ) ; ( function ( ) { if ( typeof requestIdleCallback !== 'undefined' && typeof cancelIdleCallback !== 'undefined' ) { runWhenIdle = ( runner , timeout ? ) => { const handle = requestIdleCallback ( runner , typeof timeout === 'number' ? { timeout } : undefined ) ; let disposed = false ; return ( ) => { if ( disposed ) { return ; } disposed = true ; clearTimeout ( handle ) ; } ; } ; } else { const dummyIdle = Object . freeze ( { didTimeout : true , timeRemaining ( ) { return 15 ; } , } ) ; runWhenIdle = ( runner ) => { const handle = setTimeout ( ( ) => runner ( dummyIdle ) ) ; let disposed = false ; return ( ) => { if ( disposed ) { return ; } disposed = true ; clearTimeout ( handle ) ; } ; } ; } } ) ( ) ; /**
 * a wrapper of a executor so it can be evaluated when it's necessary or the CPU is idle
 *
 * the type of the returned value of the executor would be T
 */ export class IdleValue < T > implements Disposable { private readonly executor : ( ) => void ; private readonly disposeCallback : ( ) => void ; private didRun = false ; private value ? : T ; private error ? : Error ; constructor ( executor ) { this . executor = ( ) => { try { this . value = executor ( ) ; } catch ( err ) { this . error = err ; } finally { this . didRun = true ; } } ; this . disposeCallback = runWhenIdle ( ( ) => this . executor ( ) ) ; } dispose ( ) { this . disposeCallback ( ) ; } getValue ( ) { if ( ! this . didRun ) { this . dispose ( ) ; this . executor ( ) ; } if ( this . error ) { throw this . error ; } return this . value ! ; } }