@@ -25,6 +25,7 @@ export function setTaskScheduler(scheduler: TaskScheduler): void {
2525 taskScheduler = scheduler ;
2626}
2727
28+ // Returns a function that calls `fn` with `self` as `this` pointer. */
2829function bind < T extends Function > ( fn : T , self ?: object ) : T {
2930 return self ? fn . bind ( self ) : fn ;
3031}
@@ -537,8 +538,6 @@ export class AsyncIterator<T> extends EventEmitter {
537538 */
538539 range ( start : number , end : number ) : AsyncIterator < T > {
539540 return this . transform ( { offset : start , limit : Math . max ( end - start + 1 , 0 ) } ) ;
540- // TODO: Implement as following when .take is optimised
541- // return this.skip(start).take(Math.max(end - start + 1, 0));
542541 }
543542
544543 /**
@@ -582,7 +581,8 @@ function addSingleListener(source: EventEmitter, eventName: string,
582581 source . on ( eventName , listener ) ;
583582}
584583
585- function _validateSource < S > ( source ?: AsyncIterator < S > , allowDestination = false ) {
584+ // Validates an AsyncIterator for use as a source within another AsyncIterator
585+ function ensureSourceAvailable < S > ( source ?: AsyncIterator < S > , allowDestination = false ) {
586586 if ( ! source || ! isFunction ( source . read ) || ! isFunction ( source . on ) )
587587 throw new Error ( `Invalid source: ${ source } ` ) ;
588588 if ( ! allowDestination && ( source as any ) . _destination )
@@ -798,65 +798,66 @@ export class IntegerIterator extends AsyncIterator<number> {
798798export type MapFunction < S , D = S > = ( item : S ) => D | null ;
799799
800800/**
801- An iterator that calls a synchronous mapping function
802- on every item from its source iterator.
801+ * Function that maps an element to itself.
802+ */
803+ export function identity < S > ( item : S ) : typeof item {
804+ return item ;
805+ }
806+
807+ /**
808+ An iterator that synchronously transforms every item from its source
809+ by applying a mapping function.
803810 @extends module:asynciterator.AsyncIterator
804811*/
805812export class MappingIterator < S , D = S > extends AsyncIterator < D > {
806- private readonly _destroySource : boolean ;
807- protected _source : InternalSource < S > ;
813+ protected readonly _map : MapFunction < S , D > ;
814+ protected readonly _source : InternalSource < S > ;
815+ protected readonly _destroySource : boolean ;
808816
809817 /**
810818 * Applies the given mapping to the source iterator.
811819 */
812820 constructor (
813- _source : AsyncIterator < S > ,
814- private _map : MapFunction < S , D > ,
821+ source : AsyncIterator < S > ,
822+ map : MapFunction < S , D > = identity as MapFunction < S , D > ,
815823 options : SourcedIteratorOptions = { }
816824 ) {
817825 super ( ) ;
818- this . _source = _validateSource ( _source ) ;
826+ this . _map = map ;
827+ this . _source = ensureSourceAvailable ( source ) ;
819828 this . _destroySource = options . destroySource !== false ;
820829
821- if ( _source . done ) {
830+ // Close if the source is already empty
831+ if ( source . done ) {
822832 this . close ( ) ;
823833 }
834+ // Otherwise, wire up the source for reading
824835 else {
825836 this . _source . _destination = this ;
826837 this . _source . on ( 'end' , destinationClose ) ;
827838 this . _source . on ( 'error' , destinationEmitError ) ;
828839 this . _source . on ( 'readable' , destinationSetReadable ) ;
829- // If we are given a source that is already readable
830- // then we need to set the state of this iterable to readable
831- // also as there is no guarantee that the is no forthcoming
832- // readable event from the source
833840 this . readable = this . _source . readable ;
834841 }
835842 }
836843
844+ /** Tries to read the next item from the iterator. */
837845 read ( ) : D | null {
838- // Do not read the source if the current iterator is ended
839- if ( this . done )
840- return null ;
841-
842- // A source should only be read from if readable is true
843- if ( ! this . _source . readable ) {
846+ if ( ! this . done ) {
847+ // Try to read an item that maps to a non-null value
848+ if ( this . _source . readable ) {
849+ let item : S | null , mapped : D | null ;
850+ while ( ( item = this . _source . read ( ) ) !== null ) {
851+ if ( ( mapped = this . _map ( item ) ) !== null )
852+ return mapped ;
853+ }
854+ }
844855 this . readable = false ;
856+
857+ // Close this iterator if the source is empty
845858 if ( this . _source . done )
846859 this . close ( ) ;
847- return null ;
848860 }
849-
850- let item : S | null ;
851- while ( ( item = this . _source . read ( ) ) !== null ) {
852- const mapped = this . _map ( item ) ;
853- if ( mapped !== null )
854- return mapped ;
855- }
856-
857- // This will set readable to false on the current iterator
858- // if the source is no longer readable
859- this . readable = false ;
860861 return null ;
861862 }
862863
@@ -1247,7 +1248,7 @@ export class TransformIterator<S, D = S> extends BufferedIterator<D> {
12471248 protected _validateSource ( source ?: AsyncIterator < S > , allowDestination = false ) : InternalSource < S > {
12481249 if ( this . _source || typeof this . _createSource !== 'undefined' )
12491250 throw new Error ( 'The source cannot be changed after it has been set' ) ;
1250- return _validateSource ( source , allowDestination ) ;
1251+ return ensureSourceAvailable ( source , allowDestination ) ;
12511252 }
12521253
12531254 /**
@@ -1331,10 +1332,7 @@ export class TransformIterator<S, D = S> extends BufferedIterator<D> {
13311332}
13321333
13331334function destinationSetReadable < S > ( this : InternalSource < S > ) {
1334- if ( this . _destination ! . readable )
1335- this . _destination ! . emit ( 'readable' ) ;
1336- else
1337- this . _destination ! . readable = true ;
1335+ this . _destination ! . readable = true ;
13381336}
13391337function destinationEmitError < S > ( this : InternalSource < S > , error : Error ) {
13401338 this . _destination ! . emit ( 'error' , error ) ;
@@ -2064,10 +2062,9 @@ export interface BufferedIteratorOptions {
20642062 autoStart ?: boolean ;
20652063}
20662064
2067- export interface TransformIteratorOptions < S > extends BufferedIteratorOptions {
2065+ export interface TransformIteratorOptions < S > extends SourcedIteratorOptions , BufferedIteratorOptions {
20682066 source ?: SourceExpression < S > ;
20692067 optional ?: boolean ;
2070- destroySource ?: boolean ;
20712068}
20722069
20732070export interface TransformOptions < S , D > extends TransformIteratorOptions < S > {
0 commit comments