@bytecodealliance/preview2-shim 0.0.4 → 0.0.5
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/lib/browser/environment-preopens.js +3 -0
- package/lib/browser/http.js +12 -7
- package/lib/browser/index.js +12 -4
- package/lib/browser/instance-monotonic-clock.js +3 -0
- package/lib/browser/instance-wall-clock.js +3 -0
- package/lib/browser/io.js +10 -23
- package/lib/browser/preopens.js +11 -0
- package/lib/browser/random.js +1 -1
- package/lib/browser/streams.js +17 -2
- package/lib/http/make-request.js +2 -2
- package/lib/http/wasi-http.js +267 -0
- package/lib/nodejs/environment-preopens.js +3 -0
- package/lib/nodejs/index.js +10 -2
- package/lib/nodejs/instance-monotonic-clock.js +3 -0
- package/lib/nodejs/instance-wall-clock.js +3 -0
- package/lib/nodejs/io.js +16 -24
- package/lib/nodejs/preopens.js +11 -0
- package/lib/nodejs/random.js +1 -1
- package/lib/nodejs/streams.js +22 -4
- package/package.json +1 -1
- package/types/imports/preopens.d.ts +15 -0
- package/types/wasi-reactor.d.ts +2 -0
- package/lib/browser/clocks.js +0 -47
- package/lib/browser/default-clocks.js +0 -7
- package/lib/nodejs/default-clocks.js +0 -7
package/lib/browser/http.js
CHANGED
|
@@ -9,19 +9,24 @@ export function send(req) {
|
|
|
9
9
|
try {
|
|
10
10
|
const xhr = new XMLHttpRequest();
|
|
11
11
|
xhr.open(req.method.toString(), req.uri, false);
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const requestHeaders = new Headers(req.headers);
|
|
13
|
+
for (let [name, value] of requestHeaders.entries()) {
|
|
14
|
+
if (name !== "user-agent" && name !== "host") {
|
|
14
15
|
xhr.setRequestHeader(name, value);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
xhr.send(req.body.length > 0 ? req.body : null);
|
|
18
|
+
xhr.send(req.body && req.body.length > 0 ? req.body : null);
|
|
18
19
|
const body = xhr.response ? new TextEncoder().encode(xhr.response) : undefined;
|
|
20
|
+
const headers = [];
|
|
21
|
+
xhr.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach((line) => {
|
|
22
|
+
var parts = line.split(': ');
|
|
23
|
+
var key = parts.shift();
|
|
24
|
+
var value = parts.join(': ');
|
|
25
|
+
headers.push([key, value]);
|
|
26
|
+
});
|
|
19
27
|
return {
|
|
20
28
|
status: xhr.status,
|
|
21
|
-
headers
|
|
22
|
-
.getAllResponseHeaders()
|
|
23
|
-
.trim()
|
|
24
|
-
.split(/[\r\n]+/),
|
|
29
|
+
headers,
|
|
25
30
|
body,
|
|
26
31
|
};
|
|
27
32
|
} catch (err) {
|
package/lib/browser/index.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as console from "./console.js";
|
|
2
2
|
import * as defaultOutgoingHttp from "./default-outgoing-HTTP.js";
|
|
3
3
|
import * as environment from "./environment.js";
|
|
4
|
+
import * as environmentPreopens from "./environment-preopens.js";
|
|
4
5
|
import * as exit from "./exit.js";
|
|
5
6
|
import * as filesystem from "./filesystem.js";
|
|
6
7
|
import * as http from "./http.js";
|
|
8
|
+
import * as instanceMonotonicClock from "./instance-monotonic-clock.js";
|
|
9
|
+
import * as instanceWallClock from "./instance-wall-clock.js";
|
|
7
10
|
import * as io from "./io.js";
|
|
8
|
-
import * as logging from "./console.js";
|
|
9
11
|
import * as monotonicClock from "./monotonic-clock.js";
|
|
10
12
|
import * as poll from "./poll.js";
|
|
13
|
+
import * as preopens from "./preopens.js";
|
|
11
14
|
import * as random from "./random.js";
|
|
12
15
|
import * as stderr from "./stderr.js";
|
|
13
16
|
import * as streams from "./streams.js";
|
|
@@ -15,16 +18,19 @@ import * as types from "./types.js";
|
|
|
15
18
|
import * as wallClock from "./wall-clock.js";
|
|
16
19
|
|
|
17
20
|
export const importObject = {
|
|
18
|
-
"
|
|
21
|
+
"console": console,
|
|
19
22
|
"default-outgoing-HTTP": defaultOutgoingHttp,
|
|
20
23
|
"environment": environment,
|
|
24
|
+
"environment-preopens": environmentPreopens,
|
|
21
25
|
"exit": exit,
|
|
22
26
|
"filesystem": filesystem,
|
|
23
27
|
"http": http,
|
|
28
|
+
"instance-monotonic-clock": instanceMonotonicClock,
|
|
29
|
+
"instance-wall-clock": instanceWallClock,
|
|
24
30
|
"io": io,
|
|
25
|
-
"logging": logging,
|
|
26
31
|
"monotonic-clock": monotonicClock,
|
|
27
32
|
"poll": poll,
|
|
33
|
+
"preopens": preopens,
|
|
28
34
|
"random": random,
|
|
29
35
|
"stderr": stderr,
|
|
30
36
|
"streams": streams,
|
|
@@ -32,4 +38,6 @@ export const importObject = {
|
|
|
32
38
|
"wall-clock": wallClock,
|
|
33
39
|
};
|
|
34
40
|
|
|
41
|
+
export { WasiHttp } from "../http/wasi-http.js";
|
|
42
|
+
|
|
35
43
|
export default importObject;
|
package/lib/browser/io.js
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
export function
|
|
2
|
-
console.log(`[io]
|
|
1
|
+
export function read(s, len) {
|
|
2
|
+
console.log(`[io] Read ${s} ${len}`);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
export function
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function read(src, len) {
|
|
10
|
-
console.log(`[io] Read ${src} ${len}`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function write(dst, buf) {
|
|
14
|
-
switch (dst) {
|
|
5
|
+
export function write(s, buf) {
|
|
6
|
+
switch (s) {
|
|
15
7
|
case 0:
|
|
16
8
|
throw new Error(`TODO: write stdin`);
|
|
17
9
|
case 1: {
|
|
@@ -19,17 +11,12 @@ export function write(dst, buf) {
|
|
|
19
11
|
console.log(decoder.decode(buf));
|
|
20
12
|
return BigInt(buf.byteLength);
|
|
21
13
|
}
|
|
22
|
-
case 2:
|
|
23
|
-
|
|
14
|
+
case 2: {
|
|
15
|
+
const decoder = new TextDecoder();
|
|
16
|
+
console.error(decoder.decode(buf));
|
|
17
|
+
return BigInt(buf.byteLength);
|
|
18
|
+
}
|
|
24
19
|
default:
|
|
25
|
-
throw new Error(`TODO: write ${
|
|
20
|
+
throw new Error(`TODO: write ${s}`);
|
|
26
21
|
}
|
|
27
22
|
}
|
|
28
|
-
|
|
29
|
-
export function skip(src, len) {
|
|
30
|
-
console.log(`[io] Skip ${src}`, len);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function write_repeated(dst, byte, len) {
|
|
34
|
-
console.log(`[io] Write repeated ${dst}`, byte, len);
|
|
35
|
-
}
|
package/lib/browser/random.js
CHANGED
package/lib/browser/streams.js
CHANGED
|
@@ -16,8 +16,23 @@ export function subscribeToInputStream(s) {
|
|
|
16
16
|
export function dropInputStream(s) {
|
|
17
17
|
console.log(`[streams] Drop input stream ${s}`);
|
|
18
18
|
}
|
|
19
|
-
export function write(s,
|
|
20
|
-
|
|
19
|
+
export function write(s, buf) {
|
|
20
|
+
switch (s) {
|
|
21
|
+
case 0:
|
|
22
|
+
throw new Error(`TODO: write stdin`);
|
|
23
|
+
case 1: {
|
|
24
|
+
const decoder = new TextDecoder();
|
|
25
|
+
console.log(decoder.decode(buf));
|
|
26
|
+
return BigInt(buf.byteLength);
|
|
27
|
+
}
|
|
28
|
+
case 2: {
|
|
29
|
+
const decoder = new TextDecoder();
|
|
30
|
+
console.error(decoder.decode(buf));
|
|
31
|
+
return BigInt(buf.byteLength);
|
|
32
|
+
}
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`TODO: write ${s}`);
|
|
35
|
+
}
|
|
21
36
|
}
|
|
22
37
|
export function blockingWrite(s, _buf) {
|
|
23
38
|
console.log(`[streams] Blocking write ${s}`);
|
package/lib/http/make-request.js
CHANGED
|
@@ -10,12 +10,12 @@ async function makeRequest(req) {
|
|
|
10
10
|
const resp = await fetch(req.uri, {
|
|
11
11
|
method: req.method.toString(),
|
|
12
12
|
headers,
|
|
13
|
-
body: req.body.length > 0 ? req.body : undefined,
|
|
13
|
+
body: req.body && req.body.length > 0 ? req.body : undefined,
|
|
14
14
|
});
|
|
15
15
|
let arrayBuffer = await resp.arrayBuffer();
|
|
16
16
|
return JSON.stringify({
|
|
17
17
|
status: resp.status,
|
|
18
|
-
headers: resp.headers,
|
|
18
|
+
headers: Array.from(resp.headers.entries()),
|
|
19
19
|
body:
|
|
20
20
|
arrayBuffer.byteLength > 0
|
|
21
21
|
? Buffer.from(arrayBuffer).toString("base64")
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// Based on:
|
|
2
|
+
// https://github.com/bytecodealliance/wasmtime/blob/76eb40e0756d90cc9c16b26a8d8b1e0ebf75f44d/crates/wasi-http/src/http_impl.rs
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import("../../types/imports/types").Fields} Fields
|
|
6
|
+
* @typedef {import("../../types/imports/types").FutureIncomingResponse} FutureIncomingResponse
|
|
7
|
+
* @typedef {import("../../types/imports/types").Headers} Headers
|
|
8
|
+
* @typedef {import("../../types/imports/types").IncomingResponse} IncomingResponse
|
|
9
|
+
* @typedef {import("../../types/imports/types").IncomingStream} IncomingStream
|
|
10
|
+
* @typedef {import("../../types/imports/types").Method} Method
|
|
11
|
+
* @typedef {import("../../types/imports/types").OutgoingRequest} OutgoingRequest
|
|
12
|
+
* @typedef {import("../../types/imports/types").RequestOptions} RequestOptions
|
|
13
|
+
* @typedef {import("../../types/imports/types").Scheme} Scheme
|
|
14
|
+
* @typedef {import("../../types/imports/types").StatusCode} StatusCode
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as io from '@bytecodealliance/preview2-shim/io';
|
|
18
|
+
import * as http from '@bytecodealliance/preview2-shim/http';
|
|
19
|
+
|
|
20
|
+
export class WasiHttp {
|
|
21
|
+
requestIdBase = 1;
|
|
22
|
+
responseIdBase = 1;
|
|
23
|
+
fieldsIdBase = 1;
|
|
24
|
+
streamsIdBase = 3;
|
|
25
|
+
/** @type {Map<number,ActiveRequest>} */ requests = new Map();
|
|
26
|
+
/** @type {Map<number,ActiveResponse>} */ responses = new Map();
|
|
27
|
+
/** @type {Map<number,Map<string,string[]>>} */ fields = new Map();
|
|
28
|
+
/** @type {Map<number,Uint8Array>} */ streams = new Map();
|
|
29
|
+
|
|
30
|
+
constructor() {}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {OutgoingRequest} requestId
|
|
34
|
+
* @param {RequestOptions | null} options
|
|
35
|
+
* @returns {FutureIncomingResponse}
|
|
36
|
+
*/
|
|
37
|
+
handle = (requestId, {
|
|
38
|
+
connectTimeoutMs: _connectTimeoutMs = 600_000,
|
|
39
|
+
firstByteTimeoutMs: _firstByteTimeoutMs = 600_000,
|
|
40
|
+
betweenBytesTimeoutMs: _betweenBytesTimeoutMs = 600_000
|
|
41
|
+
} = {}) => {
|
|
42
|
+
const request = this.requests.get(requestId);
|
|
43
|
+
if (!request) throw Error("not found!");
|
|
44
|
+
|
|
45
|
+
const responseId = this.responseIdBase;
|
|
46
|
+
this.responseIdBase += 1;
|
|
47
|
+
const response = new ActiveResponse(responseId);
|
|
48
|
+
|
|
49
|
+
const scheme = request.scheme.tag === "HTTP" ? "http://" : "https://";
|
|
50
|
+
|
|
51
|
+
const url = scheme + request.authority + request.path + request.query;
|
|
52
|
+
const headers = {
|
|
53
|
+
"host": request.authority,
|
|
54
|
+
};
|
|
55
|
+
for (const [key, value] of request.headers.entries()) {
|
|
56
|
+
headers[key] = Array.isArray(value) ? value.join(",") : value;
|
|
57
|
+
}
|
|
58
|
+
const body = this.streams.get(request.body);
|
|
59
|
+
|
|
60
|
+
const res = http.send({
|
|
61
|
+
method: request.method.tag,
|
|
62
|
+
uri: url,
|
|
63
|
+
headers: headers,
|
|
64
|
+
params: [],
|
|
65
|
+
body: body && body.length > 0 ? body : undefined,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
response.status = res.status;
|
|
69
|
+
for (const [key, value] of res.headers) {
|
|
70
|
+
response.responseHeaders.set(key, [value]);
|
|
71
|
+
}
|
|
72
|
+
const buf = res.body;
|
|
73
|
+
response.body = this.streamsIdBase;
|
|
74
|
+
this.streamsIdBase = this.streamsIdBase + 1;
|
|
75
|
+
this.streams.set(response.body, buf);
|
|
76
|
+
this.responses.set(responseId, response);
|
|
77
|
+
return responseId;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {InputStream} stream
|
|
82
|
+
* @param {bigint} len
|
|
83
|
+
* @returns {[Uint8Array | ArrayBuffer, boolean]}
|
|
84
|
+
*/
|
|
85
|
+
read = (stream, len) => {
|
|
86
|
+
if (stream < 3) {
|
|
87
|
+
return io.read(stream);
|
|
88
|
+
}
|
|
89
|
+
const s = this.streams.get(stream);
|
|
90
|
+
if (!s) throw Error(`stream not found: ${stream}`);
|
|
91
|
+
const position = Number(len);
|
|
92
|
+
if (position === 0) {
|
|
93
|
+
return [new Uint8Array(), s.byteLength > 0];
|
|
94
|
+
} else if (s.byteLength > position) {
|
|
95
|
+
this.streams.set(stream, s.slice(position, s.byteLength));
|
|
96
|
+
return [s.slice(0, position), false];
|
|
97
|
+
} else {
|
|
98
|
+
return [s.slice(0, position), true];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @param {InputStream} stream
|
|
104
|
+
* @returns {Pollable}
|
|
105
|
+
*/
|
|
106
|
+
subscribeToInputStream = (_stream) => {
|
|
107
|
+
throw Error("unimplemented: subscribeToInputStream");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {InputStream} stream
|
|
112
|
+
*/
|
|
113
|
+
dropInputStream = (stream) => {
|
|
114
|
+
const s = this.streams.get(stream);
|
|
115
|
+
if (!s) throw Error(`no such input stream ${stream}`);
|
|
116
|
+
s.set([]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @param {OutputStream} stream
|
|
121
|
+
* @param {Uint8Array} buf
|
|
122
|
+
* @returns {bigint}
|
|
123
|
+
*/
|
|
124
|
+
write = (stream, buf) => {
|
|
125
|
+
if (stream < 3) {
|
|
126
|
+
return io.write(stream, buf);
|
|
127
|
+
}
|
|
128
|
+
this.streams.set(stream, buf);
|
|
129
|
+
return BigInt(buf.byteLength);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {OutputStream} stream
|
|
134
|
+
* @returns {Pollable}
|
|
135
|
+
*/
|
|
136
|
+
subscribeToOutputStream = (_stream) => {
|
|
137
|
+
throw Error("unimplemented: subscribeToOutputStream");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {OutputStream} stream
|
|
142
|
+
*/
|
|
143
|
+
dropOutputStream = (stream) => {
|
|
144
|
+
const s = this.streams.get(stream);
|
|
145
|
+
if (!s) throw Error(`no such output stream ${stream}`);
|
|
146
|
+
s.set([]);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {[string, string][]} entries
|
|
151
|
+
* @returns {Fields}
|
|
152
|
+
*/
|
|
153
|
+
newFields = (entries) => {
|
|
154
|
+
const map = new Map(entries);
|
|
155
|
+
|
|
156
|
+
const id = this.fieldsIdBase;
|
|
157
|
+
this.fieldsIdBase = id + 1;
|
|
158
|
+
this.fields.set(id, map);
|
|
159
|
+
|
|
160
|
+
return id;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @param {Fields} fields
|
|
165
|
+
* @returns {[string, string][]}
|
|
166
|
+
*/
|
|
167
|
+
fieldsEntries = (fields) => {
|
|
168
|
+
return this.fields.get(fields) ?? [];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {OutgoingRequest} request
|
|
173
|
+
*/
|
|
174
|
+
dropOutgoingRequest = (request) => {
|
|
175
|
+
this.requests.delete(request);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @param {Method} method
|
|
180
|
+
* @param {string} path
|
|
181
|
+
* @param {string} query
|
|
182
|
+
* @param {Scheme | null} scheme
|
|
183
|
+
* @param {string} authority
|
|
184
|
+
* @param {Headers} headers
|
|
185
|
+
* @returns {number}
|
|
186
|
+
*/
|
|
187
|
+
newOutgoingRequest = (method, path, query, scheme, authority, headers) => {
|
|
188
|
+
const id = this.requestIdBase;
|
|
189
|
+
this.requestIdBase += 1;
|
|
190
|
+
|
|
191
|
+
const req = new ActiveRequest(id);
|
|
192
|
+
req.path = path;
|
|
193
|
+
req.query = query;
|
|
194
|
+
req.authority = authority;
|
|
195
|
+
req.method = method;
|
|
196
|
+
req.headers = this.fields.get(headers);
|
|
197
|
+
req.scheme = scheme;
|
|
198
|
+
this.requests.set(id, req);
|
|
199
|
+
return id;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @param {IncomingResponse} response
|
|
204
|
+
*/
|
|
205
|
+
dropIncomingResponse = (response) => {
|
|
206
|
+
this.responses.delete(response);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @param {IncomingResponse} response
|
|
211
|
+
* @returns {StatusCode}
|
|
212
|
+
*/
|
|
213
|
+
incomingResponseStatus = (response) => {
|
|
214
|
+
const r = this.responses.get(response);
|
|
215
|
+
return r.status;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @param {IncomingResponse} response
|
|
220
|
+
* @returns {Headers}
|
|
221
|
+
*/
|
|
222
|
+
incomingResponseHeaders = (response) => {
|
|
223
|
+
const r = this.responses.get(response);
|
|
224
|
+
const id = this.fieldsIdBase;
|
|
225
|
+
this.fieldsIdBase = this.fieldsIdBase + 1;
|
|
226
|
+
|
|
227
|
+
this.fields.set(id, r.responseHeaders);
|
|
228
|
+
return id;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* @param {IncomingResponse} response
|
|
233
|
+
* @returns {IncomingStream}
|
|
234
|
+
*/
|
|
235
|
+
incomingResponseConsume = (response) => {
|
|
236
|
+
const r = this.responses.get(response);
|
|
237
|
+
return r.body;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
class ActiveRequest {
|
|
242
|
+
/** @type {number} */ id;
|
|
243
|
+
activeRequest = false;
|
|
244
|
+
/** @type {Method} */ method = { tag: 'get' };
|
|
245
|
+
/** @type {Scheme | null} */ scheme = { tag: 'HTTP' };
|
|
246
|
+
path = "";
|
|
247
|
+
query = "";
|
|
248
|
+
authority = "";
|
|
249
|
+
/** @type {Map<string,string[]>} */ headers = new Map();
|
|
250
|
+
body = 3;
|
|
251
|
+
|
|
252
|
+
constructor(id) {
|
|
253
|
+
this.id = id;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
class ActiveResponse {
|
|
258
|
+
/** @type {number} */ id;
|
|
259
|
+
activeResponse = false;
|
|
260
|
+
status = 0;
|
|
261
|
+
body = 3;
|
|
262
|
+
/** @type {Map<string,string[]>} */ responseHeaders = new Map();
|
|
263
|
+
|
|
264
|
+
constructor(id) {
|
|
265
|
+
this.id = id;
|
|
266
|
+
}
|
|
267
|
+
}
|
package/lib/nodejs/index.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import * as console from "./console.js";
|
|
2
|
-
import * as defaultClocks from "./default-clocks.js";
|
|
3
2
|
import * as defaultOutgoingHttp from "./default-outgoing-HTTP.js";
|
|
4
3
|
import * as environment from "./environment.js";
|
|
4
|
+
import * as environmentPreopens from "./environment-preopens.js";
|
|
5
5
|
import * as exit from "./exit.js";
|
|
6
6
|
import * as filesystem from "./filesystem.js";
|
|
7
7
|
import * as http from "./http.js";
|
|
8
|
+
import * as instanceMonotonicClock from "./instance-monotonic-clock.js";
|
|
9
|
+
import * as instanceWallClock from "./instance-wall-clock.js";
|
|
8
10
|
import * as io from "./io.js";
|
|
9
11
|
import * as monotonicClock from "./monotonic-clock.js";
|
|
10
12
|
import * as poll from "./poll.js";
|
|
13
|
+
import * as preopens from "./preopens.js";
|
|
11
14
|
import * as random from "./random.js";
|
|
12
15
|
import * as stderr from "./stderr.js";
|
|
13
16
|
import * as streams from "./streams.js";
|
|
@@ -16,15 +19,18 @@ import * as wallClock from "./wall-clock.js";
|
|
|
16
19
|
|
|
17
20
|
export const importObject = {
|
|
18
21
|
"console": console,
|
|
19
|
-
"default-clocks": defaultClocks,
|
|
20
22
|
"default-outgoing-HTTP": defaultOutgoingHttp,
|
|
21
23
|
"environment": environment,
|
|
24
|
+
"environment-preopens": environmentPreopens,
|
|
22
25
|
"exit": exit,
|
|
23
26
|
"filesystem": filesystem,
|
|
24
27
|
"http": http,
|
|
28
|
+
"instance-monotonic-clock": instanceMonotonicClock,
|
|
29
|
+
"instance-wall-clock": instanceWallClock,
|
|
25
30
|
"io": io,
|
|
26
31
|
"monotonic-clock": monotonicClock,
|
|
27
32
|
"poll": poll,
|
|
33
|
+
"preopens": preopens,
|
|
28
34
|
"random": random,
|
|
29
35
|
"stderr": stderr,
|
|
30
36
|
"streams": streams,
|
|
@@ -32,4 +38,6 @@ export const importObject = {
|
|
|
32
38
|
"wall-clock": wallClock,
|
|
33
39
|
};
|
|
34
40
|
|
|
41
|
+
export { WasiHttp } from "../http/wasi-http.js";
|
|
42
|
+
|
|
35
43
|
export default importObject;
|
package/lib/nodejs/io.js
CHANGED
|
@@ -1,33 +1,25 @@
|
|
|
1
|
-
export function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function read(src, len) {
|
|
10
|
-
console.log(`[io] Read ${src}`, len);
|
|
1
|
+
export function read(s, len) {
|
|
2
|
+
switch (s) {
|
|
3
|
+
case 0:
|
|
4
|
+
return [process.stdin.read(len), true];
|
|
5
|
+
default:
|
|
6
|
+
throw new Error(`TODO: write ${s}`);
|
|
7
|
+
}
|
|
11
8
|
}
|
|
12
9
|
|
|
13
|
-
export function write(
|
|
14
|
-
switch (
|
|
10
|
+
export function write(s, buf) {
|
|
11
|
+
switch (s) {
|
|
15
12
|
case 0:
|
|
16
13
|
throw new Error(`TODO: write stdin`);
|
|
17
|
-
case 1:
|
|
14
|
+
case 1: {
|
|
18
15
|
process.stdout.write(buf);
|
|
19
16
|
return BigInt(buf.byteLength);
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
}
|
|
18
|
+
case 2: {
|
|
19
|
+
process.stderr.write(buf);
|
|
20
|
+
return BigInt(buf.byteLength);
|
|
21
|
+
}
|
|
22
22
|
default:
|
|
23
|
-
throw new Error(`TODO: write ${
|
|
23
|
+
throw new Error(`TODO: write ${s}`);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
export function skip(src, len) {
|
|
28
|
-
console.log(`[io] Skip ${src}`, len);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function write_repeated(dst, byte, len) {
|
|
32
|
-
console.log(`[io] Write repeated ${dst}`, byte, len);
|
|
33
|
-
}
|
package/lib/nodejs/random.js
CHANGED
package/lib/nodejs/streams.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
export function read(s,
|
|
2
|
-
|
|
1
|
+
export function read(s, len) {
|
|
2
|
+
switch (s) {
|
|
3
|
+
case 0:
|
|
4
|
+
return [process.stdin.read(len), true];
|
|
5
|
+
default:
|
|
6
|
+
throw new Error(`TODO: write ${s}`);
|
|
7
|
+
}
|
|
3
8
|
}
|
|
4
9
|
export function blockingRead(s, _len) {
|
|
5
10
|
console.log(`[streams] Blocking read ${s}`);
|
|
@@ -16,8 +21,21 @@ export function subscribeToInputStream(s) {
|
|
|
16
21
|
export function dropInputStream(s) {
|
|
17
22
|
console.log(`[streams] Drop input stream ${s}`);
|
|
18
23
|
}
|
|
19
|
-
export function write(s,
|
|
20
|
-
|
|
24
|
+
export function write(s, buf) {
|
|
25
|
+
switch (s) {
|
|
26
|
+
case 0:
|
|
27
|
+
throw new Error(`TODO: write stdin`);
|
|
28
|
+
case 1: {
|
|
29
|
+
process.stdout.write(buf);
|
|
30
|
+
return BigInt(buf.byteLength);
|
|
31
|
+
}
|
|
32
|
+
case 2: {
|
|
33
|
+
process.stderr.write(buf);
|
|
34
|
+
return BigInt(buf.byteLength);
|
|
35
|
+
}
|
|
36
|
+
default:
|
|
37
|
+
throw new Error(`TODO: write ${s}`);
|
|
38
|
+
}
|
|
21
39
|
}
|
|
22
40
|
export function blockingWrite(s, _buf) {
|
|
23
41
|
console.log(`[streams] Blocking write ${s}`);
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export namespace Preopens {
|
|
2
|
+
export function getStdio(): StdioPreopens;
|
|
3
|
+
export function getDirectories(): [Descriptor, string][];
|
|
4
|
+
}
|
|
5
|
+
import type { InputStream } from '../imports/streams';
|
|
6
|
+
export { InputStream };
|
|
7
|
+
import type { OutputStream } from '../imports/streams';
|
|
8
|
+
export { OutputStream };
|
|
9
|
+
export interface StdioPreopens {
|
|
10
|
+
stdin: InputStream,
|
|
11
|
+
stdout: OutputStream,
|
|
12
|
+
stderr: OutputStream,
|
|
13
|
+
}
|
|
14
|
+
import type { Descriptor } from '../imports/filesystem';
|
|
15
|
+
export { Descriptor };
|
package/types/wasi-reactor.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { UdpCreateSocket as UdpCreateSocketImports } from './imports/udp-create-
|
|
|
16
16
|
import { Random as RandomImports } from './imports/random';
|
|
17
17
|
import { Environment as EnvironmentImports } from './imports/environment';
|
|
18
18
|
import { EnvironmentPreopens as EnvironmentPreopensImports } from './imports/environment-preopens';
|
|
19
|
+
import { Preopens as PreopensImports } from './imports/preopens';
|
|
19
20
|
import { Exit as ExitImports } from './imports/exit';
|
|
20
21
|
import { Stderr as StderrImports } from './imports/stderr';
|
|
21
22
|
export interface ImportObject {
|
|
@@ -37,6 +38,7 @@ export interface ImportObject {
|
|
|
37
38
|
'random': typeof RandomImports,
|
|
38
39
|
'environment': typeof EnvironmentImports,
|
|
39
40
|
'environment-preopens': typeof EnvironmentPreopensImports,
|
|
41
|
+
'preopens': typeof PreopensImports,
|
|
40
42
|
'exit': typeof ExitImports,
|
|
41
43
|
'stderr': typeof StderrImports,
|
|
42
44
|
}
|
package/lib/browser/clocks.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export function wallClockNow(clock) {
|
|
2
|
-
if (clock === 1) {
|
|
3
|
-
const seconds = BigInt(Math.floor(Date.now() / 1000));
|
|
4
|
-
const nanoseconds = (Date.now() % 1000) * 1000 * 1000;
|
|
5
|
-
return { seconds, nanoseconds };
|
|
6
|
-
}
|
|
7
|
-
console.log("[clocks] UNKNOWN CLOCK");
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function monotonicClockResolution(clock) {
|
|
11
|
-
console.log(`[clocks] Monotonic clock resolution ${clock}`);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function wallClockResolution(clock) {
|
|
15
|
-
console.log(`[clocks] Wall clock resolution ${clock}`);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let hrStart = hrtimeBigint();
|
|
19
|
-
|
|
20
|
-
export function monotonicClockNow(clock) {
|
|
21
|
-
if (clock === 0) {
|
|
22
|
-
return hrtimeBigint() - hrStart;
|
|
23
|
-
}
|
|
24
|
-
console.log("UNKNOWN CLOCK");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function hrtime(previousTimestamp) {
|
|
28
|
-
const baseNow = Math.floor((Date.now() - performance.now()) * 1e-3);
|
|
29
|
-
const clocktime = performance.now() * 1e-3;
|
|
30
|
-
let seconds = Math.floor(clocktime) + baseNow;
|
|
31
|
-
let nanoseconds = Math.floor((clocktime % 1) * 1e9);
|
|
32
|
-
|
|
33
|
-
if (previousTimestamp) {
|
|
34
|
-
seconds = seconds - previousTimestamp[0];
|
|
35
|
-
nanoseconds = nanoseconds - previousTimestamp[1];
|
|
36
|
-
if (nanoseconds < 0) {
|
|
37
|
-
seconds--;
|
|
38
|
-
nanoseconds += 1e9;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return [seconds, nanoseconds];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function hrtimeBigint(time) {
|
|
45
|
-
const diff = hrtime(time);
|
|
46
|
-
return BigInt(diff[0] * 1e9 + diff[1]);
|
|
47
|
-
}
|