@bytecodealliance/preview2-shim 0.17.2 → 0.17.4

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.
@@ -1,160 +1,163 @@
1
- import { createReadStream, createWriteStream } from "node:fs";
2
- import { hrtime, stderr, stdout } from "node:process";
3
- import { PassThrough } from "node:stream";
4
- import { format } from "node:util";
5
- import { runAsWorker } from "../synckit/index.js";
1
+ import { createReadStream, createWriteStream } from 'node:fs';
2
+ import { hrtime, stderr, stdout } from 'node:process';
3
+ import { PassThrough } from 'node:stream';
4
+ import { runAsWorker } from '../synckit/index.js';
6
5
  import {
7
- clearOutgoingResponse,
8
- createHttpRequest,
9
- setOutgoingResponse,
10
- startHttpServer,
11
- stopHttpServer,
12
- } from "./worker-http.js";
13
- import { Readable } from "node:stream";
14
- import { read } from "node:fs";
15
- import { nextTick } from "node:process";
6
+ clearOutgoingResponse,
7
+ createHttpRequest,
8
+ setOutgoingResponse,
9
+ startHttpServer,
10
+ stopHttpServer,
11
+ getHttpServerAddress,
12
+ } from './worker-http.js';
13
+ import { Readable } from 'node:stream';
14
+ import { read } from 'node:fs';
15
+ import { nextTick } from 'node:process';
16
16
  import {
17
- CALL_MASK,
18
- CALL_TYPE_MASK,
19
- CLOCKS_DURATION_SUBSCRIBE,
20
- CLOCKS_INSTANT_SUBSCRIBE,
21
- FILE,
22
- FUTURE_DISPOSE,
23
- FUTURE_SUBSCRIBE,
24
- FUTURE_TAKE_VALUE,
25
- HTTP,
26
- HTTP_CREATE_REQUEST,
27
- HTTP_OUTGOING_BODY_DISPOSE,
28
- HTTP_OUTPUT_STREAM_FINISH,
29
- HTTP_SERVER_CLEAR_OUTGOING_RESPONSE,
30
- HTTP_SERVER_SET_OUTGOING_RESPONSE,
31
- HTTP_SERVER_START,
32
- HTTP_SERVER_STOP,
33
- INPUT_STREAM_BLOCKING_READ,
34
- INPUT_STREAM_BLOCKING_SKIP,
35
- INPUT_STREAM_CREATE,
36
- INPUT_STREAM_DISPOSE,
37
- INPUT_STREAM_READ,
38
- INPUT_STREAM_SKIP,
39
- INPUT_STREAM_SUBSCRIBE,
40
- OUTPUT_STREAM_BLOCKING_FLUSH,
41
- OUTPUT_STREAM_BLOCKING_SPLICE,
42
- OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH,
43
- OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH,
44
- OUTPUT_STREAM_CHECK_WRITE,
45
- OUTPUT_STREAM_CREATE,
46
- OUTPUT_STREAM_DISPOSE,
47
- OUTPUT_STREAM_FLUSH,
48
- OUTPUT_STREAM_SPLICE,
49
- OUTPUT_STREAM_SUBSCRIBE,
50
- OUTPUT_STREAM_WRITE,
51
- OUTPUT_STREAM_WRITE_ZEROES,
52
- POLL_POLLABLE_BLOCK,
53
- POLL_POLLABLE_DISPOSE,
54
- POLL_POLLABLE_READY,
55
- POLL_POLL_LIST,
56
- SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST,
57
- SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST,
58
- SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST,
59
- SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST,
60
- SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE,
61
- SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE,
62
- SOCKET_TCP_ACCEPT,
63
- SOCKET_TCP_BIND_FINISH,
64
- SOCKET_TCP_BIND_START,
65
- SOCKET_TCP_CONNECT_FINISH,
66
- SOCKET_TCP_CONNECT_START,
67
- SOCKET_TCP_CREATE_HANDLE,
68
- SOCKET_TCP_DISPOSE,
69
- SOCKET_TCP_GET_LOCAL_ADDRESS,
70
- SOCKET_TCP_GET_REMOTE_ADDRESS,
71
- SOCKET_TCP_IS_LISTENING,
72
- SOCKET_TCP_LISTEN_FINISH,
73
- SOCKET_TCP_LISTEN_START,
74
- SOCKET_TCP_SET_KEEP_ALIVE,
75
- SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE,
76
- SOCKET_TCP_SHUTDOWN,
77
- SOCKET_TCP_SUBSCRIBE,
78
- SOCKET_UDP_BIND_FINISH,
79
- SOCKET_UDP_BIND_START,
80
- SOCKET_UDP_CREATE_HANDLE,
81
- SOCKET_UDP_DISPOSE,
82
- SOCKET_UDP_GET_LOCAL_ADDRESS,
83
- SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE,
84
- SOCKET_UDP_GET_REMOTE_ADDRESS,
85
- SOCKET_UDP_GET_SEND_BUFFER_SIZE,
86
- SOCKET_UDP_GET_UNICAST_HOP_LIMIT,
87
- SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE,
88
- SOCKET_UDP_SET_SEND_BUFFER_SIZE,
89
- SOCKET_UDP_SET_UNICAST_HOP_LIMIT,
90
- SOCKET_UDP_STREAM,
91
- SOCKET_UDP_SUBSCRIBE,
92
- SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE,
93
- SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND,
94
- SOCKET_OUTGOING_DATAGRAM_STREAM_SEND,
95
- SOCKET_DATAGRAM_STREAM_SUBSCRIBE,
96
- SOCKET_DATAGRAM_STREAM_DISPOSE,
97
- STDERR,
98
- STDIN,
99
- STDOUT,
100
- reverseMap,
101
- } from "./calls.js";
17
+ CALL_MASK,
18
+ CALL_TYPE_MASK,
19
+ CLOCKS_DURATION_SUBSCRIBE,
20
+ CLOCKS_INSTANT_SUBSCRIBE,
21
+ FILE,
22
+ FUTURE_DISPOSE,
23
+ FUTURE_SUBSCRIBE,
24
+ FUTURE_TAKE_VALUE,
25
+ HTTP,
26
+ HTTP_CREATE_REQUEST,
27
+ HTTP_OUTGOING_BODY_DISPOSE,
28
+ HTTP_OUTPUT_STREAM_FINISH,
29
+ HTTP_SERVER_CLEAR_OUTGOING_RESPONSE,
30
+ HTTP_SERVER_SET_OUTGOING_RESPONSE,
31
+ HTTP_SERVER_START,
32
+ HTTP_SERVER_STOP,
33
+ HTTP_SERVER_GET_ADDRESS,
34
+ INPUT_STREAM_BLOCKING_READ,
35
+ INPUT_STREAM_BLOCKING_SKIP,
36
+ INPUT_STREAM_CREATE,
37
+ INPUT_STREAM_DISPOSE,
38
+ INPUT_STREAM_READ,
39
+ INPUT_STREAM_SKIP,
40
+ INPUT_STREAM_SUBSCRIBE,
41
+ OUTPUT_STREAM_BLOCKING_FLUSH,
42
+ OUTPUT_STREAM_BLOCKING_SPLICE,
43
+ OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH,
44
+ OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH,
45
+ OUTPUT_STREAM_CHECK_WRITE,
46
+ OUTPUT_STREAM_CREATE,
47
+ OUTPUT_STREAM_DISPOSE,
48
+ OUTPUT_STREAM_FLUSH,
49
+ OUTPUT_STREAM_SPLICE,
50
+ OUTPUT_STREAM_SUBSCRIBE,
51
+ OUTPUT_STREAM_WRITE,
52
+ OUTPUT_STREAM_WRITE_ZEROES,
53
+ POLL_POLLABLE_BLOCK,
54
+ POLL_POLLABLE_DISPOSE,
55
+ POLL_POLLABLE_READY,
56
+ POLL_POLL_LIST,
57
+ SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST,
58
+ SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST,
59
+ SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST,
60
+ SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST,
61
+ SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE,
62
+ SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE,
63
+ SOCKET_TCP_ACCEPT,
64
+ SOCKET_TCP_BIND_FINISH,
65
+ SOCKET_TCP_BIND_START,
66
+ SOCKET_TCP_CONNECT_FINISH,
67
+ SOCKET_TCP_CONNECT_START,
68
+ SOCKET_TCP_CREATE_HANDLE,
69
+ SOCKET_TCP_DISPOSE,
70
+ SOCKET_TCP_GET_LOCAL_ADDRESS,
71
+ SOCKET_TCP_GET_REMOTE_ADDRESS,
72
+ SOCKET_TCP_IS_LISTENING,
73
+ SOCKET_TCP_LISTEN_FINISH,
74
+ SOCKET_TCP_LISTEN_START,
75
+ SOCKET_TCP_SET_KEEP_ALIVE,
76
+ SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE,
77
+ SOCKET_TCP_SHUTDOWN,
78
+ SOCKET_TCP_SUBSCRIBE,
79
+ SOCKET_UDP_BIND_FINISH,
80
+ SOCKET_UDP_BIND_START,
81
+ SOCKET_UDP_CREATE_HANDLE,
82
+ SOCKET_UDP_DISPOSE,
83
+ SOCKET_UDP_GET_LOCAL_ADDRESS,
84
+ SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE,
85
+ SOCKET_UDP_GET_REMOTE_ADDRESS,
86
+ SOCKET_UDP_GET_SEND_BUFFER_SIZE,
87
+ SOCKET_UDP_GET_UNICAST_HOP_LIMIT,
88
+ SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE,
89
+ SOCKET_UDP_SET_SEND_BUFFER_SIZE,
90
+ SOCKET_UDP_SET_UNICAST_HOP_LIMIT,
91
+ SOCKET_UDP_STREAM,
92
+ SOCKET_UDP_SUBSCRIBE,
93
+ SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE,
94
+ SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND,
95
+ SOCKET_OUTGOING_DATAGRAM_STREAM_SEND,
96
+ SOCKET_DATAGRAM_STREAM_SUBSCRIBE,
97
+ SOCKET_DATAGRAM_STREAM_DISPOSE,
98
+ STDERR,
99
+ STDIN,
100
+ STDOUT,
101
+ reverseMap,
102
+ } from './calls.js';
102
103
  import {
103
- SOCKET_STATE_BIND,
104
- SOCKET_STATE_BOUND,
105
- SOCKET_STATE_CONNECT,
106
- SOCKET_STATE_CONNECTION,
107
- SOCKET_STATE_LISTEN,
108
- SOCKET_STATE_LISTENER,
109
- socketResolveAddress,
110
- getDefaultSendBufferSize,
111
- getDefaultReceiveBufferSize,
112
- } from "./worker-sockets.js";
104
+ SOCKET_STATE_BIND,
105
+ SOCKET_STATE_BOUND,
106
+ SOCKET_STATE_CONNECT,
107
+ SOCKET_STATE_CONNECTION,
108
+ SOCKET_STATE_LISTEN,
109
+ SOCKET_STATE_LISTENER,
110
+ socketResolveAddress,
111
+ getDefaultSendBufferSize,
112
+ getDefaultReceiveBufferSize,
113
+ } from './worker-sockets.js';
113
114
  import {
114
- createTcpSocket,
115
- socketTcpAccept,
116
- socketTcpBindStart,
117
- socketTcpConnectStart,
118
- socketTcpDispose,
119
- socketTcpFinish,
120
- socketTcpGetLocalAddress,
121
- socketTcpGetRemoteAddress,
122
- socketTcpListenStart,
123
- socketTcpSetKeepAlive,
124
- socketTcpSetListenBacklogSize,
125
- socketTcpShutdown,
126
- tcpSockets,
127
- } from "./worker-socket-tcp.js";
115
+ createTcpSocket,
116
+ socketTcpAccept,
117
+ socketTcpBindStart,
118
+ socketTcpConnectStart,
119
+ socketTcpDispose,
120
+ socketTcpFinish,
121
+ socketTcpGetLocalAddress,
122
+ socketTcpGetRemoteAddress,
123
+ socketTcpListenStart,
124
+ socketTcpSetKeepAlive,
125
+ socketTcpSetListenBacklogSize,
126
+ socketTcpShutdown,
127
+ tcpSockets,
128
+ } from './worker-socket-tcp.js';
128
129
  import {
129
- createUdpSocket,
130
- datagramStreams,
131
- socketDatagramStreamDispose,
132
- socketIncomingDatagramStreamReceive,
133
- socketOutgoingDatagramStreamCheckSend,
134
- socketOutgoingDatagramStreamSend,
135
- socketUdpBindFinish,
136
- socketUdpBindStart,
137
- socketUdpDispose,
138
- socketUdpGetLocalAddress,
139
- socketUdpGetReceiveBufferSize,
140
- socketUdpGetRemoteAddress,
141
- socketUdpGetSendBufferSize,
142
- socketUdpGetUnicastHopLimit,
143
- socketUdpSetReceiveBufferSize,
144
- socketUdpSetSendBufferSize,
145
- socketUdpSetUnicastHopLimit,
146
- socketUdpStream,
147
- udpSockets,
148
- } from "./worker-socket-udp.js";
149
- import process from "node:process";
150
-
151
- function log(msg) {
152
- if (debug) process._rawDebug(msg);
130
+ createUdpSocket,
131
+ datagramStreams,
132
+ socketDatagramStreamDispose,
133
+ socketIncomingDatagramStreamReceive,
134
+ socketOutgoingDatagramStreamCheckSend,
135
+ socketOutgoingDatagramStreamSend,
136
+ socketUdpBindFinish,
137
+ socketUdpBindStart,
138
+ socketUdpDispose,
139
+ socketUdpGetLocalAddress,
140
+ socketUdpGetReceiveBufferSize,
141
+ socketUdpGetRemoteAddress,
142
+ socketUdpGetSendBufferSize,
143
+ socketUdpGetUnicastHopLimit,
144
+ socketUdpSetReceiveBufferSize,
145
+ socketUdpSetSendBufferSize,
146
+ socketUdpSetUnicastHopLimit,
147
+ socketUdpStream,
148
+ udpSockets,
149
+ } from './worker-socket-udp.js';
150
+ import process from 'node:process';
151
+
152
+ export function log(msg) {
153
+ if (debug) {
154
+ process._rawDebug(msg);
155
+ }
153
156
  }
154
157
 
155
158
  let pollCnt = 0,
156
- streamCnt = 0,
157
- futureCnt = 0;
159
+ streamCnt = 0,
160
+ futureCnt = 0;
158
161
 
159
162
  /**
160
163
  * @typedef {{
@@ -189,68 +192,68 @@ export const streams = new Map();
189
192
  export const futures = new Map();
190
193
 
191
194
  export function createReadableStreamPollState(nodeStream) {
192
- const pollState = {
193
- ready: true,
194
- listener: null,
195
- polls: [],
196
- parentStream: nodeStream,
197
- };
198
- function pollDone() {
199
- pollStateReady(pollState);
200
- nodeStream.off("end", pollDone);
201
- nodeStream.off("close", pollDone);
202
- nodeStream.off("error", pollDone);
203
- }
204
- nodeStream.on("end", pollDone);
205
- nodeStream.on("close", pollDone);
206
- nodeStream.on("error", pollDone);
207
- return pollState;
195
+ const pollState = {
196
+ ready: true,
197
+ listener: null,
198
+ polls: [],
199
+ parentStream: nodeStream,
200
+ };
201
+ function pollDone() {
202
+ pollStateReady(pollState);
203
+ nodeStream.off('end', pollDone);
204
+ nodeStream.off('close', pollDone);
205
+ nodeStream.off('error', pollDone);
206
+ }
207
+ nodeStream.on('end', pollDone);
208
+ nodeStream.on('close', pollDone);
209
+ nodeStream.on('error', pollDone);
210
+ return pollState;
208
211
  }
209
212
 
210
213
  /**
211
214
  * @param {NodeJS.ReadableStream | NodeJS.WritableStream} stream
212
215
  */
213
216
  export function createReadableStream(
214
- nodeStream,
215
- pollState = createReadableStreamPollState(nodeStream)
217
+ nodeStream,
218
+ pollState = createReadableStreamPollState(nodeStream)
216
219
  ) {
217
- const stream = {
218
- stream: nodeStream,
219
- flushPromise: null,
220
- pollState,
221
- };
222
- streams.set(++streamCnt, stream);
223
- return streamCnt;
220
+ const stream = {
221
+ stream: nodeStream,
222
+ flushPromise: null,
223
+ pollState,
224
+ };
225
+ streams.set(++streamCnt, stream);
226
+ return streamCnt;
224
227
  }
225
228
 
226
229
  export function createWritableStream(nodeStream) {
227
- const pollState = {
228
- ready: true,
229
- listener: null,
230
- polls: [],
231
- parentStream: null,
232
- };
233
- const stream = {
234
- stream: nodeStream,
235
- flushPromise: null,
236
- pollState,
237
- };
238
- streams.set(++streamCnt, stream);
239
- function pollReady() {
240
- pollStateReady(pollState);
241
- }
242
- function pollDone() {
243
- pollStateReady(pollState);
244
- nodeStream.off("drain", pollReady);
245
- nodeStream.off("finish", pollDone);
246
- nodeStream.off("error", pollDone);
247
- nodeStream.off("close", pollDone);
248
- }
249
- nodeStream.on("drain", pollReady);
250
- nodeStream.on("finish", pollDone);
251
- nodeStream.on("error", pollDone);
252
- nodeStream.on("close", pollDone);
253
- return streamCnt;
230
+ const pollState = {
231
+ ready: true,
232
+ listener: null,
233
+ polls: [],
234
+ parentStream: null,
235
+ };
236
+ const stream = {
237
+ stream: nodeStream,
238
+ flushPromise: null,
239
+ pollState,
240
+ };
241
+ streams.set(++streamCnt, stream);
242
+ function pollReady() {
243
+ pollStateReady(pollState);
244
+ }
245
+ function pollDone() {
246
+ pollStateReady(pollState);
247
+ nodeStream.off('drain', pollReady);
248
+ nodeStream.off('finish', pollDone);
249
+ nodeStream.off('error', pollDone);
250
+ nodeStream.off('close', pollDone);
251
+ }
252
+ nodeStream.on('drain', pollReady);
253
+ nodeStream.on('finish', pollDone);
254
+ nodeStream.on('error', pollDone);
255
+ nodeStream.on('close', pollDone);
256
+ return streamCnt;
254
257
  }
255
258
 
256
259
  // Stdio
@@ -263,10 +266,10 @@ createWritableStream(stderr);
263
266
  * @param {NodeJS.ReadableStream | NodeJS.WritableStream} stream
264
267
  */
265
268
  function streamError(err) {
266
- return {
267
- tag: "last-operation-failed",
268
- val: { code: err.code, message: err.message, stack: err.stack },
269
- };
269
+ return {
270
+ tag: 'last-operation-failed',
271
+ val: { code: err.code, message: err.message, stack: err.stack },
272
+ };
270
273
  }
271
274
 
272
275
  /**
@@ -274,15 +277,21 @@ function streamError(err) {
274
277
  * @returns {{ stream: NodeJS.ReadableStream | NodeJS.WritableStream, polls: number[] }}
275
278
  */
276
279
  export function getStreamOrThrow(streamId) {
277
- if (!streamId) throw new Error("wasi-io trap: no stream id provided");
278
- const stream = streams.get(streamId);
279
- // not in unfinished streams <=> closed
280
- if (!stream) throw { tag: "closed" };
281
- if (stream.stream.errored) throw streamError(stream.stream.errored);
282
- if (stream.stream.closed) {
283
- throw { tag: "closed" };
284
- }
285
- return stream;
280
+ if (!streamId) {
281
+ throw new Error('wasi-io trap: no stream id provided');
282
+ }
283
+ const stream = streams.get(streamId);
284
+ // not in unfinished streams <=> closed
285
+ if (!stream) {
286
+ throw { tag: 'closed' };
287
+ }
288
+ if (stream.stream.errored) {
289
+ throw streamError(stream.stream.errored);
290
+ }
291
+ if (stream.stream.closed) {
292
+ throw { tag: 'closed' };
293
+ }
294
+ return stream;
286
295
  }
287
296
 
288
297
  /**
@@ -292,604 +301,677 @@ export function getStreamOrThrow(streamId) {
292
301
  * @returns {Promise<any>}
293
302
  */
294
303
  function handle(call, id, payload) {
295
- if (uncaughtException) throw uncaughtException;
296
- switch (call) {
304
+ if (uncaughtException) {
305
+ throw uncaughtException;
306
+ }
307
+ switch (call) {
297
308
  // Http
298
309
  case HTTP_CREATE_REQUEST: {
299
- const {
300
- method,
301
- scheme,
302
- authority,
303
- pathWithQuery,
304
- headers,
305
- body,
306
- connectTimeout,
307
- betweenBytesTimeout,
308
- firstByteTimeout,
309
- } = payload;
310
- return createFuture(
311
- createHttpRequest(
312
- method,
313
- scheme,
314
- authority,
315
- pathWithQuery,
316
- headers,
317
- body,
318
- connectTimeout,
319
- betweenBytesTimeout,
320
- firstByteTimeout
321
- )
322
- );
310
+ const {
311
+ method,
312
+ scheme,
313
+ authority,
314
+ pathWithQuery,
315
+ headers,
316
+ body,
317
+ connectTimeout,
318
+ betweenBytesTimeout,
319
+ firstByteTimeout,
320
+ } = payload;
321
+ return createFuture(
322
+ createHttpRequest(
323
+ method,
324
+ scheme,
325
+ authority,
326
+ pathWithQuery,
327
+ headers,
328
+ body,
329
+ connectTimeout,
330
+ betweenBytesTimeout,
331
+ firstByteTimeout
332
+ )
333
+ );
323
334
  }
324
335
  case OUTPUT_STREAM_CREATE | HTTP: {
325
- const stream = new PassThrough();
326
- // content length is passed as payload
327
- stream.contentLength = payload;
328
- stream.bytesRemaining = payload;
329
- return createWritableStream(stream);
336
+ const stream = new PassThrough();
337
+ // content length is passed as payload
338
+ stream.contentLength = payload;
339
+ stream.bytesRemaining = payload;
340
+ return createWritableStream(stream);
330
341
  }
331
342
  case OUTPUT_STREAM_SUBSCRIBE | HTTP:
332
343
  case OUTPUT_STREAM_FLUSH | HTTP:
333
344
  case OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | HTTP: {
334
- // http flush is a noop
335
- const { stream } = getStreamOrThrow(id);
336
- if (call === (OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | HTTP)) {
337
- stream.bytesRemaining -= payload.byteLength;
338
- if (stream.bytesRemaining < 0) {
339
- throw {
340
- tag: "last-operation-failed",
341
- val: {
342
- tag: "HTTP-request-body-size",
343
- val: stream.contentLength - stream.bytesRemaining,
344
- },
345
- };
346
- }
347
- }
348
- // otherwise fall through to generic implementation
349
- return handle(call & ~HTTP, id, payload);
345
+ // http flush is a noop
346
+ const { stream } = getStreamOrThrow(id);
347
+ if (call === (OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | HTTP)) {
348
+ stream.bytesRemaining -= payload.byteLength;
349
+ if (stream.bytesRemaining < 0) {
350
+ throw {
351
+ tag: 'last-operation-failed',
352
+ val: {
353
+ tag: 'HTTP-request-body-size',
354
+ val: stream.contentLength - stream.bytesRemaining,
355
+ },
356
+ };
357
+ }
358
+ }
359
+ // otherwise fall through to generic implementation
360
+ return handle(call & ~HTTP, id, payload);
350
361
  }
351
362
  case OUTPUT_STREAM_WRITE | HTTP: {
352
- const { stream } = getStreamOrThrow(id);
353
- stream.bytesRemaining -= payload.byteLength;
354
- if (stream.bytesRemaining < 0) {
355
- throw {
356
- tag: "last-operation-failed",
357
- val: {
358
- tag: "HTTP-request-body-size",
359
- val: stream.contentLength - stream.bytesRemaining,
360
- },
361
- };
362
- }
363
- const output = handle(OUTPUT_STREAM_WRITE, id, payload);
364
- return output;
363
+ const { stream } = getStreamOrThrow(id);
364
+ stream.bytesRemaining -= payload.byteLength;
365
+ if (stream.bytesRemaining < 0) {
366
+ throw {
367
+ tag: 'last-operation-failed',
368
+ val: {
369
+ tag: 'HTTP-request-body-size',
370
+ val: stream.contentLength - stream.bytesRemaining,
371
+ },
372
+ };
373
+ }
374
+ const output = handle(OUTPUT_STREAM_WRITE, id, payload);
375
+ return output;
365
376
  }
366
377
  case OUTPUT_STREAM_DISPOSE | HTTP:
367
- throw new Error(
368
- "wasi-io trap: Output stream dispose not implemented as an IO-call for HTTP"
369
- );
378
+ throw new Error(
379
+ 'wasi-io trap: Output stream dispose not implemented as an IO-call for HTTP'
380
+ );
370
381
  case HTTP_OUTPUT_STREAM_FINISH: {
371
- let stream;
372
- try {
373
- ({ stream } = getStreamOrThrow(id));
374
- } catch (e) {
375
- if (e.tag === "closed")
376
- throw { tag: "internal-error", val: "stream closed" };
377
- if (e.tag === "last-operation-failed")
378
- throw { tag: "internal-error", val: e.val.message };
379
- }
380
- if (stream.bytesRemaining > 0) {
381
- throw {
382
- tag: "HTTP-request-body-size",
383
- val: stream.contentLength - stream.bytesRemaining,
384
- };
385
- }
386
- if (stream.bytesRemaining < 0) {
387
- throw {
388
- tag: "HTTP-request-body-size",
389
- val: stream.contentLength - stream.bytesRemaining,
390
- };
391
- }
392
- stream.end();
393
- return;
382
+ let stream;
383
+ try {
384
+ ({ stream } = getStreamOrThrow(id));
385
+ } catch (e) {
386
+ if (e.tag === 'closed') {
387
+ throw { tag: 'internal-error', val: 'stream closed' };
388
+ }
389
+ if (e.tag === 'last-operation-failed') {
390
+ throw { tag: 'internal-error', val: e.val.message };
391
+ }
392
+ }
393
+ if (stream.bytesRemaining > 0) {
394
+ throw {
395
+ tag: 'HTTP-request-body-size',
396
+ val: stream.contentLength - stream.bytesRemaining,
397
+ };
398
+ }
399
+ if (stream.bytesRemaining < 0) {
400
+ throw {
401
+ tag: 'HTTP-request-body-size',
402
+ val: stream.contentLength - stream.bytesRemaining,
403
+ };
404
+ }
405
+ stream.end();
406
+ return;
394
407
  }
395
408
  case HTTP_OUTGOING_BODY_DISPOSE:
396
- if (debug && !streams.has(id))
397
- console.warn(`wasi-io: stream ${id} not found to dispose`);
398
- streams.delete(id);
399
- return;
409
+ if (debug && !streams.has(id)) {
410
+ console.warn(`wasi-io: stream ${id} not found to dispose`);
411
+ }
412
+ streams.delete(id);
413
+ return;
400
414
  case HTTP_SERVER_START:
401
- return startHttpServer(id, payload);
415
+ return startHttpServer(id, payload);
402
416
  case HTTP_SERVER_STOP:
403
- return stopHttpServer(id);
417
+ return stopHttpServer(id);
404
418
  case HTTP_SERVER_SET_OUTGOING_RESPONSE:
405
- return setOutgoingResponse(id, payload);
419
+ return setOutgoingResponse(id, payload);
406
420
  case HTTP_SERVER_CLEAR_OUTGOING_RESPONSE:
407
- return clearOutgoingResponse(id);
421
+ return clearOutgoingResponse(id);
422
+ case HTTP_SERVER_GET_ADDRESS:
423
+ return getHttpServerAddress(id);
408
424
 
409
- // Sockets name resolution
425
+ // Sockets name resolution
410
426
  case SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST:
411
- return createFuture(socketResolveAddress(payload));
427
+ return createFuture(socketResolveAddress(payload));
412
428
  case SOCKET_RESOLVE_ADDRESS_SUBSCRIBE_REQUEST:
413
- return createPoll(futures.get(id).pollState);
429
+ return createPoll(futures.get(id).pollState);
414
430
  case SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST:
415
- return void futureDispose(id, true);
431
+ return void futureDispose(id, true);
416
432
  case SOCKET_RESOLVE_ADDRESS_TAKE_REQUEST: {
417
- const val = futureTakeValue(id);
418
- if (val === undefined) throw "would-block";
419
- // double take avoidance is ensured
420
- return val.val;
433
+ const val = futureTakeValue(id);
434
+ if (val === undefined) {
435
+ throw 'would-block';
436
+ }
437
+ // double take avoidance is ensured
438
+ return val.val;
421
439
  }
422
440
 
423
441
  // Sockets TCP
424
442
  case SOCKET_TCP_ACCEPT:
425
- return socketTcpAccept(id);
443
+ return socketTcpAccept(id);
426
444
  case SOCKET_TCP_CREATE_HANDLE:
427
- return createTcpSocket();
445
+ return createTcpSocket();
428
446
  case SOCKET_TCP_BIND_START:
429
- return socketTcpBindStart(id, payload.localAddress, payload.family);
447
+ return socketTcpBindStart(id, payload.localAddress, payload.family);
430
448
  case SOCKET_TCP_BIND_FINISH:
431
- return socketTcpFinish(id, SOCKET_STATE_BIND, SOCKET_STATE_BOUND);
449
+ return socketTcpFinish(id, SOCKET_STATE_BIND, SOCKET_STATE_BOUND);
432
450
  case SOCKET_TCP_CONNECT_START:
433
- return socketTcpConnectStart(id, payload.remoteAddress, payload.family);
451
+ return socketTcpConnectStart(
452
+ id,
453
+ payload.remoteAddress,
454
+ payload.family
455
+ );
434
456
  case SOCKET_TCP_CONNECT_FINISH:
435
- return socketTcpFinish(id, SOCKET_STATE_CONNECT, SOCKET_STATE_CONNECTION);
457
+ return socketTcpFinish(
458
+ id,
459
+ SOCKET_STATE_CONNECT,
460
+ SOCKET_STATE_CONNECTION
461
+ );
436
462
  case SOCKET_TCP_LISTEN_START:
437
- return socketTcpListenStart(id);
463
+ return socketTcpListenStart(id);
438
464
  case SOCKET_TCP_LISTEN_FINISH:
439
- return socketTcpFinish(id, SOCKET_STATE_LISTEN, SOCKET_STATE_LISTENER);
465
+ return socketTcpFinish(
466
+ id,
467
+ SOCKET_STATE_LISTEN,
468
+ SOCKET_STATE_LISTENER
469
+ );
440
470
  case SOCKET_TCP_IS_LISTENING:
441
- return tcpSockets.get(id).state === SOCKET_STATE_LISTENER;
471
+ return tcpSockets.get(id).state === SOCKET_STATE_LISTENER;
442
472
  case SOCKET_GET_DEFAULT_SEND_BUFFER_SIZE:
443
- return getDefaultSendBufferSize(id);
473
+ return getDefaultSendBufferSize(id);
444
474
  case SOCKET_GET_DEFAULT_RECEIVE_BUFFER_SIZE:
445
- return getDefaultReceiveBufferSize(id);
475
+ return getDefaultReceiveBufferSize(id);
446
476
  case SOCKET_TCP_SET_LISTEN_BACKLOG_SIZE:
447
- return socketTcpSetListenBacklogSize(id);
477
+ return socketTcpSetListenBacklogSize(id);
448
478
  case SOCKET_TCP_GET_LOCAL_ADDRESS:
449
- return socketTcpGetLocalAddress(id);
479
+ return socketTcpGetLocalAddress(id);
450
480
  case SOCKET_TCP_GET_REMOTE_ADDRESS:
451
- return socketTcpGetRemoteAddress(id);
481
+ return socketTcpGetRemoteAddress(id);
452
482
  case SOCKET_TCP_SHUTDOWN:
453
- return socketTcpShutdown(id, payload);
483
+ return socketTcpShutdown(id, payload);
454
484
  case SOCKET_TCP_SUBSCRIBE:
455
- return createPoll(tcpSockets.get(id).pollState);
485
+ return createPoll(tcpSockets.get(id).pollState);
456
486
  case SOCKET_TCP_SET_KEEP_ALIVE:
457
- return socketTcpSetKeepAlive(id, payload);
487
+ return socketTcpSetKeepAlive(id, payload);
458
488
  case SOCKET_TCP_DISPOSE:
459
- return socketTcpDispose(id);
489
+ return socketTcpDispose(id);
460
490
 
461
- // Sockets UDP
491
+ // Sockets UDP
462
492
  case SOCKET_UDP_CREATE_HANDLE:
463
- return createUdpSocket(payload);
493
+ return createUdpSocket(payload);
464
494
  case SOCKET_UDP_BIND_START:
465
- return socketUdpBindStart(id, payload.localAddress, payload.family);
495
+ return socketUdpBindStart(id, payload.localAddress, payload.family);
466
496
  case SOCKET_UDP_BIND_FINISH:
467
- return socketUdpBindFinish(id);
497
+ return socketUdpBindFinish(id);
468
498
  case SOCKET_UDP_STREAM:
469
- return socketUdpStream(id, payload);
499
+ return socketUdpStream(id, payload);
470
500
  case SOCKET_UDP_SUBSCRIBE:
471
- return createPoll(udpSockets.get(id).pollState);
501
+ return createPoll(udpSockets.get(id).pollState);
472
502
  case SOCKET_UDP_GET_LOCAL_ADDRESS:
473
- return socketUdpGetLocalAddress(id);
503
+ return socketUdpGetLocalAddress(id);
474
504
  case SOCKET_UDP_GET_REMOTE_ADDRESS:
475
- return socketUdpGetRemoteAddress(id);
505
+ return socketUdpGetRemoteAddress(id);
476
506
  case SOCKET_UDP_SET_RECEIVE_BUFFER_SIZE:
477
- return socketUdpSetReceiveBufferSize(id, payload);
507
+ return socketUdpSetReceiveBufferSize(id, payload);
478
508
  case SOCKET_UDP_SET_SEND_BUFFER_SIZE:
479
- return socketUdpSetSendBufferSize(id, payload);
509
+ return socketUdpSetSendBufferSize(id, payload);
480
510
  case SOCKET_UDP_SET_UNICAST_HOP_LIMIT:
481
- return socketUdpSetUnicastHopLimit(id, payload);
511
+ return socketUdpSetUnicastHopLimit(id, payload);
482
512
  case SOCKET_UDP_GET_RECEIVE_BUFFER_SIZE:
483
- return socketUdpGetReceiveBufferSize(id);
513
+ return socketUdpGetReceiveBufferSize(id);
484
514
  case SOCKET_UDP_GET_SEND_BUFFER_SIZE:
485
- return socketUdpGetSendBufferSize(id);
515
+ return socketUdpGetSendBufferSize(id);
486
516
  case SOCKET_UDP_GET_UNICAST_HOP_LIMIT:
487
- return socketUdpGetUnicastHopLimit(id);
517
+ return socketUdpGetUnicastHopLimit(id);
488
518
  case SOCKET_UDP_DISPOSE:
489
- return socketUdpDispose(id);
519
+ return socketUdpDispose(id);
490
520
 
491
521
  case SOCKET_INCOMING_DATAGRAM_STREAM_RECEIVE:
492
- return socketIncomingDatagramStreamReceive(id, payload);
522
+ return socketIncomingDatagramStreamReceive(id, payload);
493
523
  case SOCKET_OUTGOING_DATAGRAM_STREAM_CHECK_SEND:
494
- return socketOutgoingDatagramStreamCheckSend(id);
524
+ return socketOutgoingDatagramStreamCheckSend(id);
495
525
  case SOCKET_OUTGOING_DATAGRAM_STREAM_SEND:
496
- return socketOutgoingDatagramStreamSend(id, payload);
526
+ return socketOutgoingDatagramStreamSend(id, payload);
497
527
  case SOCKET_DATAGRAM_STREAM_SUBSCRIBE:
498
- return createPoll(datagramStreams.get(id).pollState);
528
+ return createPoll(datagramStreams.get(id).pollState);
499
529
  case SOCKET_DATAGRAM_STREAM_DISPOSE:
500
- return socketDatagramStreamDispose(id);
530
+ return socketDatagramStreamDispose(id);
501
531
 
502
- // Stdio
532
+ // Stdio
503
533
  case OUTPUT_STREAM_BLOCKING_FLUSH | STDOUT:
504
534
  case OUTPUT_STREAM_BLOCKING_FLUSH | STDERR:
505
- // no blocking flush for stdio in Node.js
506
- return;
535
+ // no blocking flush for stdio in Node.js
536
+ return;
507
537
  case OUTPUT_STREAM_DISPOSE | STDOUT:
508
538
  case OUTPUT_STREAM_DISPOSE | STDERR:
509
- return;
539
+ return;
510
540
  case INPUT_STREAM_CREATE | STDIN: {
511
- return createReadableStream(
512
- new Readable({
513
- read(n) {
514
- if (n <= 0) return void this.push(null);
515
- let buf = Buffer.allocUnsafeSlow(n);
516
- read(0, buf, 0, n, null, (err, bytesRead) => {
517
- if (err) {
518
- if (err.code === "EAGAIN") {
519
- nextTick(() => void this._read(n));
520
- return;
521
- }
522
- this.destroy(err);
523
- } else if (bytesRead > 0) {
524
- if (bytesRead !== buf.length) {
525
- const dst = Buffer.allocUnsafeSlow(bytesRead);
526
- buf.copy(dst, 0, 0, bytesRead);
527
- buf = dst;
528
- }
529
- this.push(buf);
530
- } else {
531
- this.push(null);
532
- }
533
- });
534
- },
535
- })
536
- );
541
+ return createReadableStream(
542
+ new Readable({
543
+ read(n) {
544
+ if (n <= 0) {
545
+ return void this.push(null);
546
+ }
547
+ let buf = Buffer.allocUnsafeSlow(n);
548
+ read(0, buf, 0, n, null, (err, bytesRead) => {
549
+ if (err) {
550
+ if (err.code === 'EAGAIN') {
551
+ nextTick(() => void this._read(n));
552
+ return;
553
+ }
554
+ this.destroy(err);
555
+ } else if (bytesRead > 0) {
556
+ if (bytesRead !== buf.length) {
557
+ const dst =
558
+ Buffer.allocUnsafeSlow(bytesRead);
559
+ buf.copy(dst, 0, 0, bytesRead);
560
+ buf = dst;
561
+ }
562
+ this.push(buf);
563
+ } else {
564
+ this.push(null);
565
+ }
566
+ });
567
+ },
568
+ })
569
+ );
537
570
  }
538
571
 
539
572
  // Clocks
540
573
  case CLOCKS_DURATION_SUBSCRIBE:
541
- payload = hrtime.bigint() + payload;
542
- // fallthrough
574
+ payload = hrtime.bigint() + payload;
575
+ // fallthrough
543
576
  case CLOCKS_INSTANT_SUBSCRIBE: {
544
- const pollState = {
545
- ready: false,
546
- listener: null,
547
- polls: [],
548
- parentStream: null,
549
- };
550
- subscribeInstant(pollState, payload);
551
- return createPoll(pollState);
577
+ const pollState = {
578
+ ready: false,
579
+ listener: null,
580
+ polls: [],
581
+ parentStream: null,
582
+ };
583
+ subscribeInstant(pollState, payload);
584
+ return createPoll(pollState);
552
585
  }
553
586
 
554
587
  // Filesystem
555
588
  case INPUT_STREAM_CREATE | FILE: {
556
- const { fd, offset } = payload;
557
- const stream = createReadStream(null, {
558
- fd,
559
- autoClose: false,
560
- highWaterMark: 64 * 1024,
561
- start: Number(offset),
562
- });
563
- return createReadableStream(stream);
589
+ const { fd, offset } = payload;
590
+ const stream = createReadStream(null, {
591
+ fd,
592
+ autoClose: false,
593
+ highWaterMark: 64 * 1024,
594
+ start: Number(offset),
595
+ });
596
+ return createReadableStream(stream);
564
597
  }
565
598
  case OUTPUT_STREAM_CREATE | FILE: {
566
- const { fd, offset } = payload;
567
- const stream = createWriteStream(null, {
568
- fd,
569
- autoClose: false,
570
- emitClose: false,
571
- highWaterMark: 64 * 1024,
572
- start: Number(offset),
573
- });
574
- return createWritableStream(stream);
575
- }
576
- }
577
-
578
- // Generic call implementations (streams + polls)
579
- switch (call & CALL_MASK) {
599
+ const { fd, offset } = payload;
600
+ const stream = createWriteStream(null, {
601
+ fd,
602
+ autoClose: false,
603
+ emitClose: false,
604
+ highWaterMark: 64 * 1024,
605
+ start: Number(offset),
606
+ });
607
+ return createWritableStream(stream);
608
+ }
609
+ }
610
+
611
+ // Generic call implementations (streams + polls)
612
+ switch (call & CALL_MASK) {
580
613
  case INPUT_STREAM_READ: {
581
- const stream = getStreamOrThrow(id);
582
- if (!stream.pollState.ready) return new Uint8Array();
583
- const res = stream.stream.read(
584
- Math.min(stream.stream.readableLength, Number(payload))
585
- );
586
- if (res) return res;
587
- if (stream.stream.readableEnded) throw { tag: "closed" };
588
- return new Uint8Array();
614
+ const stream = getStreamOrThrow(id);
615
+ if (!stream.pollState.ready) {
616
+ return new Uint8Array();
617
+ }
618
+ const res = stream.stream.read(
619
+ Math.min(stream.stream.readableLength, Number(payload))
620
+ );
621
+ if (res) {
622
+ return res;
623
+ }
624
+ if (stream.stream.readableEnded) {
625
+ throw { tag: 'closed' };
626
+ }
627
+ return new Uint8Array();
589
628
  }
590
629
  case INPUT_STREAM_BLOCKING_READ: {
591
- const { pollState } = streams.get(id);
592
- pollStateCheck(pollState);
593
- if (pollState.ready)
594
- return handle(INPUT_STREAM_READ | (call & CALL_TYPE_MASK), id, payload);
595
- return new Promise((resolve) => void (pollState.listener = resolve)).then(
596
- () => handle(INPUT_STREAM_READ | (call & CALL_TYPE_MASK), id, payload)
597
- );
630
+ const { pollState } = streams.get(id);
631
+ pollStateCheck(pollState);
632
+ if (pollState.ready) {
633
+ return handle(
634
+ INPUT_STREAM_READ | (call & CALL_TYPE_MASK),
635
+ id,
636
+ payload
637
+ );
638
+ }
639
+ return new Promise(
640
+ (resolve) => void (pollState.listener = resolve)
641
+ ).then(() =>
642
+ handle(INPUT_STREAM_READ | (call & CALL_TYPE_MASK), id, payload)
643
+ );
598
644
  }
599
645
  case INPUT_STREAM_SKIP:
600
- return handle(
601
- INPUT_STREAM_READ | (call & CALL_TYPE_MASK),
602
- id,
603
- new Uint8Array(Number(payload))
604
- );
646
+ return handle(
647
+ INPUT_STREAM_READ | (call & CALL_TYPE_MASK),
648
+ id,
649
+ new Uint8Array(Number(payload))
650
+ );
605
651
  case INPUT_STREAM_BLOCKING_SKIP:
606
- return handle(
607
- INPUT_STREAM_BLOCKING_READ | (call & CALL_TYPE_MASK),
608
- id,
609
- new Uint8Array(Number(payload))
610
- );
652
+ return handle(
653
+ INPUT_STREAM_BLOCKING_READ | (call & CALL_TYPE_MASK),
654
+ id,
655
+ new Uint8Array(Number(payload))
656
+ );
611
657
  case INPUT_STREAM_SUBSCRIBE:
612
- return createPoll(streams.get(id).pollState);
658
+ return createPoll(streams.get(id).pollState);
613
659
  case INPUT_STREAM_DISPOSE: {
614
- const stream = streams.get(id);
615
- verifyPollsDroppedForDrop(stream.pollState, "input stream");
616
- streams.delete(id);
617
- return;
660
+ const stream = streams.get(id);
661
+ verifyPollsDroppedForDrop(stream.pollState, 'input stream');
662
+ streams.delete(id);
663
+ return;
618
664
  }
619
665
  case OUTPUT_STREAM_CHECK_WRITE: {
620
- const { stream, pollState } = getStreamOrThrow(id);
621
- const bytes = stream.writableHighWaterMark - stream.writableLength;
622
- if (bytes === 0) pollState.ready = false;
623
- return BigInt(bytes);
666
+ const { stream, pollState } = getStreamOrThrow(id);
667
+ const bytes = stream.writableHighWaterMark - stream.writableLength;
668
+ if (bytes === 0) {
669
+ pollState.ready = false;
670
+ }
671
+ return BigInt(bytes);
624
672
  }
625
673
  case OUTPUT_STREAM_WRITE: {
626
- const { stream } = getStreamOrThrow(id);
627
- if (
628
- payload.byteLength >
629
- stream.writableHighWaterMark - stream.writableLength
630
- )
631
- throw new Error("wasi-io trap: attempt to write too many bytes");
632
- return void stream.write(payload);
674
+ const { stream } = getStreamOrThrow(id);
675
+ if (
676
+ payload.byteLength >
677
+ stream.writableHighWaterMark - stream.writableLength
678
+ ) {
679
+ throw new Error(
680
+ 'wasi-io trap: attempt to write too many bytes'
681
+ );
682
+ }
683
+ return void stream.write(payload);
633
684
  }
634
685
  case OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH: {
635
- const stream = getStreamOrThrow(id);
636
- // if an existing flush, try again after that
637
- if (stream.flushPromise)
638
- return stream.flushPromise.then(() => handle(call, id, payload));
639
- if (
640
- payload.byteLength >
641
- stream.stream.writableHighWaterMark - stream.stream.writableLength
642
- ) {
643
- new Error(
644
- "wasi-io trap: Cannot write more than permitted writable length"
645
- );
646
- }
647
- stream.pollState.ready = false;
648
- return (stream.flushPromise = new Promise((resolve, reject) => {
649
- if (stream.stream === stdout || stream.stream === stderr) {
650
- // Inside workers, NodeJS actually queues writes destined for
651
- // stdout/stderr in a port that is only flushed on exit of the worker.
652
- //
653
- // In this case, we cannot attempt to wait for the promise.
654
- //
655
- // This code may have to be reworked for browsers.
656
- //
657
- // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker/io.js#L288
658
- // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker.js#L303
659
- // see: https://github.com/nodejs/node/blob/v22.12.0/typings/internalBinding/messaging.d.ts#L27
660
- stream.stream.write(payload);
661
- stream.flushPromise = null;
662
- pollStateReady(stream.pollState);
663
- resolve(BigInt(payload.byteLength));
664
- } else {
665
- stream.stream.write(payload, (err) => {
666
- stream.flushPromise = null;
667
- pollStateReady(stream.pollState);
668
- if (err) return void reject(streamError(err));
669
- resolve(BigInt(payload.byteLength));
670
- });
671
- }
672
- }));
686
+ const stream = getStreamOrThrow(id);
687
+ // if an existing flush, try again after that
688
+ if (stream.flushPromise) {
689
+ return stream.flushPromise.then(() =>
690
+ handle(call, id, payload)
691
+ );
692
+ }
693
+ if (
694
+ payload.byteLength >
695
+ stream.stream.writableHighWaterMark -
696
+ stream.stream.writableLength
697
+ ) {
698
+ throw new Error(
699
+ 'wasi-io trap: Cannot write more than permitted writable length'
700
+ );
701
+ }
702
+ stream.pollState.ready = false;
703
+ return (stream.flushPromise = new Promise((resolve, reject) => {
704
+ if (stream.stream === stdout || stream.stream === stderr) {
705
+ // Inside workers, NodeJS actually queues writes destined for
706
+ // stdout/stderr in a port that is only flushed on exit of the worker.
707
+ //
708
+ // In this case, we cannot attempt to wait for the promise.
709
+ //
710
+ // This code may have to be reworked for browsers.
711
+ //
712
+ // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker/io.js#L288
713
+ // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker.js#L303
714
+ // see: https://github.com/nodejs/node/blob/v22.12.0/typings/internalBinding/messaging.d.ts#L27
715
+ stream.stream.write(payload);
716
+ stream.flushPromise = null;
717
+ pollStateReady(stream.pollState);
718
+ resolve(BigInt(payload.byteLength));
719
+ } else {
720
+ stream.stream.write(payload, (err) => {
721
+ stream.flushPromise = null;
722
+ pollStateReady(stream.pollState);
723
+ if (err) {
724
+ return void reject(streamError(err));
725
+ }
726
+ resolve(BigInt(payload.byteLength));
727
+ });
728
+ }
729
+ }));
673
730
  }
674
731
  case OUTPUT_STREAM_FLUSH: {
675
- const stream = getStreamOrThrow(id);
676
- if (stream.flushPromise) return;
677
- stream.pollState.ready = false;
678
- stream.flushPromise = new Promise((resolve, reject) => {
679
- if (stream.stream === stdout || stream.stream === stderr) {
680
- // Inside workers, NodeJS actually queues writes destined for
681
- // stdout/stderr in a port that is only flushed on exit of the worker.
682
- //
683
- // In this case, we cannot attempt to wait for the promise.
684
- //
685
- // This code may have to be reworked for browsers.
686
- //
687
- // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker/io.js#L288
688
- // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker.js#L303
689
- // see: https://github.com/nodejs/node/blob/v22.12.0/typings/internalBinding/messaging.d.ts#L27
690
- stream.flushPromise = null;
691
- pollStateReady(stream.pollState);
692
- resolve();
693
- } else {
694
- // For all other writes, we can perform the actual write and expect the write to complete
695
- // and trigger the relevant callback
696
- stream.stream.write(new Uint8Array([]), (err) => {
697
- stream.flushPromise = null;
698
- pollStateReady(stream.pollState);
699
- if (err) return void reject(streamError(err));
700
- resolve();
701
- });
702
- }
703
- });
704
- return stream.flushPromise;
732
+ const stream = getStreamOrThrow(id);
733
+ if (stream.flushPromise) {
734
+ return;
735
+ }
736
+ stream.pollState.ready = false;
737
+ stream.flushPromise = new Promise((resolve, reject) => {
738
+ if (stream.stream === stdout || stream.stream === stderr) {
739
+ // Inside workers, NodeJS actually queues writes destined for
740
+ // stdout/stderr in a port that is only flushed on exit of the worker.
741
+ //
742
+ // In this case, we cannot attempt to wait for the promise.
743
+ //
744
+ // This code may have to be reworked for browsers.
745
+ //
746
+ // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker/io.js#L288
747
+ // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker.js#L303
748
+ // see: https://github.com/nodejs/node/blob/v22.12.0/typings/internalBinding/messaging.d.ts#L27
749
+ stream.flushPromise = null;
750
+ pollStateReady(stream.pollState);
751
+ resolve();
752
+ } else {
753
+ // For all other writes, we can perform the actual write and expect the write to complete
754
+ // and trigger the relevant callback
755
+ stream.stream.write(new Uint8Array([]), (err) => {
756
+ stream.flushPromise = null;
757
+ pollStateReady(stream.pollState);
758
+ if (err) {
759
+ return void reject(streamError(err));
760
+ }
761
+ resolve();
762
+ });
763
+ }
764
+ });
765
+ return stream.flushPromise;
705
766
  }
706
767
  case OUTPUT_STREAM_BLOCKING_FLUSH: {
707
- const stream = getStreamOrThrow(id);
708
- if (stream.flushPromise) return stream.flushPromise;
709
- return new Promise((resolve, reject) => {
710
- if (stream.stream === stdout || stream.stream === stderr) {
711
- // Inside workers, NodeJS actually queues writes destined for
712
- // stdout/stderr in a port that is only flushed on exit of the worker.
713
- //
714
- // In this case, we cannot attempt to wait for the promise.
715
- //
716
- // This code may have to be reworked for browsers.
717
- //
718
- // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker/io.js#L288
719
- // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker.js#L303
720
- // see: https://github.com/nodejs/node/blob/v22.12.0/typings/internalBinding/messaging.d.ts#L27
721
- resolve();
722
- } else {
723
- // For all other writes, we can perform the actual write and expect the write to complete
724
- // and trigger the relevant callback
725
- stream.stream.write(new Uint8Array([]), (err) =>
726
- err ? reject(streamError(err)) : resolve()
727
- );
728
- }
729
- });
768
+ const stream = getStreamOrThrow(id);
769
+ if (stream.flushPromise) {
770
+ return stream.flushPromise;
771
+ }
772
+ return new Promise((resolve, reject) => {
773
+ if (stream.stream === stdout || stream.stream === stderr) {
774
+ // Inside workers, NodeJS actually queues writes destined for
775
+ // stdout/stderr in a port that is only flushed on exit of the worker.
776
+ //
777
+ // In this case, we cannot attempt to wait for the promise.
778
+ //
779
+ // This code may have to be reworked for browsers.
780
+ //
781
+ // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker/io.js#L288
782
+ // see: https://github.com/nodejs/node/blob/v22.12.0/lib/internal/worker.js#L303
783
+ // see: https://github.com/nodejs/node/blob/v22.12.0/typings/internalBinding/messaging.d.ts#L27
784
+ resolve();
785
+ } else {
786
+ // For all other writes, we can perform the actual write and expect the write to complete
787
+ // and trigger the relevant callback
788
+ stream.stream.write(new Uint8Array([]), (err) =>
789
+ err ? reject(streamError(err)) : resolve()
790
+ );
791
+ }
792
+ });
730
793
  }
731
794
  case OUTPUT_STREAM_WRITE_ZEROES:
732
- return handle(
733
- OUTPUT_STREAM_WRITE | (call & CALL_TYPE_MASK),
734
- id,
735
- new Uint8Array(Number(payload))
736
- );
795
+ return handle(
796
+ OUTPUT_STREAM_WRITE | (call & CALL_TYPE_MASK),
797
+ id,
798
+ new Uint8Array(Number(payload))
799
+ );
737
800
  case OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH:
738
- return handle(
739
- OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | (call & CALL_TYPE_MASK),
740
- id,
741
- new Uint8Array(Number(payload))
742
- );
801
+ return handle(
802
+ OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH |
803
+ (call & CALL_TYPE_MASK),
804
+ id,
805
+ new Uint8Array(Number(payload))
806
+ );
743
807
  case OUTPUT_STREAM_SPLICE: {
744
- const outputStream = getStreamOrThrow(id);
745
- const inputStream = getStreamOrThrow(payload.src);
746
- let bytesRemaining = Number(payload.len);
747
- let chunk;
748
- while (
749
- bytesRemaining > 0 &&
750
- (chunk = inputStream.stream.read(
751
- Math.min(
752
- outputStream.writableHighWaterMark - outputStream.writableLength,
753
- bytesRemaining
754
- )
755
- ))
756
- ) {
757
- bytesRemaining -= chunk.byteLength;
758
- outputStream.stream.write(chunk);
759
- }
760
- if (inputStream.stream.errored)
761
- throw streamError(inputStream.stream.errored);
762
- if (outputStream.stream.errored)
763
- throw streamError(outputStream.stream.errored);
764
- return payload.len - BigInt(bytesRemaining);
808
+ const outputStream = getStreamOrThrow(id);
809
+ const inputStream = getStreamOrThrow(payload.src);
810
+ let bytesRemaining = Number(payload.len);
811
+ let chunk;
812
+ while (
813
+ bytesRemaining > 0 &&
814
+ (chunk = inputStream.stream.read(
815
+ Math.min(
816
+ outputStream.writableHighWaterMark -
817
+ outputStream.writableLength,
818
+ bytesRemaining
819
+ )
820
+ ))
821
+ ) {
822
+ bytesRemaining -= chunk.byteLength;
823
+ outputStream.stream.write(chunk);
824
+ }
825
+ if (inputStream.stream.errored) {
826
+ throw streamError(inputStream.stream.errored);
827
+ }
828
+ if (outputStream.stream.errored) {
829
+ throw streamError(outputStream.stream.errored);
830
+ }
831
+ return payload.len - BigInt(bytesRemaining);
765
832
  }
766
833
  case OUTPUT_STREAM_SUBSCRIBE:
767
- return createPoll(streams.get(id).pollState);
834
+ return createPoll(streams.get(id).pollState);
768
835
  case OUTPUT_STREAM_BLOCKING_SPLICE: {
769
- const outputStream = getStreamOrThrow(id);
770
- let promise = Promise.resolve();
771
- let resolve, reject;
772
- if (outputStream.stream.writableNeedDrain) {
773
- promise = new Promise((_resolve, _reject) => {
774
- outputStream.stream
775
- .once("drain", (resolve = _resolve))
776
- .once("error", (reject = _reject));
777
- }).then(
778
- () => {
779
- outputStream.stream.off("error", reject);
780
- },
781
- (err) => {
782
- outputStream.stream.off("drain", resolve);
783
- throw streamError(err);
784
- }
785
- );
786
- }
787
- const inputStream = getStreamOrThrow(payload.src);
788
- if (!inputStream.stream.readable) {
789
- promise = promise.then(() =>
790
- new Promise((_resolve, _reject) => {
791
- inputStream.stream
792
- .once("readable", (resolve = _resolve))
793
- .once("error", (reject = _reject));
794
- }).then(
795
- () => {
796
- inputStream.stream.off("error", reject);
797
- },
798
- (err) => {
799
- inputStream.stream.off("readable", resolve);
800
- throw streamError(err);
801
- }
802
- )
836
+ const outputStream = getStreamOrThrow(id);
837
+ let promise = Promise.resolve();
838
+ let resolve, reject;
839
+ if (outputStream.stream.writableNeedDrain) {
840
+ promise = new Promise((_resolve, _reject) => {
841
+ outputStream.stream
842
+ .once('drain', (resolve = _resolve))
843
+ .once('error', (reject = _reject));
844
+ }).then(
845
+ () => {
846
+ outputStream.stream.off('error', reject);
847
+ },
848
+ (err) => {
849
+ outputStream.stream.off('drain', resolve);
850
+ throw streamError(err);
851
+ }
852
+ );
853
+ }
854
+ const inputStream = getStreamOrThrow(payload.src);
855
+ if (!inputStream.stream.readable) {
856
+ promise = promise.then(() =>
857
+ new Promise((_resolve, _reject) => {
858
+ inputStream.stream
859
+ .once('readable', (resolve = _resolve))
860
+ .once('error', (reject = _reject));
861
+ }).then(
862
+ () => {
863
+ inputStream.stream.off('error', reject);
864
+ },
865
+ (err) => {
866
+ inputStream.stream.off('readable', resolve);
867
+ throw streamError(err);
868
+ }
869
+ )
870
+ );
871
+ }
872
+ return promise.then(() =>
873
+ handle(OUTPUT_STREAM_SPLICE, id, payload)
803
874
  );
804
- }
805
- return promise.then(() => handle(OUTPUT_STREAM_SPLICE, id, payload));
806
875
  }
807
876
  case OUTPUT_STREAM_DISPOSE: {
808
- const stream = streams.get(id);
809
- verifyPollsDroppedForDrop(stream.pollState, "output stream");
810
- stream.stream.end();
811
- streams.delete(id);
812
- return;
877
+ const stream = streams.get(id);
878
+ verifyPollsDroppedForDrop(stream.pollState, 'output stream');
879
+ stream.stream.end();
880
+ streams.delete(id);
881
+ return;
813
882
  }
814
883
 
815
884
  case POLL_POLLABLE_READY:
816
- return polls.get(id).ready;
885
+ return polls.get(id).ready;
817
886
  case POLL_POLLABLE_BLOCK:
818
- payload = [id];
819
- // [intentional case fall-through]
887
+ payload = [id];
888
+ // [intentional case fall-through]
820
889
  case POLL_POLL_LIST: {
821
- if (payload.length === 0)
822
- throw new Error("wasi-io trap: attempt to poll on empty list");
823
- const doneList = [];
824
- const pollList = payload.map((pollId) => polls.get(pollId));
825
- for (const [idx, pollState] of pollList.entries()) {
826
- pollStateCheck(pollState);
827
- if (pollState.ready) doneList.push(idx);
828
- }
829
- if (doneList.length > 0) {
830
- return new Uint32Array(doneList);
831
- }
832
- let readyPromiseResolve;
833
- const readyPromise = new Promise(
834
- (resolve) => void (readyPromiseResolve = resolve)
835
- );
836
- for (const poll of pollList) {
837
- poll.listener = readyPromiseResolve;
838
- }
839
- return readyPromise.then(() => {
890
+ if (payload.length === 0) {
891
+ throw new Error('wasi-io trap: attempt to poll on empty list');
892
+ }
893
+ const doneList = [];
894
+ const pollList = payload.map((pollId) => polls.get(pollId));
840
895
  for (const [idx, pollState] of pollList.entries()) {
841
- pollState.listener = null;
842
- if (pollState.ready) doneList.push(idx);
896
+ pollStateCheck(pollState);
897
+ if (pollState.ready) {
898
+ doneList.push(idx);
899
+ }
900
+ }
901
+ if (doneList.length > 0) {
902
+ return new Uint32Array(doneList);
843
903
  }
844
- return new Uint32Array(doneList);
845
- });
904
+ let readyPromiseResolve;
905
+ const readyPromise = new Promise(
906
+ (resolve) => void (readyPromiseResolve = resolve)
907
+ );
908
+ for (const poll of pollList) {
909
+ poll.listener = readyPromiseResolve;
910
+ }
911
+ return readyPromise.then(() => {
912
+ for (const [idx, pollState] of pollList.entries()) {
913
+ pollState.listener = null;
914
+ if (pollState.ready) {
915
+ doneList.push(idx);
916
+ }
917
+ }
918
+ return new Uint32Array(doneList);
919
+ });
846
920
  }
847
921
  case POLL_POLLABLE_DISPOSE:
848
- if (!polls.delete(id))
849
- throw new Error(
850
- `wasi-io trap: Disposed a poll ${id} that does not exist`
851
- );
852
- return;
922
+ if (!polls.delete(id)) {
923
+ throw new Error(
924
+ `wasi-io trap: Disposed a poll ${id} that does not exist`
925
+ );
926
+ }
927
+ return;
853
928
 
854
929
  case FUTURE_TAKE_VALUE:
855
- return futureTakeValue(id);
930
+ return futureTakeValue(id);
856
931
 
857
932
  case FUTURE_SUBSCRIBE: {
858
- const { pollState } = futures.get(id);
859
- const pollId = ++pollCnt;
860
- polls.set(pollId, pollState);
861
- return pollId;
933
+ const { pollState } = futures.get(id);
934
+ const pollId = ++pollCnt;
935
+ polls.set(pollId, pollState);
936
+ return pollId;
862
937
  }
863
938
  case FUTURE_DISPOSE:
864
- return void futureDispose(id, true);
939
+ return void futureDispose(id, true);
865
940
  default:
866
- throw new Error(
867
- `wasi-io trap: Unknown call ${call} (${reverseMap[call]}) with type ${
868
- reverseMap[call & CALL_TYPE_MASK]
869
- }`
870
- );
871
- }
941
+ throw new Error(
942
+ `wasi-io trap: Unknown call ${call} (${reverseMap[call]}) with type ${
943
+ reverseMap[call & CALL_TYPE_MASK]
944
+ }`
945
+ );
946
+ }
872
947
  }
873
948
 
874
949
  /**
875
950
  * @param {PollState} pollState
876
951
  */
877
952
  function createPoll(pollState) {
878
- const pollId = ++pollCnt;
879
- pollState.polls.push(pollId);
880
- polls.set(pollId, pollState);
881
- return pollId;
953
+ const pollId = ++pollCnt;
954
+ pollState.polls.push(pollId);
955
+ polls.set(pollId, pollState);
956
+ return pollId;
882
957
  }
883
958
 
884
959
  function subscribeInstant(pollState, instant) {
885
- const duration = instant - hrtime.bigint();
886
- if (duration <= 0) return pollStateReady(pollState);
887
- function cb() {
888
- if (hrtime.bigint() < instant) return subscribeInstant(pollState, instant);
889
- pollStateReady(pollState);
890
- }
891
- if (duration < 10e6) setImmediate(cb);
892
- else setTimeout(cb, Number(duration) / 1e6);
960
+ const duration = instant - hrtime.bigint();
961
+ if (duration <= 0) {
962
+ return pollStateReady(pollState);
963
+ }
964
+ function cb() {
965
+ if (hrtime.bigint() < instant) {
966
+ return subscribeInstant(pollState, instant);
967
+ }
968
+ pollStateReady(pollState);
969
+ }
970
+ if (duration < 10e6) {
971
+ setImmediate(cb);
972
+ } else {
973
+ setTimeout(cb, Number(duration) / 1e6);
974
+ }
893
975
  }
894
976
 
895
977
  /**
@@ -897,13 +979,14 @@ function subscribeInstant(pollState, instant) {
897
979
  * @param {string} polledResourceDebugName
898
980
  */
899
981
  export function verifyPollsDroppedForDrop(pollState, polledResourceDebugName) {
900
- for (const pollId of pollState.polls) {
901
- const poll = polls.get(pollId);
902
- if (poll)
903
- throw new Error(
904
- `wasi-io trap: Cannot drop ${polledResourceDebugName} as it has a child poll resource which has not yet been dropped`
905
- );
906
- }
982
+ for (const pollId of pollState.polls) {
983
+ const poll = polls.get(pollId);
984
+ if (poll) {
985
+ throw new Error(
986
+ `wasi-io trap: Cannot drop ${polledResourceDebugName} as it has a child poll resource which has not yet been dropped`
987
+ );
988
+ }
989
+ }
907
990
  }
908
991
 
909
992
  /**
@@ -911,41 +994,41 @@ export function verifyPollsDroppedForDrop(pollState, polledResourceDebugName) {
911
994
  * @param {bool} finished
912
995
  */
913
996
  export function pollStateReady(pollState) {
914
- if (pollState.ready && pollState.listener) {
915
- uncaughtException = new Error(
916
- "wasi-io trap: poll already ready with listener attached"
917
- );
918
- }
919
- pollState.ready = true;
920
- if (pollState.listener) {
921
- pollState.listener();
922
- pollState.listener = null;
923
- }
997
+ if (pollState.ready && pollState.listener) {
998
+ uncaughtException = new Error(
999
+ 'wasi-io trap: poll already ready with listener attached'
1000
+ );
1001
+ }
1002
+ pollState.ready = true;
1003
+ if (pollState.listener) {
1004
+ pollState.listener();
1005
+ pollState.listener = null;
1006
+ }
924
1007
  }
925
1008
 
926
1009
  /**
927
1010
  * @param {PollState} pollState
928
1011
  */
929
1012
  function pollStateCheck(pollState) {
930
- if (pollState.ready && pollState.parentStream) {
931
- // stream ONLY applies to readable streams here
932
- const stream = pollState.parentStream;
933
- const res = stream.read(0);
934
- if (res !== null) {
935
- throw new Error("wasi-io trap: got data for a null read");
936
- }
937
- if (
938
- pollState.ready &&
939
- stream.readableLength === 0 &&
940
- !stream.readableEnded &&
941
- !stream.errored
942
- ) {
943
- pollState.ready = false;
944
- stream.once("readable", () => {
945
- pollStateReady(pollState);
946
- });
1013
+ if (pollState.ready && pollState.parentStream) {
1014
+ // stream ONLY applies to readable streams here
1015
+ const stream = pollState.parentStream;
1016
+ const res = stream.read(0);
1017
+ if (res !== null) {
1018
+ throw new Error('wasi-io trap: got data for a null read');
1019
+ }
1020
+ if (
1021
+ pollState.ready &&
1022
+ stream.readableLength === 0 &&
1023
+ !stream.readableEnded &&
1024
+ !stream.errored
1025
+ ) {
1026
+ pollState.ready = false;
1027
+ stream.once('readable', () => {
1028
+ pollStateReady(pollState);
1029
+ });
1030
+ }
947
1031
  }
948
- }
949
1032
  }
950
1033
 
951
1034
  /**
@@ -955,31 +1038,31 @@ function pollStateCheck(pollState) {
955
1038
  * @returns {number}
956
1039
  */
957
1040
  export function createFuture(promise, pollState) {
958
- const futureId = ++futureCnt;
959
- if (pollState) {
960
- pollState.ready = false;
961
- } else {
962
- pollState = {
963
- ready: false,
964
- listener: null,
965
- polls: [],
966
- parent: null,
967
- };
968
- }
969
- const future = { tag: "ok", val: null };
970
- futures.set(futureId, { future, pollState });
971
- promise.then(
972
- (value) => {
973
- pollStateReady(pollState);
974
- future.val = value;
975
- },
976
- (value) => {
977
- pollStateReady(pollState);
978
- future.tag = "err";
979
- future.val = value;
980
- }
981
- );
982
- return futureId;
1041
+ const futureId = ++futureCnt;
1042
+ if (pollState) {
1043
+ pollState.ready = false;
1044
+ } else {
1045
+ pollState = {
1046
+ ready: false,
1047
+ listener: null,
1048
+ polls: [],
1049
+ parent: null,
1050
+ };
1051
+ }
1052
+ const future = { tag: 'ok', val: null };
1053
+ futures.set(futureId, { future, pollState });
1054
+ promise.then(
1055
+ (value) => {
1056
+ pollStateReady(pollState);
1057
+ future.val = value;
1058
+ },
1059
+ (value) => {
1060
+ pollStateReady(pollState);
1061
+ future.tag = 'err';
1062
+ future.val = value;
1063
+ }
1064
+ );
1065
+ return futureId;
983
1066
  }
984
1067
 
985
1068
  /**
@@ -988,29 +1071,29 @@ export function createFuture(promise, pollState) {
988
1071
  * @throws {undefined}
989
1072
  */
990
1073
  export function futureTakeValue(id) {
991
- const future = futures.get(id);
992
- // Not ready = return undefined
993
- if (!future.pollState.ready) return undefined;
994
- // Ready but already taken = return { tag: 'err', val: undefined }
995
- if (!future.future) return { tag: "err", val: undefined };
996
- const out = { tag: "ok", val: future.future };
997
- future.future = null;
998
- return out;
1074
+ const future = futures.get(id);
1075
+ // Not ready = return undefined
1076
+ if (!future.pollState.ready) {
1077
+ return undefined;
1078
+ }
1079
+ // Ready but already taken = return { tag: 'err', val: undefined }
1080
+ if (!future.future) {
1081
+ return { tag: 'err', val: undefined };
1082
+ }
1083
+ const out = { tag: 'ok', val: future.future };
1084
+ future.future = null;
1085
+ return out;
999
1086
  }
1000
1087
 
1001
1088
  export function futureDispose(id, ownsState) {
1002
- const { pollState } = futures.get(id);
1003
- if (ownsState) verifyPollsDroppedForDrop(pollState, "future");
1004
- return void futures.delete(id);
1089
+ const { pollState } = futures.get(id);
1090
+ if (ownsState) {
1091
+ verifyPollsDroppedForDrop(pollState, 'future');
1092
+ }
1093
+ return void futures.delete(id);
1005
1094
  }
1006
1095
 
1007
1096
  let uncaughtException;
1008
- process.on("uncaughtException", (err) => (uncaughtException = err));
1009
-
1010
- // eslint-disable-next-line no-unused-vars
1011
- function trace(msg) {
1012
- const tmpErr = new Error(format(msg));
1013
- log(tmpErr.stack);
1014
- }
1097
+ process.on('uncaughtException', (err) => (uncaughtException = err));
1015
1098
 
1016
1099
  const debug = runAsWorker(handle);