like-thread 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +197 -272
- package/package.json +4 -2
- package/worker.js +77 -0
package/index.js
CHANGED
|
@@ -1,369 +1,294 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const { Worker } = require('worker_threads')
|
|
4
|
+
const promiseWithResolvers = require('promise-resolvers')
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
const promiseWithResolvers = require('promise-resolvers')
|
|
6
|
+
const WORKER_SCRIPT = fs.readFileSync(path.join(__dirname, 'worker.js'), 'utf8')
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
module.exports = class Thread {
|
|
9
|
+
static go (args, fn) {
|
|
10
|
+
const thread = new this(fn, args)
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
if (!thread.isGenerator) {
|
|
13
|
+
const value = thread.call(...args)
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
return value.finally(() => thread.close())
|
|
16
|
+
}
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
const iterator = thread.call(...args)
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
return {
|
|
21
|
+
[Symbol.asyncIterator] () {
|
|
22
|
+
return this
|
|
23
|
+
},
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
async next () {
|
|
26
|
+
const result = await iterator.next()
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (result.done) {
|
|
29
|
+
await thread.close()
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
return result
|
|
33
|
+
},
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
35
|
+
async return (value) {
|
|
36
|
+
try {
|
|
37
|
+
return await iterator.return(value)
|
|
38
|
+
} finally {
|
|
39
|
+
await thread.close()
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
}
|
|
43
|
+
}
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
constructor (fn, opts = {}) {
|
|
46
|
+
const workerData = {
|
|
47
|
+
fn: fn.toString()
|
|
48
|
+
}
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
const entrypoint = workerData.fn.match(/(async )?function( ?\* ?)? ([a-zA-Z0-9]+)? ?\(([^)]*?)\)/i)
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
this.isAsync = !!entrypoint[1]
|
|
53
|
+
this.isGenerator = !!entrypoint[2]
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
this.worker = new Worker(WORKER_SCRIPT, { eval: true, workerData, argv: opts.argv || null })
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
this.id = 1
|
|
58
|
+
this.requests = new Map()
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
this.worker.on('message', this._onMessage.bind(this))
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
this.promise = new Promise((resolve, reject) => {
|
|
63
|
+
let error = null
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
this.worker.on('error', err => {
|
|
66
|
+
error = err
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
for (const [id, req] of this.requests) {
|
|
69
|
+
this.requests.delete(id)
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
71
|
+
if (req.resolver) {
|
|
72
|
+
req.resolver.reject(err)
|
|
73
|
+
} else {
|
|
74
|
+
req.iterator.fail(err)
|
|
74
75
|
}
|
|
76
|
+
}
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this.worker.on('exit', (exitCode, signal) => {
|
|
80
|
-
if (error) return
|
|
81
|
-
|
|
82
|
-
const err = new Error('Worker closed (' + exitCode + ' and ' + signal + ')')
|
|
78
|
+
reject(err)
|
|
79
|
+
})
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
this.worker.on('exit', (exitCode, signal) => {
|
|
82
|
+
if (error) return
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
req.resolver.reject(err)
|
|
89
|
-
} else {
|
|
90
|
-
req.iterator.fail(err)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
84
|
+
const err = new Error('Worker closed (' + exitCode + ' and ' + signal + ')')
|
|
93
85
|
|
|
94
|
-
|
|
86
|
+
for (const [id, req] of this.requests) {
|
|
87
|
+
this.requests.delete(id)
|
|
95
88
|
|
|
96
|
-
if (
|
|
97
|
-
|
|
89
|
+
if (req.resolver) {
|
|
90
|
+
req.resolver.reject(err)
|
|
98
91
|
} else {
|
|
99
|
-
|
|
92
|
+
req.iterator.fail(err)
|
|
100
93
|
}
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
_onMessage (msg) {
|
|
106
|
-
const req = this.requests.get(msg.id)
|
|
107
|
-
|
|
108
|
-
if (!req) {
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// console.log('_onMessage', msg, !!req.iterator ? 'iterator' : 'promise')
|
|
113
|
-
|
|
114
|
-
if (msg.error) {
|
|
115
|
-
this.requests.delete(msg.id)
|
|
116
|
-
|
|
117
|
-
const err = new Error(msg.error)
|
|
118
|
-
|
|
119
|
-
if (req.resolver) {
|
|
120
|
-
req.resolver.reject(err)
|
|
121
|
-
} else {
|
|
122
|
-
req.iterator.fail(err)
|
|
123
94
|
}
|
|
124
95
|
|
|
125
|
-
|
|
126
|
-
}
|
|
96
|
+
const success = exitCode === 0 || exitCode === 130 || signal === 'SIGINT' || signal === 'SIGTERM' || signal === 'SIGHUP'
|
|
127
97
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (req.resolver) {
|
|
131
|
-
req.resolver.resolve(msg.value)
|
|
98
|
+
if (success) {
|
|
99
|
+
resolve()
|
|
132
100
|
} else {
|
|
133
|
-
|
|
101
|
+
reject(err)
|
|
134
102
|
}
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
}
|
|
135
106
|
|
|
136
|
-
|
|
137
|
-
|
|
107
|
+
_onMessage (msg) {
|
|
108
|
+
const req = this.requests.get(msg.id)
|
|
138
109
|
|
|
139
|
-
|
|
140
|
-
|
|
110
|
+
if (!req) {
|
|
111
|
+
return
|
|
112
|
+
}
|
|
141
113
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return
|
|
145
|
-
}
|
|
114
|
+
// console.log('_onMessage', msg, !!req.iterator ? 'iterator' : 'promise')
|
|
146
115
|
|
|
116
|
+
if (msg.error) {
|
|
147
117
|
this.requests.delete(msg.id)
|
|
148
118
|
|
|
119
|
+
const err = new Error(msg.error)
|
|
120
|
+
|
|
149
121
|
if (req.resolver) {
|
|
150
|
-
req.resolver.reject(
|
|
122
|
+
req.resolver.reject(err)
|
|
151
123
|
} else {
|
|
152
|
-
req.iterator.fail(
|
|
124
|
+
req.iterator.fail(err)
|
|
153
125
|
}
|
|
126
|
+
|
|
127
|
+
return
|
|
154
128
|
}
|
|
155
129
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
130
|
+
// msg.value can be a falsy value like 0 or null
|
|
131
|
+
if (msg.v) {
|
|
132
|
+
if (req.resolver) {
|
|
133
|
+
req.resolver.resolve(msg.value)
|
|
134
|
+
} else {
|
|
135
|
+
req.iterator.push(msg.value)
|
|
159
136
|
}
|
|
160
137
|
|
|
161
|
-
|
|
138
|
+
return
|
|
139
|
+
}
|
|
162
140
|
|
|
163
|
-
|
|
164
|
-
|
|
141
|
+
if (msg.done) {
|
|
142
|
+
this.requests.delete(msg.id)
|
|
165
143
|
|
|
166
|
-
|
|
144
|
+
req.iterator.close()
|
|
167
145
|
|
|
168
|
-
|
|
169
|
-
|
|
146
|
+
return
|
|
147
|
+
}
|
|
170
148
|
|
|
171
|
-
|
|
149
|
+
this.requests.delete(msg.id)
|
|
172
150
|
|
|
173
|
-
|
|
151
|
+
if (req.resolver) {
|
|
152
|
+
req.resolver.reject(new Error('Invalid message'))
|
|
153
|
+
} else {
|
|
154
|
+
req.iterator.fail(new Error('Invalid message'))
|
|
155
|
+
}
|
|
156
|
+
}
|
|
174
157
|
|
|
175
|
-
|
|
176
|
-
|
|
158
|
+
call (...args) {
|
|
159
|
+
if (this.id === 0xffffffff) {
|
|
160
|
+
this.id = 1
|
|
161
|
+
}
|
|
177
162
|
|
|
178
|
-
|
|
179
|
-
resolver: promiseWithResolvers(),
|
|
180
|
-
queue: [],
|
|
181
|
-
closed: false,
|
|
182
|
-
push: function (value) {
|
|
183
|
-
if (this.closed) {
|
|
184
|
-
return
|
|
185
|
-
}
|
|
163
|
+
const id = this.id++
|
|
186
164
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
},
|
|
190
|
-
fail: function (err) {
|
|
191
|
-
if (this.closed) {
|
|
192
|
-
return
|
|
193
|
-
}
|
|
165
|
+
const sab = new SharedArrayBuffer(4)
|
|
166
|
+
const control = new Int32Array(sab)
|
|
194
167
|
|
|
195
|
-
|
|
196
|
-
this.resolver.resolve(err)
|
|
197
|
-
},
|
|
198
|
-
close: function () {
|
|
199
|
-
if (this.closed) {
|
|
200
|
-
return
|
|
201
|
-
}
|
|
168
|
+
Atomics.store(control, 0, 0)
|
|
202
169
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
}
|
|
170
|
+
if (!this.isGenerator) {
|
|
171
|
+
const resolver = promiseWithResolvers()
|
|
207
172
|
|
|
208
|
-
this.requests.set(id, {
|
|
173
|
+
this.requests.set(id, { resolver })
|
|
209
174
|
|
|
210
175
|
this.worker.postMessage({ id, args, sab })
|
|
211
176
|
|
|
212
|
-
return
|
|
213
|
-
|
|
214
|
-
return this
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
async next () {
|
|
218
|
-
Atomics.store(control, 0, 1)
|
|
219
|
-
Atomics.notify(control, 0, 1)
|
|
220
|
-
|
|
221
|
-
const err = await iterator.resolver.promise
|
|
177
|
+
return resolver.promise
|
|
178
|
+
}
|
|
222
179
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
180
|
+
const iterator = {
|
|
181
|
+
resolver: promiseWithResolvers(),
|
|
182
|
+
queue: [],
|
|
183
|
+
closed: false,
|
|
184
|
+
push: function (value) {
|
|
185
|
+
if (this.closed) {
|
|
186
|
+
return
|
|
187
|
+
}
|
|
226
188
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
189
|
+
this.queue.push({ value, done: false })
|
|
190
|
+
this.resolver.resolve()
|
|
191
|
+
},
|
|
192
|
+
fail: function (err) {
|
|
193
|
+
if (this.closed) {
|
|
194
|
+
return
|
|
195
|
+
}
|
|
230
196
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
197
|
+
this.closed = true
|
|
198
|
+
this.resolver.resolve(err)
|
|
199
|
+
},
|
|
200
|
+
close: function () {
|
|
201
|
+
if (this.closed) {
|
|
202
|
+
return
|
|
203
|
+
}
|
|
234
204
|
|
|
235
|
-
|
|
205
|
+
this.closed = true
|
|
206
|
+
this.resolver.resolve()
|
|
207
|
+
}
|
|
208
|
+
}
|
|
236
209
|
|
|
237
|
-
|
|
238
|
-
},
|
|
210
|
+
this.requests.set(id, { iterator })
|
|
239
211
|
|
|
240
|
-
|
|
241
|
-
iterator.closed = true
|
|
212
|
+
this.worker.postMessage({ id, args, sab })
|
|
242
213
|
|
|
243
|
-
|
|
244
|
-
|
|
214
|
+
return {
|
|
215
|
+
[Symbol.asyncIterator] () {
|
|
216
|
+
return this
|
|
217
|
+
},
|
|
245
218
|
|
|
246
|
-
|
|
247
|
-
|
|
219
|
+
async next () {
|
|
220
|
+
Atomics.store(control, 0, 1)
|
|
221
|
+
Atomics.notify(control, 0, 1)
|
|
248
222
|
|
|
249
|
-
|
|
250
|
-
// iterator.resolver.resolve()
|
|
223
|
+
const err = await iterator.resolver.promise
|
|
251
224
|
|
|
252
|
-
|
|
225
|
+
if (err) {
|
|
226
|
+
throw err
|
|
253
227
|
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
228
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
async next () {
|
|
264
|
-
const { done, value } = await this.iterator.next()
|
|
229
|
+
if (iterator.queue.length === 0) {
|
|
230
|
+
return { done: true }
|
|
231
|
+
}
|
|
265
232
|
|
|
266
|
-
|
|
267
|
-
|
|
233
|
+
if (iterator.queue.length === 1) {
|
|
234
|
+
iterator.resolver = promiseWithResolvers()
|
|
235
|
+
}
|
|
268
236
|
|
|
269
|
-
|
|
270
|
-
return this.iterator.return()
|
|
271
|
-
}
|
|
237
|
+
const item = iterator.queue.shift()
|
|
272
238
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
239
|
+
return item
|
|
240
|
+
},
|
|
276
241
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
242
|
+
return: () => {
|
|
243
|
+
iterator.closed = true
|
|
280
244
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
245
|
+
Atomics.store(control, 0, 2)
|
|
246
|
+
Atomics.notify(control, 0, 1)
|
|
284
247
|
|
|
285
|
-
|
|
286
|
-
|
|
248
|
+
// this.worker.postMessage({ id, command: 'stop' })
|
|
249
|
+
// return
|
|
287
250
|
|
|
288
|
-
|
|
251
|
+
// iterator.queue.length = 0
|
|
252
|
+
// iterator.resolver.resolve()
|
|
289
253
|
|
|
290
|
-
|
|
254
|
+
return Promise.resolve({ done: true })
|
|
255
|
+
}
|
|
291
256
|
}
|
|
292
257
|
}
|
|
293
|
-
} else {
|
|
294
|
-
const entrypoint = workerData.fn.match(/(async )?function( ?\* ?)? ([a-zA-Z0-9]+)? ?\(([^)]*?)\)/i)
|
|
295
258
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const functionArgs = entrypoint[4] || ''
|
|
300
|
-
|
|
301
|
-
const fn = workerData.fn.replace(entrypoint[0], (isAsync ? 'async ' : '') + 'function ' + (isGenerator ? '* ' : '') + functionName + ' (' + (functionArgs) + ')')
|
|
302
|
-
|
|
303
|
-
parentPort.on('message', async (msg) => {
|
|
304
|
-
if (msg.command === 'exit') {
|
|
305
|
-
process.exit(0)
|
|
306
|
-
return
|
|
259
|
+
async * [Symbol.asyncIterator] () {
|
|
260
|
+
for await (const [value] of this.iterator) {
|
|
261
|
+
yield value
|
|
307
262
|
}
|
|
263
|
+
}
|
|
308
264
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const source = fn + '\n\nmodule.exports = ' + functionName + '(...' + JSON.stringify(msg.args || []) + ')'
|
|
312
|
-
|
|
313
|
-
const wrap = new Function('require', '__dirname', '__filename', 'module', 'exports', 'parentPort', source) // eslint-disable-line no-new-func
|
|
314
|
-
|
|
315
|
-
const mod = { exports: {} }
|
|
316
|
-
|
|
317
|
-
wrap(require, __dirname, __filename, mod, mod.exports, parentPort)
|
|
318
|
-
|
|
319
|
-
const out = mod.exports
|
|
320
|
-
|
|
321
|
-
if (isGenerator) {
|
|
322
|
-
const control = new Int32Array(msg.sab)
|
|
323
|
-
const it = out[Symbol.asyncIterator] ? out[Symbol.asyncIterator]() : out[Symbol.iterator]()
|
|
324
|
-
|
|
325
|
-
while (true) {
|
|
326
|
-
while (Atomics.load(control, 0) === 0) {
|
|
327
|
-
const res = Atomics.waitAsync(control, 0, 0)
|
|
328
|
-
|
|
329
|
-
if (res.async) {
|
|
330
|
-
await res.value
|
|
331
|
-
} else {
|
|
332
|
-
break
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (Atomics.load(control, 0) === 2) {
|
|
337
|
-
break
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const { value, done } = await it.next()
|
|
265
|
+
async next () {
|
|
266
|
+
const { done, value } = await this.iterator.next()
|
|
341
267
|
|
|
342
|
-
|
|
268
|
+
return { done, value: done ? undefined : value[0] }
|
|
269
|
+
}
|
|
343
270
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}
|
|
271
|
+
return () {
|
|
272
|
+
return this.iterator.return()
|
|
273
|
+
}
|
|
348
274
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
275
|
+
then (onFulfilled, onRejected) {
|
|
276
|
+
return this.promise.then(onFulfilled, onRejected)
|
|
277
|
+
}
|
|
352
278
|
|
|
353
|
-
|
|
354
|
-
|
|
279
|
+
catch (onRejected) {
|
|
280
|
+
return this.promise.catch(onRejected)
|
|
281
|
+
}
|
|
355
282
|
|
|
356
|
-
|
|
357
|
-
|
|
283
|
+
finally (onFinally) {
|
|
284
|
+
return this.promise.finally(onFinally)
|
|
285
|
+
}
|
|
358
286
|
|
|
359
|
-
|
|
287
|
+
async close () {
|
|
288
|
+
this.worker.postMessage({ command: 'exit' })
|
|
360
289
|
|
|
361
|
-
|
|
362
|
-
}
|
|
290
|
+
await this.promise
|
|
363
291
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
parentPort.postMessage({ id: msg.id, error: err })
|
|
367
|
-
}
|
|
368
|
-
})
|
|
292
|
+
// await this.worker.terminate()
|
|
293
|
+
}
|
|
369
294
|
}
|
package/package.json
CHANGED
package/worker.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const { workerData, parentPort } = require('worker_threads')
|
|
2
|
+
|
|
3
|
+
const entrypoint = workerData.fn.match(/(async )?function( ?\* ?)? ([a-zA-Z0-9]+)? ?\(([^)]*?)\)/i)
|
|
4
|
+
|
|
5
|
+
const isAsync = !!entrypoint[1]
|
|
6
|
+
const isGenerator = !!entrypoint[2]
|
|
7
|
+
const functionName = entrypoint[3] || '_WORKER_MAIN_'
|
|
8
|
+
const functionArgs = entrypoint[4] || ''
|
|
9
|
+
|
|
10
|
+
const fn = workerData.fn.replace(entrypoint[0], (isAsync ? 'async ' : '') + 'function ' + (isGenerator ? '* ' : '') + functionName + ' (' + (functionArgs) + ')')
|
|
11
|
+
|
|
12
|
+
parentPort.on('message', async (msg) => {
|
|
13
|
+
if (msg.command === 'exit') {
|
|
14
|
+
process.exit(0)
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// TODO: Optimize by creating the function only once by fixing the args
|
|
20
|
+
const source = fn + '\n\nmodule.exports = ' + functionName + '(...' + JSON.stringify(msg.args || []) + ')'
|
|
21
|
+
|
|
22
|
+
const wrap = new Function('require', '__dirname', '__filename', 'module', 'exports', 'parentPort', source) // eslint-disable-line no-new-func
|
|
23
|
+
|
|
24
|
+
const mod = { exports: {} }
|
|
25
|
+
|
|
26
|
+
wrap(require, __dirname, __filename, mod, mod.exports, parentPort)
|
|
27
|
+
|
|
28
|
+
const out = mod.exports
|
|
29
|
+
|
|
30
|
+
if (isGenerator) {
|
|
31
|
+
const control = new Int32Array(msg.sab)
|
|
32
|
+
const it = out[Symbol.asyncIterator] ? out[Symbol.asyncIterator]() : out[Symbol.iterator]()
|
|
33
|
+
|
|
34
|
+
while (true) {
|
|
35
|
+
while (Atomics.load(control, 0) === 0) {
|
|
36
|
+
const res = Atomics.waitAsync(control, 0, 0)
|
|
37
|
+
|
|
38
|
+
if (res.async) {
|
|
39
|
+
await res.value
|
|
40
|
+
} else {
|
|
41
|
+
break
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (Atomics.load(control, 0) === 2) {
|
|
46
|
+
break
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const { value, done } = await it.next()
|
|
50
|
+
|
|
51
|
+
Atomics.store(control, 0, 0)
|
|
52
|
+
|
|
53
|
+
if (done) {
|
|
54
|
+
parentPort.postMessage({ id: msg.id, done: true })
|
|
55
|
+
break
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Keep "v" because "value" can be falsy like 0 or null
|
|
59
|
+
parentPort.postMessage({ id: msg.id, value, v: true })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (isAsync) {
|
|
66
|
+
const value = await out
|
|
67
|
+
|
|
68
|
+
parentPort.postMessage({ id: msg.id, value, v: true })
|
|
69
|
+
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
parentPort.postMessage({ id: msg.id, value: out, v: true })
|
|
74
|
+
} catch (err) {
|
|
75
|
+
parentPort.postMessage({ id: msg.id, error: err })
|
|
76
|
+
}
|
|
77
|
+
})
|