@bytecodealliance/preview2-shim 0.14.1 → 0.15.0

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.
@@ -15,6 +15,3 @@ export {
15
15
  sockets,
16
16
  cli
17
17
  }
18
-
19
- export { WasiSockets } from "./sockets/wasi-sockets.js";
20
-
@@ -1,11 +1,571 @@
1
- import { WasiSockets } from "./sockets/wasi-sockets.js";
2
-
3
- export const {
4
- ipNameLookup,
5
- instanceNetwork,
6
- network,
7
- tcpCreateSocket,
8
- udpCreateSocket,
9
- tcp,
10
- udp,
11
- } = new WasiSockets();
1
+ import {
2
+ SOCKET_DATAGRAM_STREAM_DISPOSE,
3
+ SOCKET_DATAGRAM_STREAM_SUBSCRIBE,
4
+ SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE,
5
+ SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND,
6
+ SOCKET_OUTGOING_DATAGRAM_STREAM_SEND,
7
+ SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST,
8
+ SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST,
9
+ SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST,
10
+ SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST,
11
+ SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE,
12
+ SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE,
13
+ SOCKET_TCP_ACCEPT,
14
+ SOCKET_TCP_BIND_FINISH,
15
+ SOCKET_TCP_BIND_START,
16
+ SOCKET_TCP_CONNECT_FINISH,
17
+ SOCKET_TCP_CONNECT_START,
18
+ SOCKET_TCP_CREATE_HANDLE,
19
+ SOCKET_TCP_DISPOSE,
20
+ SOCKET_TCP_GET_LOCAL_ADDRESS,
21
+ SOCKET_TCP_GET_REMOTE_ADDRESS,
22
+ SOCKET_TCP_IS_LISTENING,
23
+ SOCKET_TCP_LISTEN_FINISH,
24
+ SOCKET_TCP_LISTEN_START,
25
+ SOCKET_TCP_SET_KEEP_ALIVE,
26
+ SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE,
27
+ SOCKET_TCP_SHUTDOWN,
28
+ SOCKET_TCP_SUBSCRIBE,
29
+ SOCKET_TCP,
30
+ SOCKET_UDP_BIND_FINISH,
31
+ SOCKET_UDP_BIND_START,
32
+ SOCKET_UDP_CREATE_HANDLE,
33
+ SOCKET_UDP_DISPOSE,
34
+ SOCKET_UDP_GET_LOCAL_ADDRESS,
35
+ SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE,
36
+ SOCKET_UDP_GET_REMOTE_ADDRESS,
37
+ SOCKET_UDP_GET_SEND_BUFFER_SIZE,
38
+ SOCKET_UDP_GET_UNICAST_HOP_LIMIT,
39
+ SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE,
40
+ SOCKET_UDP_SET_SEND_BUFFER_SIZE,
41
+ SOCKET_UDP_SET_UNICAST_HOP_LIMIT,
42
+ SOCKET_UDP_STREAM,
43
+ SOCKET_UDP_SUBSCRIBE,
44
+ } from "../io/calls.js";
45
+ import {
46
+ earlyDispose,
47
+ inputStreamCreate,
48
+ ioCall,
49
+ outputStreamCreate,
50
+ pollableCreate,
51
+ registerDispose,
52
+ } from "../io/worker-io.js";
53
+
54
+ const symbolDispose = Symbol.dispose || Symbol.for("dispose");
55
+
56
+ /**
57
+ * @typedef {import("../../types/interfaces/wasi-sockets-network").IpSocketAddress} IpSocketAddress
58
+ * @typedef {import("../../types/interfaces/wasi-sockets-network").IpAddressFamily} IpAddressFamily
59
+ */
60
+
61
+ // Network class privately stores capabilities
62
+ class Network {
63
+ #allowDnsLookup = true;
64
+ #allowTcp = true;
65
+ #allowUdp = true;
66
+
67
+ static _denyDnsLookup(network = defaultNetwork) {
68
+ network.#allowDnsLookup = false;
69
+ }
70
+ static _denyTcp(network = defaultNetwork) {
71
+ network.#allowTcp = false;
72
+ }
73
+ static _denyUdp(network = defaultNetwork) {
74
+ network.#allowUdp = false;
75
+ }
76
+ static _mayDnsLookup(network = defaultNetwork) {
77
+ return network.#allowDnsLookup;
78
+ }
79
+ static _mayTcp(network = defaultNetwork) {
80
+ return network.#allowTcp;
81
+ }
82
+ static _mayUdp(network = defaultNetwork) {
83
+ return network.#allowUdp;
84
+ }
85
+ }
86
+
87
+ export const _denyDnsLookup = Network._denyDnsLookup;
88
+ delete Network._denyDnsLookup;
89
+
90
+ export const _denyTcp = Network._denyTcp;
91
+ delete Network._denyTcp;
92
+
93
+ export const _denyUdp = Network._denyUdp;
94
+ delete Network._denyUdp;
95
+
96
+ const mayDnsLookup = Network._mayDnsLookup;
97
+ delete Network._mayDnsLookup;
98
+
99
+ const mayTcp = Network._mayTcp;
100
+ delete Network._mayTcp;
101
+
102
+ const mayUdp = Network._mayUdp;
103
+ delete Network._mayUdp;
104
+
105
+ const defaultNetwork = new Network();
106
+
107
+ export const instanceNetwork = {
108
+ instanceNetwork() {
109
+ return defaultNetwork;
110
+ },
111
+ };
112
+
113
+ export const network = { Network };
114
+
115
+ class ResolveAddressStream {
116
+ #id;
117
+ #data;
118
+ #curItem = 0;
119
+ #error = false;
120
+ #finalizer;
121
+ resolveNextAddress() {
122
+ if (!this.#data) {
123
+ const res = ioCall(SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST, this.#id, null);
124
+ this.#data = res.val;
125
+ this.#error = res.tag === "err";
126
+ }
127
+ if (this.#error) throw this.#data;
128
+ if (this.#curItem < this.#data.length) return this.#data[this.#curItem++];
129
+ return undefined;
130
+ }
131
+ subscribe() {
132
+ return pollableCreate(
133
+ ioCall(SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST, this.#id, null),
134
+ this
135
+ );
136
+ }
137
+ static _resolveAddresses(network, name) {
138
+ if (!mayDnsLookup(network)) throw "permanent-resolver-failure";
139
+ const res = new ResolveAddressStream();
140
+ res.#id = ioCall(SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST, null, name);
141
+ res.#finalizer = registerDispose(
142
+ res,
143
+ null,
144
+ res.#id,
145
+ resolveAddressStreamDispose
146
+ );
147
+ return res;
148
+ }
149
+ [symbolDispose]() {
150
+ if (this.#finalizer) {
151
+ earlyDispose(this.#finalizer);
152
+ this.#finalizer = null;
153
+ }
154
+ }
155
+ }
156
+ function resolveAddressStreamDispose(id) {
157
+ ioCall(SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST, id, null);
158
+ }
159
+
160
+ const resolveAddresses = ResolveAddressStream._resolveAddresses;
161
+ delete ResolveAddressStream._resolveAddresses;
162
+
163
+ export const ipNameLookup = {
164
+ ResolveAddressStream,
165
+ resolveAddresses,
166
+ };
167
+
168
+ class TcpSocket {
169
+ #id;
170
+ #network;
171
+ #family;
172
+ #finalizer;
173
+ #options = {
174
+ // defaults per https://nodejs.org/docs/latest/api/net.html#socketsetkeepaliveenable-initialdelay
175
+ keepAlive: false,
176
+ // Node.js doesn't give us the ability to detect the OS default,
177
+ // therefore we hardcode the default value instead of using the OS default,
178
+ // since we would never be able to report it as a return value otherwise.
179
+ // We could make this configurable as a global JCO implementation configuration
180
+ // instead.
181
+ keepAliveIdleTime: 7200_000_000_000n,
182
+
183
+ // The following options are NOT configurable in Node.js!
184
+ // Any configurations set will respond correctly, but underneath retain
185
+ // system / Node.js defaults.
186
+ keepAliveInterval: 1_000_000_000n,
187
+ keepAliveCount: 10,
188
+ hopLimit: 1,
189
+
190
+ // For sendBufferSize and receiveBufferSize we can at least
191
+ // use the system defaults, but still we can't support setting them.
192
+ sendBufferSize: undefined,
193
+ receiveBufferSize: undefined,
194
+ };
195
+ /**
196
+ * @param {IpAddressFamily} addressFamily
197
+ * @param {number} id
198
+ * @returns {TcpSocket}
199
+ */
200
+ static _create(addressFamily, id) {
201
+ const socket = new TcpSocket();
202
+ socket.#id = id;
203
+ socket.#family = addressFamily;
204
+ socket.#finalizer = registerDispose(socket, null, id, socketTcpDispose);
205
+ return socket;
206
+ }
207
+ startBind(network, localAddress) {
208
+ if (!mayTcp(network)) throw "access-denied";
209
+ ioCall(SOCKET_TCP_BIND_START, this.#id, {
210
+ localAddress,
211
+ family: this.#family,
212
+ });
213
+ this.#network = network;
214
+ }
215
+ finishBind() {
216
+ ioCall(SOCKET_TCP_BIND_FINISH, this.#id, null);
217
+ }
218
+ startConnect(network, remoteAddress) {
219
+ if (this.#network && network !== this.#network) throw "invalid-argument";
220
+ if (!mayTcp(network)) throw "access-denied";
221
+ ioCall(SOCKET_TCP_CONNECT_START, this.#id, {
222
+ remoteAddress,
223
+ family: this.#family,
224
+ });
225
+ this.#network = network;
226
+ }
227
+ finishConnect() {
228
+ const [inputStreamId, outputStreamId] = ioCall(
229
+ SOCKET_TCP_CONNECT_FINISH,
230
+ this.#id,
231
+ null
232
+ );
233
+ return [
234
+ inputStreamCreate(SOCKET_TCP, inputStreamId),
235
+ outputStreamCreate(SOCKET_TCP, outputStreamId),
236
+ ];
237
+ }
238
+ startListen() {
239
+ if (!mayTcp(this.#network)) throw "access-denied";
240
+ ioCall(SOCKET_TCP_LISTEN_START, this.#id, null);
241
+ }
242
+ finishListen() {
243
+ ioCall(SOCKET_TCP_LISTEN_FINISH, this.#id, null);
244
+ }
245
+ accept() {
246
+ if (!mayTcp(this.#network)) throw "access-denied";
247
+ const [socketId, inputStreamId, outputStreamId] = ioCall(
248
+ SOCKET_TCP_ACCEPT,
249
+ this.#id,
250
+ null
251
+ );
252
+ const socket = tcpSocketCreate(this.#family, socketId);
253
+ Object.assign(socket.#options, this.#options);
254
+ return [
255
+ socket,
256
+ inputStreamCreate(SOCKET_TCP, inputStreamId),
257
+ outputStreamCreate(SOCKET_TCP, outputStreamId),
258
+ ];
259
+ }
260
+ localAddress() {
261
+ return ioCall(SOCKET_TCP_GET_LOCAL_ADDRESS, this.#id, null);
262
+ }
263
+ remoteAddress() {
264
+ return ioCall(SOCKET_TCP_GET_REMOTE_ADDRESS, this.#id, null);
265
+ }
266
+ isListening() {
267
+ return ioCall(SOCKET_TCP_IS_LISTENING, this.#id, null);
268
+ }
269
+ addressFamily() {
270
+ return this.#family;
271
+ }
272
+ setListenBacklogSize(value) {
273
+ if (value === 0n) throw "invalid-argument";
274
+ ioCall(SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE, this.#id, value);
275
+ }
276
+ keepAliveEnabled() {
277
+ return this.#options.keepAlive;
278
+ }
279
+ setKeepAliveEnabled(value) {
280
+ this.#options.keepAlive = value;
281
+ ioCall(SOCKET_TCP_SET_KEEP_ALIVE, this.#id, {
282
+ keepAlive: value,
283
+ keepAliveIdleTime: this.#options.keepAliveIdleTime,
284
+ });
285
+ }
286
+ keepAliveIdleTime() {
287
+ return this.#options.keepAliveIdleTime;
288
+ }
289
+ setKeepAliveIdleTime(value) {
290
+ if (value < 1n) throw "invalid-argument";
291
+ if (value < 1_000_000_000n) value = 1_000_000_000n;
292
+ if (value !== this.#options.keepAliveIdleTime) {
293
+ this.#options.keepAliveIdleTime = value;
294
+ if (this.#options.keepAlive) {
295
+ ioCall(SOCKET_TCP_SET_KEEP_ALIVE, this.#id, {
296
+ keepAlive: true,
297
+ keepAliveIdleTime: this.#options.keepAliveIdleTime,
298
+ });
299
+ }
300
+ }
301
+ }
302
+ keepAliveInterval() {
303
+ return this.#options.keepAliveInterval;
304
+ }
305
+ setKeepAliveInterval(value) {
306
+ if (value < 1n) throw "invalid-argument";
307
+ this.#options.keepAliveInterval = value;
308
+ }
309
+ keepAliveCount() {
310
+ return this.#options.keepAliveCount;
311
+ }
312
+ setKeepAliveCount(value) {
313
+ if (value < 1) throw "invalid-argument";
314
+ this.#options.keepAliveCount = value;
315
+ }
316
+ hopLimit() {
317
+ return this.#options.hopLimit;
318
+ }
319
+ setHopLimit(value) {
320
+ if (value < 1) throw "invalid-argument";
321
+ this.#options.hopLimit = value;
322
+ }
323
+ receiveBufferSize() {
324
+ if (!this.#options.receiveBufferSize)
325
+ this.#options.receiveBufferSize = ioCall(
326
+ SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE,
327
+ null,
328
+ null
329
+ );
330
+ return this.#options.receiveBufferSize;
331
+ }
332
+ setReceiveBufferSize(value) {
333
+ if (value === 0n) throw "invalid-argument";
334
+ this.#options.receiveBufferSize = value;
335
+ }
336
+ sendBufferSize() {
337
+ if (!this.#options.sendBufferSize)
338
+ this.#options.sendBufferSize = ioCall(
339
+ SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE,
340
+ null,
341
+ null
342
+ );
343
+ return this.#options.sendBufferSize;
344
+ }
345
+ setSendBufferSize(value) {
346
+ if (value === 0n) throw "invalid-argument";
347
+ this.#options.sendBufferSize = value;
348
+ }
349
+ subscribe() {
350
+ return pollableCreate(ioCall(SOCKET_TCP_SUBSCRIBE, this.#id, null), this);
351
+ }
352
+ shutdown(shutdownType) {
353
+ ioCall(SOCKET_TCP_SHUTDOWN, this.#id, shutdownType);
354
+ }
355
+ [symbolDispose]() {
356
+ if (this.#finalizer) {
357
+ earlyDispose(this.#finalizer);
358
+ this.#finalizer = null;
359
+ }
360
+ }
361
+ }
362
+
363
+ function socketTcpDispose(id) {
364
+ ioCall(SOCKET_TCP_DISPOSE, id, null);
365
+ }
366
+
367
+ const tcpSocketCreate = TcpSocket._create;
368
+ delete TcpSocket._create;
369
+
370
+ export const tcpCreateSocket = {
371
+ createTcpSocket(addressFamily) {
372
+ if (addressFamily !== "ipv4" && addressFamily !== "ipv6")
373
+ throw "not-supported";
374
+ return tcpSocketCreate(
375
+ addressFamily,
376
+ ioCall(SOCKET_TCP_CREATE_HANDLE, null, null)
377
+ );
378
+ },
379
+ };
380
+
381
+ export const tcp = {
382
+ TcpSocket,
383
+ };
384
+
385
+ class UdpSocket {
386
+ #id;
387
+ #network;
388
+ #family;
389
+ #finalizer;
390
+ static _create(addressFamily) {
391
+ if (addressFamily !== "ipv4" && addressFamily !== "ipv6")
392
+ throw "not-supported";
393
+ const socket = new UdpSocket();
394
+ socket.#id = ioCall(SOCKET_UDP_CREATE_HANDLE, null, {
395
+ family: addressFamily,
396
+ // we always set the unicastHopLimit, because there is no
397
+ // getter but only a setter for this in Node.js, so it is the
398
+ // only way to guarantee the consistent value
399
+ unicastHopLimit: 64,
400
+ });
401
+ socket.#family = addressFamily;
402
+ socket.#finalizer = registerDispose(
403
+ socket,
404
+ null,
405
+ socket.#id,
406
+ socketUdpDispose
407
+ );
408
+ return socket;
409
+ }
410
+ startBind(network, localAddress) {
411
+ if (!mayUdp(network)) throw "access-denied";
412
+ ioCall(SOCKET_UDP_BIND_START, this.#id, {
413
+ localAddress,
414
+ family: this.#family,
415
+ });
416
+ this.#network = network;
417
+ }
418
+ finishBind() {
419
+ ioCall(SOCKET_UDP_BIND_FINISH, this.#id, null);
420
+ }
421
+ stream(remoteAddress) {
422
+ if (!mayUdp(this.#network)) throw "access-denied";
423
+ const [incomingDatagramStreamId, outgoingDatagramStreamId] = ioCall(
424
+ SOCKET_UDP_STREAM,
425
+ this.#id,
426
+ remoteAddress
427
+ );
428
+ return [
429
+ incomingDatagramStreamCreate(incomingDatagramStreamId),
430
+ outgoingDatagramStreamCreate(outgoingDatagramStreamId),
431
+ ];
432
+ }
433
+ localAddress() {
434
+ return ioCall(SOCKET_UDP_GET_LOCAL_ADDRESS, this.#id);
435
+ }
436
+ remoteAddress() {
437
+ return ioCall(SOCKET_UDP_GET_REMOTE_ADDRESS, this.#id);
438
+ }
439
+ addressFamily() {
440
+ return this.#family;
441
+ }
442
+ unicastHopLimit() {
443
+ return ioCall(SOCKET_UDP_GET_UNICAST_HOP_LIMIT, this.#id);
444
+ }
445
+ setUnicastHopLimit(value) {
446
+ if (value < 1) throw "invalid-argument";
447
+ ioCall(SOCKET_UDP_SET_UNICAST_HOP_LIMIT, this.#id, value);
448
+ }
449
+ receiveBufferSize() {
450
+ return ioCall(SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE, this.#id);
451
+ }
452
+ setReceiveBufferSize(value) {
453
+ if (value === 0n) throw "invalid-argument";
454
+ ioCall(SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE, this.#id, value);
455
+ }
456
+ sendBufferSize() {
457
+ return ioCall(SOCKET_UDP_GET_SEND_BUFFER_SIZE, this.#id);
458
+ }
459
+ setSendBufferSize(value) {
460
+ if (value === 0n) throw "invalid-argument";
461
+ ioCall(SOCKET_UDP_SET_SEND_BUFFER_SIZE, this.#id, value);
462
+ }
463
+ subscribe() {
464
+ return pollableCreate(ioCall(SOCKET_UDP_SUBSCRIBE, this.#id, null), this);
465
+ }
466
+ [symbolDispose]() {
467
+ if (this.#finalizer) {
468
+ earlyDispose(this.#finalizer);
469
+ this.#finalizer = null;
470
+ }
471
+ }
472
+ }
473
+
474
+ function socketUdpDispose(id) {
475
+ ioCall(SOCKET_UDP_DISPOSE, id, null);
476
+ }
477
+
478
+ const createUdpSocket = UdpSocket._create;
479
+ delete UdpSocket._create;
480
+
481
+ class IncomingDatagramStream {
482
+ #id;
483
+ #finalizer;
484
+ static _create(id) {
485
+ const stream = new IncomingDatagramStream();
486
+ stream.#id = id;
487
+ stream.#finalizer = registerDispose(
488
+ stream,
489
+ null,
490
+ id,
491
+ incomingDatagramStreamDispose
492
+ );
493
+ return stream;
494
+ }
495
+ receive(maxResults) {
496
+ return ioCall(
497
+ SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE,
498
+ this.#id,
499
+ maxResults
500
+ );
501
+ }
502
+ subscribe() {
503
+ return pollableCreate(
504
+ ioCall(SOCKET_DATAGRAM_STREAM_SUBSCRIBE, this.#id, null),
505
+ this
506
+ );
507
+ }
508
+ [symbolDispose]() {
509
+ if (this.#finalizer) {
510
+ earlyDispose(this.#finalizer);
511
+ this.#finalizer = null;
512
+ }
513
+ }
514
+ }
515
+
516
+ function incomingDatagramStreamDispose(id) {
517
+ ioCall(SOCKET_DATAGRAM_STREAM_DISPOSE, id, null);
518
+ }
519
+
520
+ const incomingDatagramStreamCreate = IncomingDatagramStream._create;
521
+ delete IncomingDatagramStream._create;
522
+
523
+ class OutgoingDatagramStream {
524
+ #id = 0;
525
+ #finalizer;
526
+ static _create(id) {
527
+ const stream = new OutgoingDatagramStream();
528
+ stream.#id = id;
529
+ stream.#finalizer = registerDispose(
530
+ stream,
531
+ null,
532
+ id,
533
+ outgoingDatagramStreamDispose
534
+ );
535
+ return stream;
536
+ }
537
+ checkSend() {
538
+ return ioCall(SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND, this.#id, null);
539
+ }
540
+ send(datagrams) {
541
+ return ioCall(SOCKET_OUTGOING_DATAGRAM_STREAM_SEND, this.#id, datagrams);
542
+ }
543
+ subscribe() {
544
+ return pollableCreate(
545
+ ioCall(SOCKET_DATAGRAM_STREAM_SUBSCRIBE, this.#id, null),
546
+ this
547
+ );
548
+ }
549
+ [symbolDispose]() {
550
+ if (this.#finalizer) {
551
+ earlyDispose(this.#finalizer);
552
+ this.#finalizer = null;
553
+ }
554
+ }
555
+ }
556
+ function outgoingDatagramStreamDispose(id) {
557
+ ioCall(SOCKET_DATAGRAM_STREAM_DISPOSE, id, null);
558
+ }
559
+
560
+ const outgoingDatagramStreamCreate = OutgoingDatagramStream._create;
561
+ delete OutgoingDatagramStream._create;
562
+
563
+ export const udpCreateSocket = {
564
+ createUdpSocket,
565
+ };
566
+
567
+ export const udp = {
568
+ UdpSocket,
569
+ OutgoingDatagramStream,
570
+ IncomingDatagramStream,
571
+ };
@@ -33,7 +33,6 @@ import {
33
33
  } from "node:worker_threads";
34
34
 
35
35
  const DEFAULT_WORKER_BUFFER_SIZE = 1024;
36
- const syncFnCache = new Map();
37
36
 
38
37
  function extractProperties(object) {
39
38
  if (object && typeof object === "object") {
@@ -45,61 +44,45 @@ function extractProperties(object) {
45
44
  }
46
45
  }
47
46
 
48
- export function createSyncFn(workerPath, bufferSizeOrOptions, timeout) {
47
+ const CALL_TIMEOUT = undefined;
48
+
49
+ export function createSyncFn(workerPath, debug, callbackHandler) {
49
50
  if (!path.isAbsolute(workerPath)) {
50
51
  throw new Error("`workerPath` must be absolute");
51
52
  }
52
- const cachedSyncFn = syncFnCache.get(workerPath);
53
- if (cachedSyncFn) {
54
- return cachedSyncFn;
55
- }
56
- const syncFn = startWorkerThread(
57
- workerPath,
58
- typeof bufferSizeOrOptions === "number"
59
- ? { bufferSize: bufferSizeOrOptions, timeout }
60
- : bufferSizeOrOptions
61
- );
62
- syncFnCache.set(workerPath, syncFn);
63
- return syncFn;
64
- }
65
-
66
- function startWorkerThread(
67
- workerPath,
68
- {
69
- bufferSize = DEFAULT_WORKER_BUFFER_SIZE,
70
- timeout = undefined,
71
- execArgv = [],
72
- } = {}
73
- ) {
74
53
  const { port1: mainPort, port2: workerPort } = new MessageChannel();
75
54
  const worker = new Worker(workerPath, {
76
- workerData: { workerPort },
55
+ workerData: { workerPort, debug },
77
56
  transferList: [workerPort],
78
- execArgv: execArgv
57
+ execArgv: []
58
+ });
59
+ worker.on('message', ({ type, id, payload }) => {
60
+ if (!type)
61
+ throw new Error('Internal error: Expected a type of a worker callback');
62
+ callbackHandler(type, id, payload);
79
63
  });
80
64
  let nextID = 0;
81
65
  const syncFn = (...args) => {
82
- const id = nextID++;
83
- const sharedBuffer = new SharedArrayBuffer(bufferSize);
66
+ const cid = nextID++;
67
+ const sharedBuffer = new SharedArrayBuffer(DEFAULT_WORKER_BUFFER_SIZE);
84
68
  const sharedBufferView = new Int32Array(sharedBuffer);
85
- const msg = { sharedBuffer, id, args };
69
+ const msg = { sharedBuffer, cid, args };
86
70
  worker.postMessage(msg);
87
- const status = Atomics.wait(sharedBufferView, 0, 0, timeout);
71
+ const status = Atomics.wait(sharedBufferView, 0, 0, CALL_TIMEOUT);
88
72
  if (!["ok", "not-equal"].includes(status)) {
89
73
  throw new Error("Internal error: Atomics.wait() failed: " + status);
90
74
  }
91
75
  const {
92
- id: id2,
76
+ cid: cid2,
93
77
  result,
94
78
  error,
95
79
  properties,
96
80
  } = receiveMessageOnPort(mainPort).message;
97
- if (id !== id2) {
98
- throw new Error(`Internal error: Expected id ${id} but got id ${id2}`);
81
+ if (cid !== cid2) {
82
+ throw new Error(`Internal error: Expected id ${cid} but got id ${cid2}`);
99
83
  }
100
84
  if (error) {
101
- if (error instanceof Error)
102
- throw Object.assign(error, properties);
85
+ if (error instanceof Error) throw Object.assign(error, properties);
103
86
  throw error;
104
87
  }
105
88
  return result;
@@ -112,16 +95,16 @@ export function runAsWorker(fn) {
112
95
  if (!workerData) {
113
96
  return;
114
97
  }
115
- const { workerPort } = workerData;
98
+ const { workerPort, debug } = workerData;
116
99
  try {
117
- parentPort.on("message", ({ sharedBuffer, id, args }) => {
100
+ parentPort.on("message", ({ sharedBuffer, cid, args }) => {
118
101
  (async () => {
119
102
  const sharedBufferView = new Int32Array(sharedBuffer);
120
103
  let msg;
121
104
  try {
122
- msg = { id, result: await fn(...args) };
105
+ msg = { cid, result: await fn(...args) };
123
106
  } catch (error) {
124
- msg = { id, error, properties: extractProperties(error) };
107
+ msg = { cid, error, properties: extractProperties(error) };
125
108
  }
126
109
  workerPort.postMessage(msg);
127
110
  Atomics.add(sharedBufferView, 0, 1);
@@ -129,10 +112,10 @@ export function runAsWorker(fn) {
129
112
  })();
130
113
  });
131
114
  } catch (error) {
132
- parentPort.on("message", ({ sharedBuffer, id }) => {
115
+ parentPort.on("message", ({ sharedBuffer, cid }) => {
133
116
  const sharedBufferView = new Int32Array(sharedBuffer);
134
117
  workerPort.postMessage({
135
- id,
118
+ cid,
136
119
  error,
137
120
  properties: extractProperties(error),
138
121
  });
@@ -140,4 +123,5 @@ export function runAsWorker(fn) {
140
123
  Atomics.notify(sharedBufferView, 0);
141
124
  });
142
125
  }
126
+ return debug;
143
127
  }