@bytecodealliance/preview2-shim 0.18.1 → 0.20.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.
- package/README.md +15 -15
- package/dist/browser/cli.d.ts +16 -0
- package/dist/browser/cli.js +109 -0
- package/dist/browser/clocks.d.ts +3 -0
- package/dist/browser/clocks.js +36 -0
- package/dist/browser/config.d.ts +2 -0
- package/{lib → dist}/browser/config.js +2 -4
- package/dist/browser/environment.d.ts +5 -0
- package/dist/browser/environment.js +24 -0
- package/dist/browser/filesystem.d.ts +132 -0
- package/dist/browser/filesystem.js +488 -0
- package/dist/browser/http.d.ts +4 -0
- package/dist/browser/http.js +643 -0
- package/dist/browser/index.d.ts +7 -0
- package/dist/browser/index.js +7 -0
- package/dist/browser/io.d.ts +58 -0
- package/dist/browser/io.js +205 -0
- package/dist/browser/random.d.ts +4 -0
- package/dist/browser/random.js +49 -0
- package/dist/browser/sockets.d.ts +8 -0
- package/dist/browser/sockets.js +66 -0
- package/dist/common/instantiation.d.ts +97 -0
- package/dist/common/instantiation.js +228 -0
- package/dist/io/calls.d.ts +91 -0
- package/{lib → dist}/io/calls.js +4 -19
- package/dist/io/worker-http.d.ts +17 -0
- package/dist/io/worker-http.js +192 -0
- package/dist/io/worker-io.d.ts +84 -0
- package/dist/io/worker-io.js +381 -0
- package/dist/io/worker-socket-tcp.d.ts +34 -0
- package/dist/io/worker-socket-tcp.js +251 -0
- package/dist/io/worker-socket-udp.d.ts +54 -0
- package/dist/io/worker-socket-udp.js +493 -0
- package/dist/io/worker-sockets.d.ts +32 -0
- package/dist/io/worker-sockets.js +265 -0
- package/dist/io/worker-thread.d.ts +73 -0
- package/dist/io/worker-thread.js +794 -0
- package/dist/nodejs/cli.d.ts +30 -0
- package/dist/nodejs/cli.js +86 -0
- package/dist/nodejs/clocks.d.ts +3 -0
- package/dist/nodejs/clocks.js +61 -0
- package/dist/nodejs/filesystem.d.ts +113 -0
- package/dist/nodejs/filesystem.js +761 -0
- package/dist/nodejs/http.d.ts +82 -0
- package/dist/nodejs/http.js +674 -0
- package/dist/nodejs/index.d.ts +7 -0
- package/dist/nodejs/index.js +7 -0
- package/dist/nodejs/io.d.ts +1 -0
- package/dist/nodejs/io.js +1 -0
- package/dist/nodejs/random.d.ts +4 -0
- package/dist/nodejs/random.js +42 -0
- package/dist/nodejs/sockets.d.ts +21 -0
- package/dist/nodejs/sockets.js +482 -0
- package/dist/synckit/index.d.ts +2 -0
- package/dist/synckit/index.js +117 -0
- package/package.json +28 -15
- package/types/instantiation.d.ts +7 -7
- package/lib/browser/cli.js +0 -135
- package/lib/browser/clocks.js +0 -39
- package/lib/browser/environment.js +0 -29
- package/lib/browser/filesystem.js +0 -503
- package/lib/browser/http.js +0 -707
- package/lib/browser/index.js +0 -9
- package/lib/browser/io.js +0 -262
- package/lib/browser/random.js +0 -56
- package/lib/browser/sockets.js +0 -88
- package/lib/common/instantiation.js +0 -253
- package/lib/io/worker-http.js +0 -206
- package/lib/io/worker-io.js +0 -468
- package/lib/io/worker-socket-tcp.js +0 -331
- package/lib/io/worker-socket-udp.js +0 -587
- package/lib/io/worker-sockets.js +0 -364
- package/lib/io/worker-thread.js +0 -1051
- package/lib/nodejs/cli.js +0 -109
- package/lib/nodejs/clocks.js +0 -67
- package/lib/nodejs/filesystem.js +0 -829
- package/lib/nodejs/http.js +0 -764
- package/lib/nodejs/index.js +0 -9
- package/lib/nodejs/io.js +0 -1
- package/lib/nodejs/random.js +0 -49
- package/lib/nodejs/sockets.js +0 -565
- package/lib/synckit/index.js +0 -127
package/lib/io/worker-http.js
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { createReadableStream, getStreamOrThrow } from "./worker-thread.js";
|
|
2
|
-
import { createServer, request as httpRequest, Agent as HttpAgent } from "node:http";
|
|
3
|
-
import { request as httpsRequest, Agent as HttpsAgent } from "node:https";
|
|
4
|
-
import { parentPort } from "node:worker_threads";
|
|
5
|
-
import { HTTP_SERVER_INCOMING_HANDLER } from "./calls.js";
|
|
6
|
-
|
|
7
|
-
const agentOptions = {
|
|
8
|
-
keepAlive: true,
|
|
9
|
-
};
|
|
10
|
-
const httpAgent = new HttpAgent(agentOptions);
|
|
11
|
-
const httpsAgent = new HttpsAgent(agentOptions);
|
|
12
|
-
|
|
13
|
-
const servers = new Map();
|
|
14
|
-
|
|
15
|
-
let responseCnt = 0;
|
|
16
|
-
const responses = new Map();
|
|
17
|
-
|
|
18
|
-
export async function stopHttpServer(id) {
|
|
19
|
-
await new Promise((resolve) => servers.get(id).close(resolve));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function clearOutgoingResponse(id) {
|
|
23
|
-
responses.delete(id);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export async function getHttpServerAddress(id) {
|
|
27
|
-
return servers.get(id).address();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function setOutgoingResponse(id, { statusCode, headers, streamId }) {
|
|
31
|
-
const response = responses.get(id);
|
|
32
|
-
const textDecoder = new TextDecoder();
|
|
33
|
-
response.writeHead(
|
|
34
|
-
statusCode,
|
|
35
|
-
Object.fromEntries(headers.map(([key, val]) => [key, textDecoder.decode(val)])),
|
|
36
|
-
);
|
|
37
|
-
response.flushHeaders();
|
|
38
|
-
const { stream } = getStreamOrThrow(streamId);
|
|
39
|
-
stream.pipe(response);
|
|
40
|
-
responses.delete(id);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function startHttpServer(id, { port, host }) {
|
|
44
|
-
const server = createServer((req, res) => {
|
|
45
|
-
// create the streams and their ids
|
|
46
|
-
const streamId = createReadableStream(req);
|
|
47
|
-
const responseId = ++responseCnt;
|
|
48
|
-
parentPort.postMessage({
|
|
49
|
-
type: HTTP_SERVER_INCOMING_HANDLER,
|
|
50
|
-
id,
|
|
51
|
-
payload: {
|
|
52
|
-
responseId,
|
|
53
|
-
method: req.method,
|
|
54
|
-
host: req.headers.host || host || "localhost",
|
|
55
|
-
pathWithQuery: req.url,
|
|
56
|
-
headers: Object.entries(req.headersDistinct).flatMap(([key, val]) =>
|
|
57
|
-
val.map((val) => [key, val]),
|
|
58
|
-
),
|
|
59
|
-
streamId,
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
responses.set(responseId, res);
|
|
63
|
-
});
|
|
64
|
-
await new Promise((resolve, reject) => {
|
|
65
|
-
server.listen(port, host, resolve);
|
|
66
|
-
server.on("error", reject);
|
|
67
|
-
});
|
|
68
|
-
servers.set(id, server);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export async function createHttpRequest(
|
|
72
|
-
method,
|
|
73
|
-
scheme,
|
|
74
|
-
authority,
|
|
75
|
-
pathWithQuery,
|
|
76
|
-
headers,
|
|
77
|
-
bodyId,
|
|
78
|
-
connectTimeout,
|
|
79
|
-
betweenBytesTimeout,
|
|
80
|
-
firstByteTimeout,
|
|
81
|
-
) {
|
|
82
|
-
let stream = null;
|
|
83
|
-
if (bodyId) {
|
|
84
|
-
try {
|
|
85
|
-
({ stream } = getStreamOrThrow(bodyId));
|
|
86
|
-
} catch (e) {
|
|
87
|
-
if (e.tag === "closed") {
|
|
88
|
-
throw {
|
|
89
|
-
tag: "internal-error",
|
|
90
|
-
val: "Unexpected closed body stream",
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
// it should never be possible for the body stream to already
|
|
94
|
-
// be closed, or for there to be a write error
|
|
95
|
-
// we therefore just throw internal error here
|
|
96
|
-
if (e.tag === "last-operation-failed") {
|
|
97
|
-
throw {
|
|
98
|
-
tag: "internal-error",
|
|
99
|
-
val: e.val,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
// entirely unknown error -> trap
|
|
103
|
-
throw e;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
try {
|
|
107
|
-
// Make a request
|
|
108
|
-
let req;
|
|
109
|
-
switch (scheme) {
|
|
110
|
-
case "http:":
|
|
111
|
-
req = httpRequest({
|
|
112
|
-
agent: httpAgent,
|
|
113
|
-
method,
|
|
114
|
-
host: authority.split(":")[0],
|
|
115
|
-
port: authority.split(":")[1],
|
|
116
|
-
path: pathWithQuery,
|
|
117
|
-
timeout: connectTimeout && Number(connectTimeout / 1_000_000n),
|
|
118
|
-
});
|
|
119
|
-
break;
|
|
120
|
-
case "https:":
|
|
121
|
-
req = httpsRequest({
|
|
122
|
-
agent: httpsAgent,
|
|
123
|
-
method,
|
|
124
|
-
host: authority.split(":")[0],
|
|
125
|
-
port: authority.split(":")[1],
|
|
126
|
-
path: pathWithQuery,
|
|
127
|
-
timeout: connectTimeout && Number(connectTimeout / 1_000_000n),
|
|
128
|
-
});
|
|
129
|
-
break;
|
|
130
|
-
default:
|
|
131
|
-
throw { tag: "HTTP-protocol-error" };
|
|
132
|
-
}
|
|
133
|
-
for (const [key, value] of headers) {
|
|
134
|
-
req.appendHeader(key, value);
|
|
135
|
-
}
|
|
136
|
-
req.flushHeaders();
|
|
137
|
-
if (stream) {
|
|
138
|
-
stream.pipe(req);
|
|
139
|
-
} else {
|
|
140
|
-
req.end();
|
|
141
|
-
}
|
|
142
|
-
const res = await new Promise((resolve, reject) => {
|
|
143
|
-
req.once("timeout", () => {
|
|
144
|
-
reject({
|
|
145
|
-
tag: "connection-timeout",
|
|
146
|
-
});
|
|
147
|
-
req.destroy();
|
|
148
|
-
});
|
|
149
|
-
req.once("response", resolve);
|
|
150
|
-
req.once("close", () => reject);
|
|
151
|
-
req.once("error", reject);
|
|
152
|
-
});
|
|
153
|
-
if (firstByteTimeout) {
|
|
154
|
-
res.setTimeout(Number(firstByteTimeout / 1_000_000n));
|
|
155
|
-
}
|
|
156
|
-
if (betweenBytesTimeout) {
|
|
157
|
-
res.once("readable", () => {
|
|
158
|
-
res.setTimeout(Number(betweenBytesTimeout / 1_000_000n));
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
const bodyStreamId = createReadableStream(res);
|
|
162
|
-
return {
|
|
163
|
-
status: res.statusCode,
|
|
164
|
-
headers: Array.from(Object.entries(res.headers)),
|
|
165
|
-
bodyStreamId,
|
|
166
|
-
};
|
|
167
|
-
} catch (e) {
|
|
168
|
-
if (e?.tag) {
|
|
169
|
-
throw e;
|
|
170
|
-
}
|
|
171
|
-
const err = getFirstError(e);
|
|
172
|
-
switch (err.code) {
|
|
173
|
-
case "ECONNRESET":
|
|
174
|
-
throw { tag: "HTTP-protocol-error" };
|
|
175
|
-
case "ENOTFOUND":
|
|
176
|
-
throw {
|
|
177
|
-
tag: "DNS-error",
|
|
178
|
-
val: {
|
|
179
|
-
rcode: err.code,
|
|
180
|
-
infoCode: err.errno < 0 ? -err.errno : err.errno,
|
|
181
|
-
},
|
|
182
|
-
};
|
|
183
|
-
case "ECONNREFUSED":
|
|
184
|
-
throw {
|
|
185
|
-
tag: "connection-refused",
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
throw {
|
|
189
|
-
tag: "internal-error",
|
|
190
|
-
val: err.toString(),
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function getFirstError(e) {
|
|
196
|
-
if (typeof e !== "object" || e === null) {
|
|
197
|
-
return e;
|
|
198
|
-
}
|
|
199
|
-
if (e.cause) {
|
|
200
|
-
return getFirstError(e.cause);
|
|
201
|
-
}
|
|
202
|
-
if (e instanceof AggregateError) {
|
|
203
|
-
return getFirstError(e.errors[0]);
|
|
204
|
-
}
|
|
205
|
-
return e;
|
|
206
|
-
}
|
package/lib/io/worker-io.js
DELETED
|
@@ -1,468 +0,0 @@
|
|
|
1
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
-
import { createSyncFn } from "../synckit/index.js";
|
|
3
|
-
import {
|
|
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
|
-
|
|
38
|
-
const _rawDebug = nodeProcess._rawDebug || console.error.bind(console);
|
|
39
|
-
|
|
40
|
-
const workerPath = fileURLToPath(new URL("./worker-thread.js", import.meta.url));
|
|
41
|
-
|
|
42
|
-
const httpIncomingHandlers = new Map();
|
|
43
|
-
export function registerIncomingHttpHandler(id, handler) {
|
|
44
|
-
httpIncomingHandlers.set(id, handler);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const instanceId = Math.round(Math.random() * 1000).toString();
|
|
48
|
-
const DEBUG_DEFAULT = false;
|
|
49
|
-
const DEBUG =
|
|
50
|
-
env.PREVIEW2_SHIM_DEBUG === "0" ? false : env.PREVIEW2_SHIM_DEBUG === "1" ? true : DEBUG_DEFAULT;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @type {(call: number, id: number | null, payload: any) -> any}
|
|
54
|
-
*/
|
|
55
|
-
export let ioCall = createSyncFn(workerPath, DEBUG, (type, id, 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);
|
|
66
|
-
});
|
|
67
|
-
if (DEBUG) {
|
|
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
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
94
|
-
|
|
95
|
-
const finalizationRegistry = new FinalizationRegistry((dispose) => void dispose());
|
|
96
|
-
|
|
97
|
-
const dummySymbol = Symbol();
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
* @param {any} resource
|
|
102
|
-
* @param {any} parentResource
|
|
103
|
-
* @param {number} id
|
|
104
|
-
* @param {(number) => void} disposeFn
|
|
105
|
-
*/
|
|
106
|
-
export function registerDispose(resource, parentResource, id, disposeFn) {
|
|
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;
|
|
120
|
-
}
|
|
121
|
-
disposeFn(id);
|
|
122
|
-
}
|
|
123
|
-
finalizationRegistry.register(resource, finalizer, finalizer);
|
|
124
|
-
return finalizer;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function earlyDispose(finalizer) {
|
|
128
|
-
finalizationRegistry.unregister(finalizer);
|
|
129
|
-
finalizer();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const _Error = Error;
|
|
133
|
-
const IoError = class Error extends _Error {
|
|
134
|
-
constructor(payload) {
|
|
135
|
-
super(payload);
|
|
136
|
-
this.payload = payload;
|
|
137
|
-
}
|
|
138
|
-
toDebugString() {
|
|
139
|
-
return this.message;
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
function streamIoErrorCall(call, id, payload) {
|
|
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;
|
|
153
|
-
}
|
|
154
|
-
// any invalid error is a trap
|
|
155
|
-
console.trace(e);
|
|
156
|
-
exit(1);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
class InputStream {
|
|
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],
|
|
206
|
-
);
|
|
207
|
-
}
|
|
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;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function fileInputStreamDispose(id) {
|
|
220
|
-
ioCall(INPUT_STREAM_DISPOSE | FILE, id, null);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function socketTcpInputStreamDispose(id) {
|
|
224
|
-
ioCall(INPUT_STREAM_DISPOSE | SOCKET_TCP, id, null);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function stdinInputStreamDispose(id) {
|
|
228
|
-
ioCall(INPUT_STREAM_DISPOSE | STDIN, id, null);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function httpInputStreamDispose(id) {
|
|
232
|
-
ioCall(INPUT_STREAM_DISPOSE | HTTP, id, null);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
export const inputStreamCreate = InputStream._create;
|
|
236
|
-
delete InputStream._create;
|
|
237
|
-
|
|
238
|
-
export const inputStreamId = InputStream._id;
|
|
239
|
-
delete InputStream._id;
|
|
240
|
-
|
|
241
|
-
class OutputStream {
|
|
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);
|
|
251
|
-
}
|
|
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);
|
|
258
|
-
}
|
|
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:
|
|
323
|
-
return stream;
|
|
324
|
-
default:
|
|
325
|
-
throw new Error(
|
|
326
|
-
"wasi-io trap: Dispose function not created for stream type " + reverseMap[streamType],
|
|
327
|
-
);
|
|
328
|
-
}
|
|
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;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function stdoutOutputStreamDispose(id) {
|
|
342
|
-
ioCall(OUTPUT_STREAM_DISPOSE | STDOUT, id);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function stderrOutputStreamDispose(id) {
|
|
346
|
-
ioCall(OUTPUT_STREAM_DISPOSE | STDERR, id);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function socketTcpOutputStreamDispose(id) {
|
|
350
|
-
ioCall(OUTPUT_STREAM_DISPOSE | SOCKET_TCP, id);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function fileOutputStreamDispose(id) {
|
|
354
|
-
ioCall(OUTPUT_STREAM_DISPOSE | FILE, id);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
export const outputStreamCreate = OutputStream._create;
|
|
358
|
-
delete OutputStream._create;
|
|
359
|
-
|
|
360
|
-
export const outputStreamId = OutputStream._id;
|
|
361
|
-
delete OutputStream._id;
|
|
362
|
-
|
|
363
|
-
export const error = { Error: IoError };
|
|
364
|
-
|
|
365
|
-
export const streams = { InputStream, OutputStream };
|
|
366
|
-
|
|
367
|
-
function pollableDispose(id) {
|
|
368
|
-
ioCall(POLL_POLLABLE_DISPOSE, id);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const rep = Symbol.for("cabiRep");
|
|
372
|
-
|
|
373
|
-
class Pollable {
|
|
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;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const cabiLowerSymbol = Symbol.for("cabiLower");
|
|
396
|
-
const T_FLAG = 1 << 30;
|
|
397
|
-
|
|
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
|
-
};
|
|
404
|
-
};
|
|
405
|
-
|
|
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
|
-
};
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
Pollable[Symbol.for("cabiDispose")] = function pollableDispose(rep) {
|
|
414
|
-
ioCall(POLL_POLLABLE_DISPOSE, rep);
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
export const pollableCreate = Pollable._create;
|
|
418
|
-
delete Pollable._create;
|
|
419
|
-
|
|
420
|
-
export const poll = {
|
|
421
|
-
Pollable,
|
|
422
|
-
poll(list) {
|
|
423
|
-
return ioCall(
|
|
424
|
-
POLL_POLL_LIST,
|
|
425
|
-
null,
|
|
426
|
-
list.map((pollable) => pollable[rep]),
|
|
427
|
-
);
|
|
428
|
-
},
|
|
429
|
-
};
|
|
430
|
-
|
|
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
|
-
};
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
export function createPoll(call, id, initPayload) {
|
|
451
|
-
return pollableCreate(ioCall(call, id, initPayload));
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
export function createPollLower(call, id, table) {
|
|
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
|
-
};
|
|
468
|
-
}
|