@@ -17,10 +17,11 @@ class SimpleChannel {
17
17
} ;
18
18
mm . addMessageListener ( SIMPLE_CHANNEL_MESSAGE_NAME , messageListener ) ;
19
19
20
- channel . transport . sendMessage = obj => mm . sendAsyncMessage ( SIMPLE_CHANNEL_MESSAGE_NAME , obj ) ;
21
- channel . transport . dispose = ( ) => {
22
- mm . removeMessageListener ( SIMPLE_CHANNEL_MESSAGE_NAME , messageListener ) ;
23
- } ;
20
+ channel . setTransport ( {
21
+ sendMessage : obj => mm . sendAsyncMessage ( SIMPLE_CHANNEL_MESSAGE_NAME , obj ) ,
22
+ dispose : ( ) => mm . removeMessageListener ( SIMPLE_CHANNEL_MESSAGE_NAME , messageListener ) ,
23
+ } ) ;
24
+
24
25
return channel ;
25
26
}
26
27
@@ -30,14 +31,39 @@ class SimpleChannel {
30
31
this . _connectorId = 0 ;
31
32
this . _pendingMessages = new Map ( ) ;
32
33
this . _handlers = new Map ( ) ;
33
- this . _bufferedRequests = [ ] ;
34
+ this . _bufferedIncomingMessages = [ ] ;
35
+ this . _bufferedOutgoingMessages = [ ] ;
34
36
this . transport = {
35
37
sendMessage : null ,
36
38
dispose : null ,
37
39
} ;
40
+ this . _ready = false ;
38
41
this . _disposed = false ;
39
42
}
40
43
44
+ setTransport ( transport ) {
45
+ this . transport = transport ;
46
+ // connection handshake:
47
+ // 1. There are two channel ends in different processes.
48
+ // 2. Both ends start in the `ready = false` state, meaning that they will
49
+ // not send any messages over transport.
50
+ // 3. Once channel end is created, it sends `READY` message to the other end.
51
+ // 4. Eventually, at least one of the ends receives `READY` message and responds with
52
+ // `READY_ACK`. We assume at least one of the ends will receive "READY" event from the other, since
53
+ // channel ends have a "parent-child" relation, i.e. one end is always created before the other one.
54
+ // 5. Once channel end receives either `READY` or `READY_ACK`, it transitions to `ready` state.
55
+ this . transport . sendMessage ( 'READY' ) ;
56
+ }
57
+
58
+ _markAsReady ( ) {
59
+ if ( this . _ready )
60
+ return ;
61
+ this . _ready = true ;
62
+ for ( const msg of this . _bufferedOutgoingMessages )
63
+ this . transport . sendMessage ( msg ) ;
64
+ this . _bufferedOutgoingMessages = [ ] ;
65
+ }
66
+
41
67
dispose ( ) {
42
68
if ( this . _disposed )
43
69
return ;
@@ -72,8 +98,8 @@ class SimpleChannel {
72
98
throw new Error ( 'ERROR: double-register for namespace ' + namespace ) ;
73
99
this . _handlers . set ( namespace , handler ) ;
74
100
// Try to re-deliver all pending messages.
75
- const bufferedRequests = this . _bufferedRequests ;
76
- this . _bufferedRequests = [ ] ;
101
+ const bufferedRequests = this . _bufferedIncomingMessages ;
102
+ this . _bufferedIncomingMessages = [ ] ;
77
103
for ( const data of bufferedRequests ) {
78
104
this . _onMessage ( data ) ;
79
105
}
@@ -98,11 +124,24 @@ class SimpleChannel {
98
124
const promise = new Promise ( ( resolve , reject ) => {
99
125
this . _pendingMessages . set ( id , { connectorId, resolve, reject, methodName, namespace} ) ;
100
126
} ) ;
101
- this . transport . sendMessage ( { requestId : id , methodName, params, namespace} ) ;
127
+ const message = { requestId : id , methodName, params, namespace} ;
128
+ if ( this . _ready )
129
+ this . transport . sendMessage ( message ) ;
130
+ else
131
+ this . _bufferedOutgoingMessages . push ( message ) ;
102
132
return promise ;
103
133
}
104
134
105
135
async _onMessage ( data ) {
136
+ if ( data === 'READY' ) {
137
+ this . transport . sendMessage ( 'READY_ACK' ) ;
138
+ this . _markAsReady ( ) ;
139
+ return ;
140
+ }
141
+ if ( data === 'READY_ACK' ) {
142
+ this . _markAsReady ( ) ;
143
+ return ;
144
+ }
106
145
if ( data . responseId ) {
107
146
const { resolve, reject} = this . _pendingMessages . get ( data . responseId ) ;
108
147
this . _pendingMessages . delete ( data . responseId ) ;
@@ -114,7 +153,7 @@ class SimpleChannel {
114
153
const namespace = data . namespace ;
115
154
const handler = this . _handlers . get ( namespace ) ;
116
155
if ( ! handler ) {
117
- this . _bufferedRequests . push ( data ) ;
156
+ this . _bufferedIncomingMessages . push ( data ) ;
118
157
return ;
119
158
}
120
159
const method = handler [ data . methodName ] ;
0 commit comments