@bytecodealliance/preview2-shim 0.0.20 → 0.14.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 +4 -14
- package/lib/browser/cli.js +77 -12
- package/lib/browser/clocks.js +15 -27
- package/lib/browser/filesystem.js +147 -205
- package/lib/browser/index.js +1 -3
- package/lib/{common → browser}/io.js +8 -4
- package/lib/common/assert.js +7 -0
- package/lib/io/calls.js +64 -0
- package/lib/io/worker-http.js +95 -0
- package/lib/io/worker-io.js +322 -0
- package/lib/io/worker-thread.js +569 -0
- package/lib/nodejs/cli.js +45 -58
- package/lib/nodejs/clocks.js +13 -27
- package/lib/nodejs/filesystem.js +540 -427
- package/lib/nodejs/http.js +441 -175
- package/lib/nodejs/index.js +4 -1
- package/lib/nodejs/io.js +1 -0
- package/lib/nodejs/sockets/socket-common.js +116 -0
- package/lib/nodejs/sockets/socketopts-bindings.js +94 -0
- package/lib/nodejs/sockets/tcp-socket-impl.js +794 -0
- package/lib/nodejs/sockets/udp-socket-impl.js +628 -0
- package/lib/nodejs/sockets/wasi-sockets.js +320 -0
- package/lib/nodejs/sockets.js +11 -200
- package/lib/synckit/index.js +4 -2
- package/package.json +1 -5
- package/types/interfaces/wasi-cli-terminal-input.d.ts +4 -0
- package/types/interfaces/wasi-cli-terminal-output.d.ts +4 -0
- package/types/interfaces/wasi-clocks-monotonic-clock.d.ts +19 -6
- package/types/interfaces/wasi-filesystem-types.d.ts +1 -178
- package/types/interfaces/wasi-http-outgoing-handler.d.ts +2 -2
- package/types/interfaces/wasi-http-types.d.ts +412 -82
- package/types/interfaces/wasi-io-error.d.ts +16 -0
- package/types/interfaces/wasi-io-poll.d.ts +19 -8
- package/types/interfaces/wasi-io-streams.d.ts +26 -46
- package/types/interfaces/wasi-sockets-ip-name-lookup.d.ts +9 -21
- package/types/interfaces/wasi-sockets-network.d.ts +4 -0
- package/types/interfaces/wasi-sockets-tcp.d.ts +75 -18
- package/types/interfaces/wasi-sockets-udp-create-socket.d.ts +1 -1
- package/types/interfaces/wasi-sockets-udp.d.ts +282 -193
- package/types/wasi-cli-command.d.ts +28 -28
- package/types/wasi-http-proxy.d.ts +12 -12
- package/lib/common/make-request.js +0 -30
- package/types/interfaces/wasi-clocks-timezone.d.ts +0 -56
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
let id = 0;
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const symbolDispose = Symbol.dispose || Symbol.for('dispose');
|
|
4
|
+
|
|
5
|
+
const IoError = class Error {
|
|
4
6
|
constructor (msg) {
|
|
5
7
|
this.msg = msg;
|
|
6
8
|
}
|
|
@@ -73,7 +75,7 @@ class InputStream {
|
|
|
73
75
|
subscribe() {
|
|
74
76
|
console.log(`[streams] Subscribe to input stream ${this.id}`);
|
|
75
77
|
}
|
|
76
|
-
|
|
78
|
+
[symbolDispose] () {
|
|
77
79
|
if (this.handler.drop)
|
|
78
80
|
this.handler.drop.call(this);
|
|
79
81
|
}
|
|
@@ -158,11 +160,13 @@ class OutputStream {
|
|
|
158
160
|
subscribe() {
|
|
159
161
|
console.log(`[streams] Subscribe to output stream ${this.id}`);
|
|
160
162
|
}
|
|
161
|
-
|
|
163
|
+
[symbolDispose]() {
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
export const
|
|
167
|
+
export const error = { Error: IoError };
|
|
168
|
+
|
|
169
|
+
export const streams = { InputStream, OutputStream };
|
|
166
170
|
|
|
167
171
|
class Pollable {}
|
|
168
172
|
|
package/lib/io/calls.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
let call_id = 0;
|
|
2
|
+
|
|
3
|
+
// Call is a 32 bit integer, leading 16 bits are call number, trailing 16 bits allow custom call types
|
|
4
|
+
export const CALL_MASK = 0xff000000;
|
|
5
|
+
export const CALL_TYPE_MASK = 0x00ffffff;
|
|
6
|
+
export const CALL_SHIFT = 24;
|
|
7
|
+
|
|
8
|
+
// Io Input Stream
|
|
9
|
+
export const INPUT_STREAM_CREATE = ++call_id << CALL_SHIFT;
|
|
10
|
+
export const INPUT_STREAM_READ = ++call_id << CALL_SHIFT;
|
|
11
|
+
export const INPUT_STREAM_BLOCKING_READ = ++call_id << CALL_SHIFT;
|
|
12
|
+
export const INPUT_STREAM_SKIP = ++call_id << CALL_SHIFT;
|
|
13
|
+
export const INPUT_STREAM_BLOCKING_SKIP = ++call_id << CALL_SHIFT;
|
|
14
|
+
export const INPUT_STREAM_SUBSCRIBE = ++call_id << CALL_SHIFT;
|
|
15
|
+
export const INPUT_STREAM_DISPOSE = ++call_id << CALL_SHIFT;
|
|
16
|
+
|
|
17
|
+
// Io Output Stream
|
|
18
|
+
export const OUTPUT_STREAM_CREATE = ++call_id << CALL_SHIFT;
|
|
19
|
+
export const OUTPUT_STREAM_CHECK_WRITE = ++call_id << CALL_SHIFT;
|
|
20
|
+
export const OUTPUT_STREAM_WRITE = ++call_id << CALL_SHIFT;
|
|
21
|
+
export const OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH = ++call_id << CALL_SHIFT;
|
|
22
|
+
export const OUTPUT_STREAM_FLUSH = ++call_id << CALL_SHIFT;
|
|
23
|
+
export const OUTPUT_STREAM_BLOCKING_FLUSH = ++call_id << CALL_SHIFT;
|
|
24
|
+
export const OUTPUT_STREAM_WRITE_ZEROES = ++call_id << CALL_SHIFT;
|
|
25
|
+
export const OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH =
|
|
26
|
+
++call_id << CALL_SHIFT;
|
|
27
|
+
export const OUTPUT_STREAM_SPLICE = ++call_id << CALL_SHIFT;
|
|
28
|
+
export const OUTPUT_STREAM_BLOCKING_SPLICE = ++call_id << CALL_SHIFT;
|
|
29
|
+
export const OUTPUT_STREAM_SUBSCRIBE = ++call_id << CALL_SHIFT;
|
|
30
|
+
export const OUTPUT_STREAM_DISPOSE = ++call_id << CALL_SHIFT;
|
|
31
|
+
|
|
32
|
+
export const OUTPUT_STREAM_GET_TOTAL_BYTES = ++call_id << CALL_SHIFT;
|
|
33
|
+
|
|
34
|
+
// Io Poll
|
|
35
|
+
export const POLL_POLLABLE_READY = ++call_id << CALL_SHIFT;
|
|
36
|
+
export const POLL_POLLABLE_BLOCK = ++call_id << CALL_SHIFT;
|
|
37
|
+
export const POLL_POLL_LIST = ++call_id << CALL_SHIFT;
|
|
38
|
+
|
|
39
|
+
// Futures
|
|
40
|
+
export const FUTURE_GET_VALUE_AND_DISPOSE = ++call_id << CALL_SHIFT;
|
|
41
|
+
export const FUTURE_DISPOSE = ++call_id << CALL_SHIFT;
|
|
42
|
+
|
|
43
|
+
// Http
|
|
44
|
+
export const HTTP_CREATE_REQUEST = ++call_id << 24;
|
|
45
|
+
export const HTTP_OUTPUT_STREAM_FINISH = ++call_id << CALL_SHIFT;
|
|
46
|
+
|
|
47
|
+
// Clocks
|
|
48
|
+
export const CLOCKS_NOW = ++call_id << 24;
|
|
49
|
+
export const CLOCKS_DURATION_SUBSCRIBE = ++call_id << 24;
|
|
50
|
+
export const CLOCKS_INSTANT_SUBSCRIBE = ++call_id << 24;
|
|
51
|
+
|
|
52
|
+
// Sockets
|
|
53
|
+
export const SOCKET_RESOLVE_ADDRESS_CREATE_REQUEST = ++call_id << 24;
|
|
54
|
+
export const SOCKET_RESOLVE_ADDRESS_GET_AND_DISPOSE_REQUEST = ++call_id << 24;
|
|
55
|
+
export const SOCKET_RESOLVE_ADDRESS_DISPOSE_REQUEST = ++call_id << 24;
|
|
56
|
+
|
|
57
|
+
// Type indiciator for generic Stream, Future, and Poll calls
|
|
58
|
+
let cnt = 0;
|
|
59
|
+
export const STDIN = ++cnt;
|
|
60
|
+
export const STDOUT = ++cnt;
|
|
61
|
+
export const STDERR = ++cnt;
|
|
62
|
+
export const FILE = ++cnt;
|
|
63
|
+
export const HTTP = ++cnt;
|
|
64
|
+
export const SOCKET = ++cnt;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
import { createStream, getStreamOrThrow } from "./worker-thread.js";
|
|
3
|
+
|
|
4
|
+
export async function createHttpRequest(method, url, headers, bodyId) {
|
|
5
|
+
let body = null;
|
|
6
|
+
if (bodyId) {
|
|
7
|
+
try {
|
|
8
|
+
const { stream } = getStreamOrThrow(bodyId);
|
|
9
|
+
body = stream.readableBodyStream;
|
|
10
|
+
// this indicates we're attached
|
|
11
|
+
stream.readableBodyStream = null;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
if (e.tag === "closed")
|
|
14
|
+
throw { tag: "internal-error", val: "Unexpected closed body stream" };
|
|
15
|
+
// it should never be possible for the body stream to already
|
|
16
|
+
// be closed, or for there to be a write error
|
|
17
|
+
// we therefore just throw internal error here
|
|
18
|
+
if (e.tag === "last-operation-failed")
|
|
19
|
+
throw {
|
|
20
|
+
tag: "internal-error",
|
|
21
|
+
val: e.val,
|
|
22
|
+
};
|
|
23
|
+
// entirely unknown error -> trap
|
|
24
|
+
throw e;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(url, {
|
|
29
|
+
method,
|
|
30
|
+
headers: new Headers(headers),
|
|
31
|
+
body,
|
|
32
|
+
redirect: "manual",
|
|
33
|
+
duplex: "half",
|
|
34
|
+
});
|
|
35
|
+
const bodyStreamId = createStream(Readable.fromWeb(res.body));
|
|
36
|
+
return {
|
|
37
|
+
status: res.status,
|
|
38
|
+
headers: Array.from(res.headers),
|
|
39
|
+
bodyStreamId: bodyStreamId,
|
|
40
|
+
};
|
|
41
|
+
} catch (e) {
|
|
42
|
+
if (e?.cause) {
|
|
43
|
+
let err = e.cause;
|
|
44
|
+
if (e.cause instanceof AggregateError) err = e.cause.errors[0];
|
|
45
|
+
if (err.message === "unknown scheme")
|
|
46
|
+
throw {
|
|
47
|
+
tag: "HTTP-protocol-error",
|
|
48
|
+
};
|
|
49
|
+
switch (err.syscall) {
|
|
50
|
+
case "connect": {
|
|
51
|
+
if (err.code === "ECONNREFUSED")
|
|
52
|
+
throw {
|
|
53
|
+
tag: "connection-refused",
|
|
54
|
+
};
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case "getaddrinfo": {
|
|
58
|
+
const { errno, code } = err;
|
|
59
|
+
throw {
|
|
60
|
+
tag: "DNS-error",
|
|
61
|
+
val: {
|
|
62
|
+
rcode: code,
|
|
63
|
+
infoCode: errno,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (e?.message?.includes("Failed to parse URL")) {
|
|
70
|
+
throw {
|
|
71
|
+
tag: "HTTP-request-URI-invalid",
|
|
72
|
+
val: undefined,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (e?.message?.includes("HTTP")) {
|
|
76
|
+
switch (e?.message.replace(/'[^']+'/, "'{}'")) {
|
|
77
|
+
case "'{}' HTTP method is unsupported.":
|
|
78
|
+
throw {
|
|
79
|
+
tag: "HTTP-protocol-error",
|
|
80
|
+
val: undefined,
|
|
81
|
+
};
|
|
82
|
+
case "'{}' is not a valid HTTP method.":
|
|
83
|
+
throw {
|
|
84
|
+
tag: "HTTP-request-method-invalid",
|
|
85
|
+
val: undefined,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
throw {
|
|
89
|
+
tag: "internal-error",
|
|
90
|
+
val: e.toString(),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
throw e;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { createSyncFn } from "../synckit/index.js";
|
|
3
|
+
import {
|
|
4
|
+
CALL_MASK,
|
|
5
|
+
CALL_SHIFT,
|
|
6
|
+
CALL_TYPE_MASK,
|
|
7
|
+
INPUT_STREAM_BLOCKING_READ,
|
|
8
|
+
INPUT_STREAM_BLOCKING_SKIP,
|
|
9
|
+
INPUT_STREAM_DISPOSE,
|
|
10
|
+
INPUT_STREAM_READ,
|
|
11
|
+
INPUT_STREAM_SKIP,
|
|
12
|
+
INPUT_STREAM_SUBSCRIBE,
|
|
13
|
+
OUTPUT_STREAM_BLOCKING_FLUSH,
|
|
14
|
+
OUTPUT_STREAM_BLOCKING_SPLICE,
|
|
15
|
+
OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH,
|
|
16
|
+
OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH,
|
|
17
|
+
OUTPUT_STREAM_CHECK_WRITE,
|
|
18
|
+
OUTPUT_STREAM_DISPOSE,
|
|
19
|
+
OUTPUT_STREAM_FLUSH,
|
|
20
|
+
OUTPUT_STREAM_SPLICE,
|
|
21
|
+
OUTPUT_STREAM_SUBSCRIBE,
|
|
22
|
+
OUTPUT_STREAM_WRITE_ZEROES,
|
|
23
|
+
OUTPUT_STREAM_WRITE,
|
|
24
|
+
POLL_POLL_LIST,
|
|
25
|
+
POLL_POLLABLE_BLOCK,
|
|
26
|
+
POLL_POLLABLE_READY,
|
|
27
|
+
} from "./calls.js";
|
|
28
|
+
import { STDERR } from "./calls.js";
|
|
29
|
+
|
|
30
|
+
const DEBUG = false;
|
|
31
|
+
|
|
32
|
+
const workerPath = fileURLToPath(
|
|
33
|
+
new URL("./worker-thread.js", import.meta.url)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @type {(call: number, id: number | null, payload: any) -> any}
|
|
38
|
+
*/
|
|
39
|
+
export let ioCall = createSyncFn(workerPath);
|
|
40
|
+
if (DEBUG) {
|
|
41
|
+
const _ioCall = ioCall;
|
|
42
|
+
ioCall = function ioCall(num, id, payload) {
|
|
43
|
+
let ret;
|
|
44
|
+
try {
|
|
45
|
+
process._rawDebug(
|
|
46
|
+
(num & CALL_MASK) >> CALL_SHIFT,
|
|
47
|
+
num & CALL_TYPE_MASK,
|
|
48
|
+
id,
|
|
49
|
+
payload
|
|
50
|
+
);
|
|
51
|
+
ret = _ioCall(num, id, payload);
|
|
52
|
+
return ret;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
ret = e;
|
|
55
|
+
throw ret;
|
|
56
|
+
} finally {
|
|
57
|
+
process._rawDebug("->", ret);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const symbolDispose = Symbol.dispose || Symbol.for("dispose");
|
|
63
|
+
|
|
64
|
+
const _Error = Error;
|
|
65
|
+
const IoError = class Error extends _Error {
|
|
66
|
+
toDebugString() {
|
|
67
|
+
return this.message;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function streamIoErrorCall(call, id, payload) {
|
|
72
|
+
try {
|
|
73
|
+
return ioCall(call, id, payload);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
if (e.tag === 'closed')
|
|
76
|
+
throw e;
|
|
77
|
+
if (e.tag === "last-operation-failed") {
|
|
78
|
+
e.val = new IoError(e.val);
|
|
79
|
+
throw e;
|
|
80
|
+
}
|
|
81
|
+
// any invalid error is a trap
|
|
82
|
+
console.trace(e);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class InputStream {
|
|
88
|
+
#id;
|
|
89
|
+
#streamType;
|
|
90
|
+
get _id() {
|
|
91
|
+
return this.#id;
|
|
92
|
+
}
|
|
93
|
+
read(len) {
|
|
94
|
+
return streamIoErrorCall(
|
|
95
|
+
INPUT_STREAM_READ | this.#streamType,
|
|
96
|
+
this.#id,
|
|
97
|
+
len
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
blockingRead(len) {
|
|
101
|
+
return streamIoErrorCall(
|
|
102
|
+
INPUT_STREAM_BLOCKING_READ | this.#streamType,
|
|
103
|
+
this.#id,
|
|
104
|
+
len
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
skip(len) {
|
|
108
|
+
return streamIoErrorCall(
|
|
109
|
+
INPUT_STREAM_SKIP | this.#streamType,
|
|
110
|
+
this.#id,
|
|
111
|
+
len
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
blockingSkip(len) {
|
|
115
|
+
return streamIoErrorCall(
|
|
116
|
+
INPUT_STREAM_BLOCKING_SKIP | this.#streamType,
|
|
117
|
+
this.#id,
|
|
118
|
+
len
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
subscribe() {
|
|
122
|
+
return pollableCreate(
|
|
123
|
+
ioCall(INPUT_STREAM_SUBSCRIBE | this.#streamType, this.#id)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
[symbolDispose]() {
|
|
127
|
+
ioCall(INPUT_STREAM_DISPOSE | this.#streamType, this.#id);
|
|
128
|
+
}
|
|
129
|
+
static _id(stream) {
|
|
130
|
+
return stream.#id;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* @param {InputStreamType} streamType
|
|
134
|
+
*/
|
|
135
|
+
static _create(streamType, id) {
|
|
136
|
+
const stream = new InputStream();
|
|
137
|
+
stream.#id = id;
|
|
138
|
+
stream.#streamType = streamType;
|
|
139
|
+
return stream;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const inputStreamCreate = InputStream._create;
|
|
144
|
+
delete InputStream._create;
|
|
145
|
+
|
|
146
|
+
export const inputStreamId = InputStream._id;
|
|
147
|
+
delete InputStream._id;
|
|
148
|
+
|
|
149
|
+
class OutputStream {
|
|
150
|
+
#id;
|
|
151
|
+
#streamType;
|
|
152
|
+
get _id() {
|
|
153
|
+
return this.#id;
|
|
154
|
+
}
|
|
155
|
+
checkWrite(len) {
|
|
156
|
+
return streamIoErrorCall(
|
|
157
|
+
OUTPUT_STREAM_CHECK_WRITE | this.#streamType,
|
|
158
|
+
this.#id,
|
|
159
|
+
len
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
write(buf) {
|
|
163
|
+
if (this.#streamType <= STDERR) return this.blockingWriteAndFlush(buf);
|
|
164
|
+
return streamIoErrorCall(
|
|
165
|
+
OUTPUT_STREAM_WRITE | this.#streamType,
|
|
166
|
+
this.#id,
|
|
167
|
+
buf
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
blockingWriteAndFlush(buf) {
|
|
171
|
+
if (this.#streamType <= STDERR) {
|
|
172
|
+
const stream =
|
|
173
|
+
this.#streamType === STDERR ? process.stderr : process.stdout;
|
|
174
|
+
return void stream.write(buf);
|
|
175
|
+
}
|
|
176
|
+
return streamIoErrorCall(
|
|
177
|
+
OUTPUT_STREAM_BLOCKING_WRITE_AND_FLUSH | this.#streamType,
|
|
178
|
+
this.#id,
|
|
179
|
+
buf
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
flush() {
|
|
183
|
+
return streamIoErrorCall(OUTPUT_STREAM_FLUSH | this.#streamType, this.#id);
|
|
184
|
+
}
|
|
185
|
+
blockingFlush() {
|
|
186
|
+
return streamIoErrorCall(
|
|
187
|
+
OUTPUT_STREAM_BLOCKING_FLUSH | this.#streamType,
|
|
188
|
+
this.#id
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
writeZeroes(len) {
|
|
192
|
+
return streamIoErrorCall(
|
|
193
|
+
OUTPUT_STREAM_WRITE_ZEROES | this.#streamType,
|
|
194
|
+
this.#id,
|
|
195
|
+
len
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
blockingWriteZeroesAndFlush(len) {
|
|
199
|
+
return streamIoErrorCall(
|
|
200
|
+
OUTPUT_STREAM_BLOCKING_WRITE_ZEROES_AND_FLUSH | this.#streamType,
|
|
201
|
+
this.#id,
|
|
202
|
+
len
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
splice(src, len) {
|
|
206
|
+
return streamIoErrorCall(
|
|
207
|
+
OUTPUT_STREAM_SPLICE | this.#streamType,
|
|
208
|
+
this.#id,
|
|
209
|
+
src.#id,
|
|
210
|
+
len
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
blockingSplice(src, len) {
|
|
214
|
+
return streamIoErrorCall(
|
|
215
|
+
OUTPUT_STREAM_BLOCKING_SPLICE | this.#streamType,
|
|
216
|
+
this.#id,
|
|
217
|
+
src.#id,
|
|
218
|
+
len
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
subscribe() {
|
|
222
|
+
return pollableCreate(
|
|
223
|
+
ioCall(OUTPUT_STREAM_SUBSCRIBE | this.#streamType, this.#id)
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
[symbolDispose]() {
|
|
227
|
+
ioCall(OUTPUT_STREAM_DISPOSE | this.#streamType, this.#id);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
static _id(outputStream) {
|
|
231
|
+
return outputStream.#id;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* @param {OutputStreamType} streamType
|
|
235
|
+
* @param {any} createPayload
|
|
236
|
+
*/
|
|
237
|
+
static _create(streamType, id) {
|
|
238
|
+
const stream = new OutputStream();
|
|
239
|
+
stream.#id = id;
|
|
240
|
+
stream.#streamType = streamType;
|
|
241
|
+
return stream;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export const outputStreamCreate = OutputStream._create;
|
|
246
|
+
delete OutputStream._create;
|
|
247
|
+
|
|
248
|
+
export const outputStreamId = OutputStream._id;
|
|
249
|
+
delete OutputStream._id;
|
|
250
|
+
|
|
251
|
+
export const error = { Error: IoError };
|
|
252
|
+
|
|
253
|
+
export const streams = { InputStream, OutputStream };
|
|
254
|
+
|
|
255
|
+
class Pollable {
|
|
256
|
+
#id;
|
|
257
|
+
#ready = false;
|
|
258
|
+
get _id() {
|
|
259
|
+
return this.#id;
|
|
260
|
+
}
|
|
261
|
+
ready() {
|
|
262
|
+
if (this.#ready) return true;
|
|
263
|
+
const ready = ioCall(POLL_POLLABLE_READY, this.#id);
|
|
264
|
+
if (ready) this.#ready = true;
|
|
265
|
+
return ready;
|
|
266
|
+
}
|
|
267
|
+
block() {
|
|
268
|
+
if (!this.#ready) {
|
|
269
|
+
ioCall(POLL_POLLABLE_BLOCK, this.#id);
|
|
270
|
+
this.#ready = true;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
static _getId(pollable) {
|
|
274
|
+
return pollable.#id;
|
|
275
|
+
}
|
|
276
|
+
static _create(id) {
|
|
277
|
+
const pollable = new Pollable();
|
|
278
|
+
pollable.#id = id;
|
|
279
|
+
if (id === 0) pollable.#ready = true;
|
|
280
|
+
return pollable;
|
|
281
|
+
}
|
|
282
|
+
static _listToIds(list) {
|
|
283
|
+
return list.map((pollable) => pollable.#id);
|
|
284
|
+
}
|
|
285
|
+
static _markReady(pollable) {
|
|
286
|
+
pollable.#ready = true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export const pollableCreate = Pollable._create;
|
|
291
|
+
delete Pollable._create;
|
|
292
|
+
|
|
293
|
+
const pollableListToIds = Pollable._listToIds;
|
|
294
|
+
delete Pollable._listToIds;
|
|
295
|
+
|
|
296
|
+
const pollableMarkReady = Pollable._markReady;
|
|
297
|
+
delete Pollable._markReady;
|
|
298
|
+
|
|
299
|
+
const pollableGetId = Pollable._getId;
|
|
300
|
+
delete Pollable._getId;
|
|
301
|
+
|
|
302
|
+
export const poll = {
|
|
303
|
+
Pollable,
|
|
304
|
+
poll(list) {
|
|
305
|
+
const includeList = ioCall(POLL_POLL_LIST, null, pollableListToIds(list));
|
|
306
|
+
return list.filter((pollable) => {
|
|
307
|
+
if (includeList.includes(pollableGetId(pollable))) {
|
|
308
|
+
pollableMarkReady(pollable);
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
export function resolvedPoll() {
|
|
317
|
+
return pollableCreate(0);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function createPoll(call, id, initPayload) {
|
|
321
|
+
return pollableCreate(ioCall(call, id, initPayload));
|
|
322
|
+
}
|