@bytecodealliance/preview2-shim 0.18.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +464 -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 +227 -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 +375 -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 +492 -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 +791 -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 +758 -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 +26 -13
- 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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { streams as StreamsNamespace } from "../../types/io.js";
|
|
2
|
+
declare const symbolDispose: symbol;
|
|
3
|
+
type IInputStream = StreamsNamespace.InputStream;
|
|
4
|
+
type IOutputStream = StreamsNamespace.OutputStream;
|
|
5
|
+
export declare function registerIncomingHttpHandler(id: any, handler: any): void;
|
|
6
|
+
/**
|
|
7
|
+
* @type {(call: number, id: number | null, payload: any) -> any}
|
|
8
|
+
*/
|
|
9
|
+
export declare let ioCall: (...args: any[]) => any;
|
|
10
|
+
export declare function registerDispose(resource: any, parentResource: any, id: number, disposeFn: (id: number) => void): () => void;
|
|
11
|
+
export declare function earlyDispose(finalizer: any): void;
|
|
12
|
+
declare class InputStream implements IInputStream {
|
|
13
|
+
#private;
|
|
14
|
+
[symbolDispose]: () => void;
|
|
15
|
+
read(len: any): any;
|
|
16
|
+
blockingRead(len: any): any;
|
|
17
|
+
skip(len: any): any;
|
|
18
|
+
blockingSkip(len: any): any;
|
|
19
|
+
subscribe(): Pollable;
|
|
20
|
+
static _id(stream: any): any;
|
|
21
|
+
/**
|
|
22
|
+
* @param {FILE | SOCKET_TCP | STDIN | HTTP} streamType
|
|
23
|
+
*/
|
|
24
|
+
static _create(streamType: any, id: any): InputStream;
|
|
25
|
+
}
|
|
26
|
+
export declare const inputStreamCreate: typeof InputStream._create;
|
|
27
|
+
export declare const inputStreamId: typeof InputStream._id;
|
|
28
|
+
declare class OutputStream implements IOutputStream {
|
|
29
|
+
#private;
|
|
30
|
+
[symbolDispose]: () => void;
|
|
31
|
+
checkWrite(): any;
|
|
32
|
+
write(buf: any): any;
|
|
33
|
+
blockingWriteAndFlush(buf: any): any;
|
|
34
|
+
flush(): any;
|
|
35
|
+
blockingFlush(): any;
|
|
36
|
+
writeZeroes(len: any): any;
|
|
37
|
+
blockingWriteZeroesAndFlush(len: any): any;
|
|
38
|
+
splice(src: any, len: any): any;
|
|
39
|
+
blockingSplice(src: any, len: any): any;
|
|
40
|
+
subscribe(): Pollable;
|
|
41
|
+
static _id(outputStream: any): any;
|
|
42
|
+
/**
|
|
43
|
+
* @param {OutputStreamType} streamType
|
|
44
|
+
* @param {any} createPayload
|
|
45
|
+
*/
|
|
46
|
+
static _create(streamType: any, id: any): OutputStream;
|
|
47
|
+
}
|
|
48
|
+
export declare const outputStreamCreate: typeof OutputStream._create;
|
|
49
|
+
export declare const outputStreamId: typeof OutputStream._id;
|
|
50
|
+
export declare const error: {
|
|
51
|
+
Error: {
|
|
52
|
+
new (payload: any): {
|
|
53
|
+
payload: any;
|
|
54
|
+
toDebugString(): string;
|
|
55
|
+
name: string;
|
|
56
|
+
message: string;
|
|
57
|
+
stack?: string;
|
|
58
|
+
cause?: unknown;
|
|
59
|
+
};
|
|
60
|
+
isError(error: unknown): error is Error;
|
|
61
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
62
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
63
|
+
stackTraceLimit: number;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
export declare const streams: {
|
|
67
|
+
InputStream: typeof InputStream;
|
|
68
|
+
OutputStream: typeof OutputStream;
|
|
69
|
+
};
|
|
70
|
+
declare class Pollable {
|
|
71
|
+
#private;
|
|
72
|
+
[symbolDispose]: () => void;
|
|
73
|
+
ready(): any;
|
|
74
|
+
block(): void;
|
|
75
|
+
static _create(id: any, parent: any): Pollable;
|
|
76
|
+
}
|
|
77
|
+
export declare const pollableCreate: typeof Pollable._create;
|
|
78
|
+
export declare const poll: {
|
|
79
|
+
Pollable: typeof Pollable;
|
|
80
|
+
poll(list: any): any;
|
|
81
|
+
};
|
|
82
|
+
export declare function createPoll(call: any, id: any, initPayload: any): Pollable;
|
|
83
|
+
export declare function createPollLower(call: any, id: any, table: any): (initPayload: any) => number;
|
|
84
|
+
export {};
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { createSyncFn } from "../synckit/index.js";
|
|
3
|
+
import { CALL_MASK, CALL_TYPE_MASK, FILE, HTTP_SERVER_INCOMING_HANDLER, HTTP, INPUT_STREAM_BLOCKING_READ, INPUT_STREAM_BLOCKING_SKIP, INPUT_STREAM_DISPOSE, INPUT_STREAM_READ, INPUT_STREAM_SKIP, INPUT_STREAM_SUBSCRIBE, OUTPUT_STREAM_BLOCKING_FLUSH, OUTPUT_STREAM_BLOCKING_SPLICE, OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH, OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH, OUTPUT_STREAM_CHECK_WRITE, OUTPUT_STREAM_DISPOSE, OUTPUT_STREAM_FLUSH, OUTPUT_STREAM_SPLICE, OUTPUT_STREAM_SUBSCRIBE, OUTPUT_STREAM_WRITE_ZEROES, OUTPUT_STREAM_WRITE, POLL_POLL_LIST, POLL_POLLABLE_BLOCK, POLL_POLLABLE_DISPOSE, POLL_POLLABLE_READY, SOCKET_TCP, STDERR, STDIN, STDOUT, reverseMap, } from "./calls.js";
|
|
4
|
+
import nodeProcess, { exit, stderr, stdout, env } from "node:process";
|
|
5
|
+
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
6
|
+
const _rawDebug = "_rawDebug" in nodeProcess
|
|
7
|
+
? nodeProcess._rawDebug
|
|
8
|
+
: console.error.bind(console);
|
|
9
|
+
const workerPath = fileURLToPath(new URL("./worker-thread.js", import.meta.url));
|
|
10
|
+
const httpIncomingHandlers = new Map();
|
|
11
|
+
export function registerIncomingHttpHandler(id, handler) {
|
|
12
|
+
httpIncomingHandlers.set(id, handler);
|
|
13
|
+
}
|
|
14
|
+
const instanceId = Math.round(Math.random() * 1000).toString();
|
|
15
|
+
const DEBUG_DEFAULT = false;
|
|
16
|
+
const DEBUG = env.PREVIEW2_SHIM_DEBUG === "0" ? false : env.PREVIEW2_SHIM_DEBUG === "1" ? true : DEBUG_DEFAULT;
|
|
17
|
+
/**
|
|
18
|
+
* @type {(call: number, id: number | null, payload: any) -> any}
|
|
19
|
+
*/
|
|
20
|
+
export let ioCall = createSyncFn(workerPath, DEBUG, (type, id, payload) => {
|
|
21
|
+
// 'callbacks' from the worker
|
|
22
|
+
// ONLY happens for an http server incoming handler, and NOTHING else (not even sockets, since accept is sync!)
|
|
23
|
+
if (type !== HTTP_SERVER_INCOMING_HANDLER) {
|
|
24
|
+
throw new Error("Internal error: only incoming handler callback is permitted");
|
|
25
|
+
}
|
|
26
|
+
const handler = httpIncomingHandlers.get(id);
|
|
27
|
+
if (!handler) {
|
|
28
|
+
throw new Error(`Internal error: no incoming handler registered for server ${id}`);
|
|
29
|
+
}
|
|
30
|
+
handler(payload);
|
|
31
|
+
});
|
|
32
|
+
if (DEBUG) {
|
|
33
|
+
const _ioCall = ioCall;
|
|
34
|
+
ioCall = function ioCall(num, id, payload) {
|
|
35
|
+
if (typeof id !== "number" && id !== null) {
|
|
36
|
+
throw new Error("id must be a number or null");
|
|
37
|
+
}
|
|
38
|
+
let ret;
|
|
39
|
+
try {
|
|
40
|
+
_rawDebug(instanceId, reverseMap[num & CALL_MASK], reverseMap[num & CALL_TYPE_MASK], id, payload);
|
|
41
|
+
ret = _ioCall(num, id, payload);
|
|
42
|
+
return ret;
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
ret = e;
|
|
46
|
+
throw ret;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
_rawDebug(instanceId, "->", ret);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const finalizationRegistry = new FinalizationRegistry((dispose) => void dispose());
|
|
54
|
+
const dummySymbol = Symbol();
|
|
55
|
+
export function registerDispose(resource, parentResource, id, disposeFn) {
|
|
56
|
+
// While strictly speaking all components should handle their disposal,
|
|
57
|
+
// this acts as a last-resort to catch all missed drops through the JS GC.
|
|
58
|
+
// Mainly for two cases - (1) components which are long lived, that get shut
|
|
59
|
+
// down and (2) users that interface with low-level WASI APIs directly in JS
|
|
60
|
+
// for various reasons may end up leaning on JS GC inadvertantly.
|
|
61
|
+
function finalizer() {
|
|
62
|
+
// This has no functional purpose other than to pin a strong reference
|
|
63
|
+
// from the child resource's finalizer to the parent resource, to ensure
|
|
64
|
+
// that we can never finalize a parent resource before a child resource.
|
|
65
|
+
// This makes the generational JS GC become piecewise over child resource
|
|
66
|
+
// graphs (generational at each resource hierarchy level at least).
|
|
67
|
+
if (parentResource?.[dummySymbol]) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
disposeFn(id);
|
|
71
|
+
}
|
|
72
|
+
finalizationRegistry.register(resource, finalizer, finalizer);
|
|
73
|
+
return finalizer;
|
|
74
|
+
}
|
|
75
|
+
export function earlyDispose(finalizer) {
|
|
76
|
+
finalizationRegistry.unregister(finalizer);
|
|
77
|
+
finalizer();
|
|
78
|
+
}
|
|
79
|
+
const _Error = Error;
|
|
80
|
+
const IoError = class Error extends _Error {
|
|
81
|
+
payload;
|
|
82
|
+
constructor(payload) {
|
|
83
|
+
super(payload);
|
|
84
|
+
this.payload = payload;
|
|
85
|
+
}
|
|
86
|
+
toDebugString() {
|
|
87
|
+
return this.message;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
function streamIoErrorCall(call, id, payload) {
|
|
91
|
+
try {
|
|
92
|
+
return ioCall(call, id, payload);
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
if (e.tag === "closed") {
|
|
96
|
+
throw e;
|
|
97
|
+
}
|
|
98
|
+
if (e.tag === "last-operation-failed") {
|
|
99
|
+
e.val = new IoError(Object.assign(new Error(e.val.message), e.val));
|
|
100
|
+
throw e;
|
|
101
|
+
}
|
|
102
|
+
// any invalid error is a trap
|
|
103
|
+
console.trace(e);
|
|
104
|
+
exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
class InputStream {
|
|
108
|
+
#id;
|
|
109
|
+
#streamType;
|
|
110
|
+
#finalizer;
|
|
111
|
+
read(len) {
|
|
112
|
+
return streamIoErrorCall(INPUT_STREAM_READ | this.#streamType, this.#id, len);
|
|
113
|
+
}
|
|
114
|
+
blockingRead(len) {
|
|
115
|
+
return streamIoErrorCall(INPUT_STREAM_BLOCKING_READ | this.#streamType, this.#id, len);
|
|
116
|
+
}
|
|
117
|
+
skip(len) {
|
|
118
|
+
return streamIoErrorCall(INPUT_STREAM_SKIP | this.#streamType, this.#id, len);
|
|
119
|
+
}
|
|
120
|
+
blockingSkip(len) {
|
|
121
|
+
return streamIoErrorCall(INPUT_STREAM_BLOCKING_SKIP | this.#streamType, this.#id, len);
|
|
122
|
+
}
|
|
123
|
+
subscribe() {
|
|
124
|
+
return pollableCreate(ioCall(INPUT_STREAM_SUBSCRIBE | this.#streamType, this.#id), this);
|
|
125
|
+
}
|
|
126
|
+
static _id(stream) {
|
|
127
|
+
return stream.#id;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* @param {FILE | SOCKET_TCP | STDIN | HTTP} streamType
|
|
131
|
+
*/
|
|
132
|
+
static _create(streamType, id) {
|
|
133
|
+
const stream = new InputStream();
|
|
134
|
+
stream.#id = id;
|
|
135
|
+
stream.#streamType = streamType;
|
|
136
|
+
let disposeFn;
|
|
137
|
+
switch (streamType) {
|
|
138
|
+
case FILE:
|
|
139
|
+
disposeFn = fileInputStreamDispose;
|
|
140
|
+
break;
|
|
141
|
+
case SOCKET_TCP:
|
|
142
|
+
disposeFn = socketTcpInputStreamDispose;
|
|
143
|
+
break;
|
|
144
|
+
case STDIN:
|
|
145
|
+
disposeFn = stdinInputStreamDispose;
|
|
146
|
+
break;
|
|
147
|
+
case HTTP:
|
|
148
|
+
disposeFn = httpInputStreamDispose;
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
throw new Error("wasi-io trap: Dispose function not created for stream type " + reverseMap[streamType]);
|
|
152
|
+
}
|
|
153
|
+
stream.#finalizer = registerDispose(stream, null, id, disposeFn);
|
|
154
|
+
return stream;
|
|
155
|
+
}
|
|
156
|
+
[symbolDispose]() {
|
|
157
|
+
if (this.#finalizer) {
|
|
158
|
+
earlyDispose(this.#finalizer);
|
|
159
|
+
this.#finalizer = null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function fileInputStreamDispose(id) {
|
|
164
|
+
ioCall(INPUT_STREAM_DISPOSE | FILE, id, null);
|
|
165
|
+
}
|
|
166
|
+
function socketTcpInputStreamDispose(id) {
|
|
167
|
+
ioCall(INPUT_STREAM_DISPOSE | SOCKET_TCP, id, null);
|
|
168
|
+
}
|
|
169
|
+
function stdinInputStreamDispose(id) {
|
|
170
|
+
ioCall(INPUT_STREAM_DISPOSE | STDIN, id, null);
|
|
171
|
+
}
|
|
172
|
+
function httpInputStreamDispose(id) {
|
|
173
|
+
ioCall(INPUT_STREAM_DISPOSE | HTTP, id, null);
|
|
174
|
+
}
|
|
175
|
+
export const inputStreamCreate = InputStream._create;
|
|
176
|
+
// @ts-expect-error - Deleting static method
|
|
177
|
+
delete InputStream._create;
|
|
178
|
+
export const inputStreamId = InputStream._id;
|
|
179
|
+
// @ts-expect-error - Deleting static method
|
|
180
|
+
delete InputStream._id;
|
|
181
|
+
class OutputStream {
|
|
182
|
+
#id;
|
|
183
|
+
#streamType;
|
|
184
|
+
#finalizer;
|
|
185
|
+
checkWrite() {
|
|
186
|
+
return streamIoErrorCall(OUTPUT_STREAM_CHECK_WRITE | this.#streamType, this.#id, null);
|
|
187
|
+
}
|
|
188
|
+
write(buf) {
|
|
189
|
+
if (this.#streamType <= STDERR) {
|
|
190
|
+
return this.blockingWriteAndFlush(buf);
|
|
191
|
+
}
|
|
192
|
+
return streamIoErrorCall(OUTPUT_STREAM_WRITE | this.#streamType, this.#id, buf);
|
|
193
|
+
}
|
|
194
|
+
blockingWriteAndFlush(buf) {
|
|
195
|
+
if (this.#streamType <= STDERR) {
|
|
196
|
+
const stream = this.#streamType === STDERR ? stderr : stdout;
|
|
197
|
+
return void stream.write(buf);
|
|
198
|
+
}
|
|
199
|
+
return streamIoErrorCall(OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | this.#streamType, this.#id, buf);
|
|
200
|
+
}
|
|
201
|
+
flush() {
|
|
202
|
+
return streamIoErrorCall(OUTPUT_STREAM_FLUSH | this.#streamType, this.#id, undefined);
|
|
203
|
+
}
|
|
204
|
+
blockingFlush() {
|
|
205
|
+
return streamIoErrorCall(OUTPUT_STREAM_BLOCKING_FLUSH | this.#streamType, this.#id, undefined);
|
|
206
|
+
}
|
|
207
|
+
writeZeroes(len) {
|
|
208
|
+
return streamIoErrorCall(OUTPUT_STREAM_WRITE_ZEROES | this.#streamType, this.#id, len);
|
|
209
|
+
}
|
|
210
|
+
blockingWriteZeroesAndFlush(len) {
|
|
211
|
+
return streamIoErrorCall(OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH | this.#streamType, this.#id, len);
|
|
212
|
+
}
|
|
213
|
+
splice(src, len) {
|
|
214
|
+
return streamIoErrorCall(OUTPUT_STREAM_SPLICE | this.#streamType, this.#id, {
|
|
215
|
+
src: src.#id,
|
|
216
|
+
len,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
blockingSplice(src, len) {
|
|
220
|
+
return streamIoErrorCall(OUTPUT_STREAM_BLOCKING_SPLICE | this.#streamType, this.#id, {
|
|
221
|
+
src: inputStreamId(src),
|
|
222
|
+
len,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
subscribe() {
|
|
226
|
+
return pollableCreate(ioCall(OUTPUT_STREAM_SUBSCRIBE | this.#streamType, this.#id), undefined);
|
|
227
|
+
}
|
|
228
|
+
static _id(outputStream) {
|
|
229
|
+
return outputStream.#id;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* @param {OutputStreamType} streamType
|
|
233
|
+
* @param {any} createPayload
|
|
234
|
+
*/
|
|
235
|
+
static _create(streamType, id) {
|
|
236
|
+
const stream = new OutputStream();
|
|
237
|
+
stream.#id = id;
|
|
238
|
+
stream.#streamType = streamType;
|
|
239
|
+
let disposeFn;
|
|
240
|
+
switch (streamType) {
|
|
241
|
+
case STDOUT:
|
|
242
|
+
disposeFn = stdoutOutputStreamDispose;
|
|
243
|
+
break;
|
|
244
|
+
case STDERR:
|
|
245
|
+
disposeFn = stderrOutputStreamDispose;
|
|
246
|
+
break;
|
|
247
|
+
case SOCKET_TCP:
|
|
248
|
+
disposeFn = socketTcpOutputStreamDispose;
|
|
249
|
+
break;
|
|
250
|
+
case FILE:
|
|
251
|
+
disposeFn = fileOutputStreamDispose;
|
|
252
|
+
break;
|
|
253
|
+
case HTTP:
|
|
254
|
+
return stream;
|
|
255
|
+
default:
|
|
256
|
+
throw new Error("wasi-io trap: Dispose function not created for stream type " + reverseMap[streamType]);
|
|
257
|
+
}
|
|
258
|
+
stream.#finalizer = registerDispose(stream, null, id, disposeFn);
|
|
259
|
+
return stream;
|
|
260
|
+
}
|
|
261
|
+
[symbolDispose]() {
|
|
262
|
+
if (this.#finalizer) {
|
|
263
|
+
earlyDispose(this.#finalizer);
|
|
264
|
+
this.#finalizer = null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function stdoutOutputStreamDispose(id) {
|
|
269
|
+
ioCall(OUTPUT_STREAM_DISPOSE | STDOUT, id);
|
|
270
|
+
}
|
|
271
|
+
function stderrOutputStreamDispose(id) {
|
|
272
|
+
ioCall(OUTPUT_STREAM_DISPOSE | STDERR, id);
|
|
273
|
+
}
|
|
274
|
+
function socketTcpOutputStreamDispose(id) {
|
|
275
|
+
ioCall(OUTPUT_STREAM_DISPOSE | SOCKET_TCP, id);
|
|
276
|
+
}
|
|
277
|
+
function fileOutputStreamDispose(id) {
|
|
278
|
+
ioCall(OUTPUT_STREAM_DISPOSE | FILE, id);
|
|
279
|
+
}
|
|
280
|
+
export const outputStreamCreate = OutputStream._create;
|
|
281
|
+
// @ts-expect-error - Deleting static method
|
|
282
|
+
delete OutputStream._create;
|
|
283
|
+
export const outputStreamId = OutputStream._id;
|
|
284
|
+
// @ts-expect-error - Deleting static method
|
|
285
|
+
delete OutputStream._id;
|
|
286
|
+
export const error = { Error: IoError };
|
|
287
|
+
export const streams = { InputStream, OutputStream };
|
|
288
|
+
function pollableDispose(id) {
|
|
289
|
+
ioCall(POLL_POLLABLE_DISPOSE, id);
|
|
290
|
+
}
|
|
291
|
+
const rep = Symbol.for("cabiRep");
|
|
292
|
+
class Pollable {
|
|
293
|
+
#finalizer;
|
|
294
|
+
ready() {
|
|
295
|
+
return ioCall(POLL_POLLABLE_READY, this[rep]);
|
|
296
|
+
}
|
|
297
|
+
block() {
|
|
298
|
+
ioCall(POLL_POLLABLE_BLOCK, this[rep]);
|
|
299
|
+
}
|
|
300
|
+
static _create(id, parent) {
|
|
301
|
+
const pollable = new Pollable();
|
|
302
|
+
pollable[rep] = id;
|
|
303
|
+
pollable.#finalizer = registerDispose(pollable, parent, id, pollableDispose);
|
|
304
|
+
return pollable;
|
|
305
|
+
}
|
|
306
|
+
[symbolDispose]() {
|
|
307
|
+
if (this.#finalizer && this[rep]) {
|
|
308
|
+
earlyDispose(this.#finalizer);
|
|
309
|
+
this.#finalizer = null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const cabiLowerSymbol = Symbol.for("cabiLower");
|
|
314
|
+
const T_FLAG = 1 << 30;
|
|
315
|
+
Pollable.prototype.ready[cabiLowerSymbol] = function ({ resourceTables: [table] }) {
|
|
316
|
+
return function pollableReady(handle) {
|
|
317
|
+
const rep = table[(handle << 1) + 1] & ~T_FLAG;
|
|
318
|
+
const ready = ioCall(POLL_POLLABLE_READY, rep);
|
|
319
|
+
return ready ? 1 : 0;
|
|
320
|
+
};
|
|
321
|
+
};
|
|
322
|
+
Pollable.prototype.block[cabiLowerSymbol] = function ({ resourceTables: [table] }) {
|
|
323
|
+
return function pollableBlock(handle) {
|
|
324
|
+
const rep = table[(handle << 1) + 1] & ~T_FLAG;
|
|
325
|
+
ioCall(POLL_POLLABLE_BLOCK, rep);
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
Pollable[Symbol.for("cabiDispose")] = function pollableDispose(rep) {
|
|
329
|
+
ioCall(POLL_POLLABLE_DISPOSE, rep);
|
|
330
|
+
};
|
|
331
|
+
export const pollableCreate = Pollable._create;
|
|
332
|
+
// @ts-expect-error - Deleting static method
|
|
333
|
+
delete Pollable._create;
|
|
334
|
+
export const poll = {
|
|
335
|
+
Pollable,
|
|
336
|
+
poll(list) {
|
|
337
|
+
return ioCall(POLL_POLL_LIST, null, list.map((pollable) => pollable[rep]));
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
poll.poll[cabiLowerSymbol] = function ({ memory, realloc, resourceTables: [table] }) {
|
|
341
|
+
return function pollPollList(listPtr, len, retptr) {
|
|
342
|
+
const handleList = new Uint32Array(memory.buffer, listPtr, len);
|
|
343
|
+
const repList = Array(len);
|
|
344
|
+
for (let i = 0; i < len; i++) {
|
|
345
|
+
const handle = handleList[i];
|
|
346
|
+
repList[i] = table[(handle << 1) + 1] & ~T_FLAG;
|
|
347
|
+
}
|
|
348
|
+
const result = ioCall(POLL_POLL_LIST, null, repList);
|
|
349
|
+
const ptr = realloc(0, 0, 4, result.byteLength);
|
|
350
|
+
const out = new Uint32Array(memory.buffer, ptr, result.length);
|
|
351
|
+
out.set(result);
|
|
352
|
+
const ret = new Uint32Array(memory.buffer, retptr, 2);
|
|
353
|
+
ret[0] = ptr;
|
|
354
|
+
ret[1] = result.length;
|
|
355
|
+
return retptr;
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
export function createPoll(call, id, initPayload) {
|
|
359
|
+
return pollableCreate(ioCall(call, id, initPayload), undefined);
|
|
360
|
+
}
|
|
361
|
+
export function createPollLower(call, id, table) {
|
|
362
|
+
return function (initPayload) {
|
|
363
|
+
const rep = ioCall(call, id, initPayload);
|
|
364
|
+
const free = table[0] & ~T_FLAG;
|
|
365
|
+
if (free === 0) {
|
|
366
|
+
table.push(0);
|
|
367
|
+
table.push(rep | T_FLAG);
|
|
368
|
+
return (table.length >> 1) - 1;
|
|
369
|
+
}
|
|
370
|
+
table[0] = table[free << 1];
|
|
371
|
+
table[free << 1] = 0;
|
|
372
|
+
table[(free << 1) + 1] = rep | T_FLAG;
|
|
373
|
+
return free;
|
|
374
|
+
};
|
|
375
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { PollState } from "./worker-thread.js";
|
|
2
|
+
import { Socket as TcpSocket } from "node:net";
|
|
3
|
+
import { IpSocketAddress } from "../../types/interfaces/wasi-sockets-network.js";
|
|
4
|
+
interface PendingAccept {
|
|
5
|
+
tcpSocket: TcpSocket | null;
|
|
6
|
+
err: Error | null;
|
|
7
|
+
pollState: PollState | null;
|
|
8
|
+
}
|
|
9
|
+
interface TcpSocketRecord {
|
|
10
|
+
state: number;
|
|
11
|
+
future: number | null;
|
|
12
|
+
tcpSocket: TcpSocket | null;
|
|
13
|
+
listenBacklogSize: number;
|
|
14
|
+
handle: TCP;
|
|
15
|
+
pendingAccepts: PendingAccept[];
|
|
16
|
+
pollState: PollState | null;
|
|
17
|
+
}
|
|
18
|
+
export declare const tcpSockets: Map<number, TcpSocketRecord>;
|
|
19
|
+
export declare function createTcpSocket(): number;
|
|
20
|
+
export declare function socketTcpFinish(id: number, fromState: any, toState: any): any;
|
|
21
|
+
export declare function socketTcpBindStart(id: number, localAddress: any, family: any): void;
|
|
22
|
+
export declare function socketTcpConnectStart(id: number, remoteAddress: IpSocketAddress, family: any): void;
|
|
23
|
+
export declare function socketTcpListenStart(id: number): void;
|
|
24
|
+
export declare function socketTcpAccept(id: number): number[];
|
|
25
|
+
export declare function socketTcpSetListenBacklogSize(id: number, backlogSize: any): void;
|
|
26
|
+
export declare function socketTcpGetLocalAddress(id: number): IpSocketAddress;
|
|
27
|
+
export declare function socketTcpGetRemoteAddress(id: number): IpSocketAddress;
|
|
28
|
+
export declare function socketTcpShutdown(id: number, _shutdownType: any): void;
|
|
29
|
+
export declare function socketTcpSetKeepAlive(id: number, { keepAlive, keepAliveIdleTime }: {
|
|
30
|
+
keepAlive: any;
|
|
31
|
+
keepAliveIdleTime: any;
|
|
32
|
+
}): void;
|
|
33
|
+
export declare function socketTcpDispose(id: number): void;
|
|
34
|
+
export {};
|