3
3
const {
4
4
ArrayPrototypeIndexOf,
5
5
ArrayPrototypePush,
6
+ ArrayPrototypeShift,
6
7
ArrayPrototypeSplice,
7
8
ObjectCreate,
8
9
ObjectGetPrototypeOf,
9
10
ObjectSetPrototypeOf,
11
+ Promise,
12
+ PromiseResolve,
13
+ SymbolAsyncIterator,
10
14
SymbolHasInstance,
11
15
WeakRefPrototypeGet
12
16
} = primordials ;
@@ -21,8 +25,72 @@ const { triggerUncaughtException } = internalBinding('errors');
21
25
22
26
const { WeakReference } = internalBinding ( 'util' ) ;
23
27
28
+ class AsyncIterableChannel {
29
+ constructor ( channel ) {
30
+ this . channel = channel ;
31
+ this . events = [ ] ;
32
+ this . waiting = [ ] ;
33
+
34
+ this . subscriber = ( message ) => {
35
+ const resolve = ArrayPrototypeShift ( this . waiting ) ;
36
+ if ( resolve ) {
37
+ return resolve ( {
38
+ value : message ,
39
+ done : false
40
+ } ) ;
41
+ }
42
+
43
+ ArrayPrototypePush ( this . events , message ) ;
44
+ } ;
45
+
46
+ channel . subscribe ( this . subscriber ) ;
47
+ }
48
+
49
+ [ SymbolAsyncIterator ] ( ) {
50
+ return this ;
51
+ }
52
+
53
+ return ( ) {
54
+ const data = { done : true } ;
55
+ this . done = true ;
56
+
57
+ this . channel . unsubscribe ( this . subscriber ) ;
58
+
59
+ for ( let i = 0 ; i < this . waiting . length ; i ++ ) {
60
+ const resolve = this . waiting [ i ] ;
61
+ resolve ( data ) ;
62
+ }
63
+
64
+ return PromiseResolve ( data ) ;
65
+ }
66
+
67
+ next ( ) {
68
+ const event = ArrayPrototypeShift ( this . events ) ;
69
+ if ( event ) {
70
+ return PromiseResolve ( {
71
+ value : event ,
72
+ done : false
73
+ } ) ;
74
+ }
75
+
76
+ if ( this . done ) {
77
+ return PromiseResolve ( {
78
+ done : true
79
+ } ) ;
80
+ }
81
+
82
+ return new Promise ( ( resolve ) => {
83
+ ArrayPrototypePush ( this . waiting , resolve ) ;
84
+ } ) ;
85
+ }
86
+ }
87
+
24
88
// TODO(qard): should there be a C++ channel interface?
25
89
class ActiveChannel {
90
+ [ SymbolAsyncIterator ] ( ) {
91
+ return new AsyncIterableChannel ( this ) ;
92
+ }
93
+
26
94
subscribe ( subscription ) {
27
95
if ( typeof subscription !== 'function' ) {
28
96
throw new ERR_INVALID_ARG_TYPE ( 'subscription' , [ 'function' ] ,
@@ -71,7 +139,11 @@ class Channel {
71
139
static [ SymbolHasInstance ] ( instance ) {
72
140
const prototype = ObjectGetPrototypeOf ( instance ) ;
73
141
return prototype === Channel . prototype ||
74
- prototype === ActiveChannel . prototype ;
142
+ prototype === ActiveChannel . prototype ;
143
+ }
144
+
145
+ [ SymbolAsyncIterator ] ( ) {
146
+ return new AsyncIterableChannel ( this ) ;
75
147
}
76
148
77
149
subscribe ( subscription ) {
0 commit comments