import { $O , definePrivate , isThenable , IThenable , noop } from '../shared' ; import { commit } from './commit' ; import { freeze } from './freeze' ; import { getObservable , Observable } from './Observable' ; export type PromiseState < T = any > = PendingState | FulfilledState < T > | RejectedState ; export type PendingState = { readonly resolved : false ; } ; export type FulfilledState < T = any > = { readonly resolved : true ; readonly result : T ; readonly error : undefined ; } ; export type RejectedState = { readonly resolved : true ; readonly result : undefined ; readonly error : Error ; } ; export type PromiseResolver < T = any > = ( resolve : ( result : T | IThenable < T > ) => void , reject : ( error : Error ) => void ) => void ; const freezeState = freeze as < T = any > ( state : PromiseState < T > ) => PromiseState < T > ; const PENDING = freezeState ( { resolved : false } ) ; export class OPromise < T = any > extends Observable < PromiseState < T > > { private _state : PromiseState < T > ; constructor ( resolver ? ) { super ( ( ) => this . _state ) ; this . _state = PENDING ; if ( resolver ) { try { resolver ( this . resolve . bind ( this ) , this . reject . bind ( this ) ) ; } catch ( e ) { this . reject ( e ) ; } } } resolve < T > ( result ) ; resolve < T > ( result ) ; resolve ( result ) { if ( this . _state !== PENDING ) return ; if ( isThenable ( result ) ) { this . _state = freezeState ( { resolved : false } ) ; result . then ( this . _fulfill . bind ( this ) , this . _reject . bind ( this ) ) . then ( noop , console . error ) ; } else { this . _fulfill ( result ) ; } } reject ( error ) { if ( this . _state === PENDING ) { this . _reject ( error ) ; } } internal [ '_isCurrent' ] ( value ) { return value && value [ $O ] === this ; } static resolve < T > ( result ) ; static resolve < T > ( result ) ; /** Create a promise and resolve it immediately */ static resolve ( result ) { let p = new OPromise ( ) ; p . resolve ( result ) ; return p ; } private _fulfill ( result ) { this . _state = freezeState ( { resolved : true , result , error : undefined } ) ; commit ( this , PENDING , this . _state ) ; } private _reject ( error ) { this . _state = freezeState < T > ( { resolved : true , result : undefined , error } ) ; commit ( this , PENDING , this . _state ) ; } } internal export function bindPromise < T > ( promise ) { let observable = getObservable ( promise ) ; if ( ! observable ) { observable = OPromise . resolve ( promise ) ; definePrivate ( promise , $O , observable ) ; } return observable ; }