@@ -6,7 +6,7 @@ import * as fs from 'fs';
6
6
import * as p from 'path' ;
7
7
import { MessagePort , Worker } from 'worker_threads' ;
8
8
9
- import { SyncMessagePort } from './index' ;
9
+ import { SyncMessagePort , TimeoutException } from './index' ;
10
10
11
11
describe ( 'SyncMessagePort' , ( ) => {
12
12
describe ( 'sends a message' , ( ) => {
@@ -73,6 +73,124 @@ describe('SyncMessagePort', () => {
73
73
} ) ;
74
74
} ) ;
75
75
76
+ describe ( 'receiveMessageIfAvailable()' , ( ) => {
77
+ it ( 'without a queued message' , ( ) => {
78
+ const channel = SyncMessagePort . createChannel ( ) ;
79
+ const port = new SyncMessagePort ( channel . port1 ) ;
80
+ expect ( port . receiveMessageIfAvailable ( ) ) . toBe ( undefined ) ;
81
+ port . close ( ) ;
82
+ } ) ;
83
+
84
+ it ( 'with a queued message' , ( ) => {
85
+ const channel = SyncMessagePort . createChannel ( ) ;
86
+ const port1 = new SyncMessagePort ( channel . port1 ) ;
87
+ const port2 = new SyncMessagePort ( channel . port2 ) ;
88
+
89
+ port1 . postMessage ( 'done!' ) ;
90
+ expect ( port2 . receiveMessageIfAvailable ( ) ?. message ) . toBe ( 'done!' ) ;
91
+ port1 . close ( ) ;
92
+ } ) ;
93
+
94
+ it ( 'on a closed channel' , ( ) => {
95
+ const channel = SyncMessagePort . createChannel ( ) ;
96
+ const port1 = new SyncMessagePort ( channel . port1 ) ;
97
+ const port2 = new SyncMessagePort ( channel . port2 ) ;
98
+
99
+ port1 . close ( ) ;
100
+ expect ( port2 . receiveMessageIfAvailable ( ) ) . toBe ( undefined ) ;
101
+ } ) ;
102
+
103
+ it ( 'bewteen receiving blocking messages' , ( ) => {
104
+ const channel = SyncMessagePort . createChannel ( ) ;
105
+ const port = new SyncMessagePort ( channel . port1 ) ;
106
+
107
+ spawnWorker (
108
+ `
109
+ // Wait a little bit just to make entirely sure that the parent thread
110
+ // is awaiting a message.
111
+ setTimeout(() => {
112
+ port.postMessage('first');
113
+ port.postMessage('second');
114
+
115
+ setTimeout(() => {
116
+ port.postMessage('third');
117
+ port.close();
118
+ }, 100);
119
+ }, 100);
120
+ ` ,
121
+ channel . port2 ,
122
+ ) ;
123
+
124
+ expect ( port . receiveMessage ( ) ) . toEqual ( 'first' ) ;
125
+ expect ( port . receiveMessageIfAvailable ( ) ?. message ) . toEqual ( 'second' ) ;
126
+ expect ( port . receiveMessage ( ) ) . toEqual ( 'third' ) ;
127
+ } ) ;
128
+ } ) ;
129
+
130
+ describe ( 'timeout' , ( ) => {
131
+ it ( "returns a value if it's already available" , ( ) => {
132
+ const channel = SyncMessagePort . createChannel ( ) ;
133
+ const port1 = new SyncMessagePort ( channel . port1 ) ;
134
+ const port2 = new SyncMessagePort ( channel . port2 ) ;
135
+ port1 . postMessage ( 'message' ) ;
136
+ expect ( port2 . receiveMessage ( { timeout : 0 } ) ) . toBe ( 'message' ) ;
137
+ } ) ;
138
+
139
+ it ( 'returns a value if it becomes available before the timeout' , ( ) => {
140
+ const channel = SyncMessagePort . createChannel ( ) ;
141
+ const port = new SyncMessagePort ( channel . port1 ) ;
142
+
143
+ spawnWorker (
144
+ `
145
+ port.postMessage('ready');
146
+ setTimeout(() => {
147
+ port.postMessage('message');
148
+ port.close();
149
+ }, 100);
150
+ ` ,
151
+ channel . port2 ,
152
+ ) ;
153
+
154
+ expect ( port . receiveMessage ( ) ) . toEqual ( 'ready' ) ;
155
+ expect ( port . receiveMessage ( { timeout : 200 } ) ) . toEqual ( 'message' ) ;
156
+ } ) ;
157
+
158
+ it ( 'throws an error if it times out before a value is available' , ( ) => {
159
+ const channel = SyncMessagePort . createChannel ( ) ;
160
+ const port = new SyncMessagePort ( channel . port1 ) ;
161
+ expect ( ( ) => port . receiveMessage ( { timeout : 0 } ) ) . toThrow ( TimeoutException ) ;
162
+ } ) ;
163
+
164
+ it ( 'returns timeoutValue if it times out before a value is available' , ( ) => {
165
+ const channel = SyncMessagePort . createChannel ( ) ;
166
+ const port = new SyncMessagePort ( channel . port1 ) ;
167
+ expect ( port . receiveMessage ( { timeout : 0 , timeoutValue : 'timed out' } ) ) . toBe (
168
+ 'timed out' ,
169
+ ) ;
170
+ } ) ;
171
+
172
+ it ( 'throws an error if the channel closes before the request times out' , ( ) => {
173
+ const channel = SyncMessagePort . createChannel ( ) ;
174
+ const port = new SyncMessagePort ( channel . port1 ) ;
175
+
176
+ spawnWorker (
177
+ `
178
+ port.postMessage('ready');
179
+ setTimeout(() => {
180
+ port.close();
181
+ }, 100);
182
+ ` ,
183
+ channel . port2 ,
184
+ ) ;
185
+
186
+ expect ( port . receiveMessage ( ) ) . toEqual ( 'ready' ) ;
187
+ // timeoutValue shouldn't take precedence over this error
188
+ expect ( ( ) =>
189
+ port . receiveMessage ( { timeout : 10000 , timeoutValue : 'timed out' } ) ,
190
+ ) . toThrow ( ) ;
191
+ } ) ;
192
+ } ) ;
193
+
76
194
describe ( 'with an asynchronous listener' , ( ) => {
77
195
it ( 'receives a message sent before listening' , async ( ) => {
78
196
const channel = SyncMessagePort . createChannel ( ) ;
@@ -127,7 +245,7 @@ describe('SyncMessagePort', () => {
127
245
await new Promise ( resolve => port2 . once ( 'close' , resolve ) ) ;
128
246
} ) ;
129
247
130
- it ( ' receiveMessage() throws an error for a closed port' , ( ) => {
248
+ it ( " receiveMessage() throws an error for a port that's already closed" , ( ) => {
131
249
const channel = SyncMessagePort . createChannel ( ) ;
132
250
const port1 = new SyncMessagePort ( channel . port1 ) ;
133
251
const port2 = new SyncMessagePort ( channel . port2 ) ;
@@ -136,6 +254,52 @@ describe('SyncMessagePort', () => {
136
254
expect ( port1 . receiveMessage ) . toThrow ( ) ;
137
255
expect ( port2 . receiveMessage ) . toThrow ( ) ;
138
256
} ) ;
257
+
258
+ it ( 'receiveMessage() throws an error when a port closes' , ( ) => {
259
+ const channel = SyncMessagePort . createChannel ( ) ;
260
+ const port = new SyncMessagePort ( channel . port1 ) ;
261
+
262
+ spawnWorker (
263
+ `
264
+ setTimeout(() => {
265
+ port.close();
266
+ }, 100);
267
+ ` ,
268
+ channel . port2 ,
269
+ ) ;
270
+
271
+ expect ( port . receiveMessage ) . toThrow ( ) ;
272
+ } ) ;
273
+
274
+ it (
275
+ "receiveMessage() returns option.closedValue for a port that's " +
276
+ 'already closed' ,
277
+ ( ) => {
278
+ const channel = SyncMessagePort . createChannel ( ) ;
279
+ const port1 = new SyncMessagePort ( channel . port1 ) ;
280
+ const port2 = new SyncMessagePort ( channel . port2 ) ;
281
+
282
+ port1 . close ( ) ;
283
+ expect ( port1 . receiveMessage ( { closedValue : 'closed' } ) ) . toBe ( 'closed' ) ;
284
+ expect ( port2 . receiveMessage ( { closedValue : 'closed' } ) ) . toBe ( 'closed' ) ;
285
+ } ,
286
+ ) ;
287
+
288
+ it ( 'receiveMessage() throws an error when a port closes' , ( ) => {
289
+ const channel = SyncMessagePort . createChannel ( ) ;
290
+ const port = new SyncMessagePort ( channel . port1 ) ;
291
+
292
+ spawnWorker (
293
+ `
294
+ setTimeout(() => {
295
+ port.close();
296
+ }, 100);
297
+ ` ,
298
+ channel . port2 ,
299
+ ) ;
300
+
301
+ expect ( port . receiveMessage ( { closedValue : 'closed' } ) ) . toBe ( 'closed' ) ;
302
+ } ) ;
139
303
} ) ;
140
304
} ) ;
141
305
0 commit comments