/**
 * ThenFail v0.4
 * Just another Promises/A+ Library
 *
 * https://github.com/vilic/thenfail
 *
 * MIT License
 */ import { EventEmitter } from 'events' ; import { ChildProcess } from 'child_process' ; import * as asap from 'asap' ; import deprecated from 'deprecated-decorator' ; import { BreakSignal , GoToSignal } from './signals' ; import { Context } from './context' ; import { TimeoutError } from './errors' ; let EventEmitterConstructor ; let ChildProcessConstructor ; try { EventEmitterConstructor = require ( 'events' ) . EventEmitter ; } catch ( error ) { } try { ChildProcessConstructor = require ( 'child_process' ) . ChildProcess ; } catch ( error ) { } export interface PromiseLike < T > { param onfulfilled param onrejected return then < TResult > ( onfulfilled ? , onrejected ? ) : PromiseLike < TResult > ; then < TResult > ( onfulfilled ? , onrejected ? ) : PromiseLike < TResult > ; } export type Resolvable < T > = PromiseLike < T > | T ; export type Resolver < T > = ( resolve : ( value ? : Resolvable < T > ) => void , reject : ( reason : any ) => void ) => void ; export type OnFulfilledHandler < T , TResult > = ( value : T ) => Resolvable < TResult > ; export type OnFulfilledSpreadHandler < TResult > = ( ... values : any [ ] ) => Resolvable < TResult > ; export type OnRejectedHandler < TResult > = ( reason : any ) => Resolvable < TResult > ; export type OnAnyHandler < TResult > = ( valueOrReason : any ) => Resolvable < TResult > ; export type OnContextDisposedHandler = ( ) => void ; export type NodeStyleCallback < T > = ( error ? : any , value ? : T ) => void ; export type MapCallback < T , TResult > = ( value : T , index : number , array : T [ ] ) => Resolvable < TResult > ; export type ReduceCallback < T , TResult > = ( previousValue : TResult , currentValue : T , index : number , array : T [ ] ) => Resolvable < TResult > ; export type EachCallback < T > = ( value : T , index : number , array : T [ ] ) => Resolvable < boolean | void > ; export type WaterfallCallback < T , TResult > = ( value : T , result : TResult , index : number , array : T [ ] ) => Resolvable < TResult > ; /**
 * Possible states of a promise.
 */ const enum State { pending , fulfilled , rejected , skipped } /**
 * ThenFail promise options.
 */ export let options = { disableUnrelayedRejectionWarning : false , logger : { log : console . log , warn : console . warn , error : console . error } } ; export class Promise < T > implements PromiseLike < T > { /** To make sure type checking work with value. */ private __generic : T ; /** Current state of this promise. */ private _state = State . pending ; /**
     * Indicates whether `onfulfilled` or `onrejected` handler has been called
     * but the resolved value has not become fulfilled yet.
     */ private _running = false ; /** Indicates whether this promise has been relayed or notified as unrelayed. */ private _handled = false ; /** The fulfilled value or rejected reason associated with this promise. */ private _valueOrReason : any ; /** Context of this promise. */ private _context : Context ; /** Label of this promise. */ private _label : string ; /**
     * Next promise in the chain.
     * Avoid using an array if not necessary due to performance issue,
     * the same way applies to `_handledPromise(s)`.
     * If `_chainedPromise` is not undefined, `_chainedPromises` must be undefined.
     * Vice versa.
     */ private _chainedPromise : Promise < any > ; /** Next promises in the chain. */ private _chainedPromises : Promise < any > [ ] ; /**
     * Promise that will share the same state (and value/reason).
     *
     * Example:
     *
     * ```ts
     * let promiseA = Promise.then(() => {
     *     let promiseB = Promise.then(() => ...);
     *     return promiseB;
     * });
     * ```
     *
     * The state of `promiseB` will determine the state of `promiseA`.
     * And `promiseA` will then be in here.
     */ private _handledPromise : Promise < T > ; /** Promises that will share the same state (and value/reason). */ private _handledPromises : Promise < T > [ ] ; private _onPreviousFulfilled : OnFulfilledHandler < any , T > ; private _onPreviousRejected : OnRejectedHandler < T > ; private _onContextDisposed : OnContextDisposedHandler ; /**
     * Promise constructor.
     */ constructor ( ) ; constructor ( resolver ) ; constructor ( context ) ; constructor ( resolverOrContext ? ) { if ( resolverOrContext instanceof Context && ! resolverOrContext . _enclosed ) { this . _context = resolverOrContext ; } else { this . _context = new Context ( ) ; } if ( typeof resolverOrContext === 'function' ) { try { ( < Resolver < T > > resolverOrContext ) ( value => this . resolve ( value ) , reason => this . reject ( reason ) ) ; } catch ( error ) { this . reject ( error ) ; } } } /**
     * Get the state from previous promise in chain.
     */ private _grab ( previousState , previousValueOrReason ? ) { if ( this . _state !== State . pending ) { return ; } let handler ; if ( previousState === State . fulfilled ) { handler = this . _onPreviousFulfilled ; } else if ( previousState === State . rejected ) { handler = this . _onPreviousRejected ; } if ( handler ) { this . _run ( handler , previousValueOrReason ) ; } else { this . _relay ( previousState , previousValueOrReason ) ; } } /**
     * Invoke `onfulfilled` or `onrejected` handlers.
     */ private _run ( handler , previousValueOrReason ) { this . _running = true ; asap ( ( ) => { let resolvable ; try { resolvable = handler ( previousValueOrReason ) ; } catch ( error ) { this . _decide ( State . rejected , error ) ; this . _running = false ; return ; } this . _unpack ( resolvable , ( state , valueOrReason ) => { this . _decide ( state , valueOrReason ) ; this . _running = false ; } ) ; } ) ; } /**
     * The resolve process defined in Promises/A+ specifications.
     */ private _unpack ( value , callback ) { if ( this === value ) { callback ( State . rejected , new TypeError ( 'The promise should not return itself' ) ) ; return ; } if ( value instanceof Promise ) { if ( value . _state === State . pending ) { if ( value . _handledPromise ) { value . _handledPromises = [ value . _handledPromise , this ] ; value . _handledPromise = undefined ; } else if ( value . _handledPromises ) { value . _handledPromises . push ( this ) ; } else { value . _handledPromise = this ; } let context = this . _context ; if ( context . _subContexts ) { context . _subContexts . push ( value . _context ) ; } else { context . _subContexts = [ value . _context ] ; } } else { callback ( value . _state , value . _valueOrReason ) ; value . _handled = true ; } return ; } if ( value && ( typeof value === 'object' || typeof value === 'function' ) ) { try { let then = ( value as PromiseLike < any > ) . then ; if ( typeof then === 'function' ) { then . call ( value , ( value ) => { if ( callback ) { this . _unpack ( value , callback ) ; callback = undefined ; } } , ( reason ) => { if ( callback ) { callback ( State . rejected , reason ) ; callback = undefined ; } } ) ; return ; } } catch ( error ) { if ( callback ) { callback ( State . rejected , error ) ; callback = undefined ; } return ; } } callback ( State . fulfilled , value ) ; } /**
     * Decide whether to call `_relay`, `_skip` or `_goto`.
     */ private _decide ( state , valueOrReason ? ) { if ( valueOrReason instanceof BreakSignal ) { this . _skip ( valueOrReason ) ; } else if ( valueOrReason instanceof GoToSignal ) { this . _goto ( valueOrReason ) ; } else { this . _relay ( state , valueOrReason ) ; } } /**
     * Set the state of current promise and relay it to next promises.
     */ private _relay ( state , valueOrReason ? ) { if ( this . _state !== State . pending ) { return ; } if ( this . _context . _disposed ) { this . _skip ( ) ; return ; } this . _state = state ; this . _valueOrReason = valueOrReason ; if ( this . _chainedPromise ) { this . _chainedPromise . _grab ( state , valueOrReason ) ; } else if ( this . _chainedPromises ) { for ( let promise of this . _chainedPromises ) { promise . _grab ( state , valueOrReason ) ; } } if ( this . _handledPromise ) { this . _handledPromise . _relay ( state , valueOrReason ) ; } else if ( this . _handledPromises ) { for ( let promise of this . _handledPromises ) { promise . _relay ( state , valueOrReason ) ; } } asap ( ( ) => { if ( state === State . rejected && ! this . _handled ) { this . _handled = true ; let relayed = ! ! ( this . _chainedPromise || this . _chainedPromises || this . _handledPromise || this . _handledPromises ) ; if ( ! relayed && ! options . disableUnrelayedRejectionWarning ) { let error = valueOrReason && ( valueOrReason . stack || valueOrReason . message ) || valueOrReason ; options . logger . warn ( `An unrelayed rejection happens:\n${ error }` ) ; } } this . _relax ( ) ; } ) ; } /**
     * Skip some promises.
     */ private _skip ( signal ? ) { if ( this . _state !== State . pending ) { return ; } if ( this . _running ) { if ( ! signal ) { if ( this . _onContextDisposed ) { try { this . _onContextDisposed . call ( undefined ) ; } catch ( error ) { asap ( ( ) => { throw error ; } ) ; } } } this . _state = State . fulfilled ; } else { this . _state = State . skipped ; } if ( this . _chainedPromise ) { let promise = this . _chainedPromise ; if ( promise . _context === this . _context ) { promise . _skip ( signal ) ; } else { promise . _grab ( State . fulfilled ) ; } } else if ( this . _chainedPromises ) { for ( let promise of this . _chainedPromises ) { if ( promise . _context === this . _context ) { promise . _skip ( signal ) ; } else { promise . _grab ( State . fulfilled ) ; } } } if ( signal && signal . preliminary ) { signal . preliminary = false ; if ( this . _handledPromise ) { this . _handledPromise . _skip ( signal ) ; } else if ( this . _handledPromises ) { for ( let promise of this . _handledPromises ) { promise . _skip ( signal ) ; } } } else { if ( this . _handledPromise ) { this . _handledPromise . _relay ( State . fulfilled ) ; } else if ( this . _handledPromises ) { for ( let promise of this . _handledPromises ) { promise . _relay ( State . fulfilled ) ; } } } this . _relax ( ) ; } /**
     * Go to a specific promise that matches given label.
     */ private _goto ( signal ) { if ( this . _state !== State . pending ) { return ; } this . _state = this . _running ? State . fulfilled : State . skipped ; if ( this . _chainedPromise ) { let promise = this . _chainedPromise ; if ( promise . _label === signal . label ) { promise . _grab ( State . fulfilled , signal . value ) ; } else { promise . _goto ( signal ) ; } } else if ( this . _chainedPromises ) { for ( let promise of this . _chainedPromises ) { if ( promise . _label === signal . label ) { promise . _grab ( State . fulfilled , signal . value ) ; } else { promise . _goto ( signal ) ; } } } if ( signal && signal . preliminary ) { signal . preliminary = false ; if ( this . _handledPromise ) { this . _handledPromise . _goto ( signal ) ; } else if ( this . _handledPromises ) { for ( let promise of this . _handledPromises ) { promise . _goto ( signal ) ; } } } else { if ( this . _handledPromise ) { this . _handledPromise . _relay ( State . fulfilled ) ; } else if ( this . _handledPromises ) { for ( let promise of this . _handledPromises ) { promise . _relay ( State . fulfilled ) ; } } } this . _relax ( ) ; } /**
     * Set handlers to undefined.
     */ private _relax ( ) { if ( this . _onPreviousFulfilled ) { this . _onPreviousFulfilled = undefined ; } if ( this . _onPreviousRejected ) { this . _onPreviousRejected = undefined ; } if ( this . _onContextDisposed ) { this . _onContextDisposed = undefined ; } if ( this . _chainedPromise ) { this . _chainedPromise = undefined ; } else { this . _chainedPromises = undefined ; } if ( this . _handledPromise ) { this . _handledPromise = undefined ; } else { this . _handledPromises = undefined ; } } param onfulfilled param onrejected return then < TResult > ( onfulfilled , onrejected ? ) { let promise = new Promise < any > ( this . _context ) ; if ( typeof onfulfilled === 'function' ) { promise . _onPreviousFulfilled = onfulfilled ; } if ( typeof onrejected === 'function' ) { promise . _onPreviousRejected = onrejected ; } if ( this . _state === State . pending ) { if ( this . _chainedPromise ) { this . _chainedPromises = [ this . _chainedPromise , promise ] ; this . _chainedPromise = undefined ; } else if ( this . _chainedPromises ) { this . _chainedPromises . push ( promise ) ; } else { this . _chainedPromise = promise ; } } else { if ( ! this . _handled ) { this . _handled = true ; } promise . _grab ( this . _state , this . _valueOrReason ) ; } return promise ; } param resolvable resolve ( resolvable ? ) { this . _unpack ( resolvable , ( state , valueOrReason ) => this . _grab ( state , valueOrReason ) ) ; } param reason reject ( reason ) { this . _grab ( State . rejected , reason ) ; } param label param onfulfilled param onrejected return label < TResult > ( label , onfulfilled , onrejected ? ) { let promise = this . then ( onfulfilled , onrejected ) ; promise . _label = label ; return promise ; } param oninerrupted return interruption ( oncontextdisposed ) { if ( this . _state === State . pending ) { if ( this . _onContextDisposed ) { throw new Error ( 'Interruption handler has already been set' ) ; } this . _onContextDisposed = oncontextdisposed ; } else { options . logger . warn ( 'Handler added after promise state no longer being pending' ) ; } return this ; } return enclose ( ) { this . _context . _enclosed = true ; return this ; } param timeout return delay ( timeout ) { return this . then ( value => { return new Promise < T > ( resolve => { setTimeout ( ( ) => resolve ( value ) , Math . floor ( timeout ) || 0 ) ; } ) ; } ) ; } param timeout return timeout ( timeout , message ? ) { this . _context . _enclosed = true ; setTimeout ( ( ) => { if ( this . _state === State . pending ) { this . _relay ( State . rejected , new TimeoutError ( message ) ) ; this . _context . disposeSubContexts ( ) ; } } , Math . floor ( timeout ) || 0 ) ; return this ; } param promise return handle ( promise ) ; param callback return handle ( callback ) ; handle ( promiseOrCallback ) { if ( promiseOrCallback instanceof Promise ) { if ( this . _state === State . pending ) { if ( this . _handledPromise ) { this . _handledPromises = [ this . _handledPromise , promiseOrCallback ] ; this . _handledPromise = undefined ; } else if ( this . _handledPromises ) { this . _handledPromises . push ( promiseOrCallback ) ; } else { this . _handledPromise = promiseOrCallback ; } } else { if ( ! this . _handled ) { this . _handled = true ; } promiseOrCallback . _relay ( this . _state , this . _valueOrReason ) ; } } else if ( typeof promiseOrCallback === 'function' ) { this . then ( value => { ( promiseOrCallback as NodeStyleCallback < T > ) ( undefined , value ) ; } , reason => { ( promiseOrCallback as NodeStyleCallback < T > ) ( reason , undefined ) ; } ) ; } else { throw new TypeError ( 'Unsupported type to handle' ) ; } return this ; } param disposor return disposable ( disposer ) { return this . then ( resource => { return { resource , dispose : disposer } ; } ) ; } param onfulfilled return tap ( onfulfilled ) { let relayValue ; return this . then ( value => { relayValue = value ; return onfulfilled ( value ) ; } ) . then ( ( ) => relayValue ) ; } param onfulfilled return spread < TResult > ( onfulfilled ) { return this . then ( value => onfulfilled . apply ( undefined , value ) ) ; } /**
     * A shortcut of `promise.then(undefined, onrejected)`.
     */ fail ( onrejected ) { return this . then < T > ( undefined , onrejected ) ; } param onrejected return catch ( onrejected ) ; param ReasonType param onrejected return catch ( ReasonType , onrejected ) ; catch ( ReasonType , onrejected ? ) { if ( typeof onrejected === 'function' ) { return this . then < T > ( undefined , reason => { if ( reason instanceof ReasonType ) { return onrejected ( reason ) ; } else { throw reason ; } } ) ; } else { onrejected = ReasonType as OnRejectedHandler < T > ; return this . then < T > ( undefined , onrejected ) ; } } param callback return map < T > ( callback ) { return this . then ( ( values ) => Promise . map ( values , callback ) ) ; } param callback return reduce < TResult > ( callback , initialValue ? ) { return this . then ( ( values ) => Promise . reduce ( values , callback , initialValue ) ) ; } param callback return each < T > ( callback ) { return this . then ( ( values ) => Promise . each ( values , callback ) ) ; } /**
     * A shortcut of `Promise.waterfall`, take the fulfilled value of
     * previous promise as initial result.
     */ waterfall < TValue > ( values , callback ) { return this . then ( initialResult => Promise . waterfall ( values , initialResult , callback ) ) ; } /**
     * A shortcut of `Promise.retry`.
     */ retry < TResult > ( callback ) ; retry < TResult > ( options , callback ) ; retry < TResult > ( options , callback ? ) { return this . then ( ( ) => Promise . retry ( options , callback ) ) ; } param object return log ( object ? ) { if ( object === undefined ) { return this . then ( value => { if ( value !== undefined ) { options . logger . log ( value ) ; } return value ; } , reason => { options . logger . error ( reason && ( reason . stack || reason . message ) || reason ) ; return undefined ; } ) ; } else { return this . tap ( ( ) => { options . logger . log ( object ) ; } ) ; } } /**
     * Call `this.then` with `onrejected` handler only, and throw the
     * rejection reason if any.
     */ done ( ) { this . then ( undefined , reason => { asap ( ( ) => { throw reason ; } ) ; } ) ; } /**
     * (get) A promise that will be rejected with a pre-break signal if previous
     * promise is fulfilled with a non-`false` value.
     */ get break ( ) : Promise < any > { return this . then ( value => { if ( < any > value !== false ) { throw new BreakSignal ( true ) ; } } ) ; } /**
     * Create a promise that will be rejected with a goto signal if previous
     * promise is fulfilled with a non-`false` value.
     */ goto ( label , value ? ) { return this . then ( value => { if ( < any > value !== false ) { throw new GoToSignal ( label , value , true ) ; } } ) ; } /**
     * (get) A promise that will eventually be fulfilled with `undefined`.
     */ get void ( ) : Promise < void > { return this . then ( ( ) => undefined ) ; } /**
     * (get) A promise that will eventually been fulfilled with `true`.
     */ get true ( ) : Promise < boolean > { return this . then ( ( ) => true ) ; } /**
     * (get) A promise that will eventually been fulfilled with `false`.
     */ get false ( ) : Promise < boolean > { return this . then ( ( ) => false ) ; } /**
     * (get) Get the context of current promise.
     */ get context ( ) : Context { return this . _context ; } /**
     * (get) A boolean that indicates whether the promise is pending.
     */ get pending ( ) : boolean { return this . _state === State . pending ; } /**
     * (get) A boolean that indicates whether the promise is fulfilled.
     */ get fulfilled ( ) : boolean { return this . _state === State . fulfilled ; } /**
     * (get) A boolean that indicates whether the promise is rejected.
     */ get rejected ( ) : boolean { return this . _state === State . rejected ; } /**
     * (get) A boolean that indicates whether the promise is interrupted.
     */ get skipped ( ) : boolean { return this . _state === State . skipped ; } deperacated @ deprecated ( 'skipped' , '0.4' ) get interrupted ( ) : boolean { return this . _state === State . skipped ; } param onfulfilled return static then < TResult > ( onfulfilled ) { return Promise . void . then ( onfulfilled ) ; } return static resolve ( ) ; return static resolve < T > ( resolvable ) ; static resolve < T > ( resolvable ? ) { if ( resolvable instanceof Promise ) { return resolvable ; } else { let promise = new Promise < T > ( ) ; promise . resolve ( resolvable ) ; return promise ; } } param reason return static reject ( reason ) ; param reason return static reject < T > ( reason ) ; static reject < T > ( reason ) { let promise = new Promise < T > ( ) ; promise . reject ( reason ) ; return promise ; } /**
     * Alias of `Promise.resolve`.
     */ static when < T > ( value ) { return Promise . resolve ( value ) ; } param context return static context ( context ) { let promise = new Promise < void > ( context ) ; promise . resolve ( ) ; return promise ; } param timeout return static delay ( timeout ) { return new Promise < void > ( resolve => { setTimeout ( ( ) => resolve ( ) , Math . floor ( timeout ) || 0 ) ; } ) ; } return static all < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 > ( values ) ; static all < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 > ( values ) ; static all < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 > ( values ) ; static all < T1 , T2 , T3 , T4 , T5 , T6 , T7 > ( values ) ; static all < T1 , T2 , T3 , T4 , T5 , T6 > ( values ) ; static all < T1 , T2 , T3 , T4 , T5 > ( values ) ; static all < T1 , T2 , T3 , T4 > ( values ) ; static all < T1 , T2 , T3 > ( values ) ; static all < T1 , T2 > ( values ) ; static all < T1 > ( values ) ; param resolvables return static all < T > ( resolvables ) ; static all < T > ( resolvables ) { if ( ! resolvables . length ) { return Promise . resolve ( [ ] ) ; } let resultsPromise = new Promise < T [ ] > ( ) ; let results = [ ] ; let remaining = resolvables . length ; let rejected = false ; resolvables . forEach ( ( resolvable , index ) => { Promise . resolve ( resolvable ) . then ( result => { if ( rejected ) { return ; } results [ index ] = result ; if ( -- remaining === 0 ) { resultsPromise . resolve ( results ) ; } } , reason => { if ( rejected ) { return ; } rejected = true ; resultsPromise . reject ( reason ) ; results = undefined ; } ) ; } ) ; return resultsPromise ; } param resolvables return static race < TResult > ( resolvables ) { let promise = new Promise < TResult > ( ) ; for ( let resolvable of resolvables ) { Promise . resolve ( resolvable ) . handle ( promise ) ; } return promise ; } param values param callback return static map < T , TResult > ( values , callback ) { let results = new Array < TResult > ( values . length ) ; return values . reduce ( ( promise , value , index , values ) => { return promise . then ( ( ) => callback ( value , index , values ) ) . then ( result => { results [ index ] = result ; } ) ; } , Promise . resolve ( ) ) . then ( ( ) => results ) ; } param values param callback return static reduce < T , TResult > ( values , callback , initialValue ? ) { return values . reduce ( ( promise , value , index , values ) => { return promise . then ( previousValue => { return callback ( previousValue , value , index , values ) ; } ) ; } , Promise . resolve ( initialValue ) ) ; } param values param callback return static each < T > ( values , callback ) { return values . reduce ( ( promise , value , index , values ) => { return promise . then ( result => { if ( result === false ) { throw new BreakSignal ( ) ; } return callback ( value , index , values ) ; } ) ; } , Promise . resolve < boolean | void > ( undefined ) ) . then ( ( ) => true ) . enclose ( ) . then ( completed => ! ! completed ) ; } param values param initialResult param callback static waterfall < T , TResult > ( values , initialResult , callback ) { let lastResult = initialResult ; return Promise . each ( values , ( value , index , array ) => { let callbackPromise = Promise . then ( ( ) => callback ( value , lastResult , index , array ) ) . then ( result => result ) ; return callbackPromise . enclose ( ) . then ( result => { if ( callbackPromise . interrupted ) { return false ; } else { lastResult = result ; return undefined ; } } ) ; } ) . then ( ( ) => lastResult ) ; } param callback return static retry < TResult > ( callback ) ; param options param callback return static retry < TResult > ( options , callback ) ; static retry < TResult > ( options = { } , callback ? ) { if ( callback === undefined && typeof options === 'function' ) { callback = < any > options ; options = { } ; } let { limit = 3 , interval = 0 } = options ; let lastReason ; let attemptIndex = 0 ; return process ( ) ; function process ( ) { return Promise . then ( ( ) => callback ( lastReason , attemptIndex ++ ) ) . enclose ( ) . fail ( reason => { if ( attemptIndex >= limit ) { throw reason ; } lastReason = reason ; if ( interval ) { return Promise . delay ( interval ) . then ( ( ) => process ( ) ) ; } else { return process ( ) ; } } ) ; } } param disposable param handler return static using < T , TResult > ( disposable , handler ) { let resolvedDisposable ; let promise = Promise . resolve ( disposable ) . then ( disposable => { resolvedDisposable = disposable ; return handler ( disposable . resource ) ; } ) ; let disposed = false ; function dispose ( ) { if ( ! disposed ) { disposed = true ; resolvedDisposable . dispose ( resolvedDisposable . resource ) ; } } promise . interruption ( dispose ) . then ( dispose , dispose ) ; return promise ; } param fn param args return static invoke ( fn , ... args ) ; static invoke < TResult > ( fn , ... args ) ; static invoke < TResult > ( fn , ... args ) { return new Promise < TResult > ( ( resolve , reject ) => { args = args . concat ( ( error , value ) => { if ( error ) { reject ( error ) ; } else { resolve ( value ) ; } } ) ; fn . apply ( undefined , args ) ; } ) ; } private static _forChildProcess ( process ) { return new Promise < void > ( ( resolve , reject ) => { process . on ( 'exit' , onexit ) ; process . on ( 'error' , onerror ) ; function removeListeners ( ) { process . removeListener ( 'exit' , onexit ) ; process . removeListener ( 'error' , onerror ) ; } function onexit ( code ) { removeListeners ( ) ; if ( code === 0 ) { resolve ( ) ; } else { reject ( new Error ( 'Invalid exit code' ) ) ; } } function onerror ( error ) { asap ( removeListeners ) ; reject ( error ) ; } } ) ; } private static _forEventEmitter < T > ( emitter , types , errorEmitters = [ ] ) { errorEmitters . unshift ( emitter ) ; if ( typeof types === 'string' ) { types = [ types as string ] ; } return new Promise < T > ( ( resolve , reject ) => { for ( let type of types ) { emitter . on ( type , onsuccess ) ; } for ( let emitter of errorEmitters ) { emitter . on ( 'error' , onerror ) ; } function removeListeners ( ) { for ( let type of types ) { emitter . removeListener ( type , onsuccess ) ; } for ( let emitter of errorEmitters ) { emitter . removeListener ( 'error' , onerror ) ; } } function onsuccess ( value ) { removeListeners ( ) ; resolve ( value ) ; } function onerror ( error ) { asap ( removeListeners ) ; reject ( error ) ; } } ) ; } param process static for ( process ) ; param emitter param type param errorEmitters static for ( emitter , types , errorEmitters ? ) ; static for < T > ( emitter , types , errorEmitters ? ) ; static for < T > ( emitter , types ? , errorEmitters ? ) { if ( ChildProcessConstructor && emitter instanceof ChildProcessConstructor && types === undefined ) { return this . _forChildProcess ( emitter as ChildProcess ) ; } if ( EventEmitterConstructor && emitter instanceof EventEmitterConstructor ) { return this . _forEventEmitter < T > ( emitter , types , errorEmitters ) ; } throw new TypeError ( 'Unsupported object' ) ; } /**
     * (fake statement) This getter will always throw a break signal that interrupts the promises chain.
     *
     * Example:
     *
     * ```ts
     * promise
     *     .then(() => {
     *         if (toBreak) {
     *             Promise.break;
     *         }
     *
     *         // Or not to break.
     *     })
     *     .then(() => {
     *         // If `toBreak` is true, it will never enter this handler.
     *     }, () => {
     *         // Nor this handler.
     *     });
     * ```
     */ static get break ( ) : void { throw new BreakSignal ( ) ; } /** (get) The break signal. */ static get breakSignal ( ) : any { return new BreakSignal ( ) ; } /** (get) The pre-break signal. */ static get preBreakSignal ( ) : any { return new BreakSignal ( true ) ; } /** (fake statement) This method will throw an `GoToSignal` with specified `label`. */ static goto ( label , value ? ) { throw new GoToSignal ( label , value ) ; } /**
     * (get) A promise that has already been fulfilled with `undefined`.
     */ static get void ( ) : Promise < void > { let promise = new Promise < void > ( ) ; promise . resolve ( undefined ) ; return promise ; } /**
     * (get) A promise that has already been fulfilled with `true`.
     */ static get true ( ) : Promise < boolean > { let promise = new Promise < boolean > ( ) ; promise . resolve ( true ) ; return promise ; } /**
     * (get) A promise that has already been fulfilled with `false`.
     */ static get false ( ) : Promise < boolean > { let promise = new Promise < boolean > ( ) ; promise . resolve ( false ) ; return promise ; } } export type RetryCallback < TResult > = ( lastReason : any , attemptIndex : number ) => Resolvable < TResult > ; export interface RetryOptions { /** Try limit times (defaults to 3). */ limit ? : number ; /** Interval between two tries (defaults to 0). */ interval ? : number ; } export type Disposer < TResource > = ( resource : TResource ) => void ; export interface Disposable < TResource > { resource : TResource ; dispose : Disposer < TResource > ; } export const using = Promise . using ; export const invoke = Promise . invoke ;