@bytecodealliance/preview2-shim 0.17.7 → 0.17.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -18
- package/lib/browser/cli.js +71 -71
- package/lib/browser/clocks.js +34 -30
- package/lib/browser/config.js +3 -3
- package/lib/browser/environment.js +15 -15
- package/lib/browser/filesystem.js +382 -396
- package/lib/browser/http.js +683 -144
- package/lib/browser/index.js +7 -7
- package/lib/browser/io.js +199 -133
- package/lib/browser/random.js +42 -44
- package/lib/browser/sockets.js +52 -52
- package/lib/common/instantiation.js +147 -151
- package/lib/io/calls.js +7 -9
- package/lib/io/worker-http.js +167 -178
- package/lib/io/worker-io.js +338 -406
- package/lib/io/worker-socket-tcp.js +259 -271
- package/lib/io/worker-socket-udp.js +437 -491
- package/lib/io/worker-sockets.js +230 -251
- package/lib/io/worker-thread.js +774 -822
- package/lib/nodejs/cli.js +53 -65
- package/lib/nodejs/clocks.js +49 -52
- package/lib/nodejs/filesystem.js +726 -785
- package/lib/nodejs/http.js +651 -697
- package/lib/nodejs/index.js +7 -7
- package/lib/nodejs/io.js +1 -1
- package/lib/nodejs/random.js +32 -32
- package/lib/nodejs/sockets.js +468 -538
- package/lib/synckit/index.js +85 -94
- package/package.json +11 -10
package/lib/io/worker-io.js
CHANGED
|
@@ -1,110 +1,98 @@
|
|
|
1
|
-
import { fileURLToPath } from
|
|
2
|
-
import { createSyncFn } from
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { createSyncFn } from "../synckit/index.js";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} from
|
|
36
|
-
import nodeProcess, { exit, stderr, stdout, env } from
|
|
4
|
+
CALL_MASK,
|
|
5
|
+
CALL_TYPE_MASK,
|
|
6
|
+
FILE,
|
|
7
|
+
HTTP_SERVER_INCOMING_HANDLER,
|
|
8
|
+
HTTP,
|
|
9
|
+
INPUT_STREAM_BLOCKING_READ,
|
|
10
|
+
INPUT_STREAM_BLOCKING_SKIP,
|
|
11
|
+
INPUT_STREAM_DISPOSE,
|
|
12
|
+
INPUT_STREAM_READ,
|
|
13
|
+
INPUT_STREAM_SKIP,
|
|
14
|
+
INPUT_STREAM_SUBSCRIBE,
|
|
15
|
+
OUTPUT_STREAM_BLOCKING_FLUSH,
|
|
16
|
+
OUTPUT_STREAM_BLOCKING_SPLICE,
|
|
17
|
+
OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH,
|
|
18
|
+
OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH,
|
|
19
|
+
OUTPUT_STREAM_CHECK_WRITE,
|
|
20
|
+
OUTPUT_STREAM_DISPOSE,
|
|
21
|
+
OUTPUT_STREAM_FLUSH,
|
|
22
|
+
OUTPUT_STREAM_SPLICE,
|
|
23
|
+
OUTPUT_STREAM_SUBSCRIBE,
|
|
24
|
+
OUTPUT_STREAM_WRITE_ZEROES,
|
|
25
|
+
OUTPUT_STREAM_WRITE,
|
|
26
|
+
POLL_POLL_LIST,
|
|
27
|
+
POLL_POLLABLE_BLOCK,
|
|
28
|
+
POLL_POLLABLE_DISPOSE,
|
|
29
|
+
POLL_POLLABLE_READY,
|
|
30
|
+
SOCKET_TCP,
|
|
31
|
+
STDERR,
|
|
32
|
+
STDIN,
|
|
33
|
+
STDOUT,
|
|
34
|
+
reverseMap,
|
|
35
|
+
} from "./calls.js";
|
|
36
|
+
import nodeProcess, { exit, stderr, stdout, env } from "node:process";
|
|
37
37
|
|
|
38
38
|
const _rawDebug = nodeProcess._rawDebug || console.error.bind(console);
|
|
39
39
|
|
|
40
|
-
const workerPath = fileURLToPath(
|
|
41
|
-
new URL('./worker-thread.js', import.meta.url)
|
|
42
|
-
);
|
|
40
|
+
const workerPath = fileURLToPath(new URL("./worker-thread.js", import.meta.url));
|
|
43
41
|
|
|
44
42
|
const httpIncomingHandlers = new Map();
|
|
45
43
|
export function registerIncomingHttpHandler(id, handler) {
|
|
46
|
-
|
|
44
|
+
httpIncomingHandlers.set(id, handler);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
const instanceId = Math.round(Math.random() * 1000).toString();
|
|
50
48
|
const DEBUG_DEFAULT = false;
|
|
51
49
|
const DEBUG =
|
|
52
|
-
|
|
53
|
-
? false
|
|
54
|
-
: env.PREVIEW2_SHIM_DEBUG === '1'
|
|
55
|
-
? true
|
|
56
|
-
: DEBUG_DEFAULT;
|
|
50
|
+
env.PREVIEW2_SHIM_DEBUG === "0" ? false : env.PREVIEW2_SHIM_DEBUG === "1" ? true : DEBUG_DEFAULT;
|
|
57
51
|
|
|
58
52
|
/**
|
|
59
53
|
* @type {(call: number, id: number | null, payload: any) -> any}
|
|
60
54
|
*/
|
|
61
55
|
export let ioCall = createSyncFn(workerPath, DEBUG, (type, id, payload) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
`Internal error: no incoming handler registered for server ${id}`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
handler(payload);
|
|
56
|
+
// 'callbacks' from the worker
|
|
57
|
+
// ONLY happens for an http server incoming handler, and NOTHING else (not even sockets, since accept is sync!)
|
|
58
|
+
if (type !== HTTP_SERVER_INCOMING_HANDLER) {
|
|
59
|
+
throw new Error("Internal error: only incoming handler callback is permitted");
|
|
60
|
+
}
|
|
61
|
+
const handler = httpIncomingHandlers.get(id);
|
|
62
|
+
if (!handler) {
|
|
63
|
+
throw new Error(`Internal error: no incoming handler registered for server ${id}`);
|
|
64
|
+
}
|
|
65
|
+
handler(payload);
|
|
76
66
|
});
|
|
77
67
|
if (DEBUG) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
68
|
+
const _ioCall = ioCall;
|
|
69
|
+
ioCall = function ioCall(num, id, payload) {
|
|
70
|
+
if (typeof id !== "number" && id !== null) {
|
|
71
|
+
throw new Error("id must be a number or null");
|
|
72
|
+
}
|
|
73
|
+
let ret;
|
|
74
|
+
try {
|
|
75
|
+
_rawDebug(
|
|
76
|
+
instanceId,
|
|
77
|
+
reverseMap[num & CALL_MASK],
|
|
78
|
+
reverseMap[num & CALL_TYPE_MASK],
|
|
79
|
+
id,
|
|
80
|
+
payload,
|
|
81
|
+
);
|
|
82
|
+
ret = _ioCall(num, id, payload);
|
|
83
|
+
return ret;
|
|
84
|
+
} catch (e) {
|
|
85
|
+
ret = e;
|
|
86
|
+
throw ret;
|
|
87
|
+
} finally {
|
|
88
|
+
_rawDebug(instanceId, "->", ret);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
101
91
|
}
|
|
102
92
|
|
|
103
|
-
const symbolDispose = Symbol.dispose || Symbol.for(
|
|
93
|
+
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
104
94
|
|
|
105
|
-
const finalizationRegistry = new FinalizationRegistry(
|
|
106
|
-
(dispose) => void dispose()
|
|
107
|
-
);
|
|
95
|
+
const finalizationRegistry = new FinalizationRegistry((dispose) => void dispose());
|
|
108
96
|
|
|
109
97
|
const dummySymbol = Symbol();
|
|
110
98
|
|
|
@@ -116,152 +104,132 @@ const dummySymbol = Symbol();
|
|
|
116
104
|
* @param {(number) => void} disposeFn
|
|
117
105
|
*/
|
|
118
106
|
export function registerDispose(resource, parentResource, id, disposeFn) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
disposeFn(id);
|
|
107
|
+
// While strictly speaking all components should handle their disposal,
|
|
108
|
+
// this acts as a last-resort to catch all missed drops through the JS GC.
|
|
109
|
+
// Mainly for two cases - (1) components which are long lived, that get shut
|
|
110
|
+
// down and (2) users that interface with low-level WASI APIs directly in JS
|
|
111
|
+
// for various reasons may end up leaning on JS GC inadvertantly.
|
|
112
|
+
function finalizer() {
|
|
113
|
+
// This has no functional purpose other than to pin a strong reference
|
|
114
|
+
// from the child resource's finalizer to the parent resource, to ensure
|
|
115
|
+
// that we can never finalize a parent resource before a child resource.
|
|
116
|
+
// This makes the generational JS GC become piecewise over child resource
|
|
117
|
+
// graphs (generational at each resource hierarchy level at least).
|
|
118
|
+
if (parentResource?.[dummySymbol]) {
|
|
119
|
+
return;
|
|
134
120
|
}
|
|
135
|
-
|
|
136
|
-
|
|
121
|
+
disposeFn(id);
|
|
122
|
+
}
|
|
123
|
+
finalizationRegistry.register(resource, finalizer, finalizer);
|
|
124
|
+
return finalizer;
|
|
137
125
|
}
|
|
138
126
|
|
|
139
127
|
export function earlyDispose(finalizer) {
|
|
140
|
-
|
|
141
|
-
|
|
128
|
+
finalizationRegistry.unregister(finalizer);
|
|
129
|
+
finalizer();
|
|
142
130
|
}
|
|
143
131
|
|
|
144
132
|
const _Error = Error;
|
|
145
133
|
const IoError = class Error extends _Error {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
134
|
+
constructor(payload) {
|
|
135
|
+
super(payload);
|
|
136
|
+
this.payload = payload;
|
|
137
|
+
}
|
|
138
|
+
toDebugString() {
|
|
139
|
+
return this.message;
|
|
140
|
+
}
|
|
153
141
|
};
|
|
154
142
|
|
|
155
143
|
function streamIoErrorCall(call, id, payload) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
// any invalid error is a trap
|
|
167
|
-
console.trace(e);
|
|
168
|
-
exit(1);
|
|
144
|
+
try {
|
|
145
|
+
return ioCall(call, id, payload);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
if (e.tag === "closed") {
|
|
148
|
+
throw e;
|
|
149
|
+
}
|
|
150
|
+
if (e.tag === "last-operation-failed") {
|
|
151
|
+
e.val = new IoError(Object.assign(new Error(e.val.message), e.val));
|
|
152
|
+
throw e;
|
|
169
153
|
}
|
|
154
|
+
// any invalid error is a trap
|
|
155
|
+
console.trace(e);
|
|
156
|
+
exit(1);
|
|
157
|
+
}
|
|
170
158
|
}
|
|
171
159
|
|
|
172
160
|
class InputStream {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
161
|
+
#id;
|
|
162
|
+
#streamType;
|
|
163
|
+
#finalizer;
|
|
164
|
+
read(len) {
|
|
165
|
+
return streamIoErrorCall(INPUT_STREAM_READ | this.#streamType, this.#id, len);
|
|
166
|
+
}
|
|
167
|
+
blockingRead(len) {
|
|
168
|
+
return streamIoErrorCall(INPUT_STREAM_BLOCKING_READ | this.#streamType, this.#id, len);
|
|
169
|
+
}
|
|
170
|
+
skip(len) {
|
|
171
|
+
return streamIoErrorCall(INPUT_STREAM_SKIP | this.#streamType, this.#id, len);
|
|
172
|
+
}
|
|
173
|
+
blockingSkip(len) {
|
|
174
|
+
return streamIoErrorCall(INPUT_STREAM_BLOCKING_SKIP | this.#streamType, this.#id, len);
|
|
175
|
+
}
|
|
176
|
+
subscribe() {
|
|
177
|
+
return pollableCreate(ioCall(INPUT_STREAM_SUBSCRIBE | this.#streamType, this.#id), this);
|
|
178
|
+
}
|
|
179
|
+
static _id(stream) {
|
|
180
|
+
return stream.#id;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* @param {FILE | SOCKET_TCP | STDIN | HTTP} streamType
|
|
184
|
+
*/
|
|
185
|
+
static _create(streamType, id) {
|
|
186
|
+
const stream = new InputStream();
|
|
187
|
+
stream.#id = id;
|
|
188
|
+
stream.#streamType = streamType;
|
|
189
|
+
let disposeFn;
|
|
190
|
+
switch (streamType) {
|
|
191
|
+
case FILE:
|
|
192
|
+
disposeFn = fileInputStreamDispose;
|
|
193
|
+
break;
|
|
194
|
+
case SOCKET_TCP:
|
|
195
|
+
disposeFn = socketTcpInputStreamDispose;
|
|
196
|
+
break;
|
|
197
|
+
case STDIN:
|
|
198
|
+
disposeFn = stdinInputStreamDispose;
|
|
199
|
+
break;
|
|
200
|
+
case HTTP:
|
|
201
|
+
disposeFn = httpInputStreamDispose;
|
|
202
|
+
break;
|
|
203
|
+
default:
|
|
204
|
+
throw new Error(
|
|
205
|
+
"wasi-io trap: Dispose function not created for stream type " + reverseMap[streamType],
|
|
208
206
|
);
|
|
209
207
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const stream = new InputStream();
|
|
218
|
-
stream.#id = id;
|
|
219
|
-
stream.#streamType = streamType;
|
|
220
|
-
let disposeFn;
|
|
221
|
-
switch (streamType) {
|
|
222
|
-
case FILE:
|
|
223
|
-
disposeFn = fileInputStreamDispose;
|
|
224
|
-
break;
|
|
225
|
-
case SOCKET_TCP:
|
|
226
|
-
disposeFn = socketTcpInputStreamDispose;
|
|
227
|
-
break;
|
|
228
|
-
case STDIN:
|
|
229
|
-
disposeFn = stdinInputStreamDispose;
|
|
230
|
-
break;
|
|
231
|
-
case HTTP:
|
|
232
|
-
disposeFn = httpInputStreamDispose;
|
|
233
|
-
break;
|
|
234
|
-
default:
|
|
235
|
-
throw new Error(
|
|
236
|
-
'wasi-io trap: Dispose function not created for stream type ' +
|
|
237
|
-
reverseMap[streamType]
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
stream.#finalizer = registerDispose(stream, null, id, disposeFn);
|
|
241
|
-
return stream;
|
|
242
|
-
}
|
|
243
|
-
[symbolDispose]() {
|
|
244
|
-
if (this.#finalizer) {
|
|
245
|
-
earlyDispose(this.#finalizer);
|
|
246
|
-
this.#finalizer = null;
|
|
247
|
-
}
|
|
208
|
+
stream.#finalizer = registerDispose(stream, null, id, disposeFn);
|
|
209
|
+
return stream;
|
|
210
|
+
}
|
|
211
|
+
[symbolDispose]() {
|
|
212
|
+
if (this.#finalizer) {
|
|
213
|
+
earlyDispose(this.#finalizer);
|
|
214
|
+
this.#finalizer = null;
|
|
248
215
|
}
|
|
216
|
+
}
|
|
249
217
|
}
|
|
250
218
|
|
|
251
219
|
function fileInputStreamDispose(id) {
|
|
252
|
-
|
|
220
|
+
ioCall(INPUT_STREAM_DISPOSE | FILE, id, null);
|
|
253
221
|
}
|
|
254
222
|
|
|
255
223
|
function socketTcpInputStreamDispose(id) {
|
|
256
|
-
|
|
224
|
+
ioCall(INPUT_STREAM_DISPOSE | SOCKET_TCP, id, null);
|
|
257
225
|
}
|
|
258
226
|
|
|
259
227
|
function stdinInputStreamDispose(id) {
|
|
260
|
-
|
|
228
|
+
ioCall(INPUT_STREAM_DISPOSE | STDIN, id, null);
|
|
261
229
|
}
|
|
262
230
|
|
|
263
231
|
function httpInputStreamDispose(id) {
|
|
264
|
-
|
|
232
|
+
ioCall(INPUT_STREAM_DISPOSE | HTTP, id, null);
|
|
265
233
|
}
|
|
266
234
|
|
|
267
235
|
export const inputStreamCreate = InputStream._create;
|
|
@@ -271,142 +239,119 @@ export const inputStreamId = InputStream._id;
|
|
|
271
239
|
delete InputStream._id;
|
|
272
240
|
|
|
273
241
|
class OutputStream {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
242
|
+
#id;
|
|
243
|
+
#streamType;
|
|
244
|
+
#finalizer;
|
|
245
|
+
checkWrite(len) {
|
|
246
|
+
return streamIoErrorCall(OUTPUT_STREAM_CHECK_WRITE | this.#streamType, this.#id, len);
|
|
247
|
+
}
|
|
248
|
+
write(buf) {
|
|
249
|
+
if (this.#streamType <= STDERR) {
|
|
250
|
+
return this.blockingWriteAndFlush(buf);
|
|
283
251
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
this.#id,
|
|
291
|
-
buf
|
|
292
|
-
);
|
|
252
|
+
return streamIoErrorCall(OUTPUT_STREAM_WRITE | this.#streamType, this.#id, buf);
|
|
253
|
+
}
|
|
254
|
+
blockingWriteAndFlush(buf) {
|
|
255
|
+
if (this.#streamType <= STDERR) {
|
|
256
|
+
const stream = this.#streamType === STDERR ? stderr : stdout;
|
|
257
|
+
return void stream.write(buf);
|
|
293
258
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
static _create(streamType, id) {
|
|
359
|
-
const stream = new OutputStream();
|
|
360
|
-
stream.#id = id;
|
|
361
|
-
stream.#streamType = streamType;
|
|
362
|
-
let disposeFn;
|
|
363
|
-
switch (streamType) {
|
|
364
|
-
case STDOUT:
|
|
365
|
-
disposeFn = stdoutOutputStreamDispose;
|
|
366
|
-
break;
|
|
367
|
-
case STDERR:
|
|
368
|
-
disposeFn = stderrOutputStreamDispose;
|
|
369
|
-
break;
|
|
370
|
-
case SOCKET_TCP:
|
|
371
|
-
disposeFn = socketTcpOutputStreamDispose;
|
|
372
|
-
break;
|
|
373
|
-
case FILE:
|
|
374
|
-
disposeFn = fileOutputStreamDispose;
|
|
375
|
-
break;
|
|
376
|
-
case HTTP:
|
|
377
|
-
return stream;
|
|
378
|
-
default:
|
|
379
|
-
throw new Error(
|
|
380
|
-
'wasi-io trap: Dispose function not created for stream type ' +
|
|
381
|
-
reverseMap[streamType]
|
|
382
|
-
);
|
|
383
|
-
}
|
|
384
|
-
stream.#finalizer = registerDispose(stream, null, id, disposeFn);
|
|
259
|
+
return streamIoErrorCall(
|
|
260
|
+
OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | this.#streamType,
|
|
261
|
+
this.#id,
|
|
262
|
+
buf,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
flush() {
|
|
266
|
+
return streamIoErrorCall(OUTPUT_STREAM_FLUSH | this.#streamType, this.#id);
|
|
267
|
+
}
|
|
268
|
+
blockingFlush() {
|
|
269
|
+
return streamIoErrorCall(OUTPUT_STREAM_BLOCKING_FLUSH | this.#streamType, this.#id);
|
|
270
|
+
}
|
|
271
|
+
writeZeroes(len) {
|
|
272
|
+
return streamIoErrorCall(OUTPUT_STREAM_WRITE_ZEROES | this.#streamType, this.#id, len);
|
|
273
|
+
}
|
|
274
|
+
blockingWriteZeroesAndFlush(len) {
|
|
275
|
+
return streamIoErrorCall(
|
|
276
|
+
OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH | this.#streamType,
|
|
277
|
+
this.#id,
|
|
278
|
+
len,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
splice(src, len) {
|
|
282
|
+
return streamIoErrorCall(OUTPUT_STREAM_SPLICE | this.#streamType, this.#id, {
|
|
283
|
+
src: src.#id,
|
|
284
|
+
len,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
blockingSplice(src, len) {
|
|
288
|
+
return streamIoErrorCall(OUTPUT_STREAM_BLOCKING_SPLICE | this.#streamType, this.#id, {
|
|
289
|
+
src: inputStreamId(src),
|
|
290
|
+
len,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
subscribe() {
|
|
294
|
+
return pollableCreate(ioCall(OUTPUT_STREAM_SUBSCRIBE | this.#streamType, this.#id));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
static _id(outputStream) {
|
|
298
|
+
return outputStream.#id;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* @param {OutputStreamType} streamType
|
|
302
|
+
* @param {any} createPayload
|
|
303
|
+
*/
|
|
304
|
+
static _create(streamType, id) {
|
|
305
|
+
const stream = new OutputStream();
|
|
306
|
+
stream.#id = id;
|
|
307
|
+
stream.#streamType = streamType;
|
|
308
|
+
let disposeFn;
|
|
309
|
+
switch (streamType) {
|
|
310
|
+
case STDOUT:
|
|
311
|
+
disposeFn = stdoutOutputStreamDispose;
|
|
312
|
+
break;
|
|
313
|
+
case STDERR:
|
|
314
|
+
disposeFn = stderrOutputStreamDispose;
|
|
315
|
+
break;
|
|
316
|
+
case SOCKET_TCP:
|
|
317
|
+
disposeFn = socketTcpOutputStreamDispose;
|
|
318
|
+
break;
|
|
319
|
+
case FILE:
|
|
320
|
+
disposeFn = fileOutputStreamDispose;
|
|
321
|
+
break;
|
|
322
|
+
case HTTP:
|
|
385
323
|
return stream;
|
|
324
|
+
default:
|
|
325
|
+
throw new Error(
|
|
326
|
+
"wasi-io trap: Dispose function not created for stream type " + reverseMap[streamType],
|
|
327
|
+
);
|
|
386
328
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
329
|
+
stream.#finalizer = registerDispose(stream, null, id, disposeFn);
|
|
330
|
+
return stream;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
[symbolDispose]() {
|
|
334
|
+
if (this.#finalizer) {
|
|
335
|
+
earlyDispose(this.#finalizer);
|
|
336
|
+
this.#finalizer = null;
|
|
393
337
|
}
|
|
338
|
+
}
|
|
394
339
|
}
|
|
395
340
|
|
|
396
341
|
function stdoutOutputStreamDispose(id) {
|
|
397
|
-
|
|
342
|
+
ioCall(OUTPUT_STREAM_DISPOSE | STDOUT, id);
|
|
398
343
|
}
|
|
399
344
|
|
|
400
345
|
function stderrOutputStreamDispose(id) {
|
|
401
|
-
|
|
346
|
+
ioCall(OUTPUT_STREAM_DISPOSE | STDERR, id);
|
|
402
347
|
}
|
|
403
348
|
|
|
404
349
|
function socketTcpOutputStreamDispose(id) {
|
|
405
|
-
|
|
350
|
+
ioCall(OUTPUT_STREAM_DISPOSE | SOCKET_TCP, id);
|
|
406
351
|
}
|
|
407
352
|
|
|
408
353
|
function fileOutputStreamDispose(id) {
|
|
409
|
-
|
|
354
|
+
ioCall(OUTPUT_STREAM_DISPOSE | FILE, id);
|
|
410
355
|
}
|
|
411
356
|
|
|
412
357
|
export const outputStreamCreate = OutputStream._create;
|
|
@@ -420,117 +365,104 @@ export const error = { Error: IoError };
|
|
|
420
365
|
export const streams = { InputStream, OutputStream };
|
|
421
366
|
|
|
422
367
|
function pollableDispose(id) {
|
|
423
|
-
|
|
368
|
+
ioCall(POLL_POLLABLE_DISPOSE, id);
|
|
424
369
|
}
|
|
425
370
|
|
|
426
|
-
const rep = Symbol.for(
|
|
371
|
+
const rep = Symbol.for("cabiRep");
|
|
427
372
|
|
|
428
373
|
class Pollable {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
[symbolDispose]() {
|
|
448
|
-
if (this.#finalizer && this[rep]) {
|
|
449
|
-
earlyDispose(this.#finalizer);
|
|
450
|
-
this.#finalizer = null;
|
|
451
|
-
}
|
|
374
|
+
#finalizer;
|
|
375
|
+
ready() {
|
|
376
|
+
return ioCall(POLL_POLLABLE_READY, this[rep]);
|
|
377
|
+
}
|
|
378
|
+
block() {
|
|
379
|
+
ioCall(POLL_POLLABLE_BLOCK, this[rep]);
|
|
380
|
+
}
|
|
381
|
+
static _create(id, parent) {
|
|
382
|
+
const pollable = new Pollable();
|
|
383
|
+
pollable[rep] = id;
|
|
384
|
+
pollable.#finalizer = registerDispose(pollable, parent, id, pollableDispose);
|
|
385
|
+
return pollable;
|
|
386
|
+
}
|
|
387
|
+
[symbolDispose]() {
|
|
388
|
+
if (this.#finalizer && this[rep]) {
|
|
389
|
+
earlyDispose(this.#finalizer);
|
|
390
|
+
this.#finalizer = null;
|
|
452
391
|
}
|
|
392
|
+
}
|
|
453
393
|
}
|
|
454
394
|
|
|
455
|
-
const cabiLowerSymbol = Symbol.for(
|
|
395
|
+
const cabiLowerSymbol = Symbol.for("cabiLower");
|
|
456
396
|
const T_FLAG = 1 << 30;
|
|
457
397
|
|
|
458
|
-
Pollable.prototype.ready[cabiLowerSymbol] = function({
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
return ready ? 1 : 0;
|
|
465
|
-
};
|
|
398
|
+
Pollable.prototype.ready[cabiLowerSymbol] = function ({ resourceTables: [table] }) {
|
|
399
|
+
return function pollableReady(handle) {
|
|
400
|
+
const rep = table[(handle << 1) + 1] & ~T_FLAG;
|
|
401
|
+
const ready = ioCall(POLL_POLLABLE_READY, rep);
|
|
402
|
+
return ready ? 1 : 0;
|
|
403
|
+
};
|
|
466
404
|
};
|
|
467
405
|
|
|
468
|
-
Pollable.prototype.block[cabiLowerSymbol] = function({
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
ioCall(POLL_POLLABLE_BLOCK, rep);
|
|
474
|
-
};
|
|
406
|
+
Pollable.prototype.block[cabiLowerSymbol] = function ({ resourceTables: [table] }) {
|
|
407
|
+
return function pollableBlock(handle) {
|
|
408
|
+
const rep = table[(handle << 1) + 1] & ~T_FLAG;
|
|
409
|
+
ioCall(POLL_POLLABLE_BLOCK, rep);
|
|
410
|
+
};
|
|
475
411
|
};
|
|
476
412
|
|
|
477
|
-
Pollable[Symbol.for(
|
|
478
|
-
|
|
413
|
+
Pollable[Symbol.for("cabiDispose")] = function pollableDispose(rep) {
|
|
414
|
+
ioCall(POLL_POLLABLE_DISPOSE, rep);
|
|
479
415
|
};
|
|
480
416
|
|
|
481
417
|
export const pollableCreate = Pollable._create;
|
|
482
418
|
delete Pollable._create;
|
|
483
419
|
|
|
484
420
|
export const poll = {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
421
|
+
Pollable,
|
|
422
|
+
poll(list) {
|
|
423
|
+
return ioCall(
|
|
424
|
+
POLL_POLL_LIST,
|
|
425
|
+
null,
|
|
426
|
+
list.map((pollable) => pollable[rep]),
|
|
427
|
+
);
|
|
428
|
+
},
|
|
493
429
|
};
|
|
494
430
|
|
|
495
|
-
poll.poll[cabiLowerSymbol] = function({
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
ret[0] = ptr;
|
|
513
|
-
ret[1] = result.length;
|
|
514
|
-
return retptr;
|
|
515
|
-
};
|
|
431
|
+
poll.poll[cabiLowerSymbol] = function ({ memory, realloc, resourceTables: [table] }) {
|
|
432
|
+
return function pollPollList(listPtr, len, retptr) {
|
|
433
|
+
const handleList = new Uint32Array(memory.buffer, listPtr, len);
|
|
434
|
+
const repList = Array(len);
|
|
435
|
+
for (let i = 0; i < len; i++) {
|
|
436
|
+
const handle = handleList[i];
|
|
437
|
+
repList[i] = table[(handle << 1) + 1] & ~T_FLAG;
|
|
438
|
+
}
|
|
439
|
+
const result = ioCall(POLL_POLL_LIST, null, repList);
|
|
440
|
+
const ptr = realloc(0, 0, 4, result.byteLength);
|
|
441
|
+
const out = new Uint32Array(memory.buffer, ptr, result.length);
|
|
442
|
+
out.set(result);
|
|
443
|
+
const ret = new Uint32Array(memory.buffer, retptr, 2);
|
|
444
|
+
ret[0] = ptr;
|
|
445
|
+
ret[1] = result.length;
|
|
446
|
+
return retptr;
|
|
447
|
+
};
|
|
516
448
|
};
|
|
517
449
|
|
|
518
450
|
export function createPoll(call, id, initPayload) {
|
|
519
|
-
|
|
451
|
+
return pollableCreate(ioCall(call, id, initPayload));
|
|
520
452
|
}
|
|
521
453
|
|
|
522
454
|
export function createPollLower(call, id, table) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
455
|
+
return function (initPayload) {
|
|
456
|
+
const rep = ioCall(call, id, initPayload);
|
|
457
|
+
const free = table[0] & ~T_FLAG;
|
|
458
|
+
if (free === 0) {
|
|
459
|
+
table.push(0);
|
|
460
|
+
table.push(rep | T_FLAG);
|
|
461
|
+
return (table.length >> 1) - 1;
|
|
462
|
+
}
|
|
463
|
+
table[0] = table[free << 1];
|
|
464
|
+
table[free << 1] = 0;
|
|
465
|
+
table[(free << 1) + 1] = rep | T_FLAG;
|
|
466
|
+
return free;
|
|
467
|
+
};
|
|
536
468
|
}
|