1- import  {  reflectCall  }  from  'lib/helpers/webidl' ; 
1+ import  { 
2+   PerformPromiseThen , 
3+   promiseRejectedWith , 
4+   promiseResolve , 
5+   promiseResolvedWith , 
6+   reflectCall 
7+ }  from  'lib/helpers/webidl' ; 
28import  {  typeIsObject  }  from  '../helpers/miscellaneous' ; 
39import  assert  from  '../../stub/assert' ; 
410
@@ -79,9 +85,11 @@ export function GetMethod<T, K extends MethodName<T>>(receiver: T, prop: K): T[K
7985  return  func ; 
8086} 
8187
88+ export  type  SyncOrAsync < T >  =  T  |  Promise < T > ; 
89+ 
8290export  interface  SyncIteratorRecord < T >  { 
8391  iterator : Iterator < T > , 
84-   nextMethod : Iterator < T > [ 'next' ] , 
92+   nextMethod : ( )   =>   SyncOrAsync < IteratorResult < SyncOrAsync < T > > > , 
8593  done : boolean ; 
8694} 
8795
@@ -93,23 +101,57 @@ export interface AsyncIteratorRecord<T> {
93101
94102export  type  SyncOrAsyncIteratorRecord < T >  =  SyncIteratorRecord < T >  |  AsyncIteratorRecord < T > ; 
95103
96- export  function  CreateAsyncFromSyncIterator < T > ( syncIteratorRecord : SyncIteratorRecord < T > ) : AsyncIteratorRecord < T >  { 
97-   // Instead of re-implementing CreateAsyncFromSyncIterator and %AsyncFromSyncIteratorPrototype%, 
98-   // we use yield* inside an async generator function to achieve the same result. 
99- 
100-   // Wrap the sync iterator inside a sync iterable, so we can use it with yield*. 
101-   const  syncIterable  =  { 
102-     [ Symbol . iterator ] : ( )  =>  syncIteratorRecord . iterator 
104+ export  function  CreateAsyncFromSyncIterator < T > ( 
105+   syncIteratorRecord : SyncIteratorRecord < SyncOrAsync < T > > 
106+ ) : AsyncIteratorRecord < T >  { 
107+   const  asyncIterator : AsyncIterator < T >  =  { 
108+     // https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.next 
109+     next ( )  { 
110+       let  result ; 
111+       try  { 
112+         result  =  IteratorNext ( syncIteratorRecord ) ; 
113+       }  catch  ( e )  { 
114+         return  promiseRejectedWith ( e ) ; 
115+       } 
116+       return  AsyncFromSyncIteratorContinuation ( result ) ; 
117+     } , 
118+     // https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.return 
119+     return ( value : any )  { 
120+       let  result ; 
121+       try  { 
122+         const  returnMethod  =  GetMethod ( syncIteratorRecord . iterator ,  'return' ) ; 
123+         if  ( returnMethod  ===  undefined )  { 
124+           return  promiseResolvedWith ( {  done : true ,  value } ) ; 
125+         } 
126+         // Note: ReadableStream.from() always calls return() with a value. 
127+         result  =  reflectCall ( returnMethod ,  syncIteratorRecord . iterator ,  [ value ] ) ; 
128+       }  catch  ( e )  { 
129+         return  promiseRejectedWith ( e ) ; 
130+       } 
131+       if  ( ! typeIsObject ( result ) )  { 
132+         return  promiseRejectedWith ( new  TypeError ( 'The iterator.return() method must return an object' ) ) ; 
133+       } 
134+       return  AsyncFromSyncIteratorContinuation ( result ) ; 
135+     } 
136+     // Note: throw() is never used by the Streams spec. 
103137  } ; 
104-   // Create an async generator function and immediately invoke it. 
105-   const  asyncIterator  =  ( async  function *  ( )  { 
106-     return  yield *  syncIterable ; 
107-   } ( ) ) ; 
108138  // Return as an async iterator record. 
109139  const  nextMethod  =  asyncIterator . next ; 
110140  return  {  iterator : asyncIterator ,  nextMethod,  done : false  } ; 
111141} 
112142
143+ // https://tc39.es/ecma262/#sec-asyncfromsynciteratorcontinuation 
144+ function  AsyncFromSyncIteratorContinuation < T > ( result : IteratorResult < SyncOrAsync < T > > ) : Promise < IteratorResult < T > >  { 
145+   try  { 
146+     const  done  =  result . done ; 
147+     const  value  =  result . value ; 
148+     const  valueWrapper  =  promiseResolve ( value ) ; 
149+     return  PerformPromiseThen ( valueWrapper ,  v  =>  ( {  done,  value : v  } ) ) ; 
150+   }  catch  ( e )  { 
151+     return  promiseRejectedWith ( e ) ; 
152+   } 
153+ } 
154+ 
113155// Aligns with core-js/modules/es.symbol.async-iterator.js 
114156export  const  SymbolAsyncIterator : ( typeof  Symbol ) [ 'asyncIterator' ]  = 
115157  Symbol . asyncIterator  ?? 
@@ -160,22 +202,15 @@ function GetIterator<T>(
160202
161203export  {  GetIterator  } ; 
162204
163- export  function  IteratorNext < T > ( iteratorRecord : AsyncIteratorRecord < T > ) : Promise < IteratorResult < T > >  { 
205+ export  function  IteratorNext < T > ( iteratorRecord : SyncIteratorRecord < T > ) : IteratorResult < T > ; 
206+ export  function  IteratorNext < T > ( iteratorRecord : AsyncIteratorRecord < T > ) : Promise < IteratorResult < T > > ; 
207+ export  function  IteratorNext < T > ( 
208+   iteratorRecord : SyncOrAsyncIteratorRecord < T > 
209+ ) : SyncOrAsync < IteratorResult < SyncOrAsync < T > > >  { 
164210  const  result  =  reflectCall ( iteratorRecord . nextMethod ,  iteratorRecord . iterator ,  [ ] ) ; 
165211  if  ( ! typeIsObject ( result ) )  { 
166212    throw  new  TypeError ( 'The iterator.next() method must return an object' ) ; 
167213  } 
168214  return  result ; 
169215} 
170216
171- export  function  IteratorComplete < TReturn > ( 
172-   iterResult : IteratorResult < unknown ,  TReturn > 
173- ) : iterResult  is IteratorReturnResult < TReturn >  { 
174-   assert ( typeIsObject ( iterResult ) ) ; 
175-   return  Boolean ( iterResult . done ) ; 
176- } 
177- 
178- export  function  IteratorValue < T > ( iterResult : IteratorYieldResult < T > ) : T  { 
179-   assert ( typeIsObject ( iterResult ) ) ; 
180-   return  iterResult . value ; 
181- } 
0 commit comments