@@ -9,86 +9,99 @@ export function isAsyncIteratorObject(maybe: unknown): maybe is AsyncIteratorObj
99 return Symbol . asyncIterator in maybe && typeof maybe [ Symbol . asyncIterator ] === 'function'
1010}
1111
12- export interface CreateAsyncIteratorObjectCleanupFn {
12+ export interface AsyncIteratorClassNextFn < T , TReturn > {
13+ ( ) : Promise < IteratorResult < T , TReturn > >
14+ }
15+
16+ export interface AsyncIteratorClassCleanupFn {
1317 ( reason : 'return' | 'throw' | 'next' | 'dispose' ) : Promise < void >
1418}
1519
16- export function createAsyncIteratorObject < T , TReturn , TNext > (
17- next : ( ) => Promise < IteratorResult < T , TReturn > > ,
18- cleanup : CreateAsyncIteratorObjectCleanupFn ,
19- ) : AsyncIteratorObject < T , TReturn , TNext > & AsyncGenerator < T , TReturn , TNext > {
20- let isExecuteComplete = false
21- let isDone = false
20+ const fallbackAsyncDisposeSymbol : unique symbol = Symbol . for ( 'asyncDispose' )
21+ const asyncDisposeSymbol : typeof Symbol extends { asyncDispose : infer T } ? T : typeof fallbackAsyncDisposeSymbol = ( Symbol as any ) . asyncDispose ?? fallbackAsyncDisposeSymbol
22+
23+ export class AsyncIteratorClass < T , TReturn = unknown , TNext = unknown > implements AsyncIteratorObject < T , TReturn , TNext > , AsyncGenerator < T , TReturn , TNext > {
24+ #isDone = false
25+ #isExecuteComplete = false
26+ #cleanup: AsyncIteratorClassCleanupFn
27+ #next: AsyncIteratorClassNextFn < T , TReturn >
2228
23- const iterator = {
24- next : sequential ( async ( ) => {
25- if ( isDone ) {
29+ constructor ( next : AsyncIteratorClassNextFn < T , TReturn > , cleanup : AsyncIteratorClassCleanupFn ) {
30+ this . #cleanup = cleanup
31+ this . #next = sequential ( async ( ) => {
32+ if ( this . #isDone) {
2633 return { done : true , value : undefined as any }
2734 }
2835
2936 try {
3037 const result = await next ( )
3138
3239 if ( result . done ) {
33- isDone = true
40+ this . # isDone = true
3441 }
3542
3643 return result
3744 }
3845 catch ( err ) {
39- isDone = true
46+ this . # isDone = true
4047 throw err
4148 }
4249 finally {
43- if ( isDone && ! isExecuteComplete ) {
44- isExecuteComplete = true
45- await cleanup ( 'next' )
50+ if ( this . # isDone && ! this . # isExecuteComplete) {
51+ this . # isExecuteComplete = true
52+ await this . # cleanup( 'next' )
4653 }
4754 }
48- } ) ,
49- async return ( value : any ) {
50- isDone = true
51- if ( ! isExecuteComplete ) {
52- isExecuteComplete = true
53- await cleanup ( 'return' )
54- }
55+ } )
56+ }
5557
56- return { done : true , value }
57- } ,
58- async throw ( err : any ) {
59- isDone = true
60- if ( ! isExecuteComplete ) {
61- isExecuteComplete = true
62- await cleanup ( 'throw' )
63- }
58+ next ( ) : Promise < IteratorResult < T , TReturn > > {
59+ return this . #next( )
60+ }
6461
65- throw err
66- } ,
67- /**
68- * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose')
69- */
70- async [ ( Symbol as any ) . asyncDispose as typeof Symbol extends { asyncDispose : infer T } ? T : any ?? Symbol . for ( 'asyncDispose' ) ] ( ) {
71- isDone = true
72- if ( ! isExecuteComplete ) {
73- isExecuteComplete = true
74- await cleanup ( 'dispose' )
75- }
76- } ,
77- [ Symbol . asyncIterator ] ( ) {
78- return iterator
79- } ,
62+ async return ( value ?: any ) : Promise < IteratorResult < T , TReturn > > {
63+ this . #isDone = true
64+ if ( ! this . #isExecuteComplete) {
65+ this . #isExecuteComplete = true
66+ await this . #cleanup( 'return' )
67+ }
68+
69+ return { done : true , value }
70+ }
71+
72+ async throw ( err : any ) : Promise < IteratorResult < T , TReturn > > {
73+ this . #isDone = true
74+ if ( ! this . #isExecuteComplete) {
75+ this . #isExecuteComplete = true
76+ await this . #cleanup( 'throw' )
77+ }
78+
79+ throw err
8080 }
8181
82- return iterator
82+ /**
83+ * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose')
84+ */
85+ async [ asyncDisposeSymbol ] ( ) : Promise < void > {
86+ this . #isDone = true
87+ if ( ! this . #isExecuteComplete) {
88+ this . #isExecuteComplete = true
89+ await this . #cleanup( 'dispose' )
90+ }
91+ }
92+
93+ [ Symbol . asyncIterator ] ( ) : this {
94+ return this
95+ }
8396}
8497
8598export function replicateAsyncIterator < T , TReturn , TNext > (
8699 source : AsyncIterator < T , TReturn , TNext > ,
87100 count : number ,
88- ) : ( AsyncIteratorObject < T , TReturn , TNext > & AsyncGenerator < T , TReturn , TNext > ) [ ] {
101+ ) : ( AsyncIteratorClass < T , TReturn , TNext > ) [ ] {
89102 const queue = new AsyncIdQueue < IteratorResult < T , TReturn > > ( )
90103
91- const replicated : ( AsyncIteratorObject < T , TReturn , TNext > & AsyncGenerator < T , TReturn , TNext > ) [ ] = [ ]
104+ const replicated : AsyncIteratorClass < T , TReturn , TNext > [ ] = [ ]
92105
93106 let error : undefined | { value : unknown }
94107
@@ -115,7 +128,7 @@ export function replicateAsyncIterator<T, TReturn, TNext>(
115128
116129 for ( let id = 0 ; id < count ; id ++ ) {
117130 queue . open ( id )
118- replicated . push ( createAsyncIteratorObject (
131+ replicated . push ( new AsyncIteratorClass (
119132 ( ) => {
120133 start ( )
121134
0 commit comments