@@ -2,10 +2,10 @@ import { DEBUG, console } from "./debug.js";
22import { deferred , isObjectLike , isPromiseLike } from "./deferred.js" ;
33export const Iterability = Symbol ( "Iterability" ) ;
44// NB: This also (incorrectly) passes sync iterators, as the protocol names are the same
5- export function isAsyncIterator ( o ) {
5+ function isAsyncIterator ( o ) {
66 return isObjectLike ( o ) && 'next' in o && typeof o ?. next === 'function' ;
77}
8- export function isAsyncIterable ( o ) {
8+ function isAsyncIterable ( o ) {
99 return isObjectLike ( o ) && ( Symbol . asyncIterator in o ) && typeof o [ Symbol . asyncIterator ] === 'function' ;
1010}
1111export function isAsyncIter ( o ) {
@@ -367,47 +367,51 @@ export const merge = (...ai) => {
367367 } ;
368368 const results = new Array ( ai . length ) ;
369369 const merged = {
370- [ Symbol . asyncIterator ] ( ) { return merged ; } ,
371- next ( ) {
372- init ( ) ;
373- return promises . size
374- ? Promise . race ( promises . values ( ) ) . then ( ( { key, result } ) => {
375- if ( result . done ) {
376- promises . delete ( key ) ;
377- it . delete ( key ) ;
378- results [ key ] = result . value ;
379- return merged . next ( ) ;
370+ [ Symbol . asyncIterator ] ( ) {
371+ return {
372+ __proto__ : merged ,
373+ next ( ) {
374+ init ( ) ;
375+ return promises . size
376+ ? Promise . race ( promises . values ( ) ) . then ( ( { key, result } ) => {
377+ if ( result . done ) {
378+ promises . delete ( key ) ;
379+ it . delete ( key ) ;
380+ results [ key ] = result . value ;
381+ return this . next ( ) ;
382+ }
383+ else {
384+ promises . set ( key , it . has ( key )
385+ ? it . get ( key ) . next ( ) . then ( result => ( { key, result } ) ) . catch ( ex => ( { key, result : { done : true , value : ex } } ) )
386+ : Promise . resolve ( { key, result : { done : true , value : undefined } } ) ) ;
387+ return result ;
388+ }
389+ } ) . catch ( ex => {
390+ // `ex` is the underlying async iteration exception
391+ return this . throw ( ex ) ; // ?? Promise.reject({ done: true as const, value: new Error("Iterator merge exception") });
392+ } )
393+ : Promise . resolve ( { done : true , value : results } ) ;
394+ } ,
395+ async return ( r ) {
396+ for ( const key of it . keys ( ) ) {
397+ if ( promises . has ( key ) ) {
398+ promises . delete ( key ) ;
399+ results [ key ] = await it . get ( key ) ?. return ?. ( { done : true , value : r } ) . then ( v => v . value , ex => ex ) ;
400+ }
380401 }
381- else {
382- promises . set ( key , it . has ( key )
383- ? it . get ( key ) . next ( ) . then ( result => ( { key, result } ) ) . catch ( ex => ( { key, result : { done : true , value : ex } } ) )
384- : Promise . resolve ( { key, result : { done : true , value : undefined } } ) ) ;
385- return result ;
402+ return { done : true , value : results } ;
403+ } ,
404+ async throw ( ex ) {
405+ for ( const key of it . keys ( ) ) {
406+ if ( promises . has ( key ) ) {
407+ promises . delete ( key ) ;
408+ results [ key ] = await it . get ( key ) ?. throw ?. ( ex ) . then ( v => v . value , ex => ex ) ;
409+ }
386410 }
387- } ) . catch ( ex => {
388- // `ex` is the underlying async iteration exception
389- return merged . throw ( ex ) ; // ?? Promise.reject({ done: true as const, value: new Error("Iterator merge exception") });
390- } )
391- : Promise . resolve ( { done : true , value : results } ) ;
392- } ,
393- async return ( r ) {
394- for ( const key of it . keys ( ) ) {
395- if ( promises . has ( key ) ) {
396- promises . delete ( key ) ;
397- results [ key ] = await it . get ( key ) ?. return ?. ( { done : true , value : r } ) . then ( v => v . value , ex => ex ) ;
398- }
399- }
400- return { done : true , value : results } ;
401- } ,
402- async throw ( ex ) {
403- for ( const key of it . keys ( ) ) {
404- if ( promises . has ( key ) ) {
405- promises . delete ( key ) ;
406- results [ key ] = await it . get ( key ) ?. throw ?. ( ex ) . then ( v => v . value , ex => ex ) ;
411+ // Because we've passed the exception on to all the sources, we're now done
412+ return { done : true , value : results } ;
407413 }
408- }
409- // Because we've passed the exception on to all the sources, we're now done
410- return { done : true , value : results } ;
414+ } ;
411415 }
412416 } ;
413417 return iterableHelpers ( merged ) ;
@@ -417,47 +421,51 @@ export const combine = (src, opts = {}) => {
417421 const si = new Map ( ) ;
418422 let pc ; // Initialized lazily
419423 const ci = {
420- [ Symbol . asyncIterator ] ( ) { return ci ; } ,
421- next ( ) {
422- if ( pc === undefined ) {
423- pc = new Map ( Object . entries ( src ) . map ( ( [ k , sit ] ) => {
424- const source = sit [ Symbol . asyncIterator ] ( ) ;
425- si . set ( k , source ) ;
426- return [ k , source . next ( ) . then ( ir => ( { si, k, ir } ) ) ] ;
427- } ) ) ;
428- }
429- return ( function step ( ) {
430- return Promise . race ( pc . values ( ) ) . then ( ( { k, ir } ) => {
431- if ( ir . done ) {
432- pc . delete ( k ) ;
433- si . delete ( k ) ;
434- if ( ! pc . size )
435- return { done : true , value : undefined } ;
436- return step ( ) ;
437- }
438- else {
439- accumulated [ k ] = ir . value ;
440- pc . set ( k , si . get ( k ) . next ( ) . then ( ir => ( { k, ir } ) ) ) ;
424+ [ Symbol . asyncIterator ] ( ) {
425+ return {
426+ __proto__ : ci ,
427+ next ( ) {
428+ if ( pc === undefined ) {
429+ pc = new Map ( Object . entries ( src ) . map ( ( [ k , sit ] ) => {
430+ const source = sit [ Symbol . asyncIterator ] ( ) ;
431+ si . set ( k , source ) ;
432+ return [ k , source . next ( ) . then ( ir => ( { si, k, ir } ) ) ] ;
433+ } ) ) ;
441434 }
442- if ( opts . ignorePartial ) {
443- if ( Object . keys ( accumulated ) . length < Object . keys ( src ) . length )
444- return step ( ) ;
435+ return ( function step ( ) {
436+ return Promise . race ( pc . values ( ) ) . then ( ( { k, ir } ) => {
437+ if ( ir . done ) {
438+ pc . delete ( k ) ;
439+ si . delete ( k ) ;
440+ if ( ! pc . size )
441+ return { done : true , value : undefined } ;
442+ return step ( ) ;
443+ }
444+ else {
445+ accumulated [ k ] = ir . value ;
446+ pc . set ( k , si . get ( k ) . next ( ) . then ( ir => ( { k, ir } ) ) ) ;
447+ }
448+ if ( opts . ignorePartial ) {
449+ if ( Object . keys ( accumulated ) . length < Object . keys ( src ) . length )
450+ return step ( ) ;
451+ }
452+ return { done : false , value : accumulated } ;
453+ } ) ;
454+ } ) ( ) ;
455+ } ,
456+ return ( v ) {
457+ for ( const ai of si . values ( ) ) {
458+ ai . return ?. ( v ) ;
445459 }
446- return { done : false , value : accumulated } ;
447- } ) ;
448- } ) ( ) ;
449- } ,
450- return ( v ) {
451- for ( const ai of si . values ( ) ) {
452- ai . return ?. ( v ) ;
453- }
454- ;
455- return Promise . resolve ( { done : true , value : v } ) ;
456- } ,
457- throw ( ex ) {
458- for ( const ai of si . values ( ) )
459- ai . throw ?. ( ex ) ;
460- return Promise . resolve ( { done : true , value : ex } ) ;
460+ ;
461+ return Promise . resolve ( { done : true , value : v } ) ;
462+ } ,
463+ throw ( ex ) {
464+ for ( const ai of si . values ( ) )
465+ ai . throw ?. ( ex ) ;
466+ return Promise . resolve ( { done : true , value : ex } ) ;
467+ }
468+ } ;
461469 }
462470 } ;
463471 return iterableHelpers ( ci ) ;
@@ -511,60 +519,62 @@ export function filterMap(source, fn, initialValue = Ignore, prev = Ignore) {
511519 }
512520 let fai = {
513521 [ Symbol . asyncIterator ] ( ) {
514- return fai ;
515- } ,
516- next ( ...args ) {
517- if ( initialValue !== Ignore ) {
518- if ( isPromiseLike ( initialValue ) ) {
519- const init = initialValue . then ( value => ( { done : false , value } ) ) ;
520- initialValue = Ignore ;
521- return init ;
522- }
523- else {
524- const init = Promise . resolve ( { done : false , value : initialValue } ) ;
525- initialValue = Ignore ;
526- return init ;
527- }
528- }
529- return new Promise ( function step ( resolve , reject ) {
530- if ( ! ai )
531- ai = source [ Symbol . asyncIterator ] ( ) ;
532- ai . next ( ...args ) . then ( p => p . done
533- ? ( prev = Ignore , resolve ( p ) )
534- : resolveSync ( fn ( p . value , prev ) , f => f === Ignore
535- ? step ( resolve , reject )
536- : resolve ( { done : false , value : prev = f } ) , ex => {
537- prev = Ignore ; // Remove reference for GC
538- // The filter function failed. We check ai here as it might have been terminated already
539- const sourceResponse = ai ?. throw ?. ( ex ) ?? ai ?. return ?. ( ex ) ;
540- // Terminate the source (ai) and consumer (reject)
541- if ( isPromiseLike ( sourceResponse ) )
542- sourceResponse . then ( reject , reject ) ;
543- else
522+ return {
523+ __proto__ : fai ,
524+ next ( ...args ) {
525+ if ( initialValue !== Ignore ) {
526+ if ( isPromiseLike ( initialValue ) ) {
527+ const init = initialValue . then ( value => ( { done : false , value } ) ) ;
528+ initialValue = Ignore ;
529+ return init ;
530+ }
531+ else {
532+ const init = Promise . resolve ( { done : false , value : initialValue } ) ;
533+ initialValue = Ignore ;
534+ return init ;
535+ }
536+ }
537+ return new Promise ( function step ( resolve , reject ) {
538+ if ( ! ai )
539+ ai = source [ Symbol . asyncIterator ] ( ) ;
540+ ai . next ( ...args ) . then ( p => p . done
541+ ? ( prev = Ignore , resolve ( p ) )
542+ : resolveSync ( fn ( p . value , prev ) , f => f === Ignore
543+ ? step ( resolve , reject )
544+ : resolve ( { done : false , value : prev = f } ) , ex => {
545+ prev = Ignore ; // Remove reference for GC
546+ // The filter function failed. We check ai here as it might have been terminated already
547+ const sourceResponse = ai ?. throw ?. ( ex ) ?? ai ?. return ?. ( ex ) ;
548+ // Terminate the source (ai) and consumer (reject)
549+ if ( isPromiseLike ( sourceResponse ) )
550+ sourceResponse . then ( reject , reject ) ;
551+ else
552+ reject ( { done : true , value : ex } ) ;
553+ } ) , ex => {
554+ // The source threw. Tell the consumer
555+ prev = Ignore ; // Remove reference for GC
544556 reject ( { done : true , value : ex } ) ;
545- } ) , ex => {
546- // The source threw. Tell the consumer
547- prev = Ignore ; // Remove reference for GC
548- reject ( { done : true , value : ex } ) ;
549- } ) . catch ( ex => {
550- // The callback threw
551- prev = Ignore ; // Remove reference for GC
552- const sourceResponse = ai . throw ?. ( ex ) ?? ai . return ?. ( ex ) ;
553- // Terminate the source (ai) and consumer (reject)
554- if ( isPromiseLike ( sourceResponse ) )
555- sourceResponse . then ( reject , reject ) ;
556- else
557- reject ( { done : true , value : sourceResponse } ) ;
558- } ) ;
559- } ) ;
560- } ,
561- throw ( ex ) {
562- // The consumer wants us to exit with an exception. Tell the source
563- return Promise . resolve ( ai ?. throw ?. ( ex ) ?? ai ?. return ?. ( ex ) ) . then ( done , done ) ;
564- } ,
565- return ( v ) {
566- // The consumer told us to return, so we need to terminate the source
567- return Promise . resolve ( ai ?. return ?. ( v ) ) . then ( done , done ) ;
557+ } ) . catch ( ex => {
558+ // The callback threw
559+ prev = Ignore ; // Remove reference for GC
560+ const sourceResponse = ai . throw ?. ( ex ) ?? ai . return ?. ( ex ) ;
561+ // Terminate the source (ai) and consumer (reject)
562+ if ( isPromiseLike ( sourceResponse ) )
563+ sourceResponse . then ( reject , reject ) ;
564+ else
565+ reject ( { done : true , value : sourceResponse } ) ;
566+ } ) ;
567+ } ) ;
568+ } ,
569+ throw ( ex ) {
570+ // The consumer wants us to exit with an exception. Tell the source
571+ return Promise . resolve ( ai ?. throw ?. ( ex ) ?? ai ?. return ?. ( ex ) ) . then ( done , done ) ;
572+ } ,
573+ return ( v ) {
574+ // The consumer told us to return, so we need to terminate the source
575+ return Promise . resolve ( ai ?. return ?. ( v ) ) . then ( done , done ) ;
576+ }
577+ } ;
568578 }
569579 } ;
570580 return iterableHelpers ( fai ) ;
@@ -623,7 +633,8 @@ function multi() {
623633 }
624634 let mai = {
625635 [ Symbol . asyncIterator ] ( ) {
626- return Object . create ( mai , Object . getOwnPropertyDescriptors ( {
636+ return {
637+ __proto__ : mai ,
627638 next ( ) {
628639 if ( ! ai ) {
629640 ai = source [ Symbol . asyncIterator ] ( ) ;
@@ -650,7 +661,7 @@ function multi() {
650661 return Promise . resolve ( { done : true , value : v } ) ;
651662 return Promise . resolve ( ai ?. return ?. ( v ) ) . then ( done , done ) ;
652663 }
653- } ) ) ;
664+ } ;
654665 }
655666 } ;
656667 return iterableHelpers ( mai ) ;
0 commit comments