@@ -430,13 +430,18 @@ export class Effected<out E extends Effect, out R> implements Iterable<E, R, unk
430430 ...effect . payloads ,
431431 ) ;
432432
433- if ( ! ( handlerResult instanceof Effected ) && ! isGenerator ( handlerResult ) )
433+ if (
434+ ! ( handlerResult instanceof Effected ) &&
435+ ! isGenerator ( handlerResult ) &&
436+ ! isEffectedIterator ( handlerResult )
437+ )
434438 return { done : false , value : constructHandledEffect ( ) } as never ;
435439
436- const it = handlerResult [ Symbol . iterator ] ( ) ;
440+ const iter =
441+ Symbol . iterator in handlerResult ? handlerResult [ Symbol . iterator ] ( ) : handlerResult ;
437442 interceptIterator = {
438443 next : ( ...args : [ ] | [ unknown ] ) => {
439- const result = it . next ( ...args ) ;
444+ const result = iter . next ( ...args ) ;
440445 if ( result . done ) {
441446 interceptIterator = null ;
442447 return { done : false , value : constructHandledEffect ( ) } as never ;
@@ -480,9 +485,15 @@ export class Effected<out E extends Effect, out R> implements Iterable<E, R, unk
480485 return this . handle ( effect , ( ( { resume } : any , ...payloads : unknown [ ] ) => {
481486 const it = handler ( ...payloads ) ;
482487 if ( ! ( it instanceof Effected ) && ! isGenerator ( it ) ) return resume ( it ) ;
483- return ( function * ( ) {
484- resume ( yield * it ) ;
485- } ) ( ) ;
488+ const iterator = it [ Symbol . iterator ] ( ) ;
489+ return {
490+ _effectedIterator : true ,
491+ next : ( ...args : [ ] | [ unknown ] ) => {
492+ const result = iterator . next ( ...args ) ;
493+ if ( result . done ) return { done : true , value : resume ( result . value ) } ;
494+ return result ;
495+ } ,
496+ } ;
486497 } ) as never ) ;
487498 }
488499
@@ -521,9 +532,15 @@ export class Effected<out E extends Effect, out R> implements Iterable<E, R, unk
521532 return this . handle ( effect , ( ( { terminate } : any , ...payloads : unknown [ ] ) => {
522533 const it = handler ( ...payloads ) ;
523534 if ( ! ( it instanceof Effected ) && ! isGenerator ( it ) ) return terminate ( it ) ;
524- return ( function * ( ) {
525- terminate ( yield * it ) ;
526- } ) ( ) ;
535+ const iterator = it [ Symbol . iterator ] ( ) ;
536+ return {
537+ _effectedIterator : true ,
538+ next : ( ...args : [ ] | [ unknown ] ) => {
539+ const result = iterator . next ( ...args ) ;
540+ if ( result . done ) return { done : true , value : terminate ( result . value ) } ;
541+ return result ;
542+ } ,
543+ } ;
527544 } ) as never ) ;
528545 }
529546
@@ -549,8 +566,9 @@ export class Effected<out E extends Effect, out R> implements Iterable<E, R, unk
549566 if ( ! result . done ) return result ;
550567 originalIteratorDone = true ;
551568 const it = handler ( result . value ) ;
552- if ( ! ( it instanceof Effected ) && ! isGenerator ( it ) ) return { done : true , value : it } ;
553- appendedIterator = it [ Symbol . iterator ] ( ) ;
569+ if ( ! ( it instanceof Effected ) && ! isGenerator ( it ) && ! isEffectedIterator ( it ) )
570+ return { done : true , value : it } ;
571+ appendedIterator = Symbol . iterator in it ? it [ Symbol . iterator ] ( ) : it ;
554572 return appendedIterator . next ( ) ;
555573 } ,
556574 } ;
@@ -570,10 +588,15 @@ export class Effected<out E extends Effect, out R> implements Iterable<E, R, unk
570588 return this . map ( ( value ) => {
571589 const it = handler ( value ) ;
572590 if ( ! ( it instanceof Effected ) && ! isGenerator ( it ) ) return value ;
573- return ( function * ( ) {
574- yield * it ;
575- return value ;
576- } ) ( ) ;
591+ const iterator = it [ Symbol . iterator ] ( ) ;
592+ return {
593+ _effectedIterator : true ,
594+ next : ( ...args : [ ] | [ unknown ] ) => {
595+ const result = iterator . next ( ...args ) ;
596+ if ( result . done ) return { done : true , value } ;
597+ return result ;
598+ } ,
599+ } ;
577600 } ) as never ;
578601 }
579602
@@ -617,9 +640,15 @@ export class Effected<out E extends Effect, out R> implements Iterable<E, R, unk
617640 const error = effect . name . slice ( 6 ) as ErrorName < E > ;
618641 const it = handler ( error , ...payloads ) ;
619642 if ( ! ( it instanceof Effected ) && ! isGenerator ( it ) ) return terminate ( it ) ;
620- return ( function * ( ) {
621- terminate ( yield * it ) ;
622- } ) ( ) ;
643+ const iterator = it [ Symbol . iterator ] ( ) ;
644+ return {
645+ _effectedIterator : true ,
646+ next : ( ...args : [ ] | [ unknown ] ) => {
647+ const result = iterator . next ( ...args ) ;
648+ if ( result . done ) return { done : true , value : terminate ( result . value ) } ;
649+ return result ;
650+ } ,
651+ } ;
623652 } ) as never ,
624653 ) ;
625654 }
@@ -1083,6 +1112,20 @@ export function runAsync<E extends Effected<Effect, unknown>>(
10831112const isGenerator = ( value : unknown ) : value is Generator =>
10841113 Object . prototype . toString . call ( value ) === "[object Generator]" ;
10851114
1115+ /**
1116+ * Check if a value is an `EffectedIterator` (i.e., an {@link Iterator} with an `_effectedIterator`
1117+ * property set to `true`).
1118+ *
1119+ * This is only used internally as an alternative to generators to reduce the overhead of creating
1120+ * generator functions.
1121+ * @param value
1122+ * @returns
1123+ */
1124+ const isEffectedIterator = (
1125+ value : unknown ,
1126+ ) : value is Iterator < Effect , unknown , unknown > & { _effectedIterator : true } =>
1127+ typeof value === "object" && value !== null && ( value as any ) . _effectedIterator === true ;
1128+
10861129/**
10871130 * Capitalize the first letter of a string.
10881131 * @param str The string to capitalize.
0 commit comments