@bytecodealliance/preview2-shim 0.18.1 → 0.19.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.
Files changed (81) hide show
  1. package/dist/browser/cli.d.ts +16 -0
  2. package/dist/browser/cli.js +109 -0
  3. package/dist/browser/clocks.d.ts +3 -0
  4. package/dist/browser/clocks.js +36 -0
  5. package/dist/browser/config.d.ts +2 -0
  6. package/{lib → dist}/browser/config.js +2 -4
  7. package/dist/browser/environment.d.ts +5 -0
  8. package/dist/browser/environment.js +24 -0
  9. package/dist/browser/filesystem.d.ts +132 -0
  10. package/dist/browser/filesystem.js +464 -0
  11. package/dist/browser/http.d.ts +4 -0
  12. package/dist/browser/http.js +643 -0
  13. package/dist/browser/index.d.ts +7 -0
  14. package/dist/browser/index.js +7 -0
  15. package/dist/browser/io.d.ts +58 -0
  16. package/dist/browser/io.js +205 -0
  17. package/dist/browser/random.d.ts +4 -0
  18. package/dist/browser/random.js +49 -0
  19. package/dist/browser/sockets.d.ts +8 -0
  20. package/dist/browser/sockets.js +66 -0
  21. package/dist/common/instantiation.d.ts +97 -0
  22. package/dist/common/instantiation.js +227 -0
  23. package/dist/io/calls.d.ts +91 -0
  24. package/{lib → dist}/io/calls.js +4 -19
  25. package/dist/io/worker-http.d.ts +17 -0
  26. package/dist/io/worker-http.js +192 -0
  27. package/dist/io/worker-io.d.ts +84 -0
  28. package/dist/io/worker-io.js +375 -0
  29. package/dist/io/worker-socket-tcp.d.ts +34 -0
  30. package/dist/io/worker-socket-tcp.js +251 -0
  31. package/dist/io/worker-socket-udp.d.ts +54 -0
  32. package/dist/io/worker-socket-udp.js +492 -0
  33. package/dist/io/worker-sockets.d.ts +32 -0
  34. package/dist/io/worker-sockets.js +265 -0
  35. package/dist/io/worker-thread.d.ts +73 -0
  36. package/dist/io/worker-thread.js +791 -0
  37. package/dist/nodejs/cli.d.ts +30 -0
  38. package/dist/nodejs/cli.js +86 -0
  39. package/dist/nodejs/clocks.d.ts +3 -0
  40. package/dist/nodejs/clocks.js +61 -0
  41. package/dist/nodejs/filesystem.d.ts +113 -0
  42. package/dist/nodejs/filesystem.js +758 -0
  43. package/dist/nodejs/http.d.ts +82 -0
  44. package/dist/nodejs/http.js +674 -0
  45. package/dist/nodejs/index.d.ts +7 -0
  46. package/dist/nodejs/index.js +7 -0
  47. package/dist/nodejs/io.d.ts +1 -0
  48. package/dist/nodejs/io.js +1 -0
  49. package/dist/nodejs/random.d.ts +4 -0
  50. package/dist/nodejs/random.js +42 -0
  51. package/dist/nodejs/sockets.d.ts +21 -0
  52. package/dist/nodejs/sockets.js +482 -0
  53. package/dist/synckit/index.d.ts +2 -0
  54. package/dist/synckit/index.js +117 -0
  55. package/package.json +26 -13
  56. package/types/instantiation.d.ts +7 -7
  57. package/lib/browser/cli.js +0 -135
  58. package/lib/browser/clocks.js +0 -39
  59. package/lib/browser/environment.js +0 -29
  60. package/lib/browser/filesystem.js +0 -503
  61. package/lib/browser/http.js +0 -707
  62. package/lib/browser/index.js +0 -9
  63. package/lib/browser/io.js +0 -262
  64. package/lib/browser/random.js +0 -56
  65. package/lib/browser/sockets.js +0 -88
  66. package/lib/common/instantiation.js +0 -253
  67. package/lib/io/worker-http.js +0 -206
  68. package/lib/io/worker-io.js +0 -468
  69. package/lib/io/worker-socket-tcp.js +0 -331
  70. package/lib/io/worker-socket-udp.js +0 -587
  71. package/lib/io/worker-sockets.js +0 -364
  72. package/lib/io/worker-thread.js +0 -1051
  73. package/lib/nodejs/cli.js +0 -109
  74. package/lib/nodejs/clocks.js +0 -67
  75. package/lib/nodejs/filesystem.js +0 -829
  76. package/lib/nodejs/http.js +0 -764
  77. package/lib/nodejs/index.js +0 -9
  78. package/lib/nodejs/io.js +0 -1
  79. package/lib/nodejs/random.js +0 -49
  80. package/lib/nodejs/sockets.js +0 -565
  81. package/lib/synckit/index.js +0 -127
@@ -0,0 +1,42 @@
1
+ import { randomBytes, randomFillSync } from "node:crypto";
2
+ export const insecure = {
3
+ getInsecureRandomBytes: getRandomBytes,
4
+ getInsecureRandomU64() {
5
+ return new BigUint64Array(randomBytes(8).buffer)[0];
6
+ },
7
+ };
8
+ let insecureSeedValue1, insecureSeedValue2;
9
+ export const insecureSeed = {
10
+ insecureSeed() {
11
+ if (insecureSeedValue1 === undefined) {
12
+ insecureSeedValue1 = random.getRandomU64();
13
+ insecureSeedValue2 = random.getRandomU64();
14
+ }
15
+ return [insecureSeedValue1, insecureSeedValue2];
16
+ },
17
+ };
18
+ export const random = {
19
+ getRandomBytes,
20
+ getRandomU64() {
21
+ return new BigUint64Array(randomBytes(8).buffer)[0];
22
+ },
23
+ };
24
+ function getRandomBytes(len) {
25
+ return randomBytes(Number(len));
26
+ }
27
+ getRandomBytes[Symbol.for("cabiLower")] = ({ memory, realloc }) => {
28
+ let buf32 = new Uint32Array(memory.buffer);
29
+ return function randomBytesImpl(len, retptr) {
30
+ len = Number(len);
31
+ const ptr = realloc(0, 0, 1, len);
32
+ randomFillSync(memory.buffer, ptr, len);
33
+ if (memory.buffer !== buf32.buffer) {
34
+ buf32 = new Uint32Array(memory.buffer);
35
+ }
36
+ if (retptr % 4) {
37
+ throw new Error("wasi-io trap: retptr not aligned");
38
+ }
39
+ buf32[retptr >> 2] = ptr;
40
+ buf32[(retptr >> 2) + 1] = len;
41
+ };
42
+ };
@@ -0,0 +1,21 @@
1
+ import type { instanceNetwork as InstanceNetworkNamespace, ipNameLookup as IpNameLookupNamespace, network as NetworkNamespace, tcpCreateSocket as TcpCreateSocketNamespace, tcp as TcpNamespace, udpCreateSocket as UdpCreateSocketNamespace, udp as UdpNamespace } from "../../types/sockets.js";
2
+ declare class Network implements NetworkNamespace.Network {
3
+ #private;
4
+ static _denyDnsLookup(network?: Network): void;
5
+ static _denyTcp(network?: Network): void;
6
+ static _denyUdp(network?: Network): void;
7
+ static _mayDnsLookup(network?: Network): boolean;
8
+ static _mayTcp(network?: Network): boolean;
9
+ static _mayUdp(network?: Network): boolean;
10
+ }
11
+ export declare const _denyDnsLookup: typeof Network._denyDnsLookup;
12
+ export declare const _denyTcp: typeof Network._denyTcp;
13
+ export declare const _denyUdp: typeof Network._denyUdp;
14
+ export declare const instanceNetwork: typeof InstanceNetworkNamespace;
15
+ export declare const network: typeof NetworkNamespace;
16
+ export declare const ipNameLookup: typeof IpNameLookupNamespace;
17
+ export declare const tcpCreateSocket: typeof TcpCreateSocketNamespace;
18
+ export declare const tcp: typeof TcpNamespace;
19
+ export declare const udpCreateSocket: typeof UdpCreateSocketNamespace;
20
+ export declare const udp: typeof UdpNamespace;
21
+ export {};
@@ -0,0 +1,482 @@
1
+ import { SOCKET_DATAGRAM_STREAM_DISPOSE, SOCKET_DATAGRAM_STREAM_SUBSCRIBE, SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE, SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND, SOCKET_OUTGOING_DATAGRAM_STREAM_SEND, SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST, SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST, SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST, SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST, SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE, SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE, SOCKET_TCP_ACCEPT, SOCKET_TCP_BIND_FINISH, SOCKET_TCP_BIND_START, SOCKET_TCP_CONNECT_FINISH, SOCKET_TCP_CONNECT_START, SOCKET_TCP_CREATE_HANDLE, SOCKET_TCP_DISPOSE, SOCKET_TCP_GET_LOCAL_ADDRESS, SOCKET_TCP_GET_REMOTE_ADDRESS, SOCKET_TCP_IS_LISTENING, SOCKET_TCP_LISTEN_FINISH, SOCKET_TCP_LISTEN_START, SOCKET_TCP_SET_KEEP_ALIVE, SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE, SOCKET_TCP_SHUTDOWN, SOCKET_TCP_SUBSCRIBE, SOCKET_TCP, SOCKET_UDP_BIND_FINISH, SOCKET_UDP_BIND_START, SOCKET_UDP_CREATE_HANDLE, SOCKET_UDP_DISPOSE, SOCKET_UDP_GET_LOCAL_ADDRESS, SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE, SOCKET_UDP_GET_REMOTE_ADDRESS, SOCKET_UDP_GET_SEND_BUFFER_SIZE, SOCKET_UDP_GET_UNICAST_HOP_LIMIT, SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE, SOCKET_UDP_SET_SEND_BUFFER_SIZE, SOCKET_UDP_SET_UNICAST_HOP_LIMIT, SOCKET_UDP_STREAM, SOCKET_UDP_SUBSCRIBE, } from "../io/calls.js";
2
+ import { earlyDispose, inputStreamCreate, ioCall, outputStreamCreate, pollableCreate, registerDispose, } from "../io/worker-io.js";
3
+ const symbolDispose = Symbol.dispose || Symbol.for("dispose");
4
+ // Network class privately stores capabilities
5
+ class Network {
6
+ #allowDnsLookup = true;
7
+ #allowTcp = true;
8
+ #allowUdp = true;
9
+ static _denyDnsLookup(network = defaultNetwork) {
10
+ network.#allowDnsLookup = false;
11
+ }
12
+ static _denyTcp(network = defaultNetwork) {
13
+ network.#allowTcp = false;
14
+ }
15
+ static _denyUdp(network = defaultNetwork) {
16
+ network.#allowUdp = false;
17
+ }
18
+ static _mayDnsLookup(network = defaultNetwork) {
19
+ return network.#allowDnsLookup;
20
+ }
21
+ static _mayTcp(network = defaultNetwork) {
22
+ return network.#allowTcp;
23
+ }
24
+ static _mayUdp(network = defaultNetwork) {
25
+ return network.#allowUdp;
26
+ }
27
+ }
28
+ export const _denyDnsLookup = Network._denyDnsLookup;
29
+ // @ts-expect-error - Deleting static method
30
+ delete Network._denyDnsLookup;
31
+ export const _denyTcp = Network._denyTcp;
32
+ // @ts-expect-error - Deleting static method
33
+ delete Network._denyTcp;
34
+ export const _denyUdp = Network._denyUdp;
35
+ // @ts-expect-error - Deleting static method
36
+ delete Network._denyUdp;
37
+ const mayDnsLookup = Network._mayDnsLookup;
38
+ // @ts-expect-error - Deleting static method
39
+ delete Network._mayDnsLookup;
40
+ const mayTcp = Network._mayTcp;
41
+ // @ts-expect-error - Deleting static method
42
+ delete Network._mayTcp;
43
+ const mayUdp = Network._mayUdp;
44
+ // @ts-expect-error - Deleting static method
45
+ delete Network._mayUdp;
46
+ const defaultNetwork = new Network();
47
+ export const instanceNetwork = {
48
+ instanceNetwork() {
49
+ return defaultNetwork;
50
+ },
51
+ };
52
+ export const network = {
53
+ Network,
54
+ };
55
+ class ResolveAddressStream {
56
+ #id = 0;
57
+ #data = null;
58
+ #curItem = 0;
59
+ #error = false;
60
+ #finalizer;
61
+ resolveNextAddress() {
62
+ if (!this.#data) {
63
+ const res = ioCall(SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST, this.#id, null);
64
+ this.#data = res.val;
65
+ this.#error = res.tag === "err";
66
+ }
67
+ if (this.#error) {
68
+ throw this.#data;
69
+ }
70
+ if (this.#data && this.#curItem < this.#data.length) {
71
+ return this.#data[this.#curItem++];
72
+ }
73
+ return undefined;
74
+ }
75
+ subscribe() {
76
+ return pollableCreate(ioCall(SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST, this.#id, null), this);
77
+ }
78
+ static _resolveAddresses(network, name) {
79
+ if (!(network instanceof Network) || !mayDnsLookup(network)) {
80
+ throw "permanent-resolver-failure";
81
+ }
82
+ const res = new ResolveAddressStream();
83
+ res.#id = ioCall(SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST, null, name);
84
+ res.#finalizer = registerDispose(res, null, res.#id, resolveAddressStreamDispose);
85
+ return res;
86
+ }
87
+ [symbolDispose]() {
88
+ if (this.#finalizer) {
89
+ earlyDispose(this.#finalizer);
90
+ this.#finalizer = null;
91
+ }
92
+ }
93
+ }
94
+ function resolveAddressStreamDispose(id) {
95
+ ioCall(SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST, id, null);
96
+ }
97
+ const resolveAddresses = ResolveAddressStream._resolveAddresses;
98
+ // @ts-expect-error - Deleting static method
99
+ delete ResolveAddressStream._resolveAddresses;
100
+ export const ipNameLookup = {
101
+ ResolveAddressStream,
102
+ resolveAddresses,
103
+ };
104
+ class TcpSocket {
105
+ #id = 0;
106
+ #network;
107
+ #family;
108
+ #finalizer;
109
+ #options = {
110
+ // defaults per https://nodejs.org/docs/latest/api/net.html#socketsetkeepaliveenable-initialdelay
111
+ keepAlive: false,
112
+ // Node.js doesn't give us the ability to detect the OS default,
113
+ // therefore we hardcode the default value instead of using the OS default,
114
+ // since we would never be able to report it as a return value otherwise.
115
+ // We could make this configurable as a global JCO implementation configuration
116
+ // instead.
117
+ keepAliveIdleTime: 7200000000000n,
118
+ // The following options are NOT configurable in Node.js!
119
+ // Any configurations set will respond correctly, but underneath retain
120
+ // system / Node.js defaults.
121
+ keepAliveInterval: 1000000000n,
122
+ keepAliveCount: 10,
123
+ hopLimit: 1,
124
+ // For sendBufferSize and receiveBufferSize we can at least
125
+ // use the system defaults, but still we can't support setting them.
126
+ sendBufferSize: undefined,
127
+ receiveBufferSize: undefined,
128
+ };
129
+ static _create(addressFamily, id) {
130
+ const socket = new TcpSocket();
131
+ socket.#id = id;
132
+ socket.#family = addressFamily;
133
+ socket.#finalizer = registerDispose(socket, null, id, socketTcpDispose);
134
+ return socket;
135
+ }
136
+ startBind(network, localAddress) {
137
+ if (!mayTcp(network)) {
138
+ throw "access-denied";
139
+ }
140
+ ioCall(SOCKET_TCP_BIND_START, this.#id, {
141
+ localAddress,
142
+ family: this.#family,
143
+ });
144
+ this.#network = network;
145
+ }
146
+ finishBind() {
147
+ ioCall(SOCKET_TCP_BIND_FINISH, this.#id, null);
148
+ }
149
+ startConnect(network, remoteAddress) {
150
+ if (this.#network && network !== this.#network) {
151
+ throw "invalid-argument";
152
+ }
153
+ if (!mayTcp(network)) {
154
+ throw "access-denied";
155
+ }
156
+ ioCall(SOCKET_TCP_CONNECT_START, this.#id, {
157
+ remoteAddress,
158
+ family: this.#family,
159
+ });
160
+ this.#network = network;
161
+ }
162
+ finishConnect() {
163
+ const [inputStreamId, outputStreamId] = ioCall(SOCKET_TCP_CONNECT_FINISH, this.#id, null);
164
+ return [
165
+ inputStreamCreate(SOCKET_TCP, inputStreamId),
166
+ outputStreamCreate(SOCKET_TCP, outputStreamId),
167
+ ];
168
+ }
169
+ startListen() {
170
+ if (!mayTcp(this.#network)) {
171
+ throw "access-denied";
172
+ }
173
+ ioCall(SOCKET_TCP_LISTEN_START, this.#id, null);
174
+ }
175
+ finishListen() {
176
+ ioCall(SOCKET_TCP_LISTEN_FINISH, this.#id, null);
177
+ }
178
+ accept() {
179
+ if (!mayTcp(this.#network)) {
180
+ throw "access-denied";
181
+ }
182
+ const [socketId, inputStreamId, outputStreamId] = ioCall(SOCKET_TCP_ACCEPT, this.#id, null);
183
+ const socket = tcpSocketCreate(this.#family, socketId);
184
+ Object.assign(socket.#options, this.#options);
185
+ return [
186
+ socket,
187
+ inputStreamCreate(SOCKET_TCP, inputStreamId),
188
+ outputStreamCreate(SOCKET_TCP, outputStreamId),
189
+ ];
190
+ }
191
+ localAddress() {
192
+ return ioCall(SOCKET_TCP_GET_LOCAL_ADDRESS, this.#id, null);
193
+ }
194
+ remoteAddress() {
195
+ return ioCall(SOCKET_TCP_GET_REMOTE_ADDRESS, this.#id, null);
196
+ }
197
+ isListening() {
198
+ return ioCall(SOCKET_TCP_IS_LISTENING, this.#id, null);
199
+ }
200
+ addressFamily() {
201
+ return this.#family;
202
+ }
203
+ setListenBacklogSize(value) {
204
+ if (value === 0n) {
205
+ throw "invalid-argument";
206
+ }
207
+ ioCall(SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE, this.#id, value);
208
+ }
209
+ keepAliveEnabled() {
210
+ return this.#options.keepAlive;
211
+ }
212
+ setKeepAliveEnabled(value) {
213
+ this.#options.keepAlive = value;
214
+ ioCall(SOCKET_TCP_SET_KEEP_ALIVE, this.#id, {
215
+ keepAlive: value,
216
+ keepAliveIdleTime: this.#options.keepAliveIdleTime,
217
+ });
218
+ }
219
+ keepAliveIdleTime() {
220
+ return this.#options.keepAliveIdleTime;
221
+ }
222
+ setKeepAliveIdleTime(value) {
223
+ if (value < 1n) {
224
+ throw "invalid-argument";
225
+ }
226
+ if (value < 1000000000n) {
227
+ value = 1000000000n;
228
+ }
229
+ if (value !== this.#options.keepAliveIdleTime) {
230
+ this.#options.keepAliveIdleTime = value;
231
+ if (this.#options.keepAlive) {
232
+ ioCall(SOCKET_TCP_SET_KEEP_ALIVE, this.#id, {
233
+ keepAlive: true,
234
+ keepAliveIdleTime: this.#options.keepAliveIdleTime,
235
+ });
236
+ }
237
+ }
238
+ }
239
+ keepAliveInterval() {
240
+ return this.#options.keepAliveInterval;
241
+ }
242
+ setKeepAliveInterval(value) {
243
+ if (value < 1n) {
244
+ throw "invalid-argument";
245
+ }
246
+ this.#options.keepAliveInterval = value;
247
+ }
248
+ keepAliveCount() {
249
+ return this.#options.keepAliveCount;
250
+ }
251
+ setKeepAliveCount(value) {
252
+ if (value < 1) {
253
+ throw "invalid-argument";
254
+ }
255
+ this.#options.keepAliveCount = value;
256
+ }
257
+ hopLimit() {
258
+ return this.#options.hopLimit;
259
+ }
260
+ setHopLimit(value) {
261
+ if (value < 1) {
262
+ throw "invalid-argument";
263
+ }
264
+ this.#options.hopLimit = value;
265
+ }
266
+ receiveBufferSize() {
267
+ if (!this.#options.receiveBufferSize) {
268
+ this.#options.receiveBufferSize = ioCall(SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE, null, null);
269
+ }
270
+ return this.#options.receiveBufferSize;
271
+ }
272
+ setReceiveBufferSize(value) {
273
+ if (value === 0n) {
274
+ throw "invalid-argument";
275
+ }
276
+ this.#options.receiveBufferSize = value;
277
+ }
278
+ sendBufferSize() {
279
+ if (!this.#options.sendBufferSize) {
280
+ this.#options.sendBufferSize = ioCall(SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE, null, null);
281
+ }
282
+ return this.#options.sendBufferSize;
283
+ }
284
+ setSendBufferSize(value) {
285
+ if (value === 0n) {
286
+ throw "invalid-argument";
287
+ }
288
+ this.#options.sendBufferSize = value;
289
+ }
290
+ subscribe() {
291
+ return pollableCreate(ioCall(SOCKET_TCP_SUBSCRIBE, this.#id, null), this);
292
+ }
293
+ shutdown(shutdownType) {
294
+ ioCall(SOCKET_TCP_SHUTDOWN, this.#id, shutdownType);
295
+ }
296
+ [symbolDispose]() {
297
+ if (this.#finalizer) {
298
+ earlyDispose(this.#finalizer);
299
+ this.#finalizer = null;
300
+ }
301
+ }
302
+ }
303
+ function socketTcpDispose(id) {
304
+ ioCall(SOCKET_TCP_DISPOSE, id, null);
305
+ }
306
+ const tcpSocketCreate = TcpSocket._create;
307
+ // @ts-expect-error - Deleting static method
308
+ delete TcpSocket._create;
309
+ export const tcpCreateSocket = {
310
+ createTcpSocket(addressFamily) {
311
+ if (addressFamily !== "ipv4" && addressFamily !== "ipv6") {
312
+ throw "not-supported";
313
+ }
314
+ return tcpSocketCreate(addressFamily, ioCall(SOCKET_TCP_CREATE_HANDLE, null, null));
315
+ },
316
+ };
317
+ export const tcp = {
318
+ TcpSocket,
319
+ };
320
+ class UdpSocket {
321
+ #id = 0;
322
+ #network;
323
+ #family;
324
+ #finalizer;
325
+ static _create(addressFamily) {
326
+ if (addressFamily !== "ipv4" && addressFamily !== "ipv6") {
327
+ throw "not-supported";
328
+ }
329
+ const socket = new UdpSocket();
330
+ socket.#id = ioCall(SOCKET_UDP_CREATE_HANDLE, null, {
331
+ family: addressFamily,
332
+ // we always set the unicastHopLimit, because there is no
333
+ // getter but only a setter for this in Node.js, so it is the
334
+ // only way to guarantee the consistent value
335
+ unicastHopLimit: 64,
336
+ });
337
+ socket.#family = addressFamily;
338
+ socket.#finalizer = registerDispose(socket, null, socket.#id, socketUdpDispose);
339
+ return socket;
340
+ }
341
+ startBind(network, localAddress) {
342
+ if (!mayUdp(network)) {
343
+ throw "access-denied";
344
+ }
345
+ ioCall(SOCKET_UDP_BIND_START, this.#id, {
346
+ localAddress,
347
+ family: this.#family,
348
+ });
349
+ this.#network = network;
350
+ }
351
+ finishBind() {
352
+ ioCall(SOCKET_UDP_BIND_FINISH, this.#id, null);
353
+ }
354
+ stream(remoteAddress) {
355
+ if (!mayUdp(this.#network)) {
356
+ throw "access-denied";
357
+ }
358
+ const [incomingDatagramStreamId, outgoingDatagramStreamId] = ioCall(SOCKET_UDP_STREAM, this.#id, remoteAddress);
359
+ return [
360
+ incomingDatagramStreamCreate(incomingDatagramStreamId),
361
+ outgoingDatagramStreamCreate(outgoingDatagramStreamId),
362
+ ];
363
+ }
364
+ localAddress() {
365
+ return ioCall(SOCKET_UDP_GET_LOCAL_ADDRESS, this.#id);
366
+ }
367
+ remoteAddress() {
368
+ return ioCall(SOCKET_UDP_GET_REMOTE_ADDRESS, this.#id);
369
+ }
370
+ addressFamily() {
371
+ return this.#family;
372
+ }
373
+ unicastHopLimit() {
374
+ return ioCall(SOCKET_UDP_GET_UNICAST_HOP_LIMIT, this.#id);
375
+ }
376
+ setUnicastHopLimit(value) {
377
+ if (value < 1) {
378
+ throw "invalid-argument";
379
+ }
380
+ ioCall(SOCKET_UDP_SET_UNICAST_HOP_LIMIT, this.#id, value);
381
+ }
382
+ receiveBufferSize() {
383
+ return ioCall(SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE, this.#id);
384
+ }
385
+ setReceiveBufferSize(value) {
386
+ if (value === 0n) {
387
+ throw "invalid-argument";
388
+ }
389
+ ioCall(SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE, this.#id, value);
390
+ }
391
+ sendBufferSize() {
392
+ return ioCall(SOCKET_UDP_GET_SEND_BUFFER_SIZE, this.#id);
393
+ }
394
+ setSendBufferSize(value) {
395
+ if (value === 0n) {
396
+ throw "invalid-argument";
397
+ }
398
+ ioCall(SOCKET_UDP_SET_SEND_BUFFER_SIZE, this.#id, value);
399
+ }
400
+ subscribe() {
401
+ return pollableCreate(ioCall(SOCKET_UDP_SUBSCRIBE, this.#id, null), this);
402
+ }
403
+ [symbolDispose]() {
404
+ if (this.#finalizer) {
405
+ earlyDispose(this.#finalizer);
406
+ this.#finalizer = null;
407
+ }
408
+ }
409
+ }
410
+ function socketUdpDispose(id) {
411
+ ioCall(SOCKET_UDP_DISPOSE, id, null);
412
+ }
413
+ const createUdpSocket = UdpSocket._create;
414
+ // @ts-expect-error - Deleting static method
415
+ delete UdpSocket._create;
416
+ class IncomingDatagramStream {
417
+ #id = 0;
418
+ #finalizer;
419
+ static _create(id) {
420
+ const stream = new IncomingDatagramStream();
421
+ stream.#id = id;
422
+ stream.#finalizer = registerDispose(stream, null, id, incomingDatagramStreamDispose);
423
+ return stream;
424
+ }
425
+ receive(maxResults) {
426
+ return ioCall(SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE, this.#id, maxResults);
427
+ }
428
+ subscribe() {
429
+ return pollableCreate(ioCall(SOCKET_DATAGRAM_STREAM_SUBSCRIBE, this.#id, null), this);
430
+ }
431
+ [symbolDispose]() {
432
+ if (this.#finalizer) {
433
+ earlyDispose(this.#finalizer);
434
+ this.#finalizer = null;
435
+ }
436
+ }
437
+ }
438
+ function incomingDatagramStreamDispose(id) {
439
+ ioCall(SOCKET_DATAGRAM_STREAM_DISPOSE, id, null);
440
+ }
441
+ const incomingDatagramStreamCreate = IncomingDatagramStream._create;
442
+ // @ts-expect-error - Deleting static method
443
+ delete IncomingDatagramStream._create;
444
+ class OutgoingDatagramStream {
445
+ #id = 0;
446
+ #finalizer;
447
+ static _create(id) {
448
+ const stream = new OutgoingDatagramStream();
449
+ stream.#id = id;
450
+ stream.#finalizer = registerDispose(stream, null, id, outgoingDatagramStreamDispose);
451
+ return stream;
452
+ }
453
+ checkSend() {
454
+ return ioCall(SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND, this.#id, null);
455
+ }
456
+ send(datagrams) {
457
+ return ioCall(SOCKET_OUTGOING_DATAGRAM_STREAM_SEND, this.#id, datagrams);
458
+ }
459
+ subscribe() {
460
+ return pollableCreate(ioCall(SOCKET_DATAGRAM_STREAM_SUBSCRIBE, this.#id, null), this);
461
+ }
462
+ [symbolDispose]() {
463
+ if (this.#finalizer) {
464
+ earlyDispose(this.#finalizer);
465
+ this.#finalizer = null;
466
+ }
467
+ }
468
+ }
469
+ function outgoingDatagramStreamDispose(id) {
470
+ ioCall(SOCKET_DATAGRAM_STREAM_DISPOSE, id, null);
471
+ }
472
+ const outgoingDatagramStreamCreate = OutgoingDatagramStream._create;
473
+ // @ts-expect-error - Deleting static method
474
+ delete OutgoingDatagramStream._create;
475
+ export const udpCreateSocket = {
476
+ createUdpSocket,
477
+ };
478
+ export const udp = {
479
+ UdpSocket,
480
+ OutgoingDatagramStream,
481
+ IncomingDatagramStream,
482
+ };
@@ -0,0 +1,2 @@
1
+ export declare function createSyncFn(workerPath: any, debug: any, callbackHandler: any): (...args: any[]) => any;
2
+ export declare function runAsWorker(fn: any): any;
@@ -0,0 +1,117 @@
1
+ // Based on: https://github.com/un-ts/synckit
2
+ /*
3
+ MIT License
4
+
5
+ Copyright (c) 2021 UnTS
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ */
25
+ import path from "node:path";
26
+ import { MessageChannel, Worker, receiveMessageOnPort, workerData, parentPort, } from "node:worker_threads";
27
+ const DEFAULT_WORKER_BUFFER_SIZE = 1024;
28
+ function extractProperties(object) {
29
+ if (object && typeof object === "object") {
30
+ const properties = {};
31
+ for (const key in object) {
32
+ properties[key] = object[key];
33
+ }
34
+ return properties;
35
+ }
36
+ }
37
+ const CALL_TIMEOUT = undefined;
38
+ export function createSyncFn(workerPath, debug, callbackHandler) {
39
+ if (!path.isAbsolute(workerPath)) {
40
+ throw new Error("`workerPath` must be absolute");
41
+ }
42
+ const { port1: mainPort, port2: workerPort } = new MessageChannel();
43
+ const worker = new Worker(workerPath, {
44
+ workerData: { workerPort, debug },
45
+ transferList: [workerPort],
46
+ execArgv: [],
47
+ });
48
+ worker.on("message", ({ type, id, payload }) => {
49
+ if (!type) {
50
+ throw new Error("Internal error: Expected a type of a worker callback");
51
+ }
52
+ callbackHandler(type, id, payload);
53
+ });
54
+ let nextID = 0;
55
+ const syncFn = (...args) => {
56
+ const cid = nextID++;
57
+ const sharedBuffer = new SharedArrayBuffer(DEFAULT_WORKER_BUFFER_SIZE);
58
+ const sharedBufferView = new Int32Array(sharedBuffer);
59
+ const msg = { sharedBuffer, cid, args };
60
+ worker.postMessage(msg);
61
+ const status = Atomics.wait(sharedBufferView, 0, 0, CALL_TIMEOUT);
62
+ if (!["ok", "not-equal"].includes(status)) {
63
+ throw new Error("Internal error: Atomics.wait() failed: " + status);
64
+ }
65
+ const { cid: cid2, result, error, properties } = receiveMessageOnPort(mainPort)?.message ?? {};
66
+ if (cid !== cid2) {
67
+ throw new Error(`Internal error: Expected id ${cid} but got id ${cid2}`);
68
+ }
69
+ if (error) {
70
+ if (error instanceof Error) {
71
+ throw Object.assign(error, properties);
72
+ }
73
+ throw error;
74
+ }
75
+ return result;
76
+ };
77
+ if (worker.unref) {
78
+ worker.unref();
79
+ }
80
+ return syncFn;
81
+ }
82
+ export function runAsWorker(fn) {
83
+ if (!workerData) {
84
+ return;
85
+ }
86
+ const { workerPort, debug } = workerData;
87
+ try {
88
+ parentPort?.on("message", ({ sharedBuffer, cid, args }) => {
89
+ (async () => {
90
+ const sharedBufferView = new Int32Array(sharedBuffer);
91
+ let msg;
92
+ try {
93
+ msg = { cid, result: await fn(...args) };
94
+ }
95
+ catch (error) {
96
+ msg = { cid, error, properties: extractProperties(error) };
97
+ }
98
+ workerPort.postMessage(msg);
99
+ Atomics.add(sharedBufferView, 0, 1);
100
+ Atomics.notify(sharedBufferView, 0);
101
+ })();
102
+ });
103
+ }
104
+ catch (error) {
105
+ parentPort?.on("message", ({ sharedBuffer, cid }) => {
106
+ const sharedBufferView = new Int32Array(sharedBuffer);
107
+ workerPort.postMessage({
108
+ cid,
109
+ error,
110
+ properties: extractProperties(error),
111
+ });
112
+ Atomics.add(sharedBufferView, 0, 1);
113
+ Atomics.notify(sharedBufferView, 0);
114
+ });
115
+ }
116
+ return debug;
117
+ }