import { AsyncIterableX } from '../asynciterablex' ; import { OperatorAsyncFunction } from '../../interfaces' ; import { wrapWithAbort } from './withabort' ; import { throwIfAborted } from '../../aborterror' ; import { identity } from '../../util/identity' ; import { safeRace } from '../../util/safeRace' ; const NEVER_PROMISE = new Promise ( ( ) => { } ) ; type MergeResult < T > = { value : T ; index : number ; } ; function wrapPromiseWithIndex < T > ( promise , index ) { return promise . then ( ( value ) => ( { value , index } ) ) as Promise < MergeResult < T > > ; } export class WithLatestFromAsyncIterable < TSource > extends AsyncIterableX < TSource [ ] > { private _source : AsyncIterable < TSource > ; private _others : AsyncIterable < TSource > [ ] ; constructor ( source , others ) { super ( ) ; this . _source = source ; this . _others = others ; } async * [ Symbol . asyncIterator ] ( signal ? ) { throwIfAborted ( signal ) ; const length = this . _others . length ; const newLength = length + 1 ; const iterators = new Array < AsyncIterator < TSource > > ( newLength ) ; const nexts = new Array < Promise < MergeResult < IteratorResult < TSource > > > > ( newLength ) ; let hasValueAll = false ; const hasValue = new Array ( length ) ; const values = new Array ( length ) ; hasValue . fill ( false ) ; for ( let i = 0 ; i < length ; i ++ ) { const iterator = wrapWithAbort ( this . _others [ i ] , signal ) [ Symbol . asyncIterator ] ( ) ; iterators [ i ] = iterator ; nexts [ i ] = wrapPromiseWithIndex ( iterator . next ( ) , i ) ; } const it = wrapWithAbort ( this . _source , signal ) [ Symbol . asyncIterator ] ( ) ; iterators [ length ] = it ; nexts [ length ] = wrapPromiseWithIndex ( it . next ( ) , length ) ; for ( ; ; ) { const next = safeRace ( nexts ) ; const { value : { value : value$ , done : done$ } , index , } = await next ; if ( index === length ) { if ( done$ ) { break ; } const iterator$ = iterators [ index ] ; nexts [ index ] = wrapPromiseWithIndex ( iterator$ . next ( ) , index ) ; if ( hasValueAll ) { yield [ value$ , ... values ] ; } } else if ( done$ ) { nexts [ index ] = < Promise < MergeResult < IteratorResult < TSource > > > > NEVER_PROMISE ; } else { values [ index ] = value$ ; hasValue [ index ] = true ; hasValueAll = hasValue . every ( identity ) ; const iterator$ = iterators [ index ] ; nexts [ index ] = wrapPromiseWithIndex ( iterator$ . next ( ) , index ) ; } } } } template T template T2 param { AsyncIterable < T2 > } source2 returns { OperatorAsyncFunction < T , [ T , T2 ] > } export function withLatestFrom < T , T2 > ( source2 ) ; template T template T2 template T3 param { AsyncIterable < T2 > } source2 param { AsyncIterable < T3 > } source3 returns { OperatorAsyncFunction < T , [ T , T2 , T3 ] > } export function withLatestFrom < T , T2 , T3 > ( source2 , source3 ) ; template T template T2 template T3 template T4 param { AsyncIterable < T2 > } source2 param { AsyncIterable < T3 > } source3 param { AsyncIterable < T4 > } source4 returns { OperatorAsyncFunction < T , [ T , T2 , T3 , T4 ] > } export function withLatestFrom < T , T2 , T3 , T4 > ( source2 , source3 , source4 ) ; template T template T2 template T3 template T4 template T5 param { AsyncIterable < T2 > } source2 param { AsyncIterable < T3 > } source3 param { AsyncIterable < T4 > } source4 param { AsyncIterable < T5 > } source5 returns { OperatorAsyncFunction < T , [ T , T2 , T3 , T4 , T5 ] > } export function withLatestFrom < T , T2 , T3 , T4 , T5 > ( source2 , source3 , source4 , source5 ) ; template T template T2 template T3 template T4 template T5 template T6 param { AsyncIterable < T2 > } source2 param { AsyncIterable < T3 > } source3 param { AsyncIterable < T4 > } source4 param { AsyncIterable < T5 > } source5 param { AsyncIterable < T6 > } source6 returns { OperatorAsyncFunction < T , [ T , T2 , T3 , T4 , T5 , T6 ] > } export function withLatestFrom < T , T2 , T3 , T4 , T5 , T6 > ( source2 , source3 , source4 , source5 , source6 ) ; template T param { ... AsyncIterable < T > [ ] } sources returns { OperatorAsyncFunction < T , T [ ] > } export function withLatestFrom < T > ( ... sources ) ; export function withLatestFrom < T > ( ... sources ) { return function withLatestFromOperatorFunction ( source ) { return new WithLatestFromAsyncIterable < T > ( source , sources ) ; } ; }