@@ -4,15 +4,15 @@ export interface QuansyncInputObject<Return, Args extends any[]> {
4
4
async : ( ...args : Args ) => Promise < Return >
5
5
}
6
6
7
- export type QuansyncInputGenerator < Return , Args extends any [ ] >
7
+ export type QuansyncGeneratorFn < Return , Args extends any [ ] >
8
8
= ( ( ...args : Args ) => QuansyncGenerator < Return > )
9
9
10
10
export type QuansyncInput < Return , Args extends any [ ] > =
11
11
| QuansyncInputObject < Return , Args >
12
- | QuansyncInputGenerator < Return , Args >
12
+ | QuansyncGeneratorFn < Return , Args >
13
13
14
14
export type QuansyncGenerator < Return = any , Yield = unknown > =
15
- Generator < Yield , Return , Awaited < Yield > >
15
+ Generator < Yield , Return , Awaited < Yield > > & { __quansync ?: true }
16
16
17
17
/**
18
18
* "Superposition" function that can be consumed in both sync and async contexts.
@@ -32,6 +32,9 @@ function isThenable<T>(value: any): value is Promise<T> {
32
32
function isGenerator < T > ( value : any ) : value is Generator < T > {
33
33
return value && typeof value === 'object' && typeof value [ Symbol . iterator ] === 'function'
34
34
}
35
+ function isQuansyncGenerator < T > ( value : any ) : value is QuansyncGenerator < T > {
36
+ return isGenerator ( value ) && '__quansync' in value
37
+ }
35
38
36
39
const GET_IS_ASYNC = Symbol . for ( 'quansync.getIsAsync' )
37
40
@@ -47,6 +50,7 @@ function fromObject<Return, Args extends any[]>(
47
50
const fn = ( ...args : Args ) : any => {
48
51
const iter = generator ( ...args ) as unknown as QuansyncGenerator < Return , Args > & Promise < Return >
49
52
iter . then = ( ...thenArgs ) => options . async ( ...args ) . then ( ...thenArgs )
53
+ iter . __quansync = true
50
54
return iter
51
55
}
52
56
fn . sync = options . sync
@@ -68,36 +72,36 @@ function fromPromise<T>(promise: Promise<T> | T): QuansyncFn<T, []> {
68
72
function unwrapYield ( value : any , isAsync ?: boolean ) : any {
69
73
if ( value === GET_IS_ASYNC )
70
74
return isAsync
75
+ if ( isQuansyncGenerator ( value ) )
76
+ return isAsync ? iterateAsync ( value ) : iterateSync ( value )
71
77
if ( ! isAsync && isThenable ( value ) )
72
78
throw new Error ( ERROR_PROMISE_IN_SYNC )
73
79
return value
74
80
}
75
81
76
- function fromGenerator < Return , Args extends any [ ] > (
77
- generator : QuansyncInputGenerator < Return , Args > ,
78
- ) : QuansyncFn < Return , Args > {
79
- function sync ( ...args : Args ) : Return {
80
- const iterator = generator ( ...args )
81
- let current = iterator . next ( )
82
- while ( ! current . done ) {
83
- current = iterator . next ( unwrapYield ( current . value ) )
84
- }
85
- return unwrapYield ( current . value )
82
+ function iterateSync < Return > ( generator : QuansyncGenerator < Return , unknown > ) : Return {
83
+ let current = generator . next ( )
84
+ while ( ! current . done ) {
85
+ current = generator . next ( unwrapYield ( current . value ) )
86
86
}
87
+ return unwrapYield ( current . value )
88
+ }
87
89
88
- async function async ( ...args : Args ) : Promise < Return > {
89
- const iterator = generator ( ...args )
90
- let current = iterator . next ( )
91
- while ( ! current . done ) {
92
- current = iterator . next ( await unwrapYield ( current . value , true ) )
93
- }
94
- return current . value
90
+ async function iterateAsync < Return > ( generator : QuansyncGenerator < Return , unknown > ) : Promise < Return > {
91
+ let current = generator . next ( )
92
+ while ( ! current . done ) {
93
+ current = generator . next ( await unwrapYield ( current . value , true ) )
95
94
}
95
+ return current . value
96
+ }
96
97
98
+ function fromGeneratorFn < Return , Args extends any [ ] > (
99
+ generatorFn : QuansyncGeneratorFn < Return , Args > ,
100
+ ) : QuansyncFn < Return , Args > {
97
101
return fromObject ( {
98
- name : generator . name ,
99
- async,
100
- sync,
102
+ name : generatorFn . name ,
103
+ async : ( ... args ) => iterateAsync ( generatorFn ( ... args ) ) ,
104
+ sync : ( ... args ) => iterateSync ( generatorFn ( ... args ) ) ,
101
105
} )
102
106
}
103
107
@@ -110,7 +114,7 @@ export function quansync<Return, Args extends any[] = []>(
110
114
if ( isThenable ( options ) )
111
115
return fromPromise < Return > ( options )
112
116
if ( typeof options === 'function' )
113
- return fromGenerator ( options )
117
+ return fromGeneratorFn ( options )
114
118
else
115
119
return fromObject ( options )
116
120
}
@@ -134,5 +138,5 @@ export function quansyncMacro<Return, Args extends any[] = []>(
134
138
export function toGenerator < T > ( promise : Promise < T > | QuansyncGenerator < T > | T ) : QuansyncGenerator < T > {
135
139
if ( isGenerator ( promise ) )
136
140
return promise
137
- return fromPromise ( promise as Promise < T > ) ( )
141
+ return fromPromise ( promise ) ( )
138
142
}
0 commit comments