@bytecodealliance/preview2-shim 0.0.19 → 0.0.20

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.
Files changed (36) hide show
  1. package/LICENSE +220 -0
  2. package/README.md +4 -6
  3. package/lib/browser/index.js +0 -2
  4. package/lib/common/io.js +2 -2
  5. package/lib/{http → common}/make-request.js +1 -1
  6. package/lib/nodejs/http.js +310 -3
  7. package/lib/nodejs/index.js +0 -5
  8. package/package.json +1 -1
  9. package/types/interfaces/wasi-cli-stderr.d.ts +1 -1
  10. package/types/interfaces/wasi-cli-stdin.d.ts +1 -1
  11. package/types/interfaces/wasi-cli-stdout.d.ts +1 -1
  12. package/types/interfaces/wasi-cli-terminal-stderr.d.ts +1 -1
  13. package/types/interfaces/wasi-cli-terminal-stdin.d.ts +1 -1
  14. package/types/interfaces/wasi-cli-terminal-stdout.d.ts +1 -1
  15. package/types/interfaces/wasi-clocks-monotonic-clock.d.ts +1 -1
  16. package/types/interfaces/wasi-clocks-timezone.d.ts +1 -1
  17. package/types/interfaces/wasi-filesystem-preopens.d.ts +1 -1
  18. package/types/interfaces/wasi-filesystem-types.d.ts +8 -8
  19. package/types/interfaces/wasi-http-incoming-handler.d.ts +19 -0
  20. package/types/interfaces/wasi-http-outgoing-handler.d.ts +23 -0
  21. package/types/interfaces/wasi-http-types.d.ts +371 -0
  22. package/types/interfaces/wasi-io-streams.d.ts +13 -21
  23. package/types/interfaces/wasi-sockets-instance-network.d.ts +1 -1
  24. package/types/interfaces/wasi-sockets-ip-name-lookup.d.ts +5 -5
  25. package/types/interfaces/wasi-sockets-tcp-create-socket.d.ts +4 -4
  26. package/types/interfaces/wasi-sockets-tcp.d.ts +7 -7
  27. package/types/interfaces/wasi-sockets-udp-create-socket.d.ts +4 -4
  28. package/types/interfaces/wasi-sockets-udp.d.ts +5 -5
  29. package/types/wasi-cli-command.d.ts +3 -3
  30. package/types/wasi-http-proxy.d.ts +13 -0
  31. package/lib/browser/io.js +0 -39
  32. package/lib/browser/poll.js +0 -53
  33. package/lib/http/wasi-http.js +0 -382
  34. package/lib/nodejs/poll.js +0 -9
  35. /package/lib/{http/synckit → synckit}/index.d.ts +0 -0
  36. /package/lib/{http/synckit → synckit}/index.js +0 -0
package/lib/browser/io.js DELETED
@@ -1,39 +0,0 @@
1
- import { Io } from '../common/io.js';
2
-
3
- // buffer until the next newline
4
- export class NewlineBufferStream {
5
- constructor (handler) {
6
- this.bufferLen = 0;
7
- this.bufferCapacity = 1024;
8
- this.buffer = new Uint8Array(1024);
9
- this.handler = handler;
10
- }
11
- write (bytes) {
12
- const newlineIdx = bytes.lastIndexOf(10);
13
- if (newlineIdx === -1) {
14
- this.#addToBuffer(bytes);
15
- } else {
16
- this.#addToBuffer(bytes.slice(0, newlineIdx + 1));
17
- this.handler(new TextDecoder().decode(this.buffer.slice(0, this.bufferLen)));
18
- this.bufferLen = 0;
19
- this.#addToBuffer(bytes.slice(newlineIdx + 1));
20
- }
21
- }
22
- #addToBuffer (bytes) {
23
- if (bytes.byteLength + this.bufferLen > this.bufferCapacity) {
24
- this.bufferCapacity *= 2;
25
- const buffer = new Uint8Array(this.bufferCapacity);
26
- buffer.set(this.buffer);
27
- this.buffer = buffer;
28
- }
29
- this.buffer.set(bytes, this.bufferLen);
30
- this.bufferLen += bytes.byteLength;
31
- }
32
- }
33
-
34
- export const _io = new Io(
35
- new NewlineBufferStream(console.log.bind(console)),
36
- new NewlineBufferStream(console.error.bind(console))
37
- );
38
-
39
- export const streams = _io.streams;
@@ -1,53 +0,0 @@
1
- let polls = {};
2
- let pollCnt = 1;
3
-
4
- let timer = null, timerInterval = 10, watching = new Set();
5
- function intervalCheck () {
6
- for (const entry of watching) {
7
- if (entry.settled) {
8
- entry.resolvePromise();
9
- entry.promise = entry.resolvePromise = null;
10
- watching.delete(entry);
11
- }
12
- }
13
- if (watching.size === 0) {
14
- clearInterval(timer);
15
- timer = null;
16
- }
17
- }
18
-
19
- export function _createPollable (promise) {
20
- const entry = { settled: false, promise: null, resolvePromise: null };
21
- promise.finally(() => entry.settled = true);
22
- polls[pollCnt] = entry;
23
- return pollCnt++;
24
- }
25
-
26
- export function _pollablePromise (pollable, maxInterval) {
27
- const entry = polls[pollable];
28
- if (entry.settled) return Promise.resolve();
29
- if (!entry.promise)
30
- entry.promise = new Promise(resolve => entry.resolvePromise = resolve);
31
- watching.add(entry);
32
- if (maxInterval) {
33
- if (timerInterval > maxInterval) {
34
- clearInterval(timer);
35
- timer = null;
36
- timerInterval = maxInterval;
37
- }
38
- }
39
- if (!timer)
40
- timer = setInterval(intervalCheck, timerInterval);
41
- return entry.promise;
42
- }
43
-
44
- export const poll = {
45
- dropPollable (pollable) {
46
- const entry = polls[pollable];
47
- watching.delete(entry);
48
- delete polls[pollable];
49
- },
50
- pollOneoff (from) {
51
- return from.map(pollable => polls[pollable].settled);
52
- }
53
- };
@@ -1,382 +0,0 @@
1
- /**
2
- * @typedef {import("../../types/interfaces/wasi-http-types").Fields} Fields
3
- * @typedef {import("../../types/interfaces/wasi-http-types").FutureIncomingResponse} FutureIncomingResponse
4
- * @typedef {import("../../types/interfaces/wasi-http-types").Headers} Headers
5
- * @typedef {import("../../types/interfaces/wasi-http-types").IncomingStream} IncomingStream
6
- * @typedef {import("../../types/interfaces/wasi-http-types").Method} Method
7
- * @typedef {import("../../types/interfaces/wasi-http-types").RequestOptions} RequestOptions
8
- * @typedef {import("../../types/interfaces/wasi-http-types").Result} Result
9
- * @typedef {import("../../types/interfaces/wasi-http-types").Scheme} Scheme
10
- * @typedef {import("../../types/interfaces/wasi-http-types").StatusCode} StatusCode
11
- * @typedef {import("../../types/interfaces/wasi-io-streams").StreamStatus} StreamStatus
12
- */
13
-
14
- import { fileURLToPath } from 'node:url';
15
- import { createSyncFn } from './synckit/index.js';
16
-
17
- const workerPath = fileURLToPath(new URL('./make-request.js', import.meta.url));
18
-
19
- function send(req) {
20
- const syncFn = createSyncFn(workerPath);
21
- let rawResponse = syncFn(req);
22
- let response = JSON.parse(rawResponse);
23
- if (response.status) {
24
- return {
25
- ...response,
26
- body: response.body ? Buffer.from(response.body, 'base64') : undefined,
27
- };
28
- }
29
- throw new UnexpectedError(response.message);
30
- }
31
-
32
- class UnexpectedError extends Error {
33
- payload;
34
- constructor(message = "unexpected-error") {
35
- super(message);
36
- this.payload = {
37
- tag: "unexpected-error",
38
- val: message,
39
- };
40
- }
41
- }
42
-
43
- function combineChunks (chunks) {
44
- if (chunks.length === 0)
45
- return new Uint8Array();
46
- if (chunks.length === 1)
47
- return chunks[0];
48
- const totalLen = chunks.reduce((total, chunk) => total + chunk.byteLength);
49
- const out = new Uint8Array(totalLen);
50
- let idx = 0;
51
- for (const chunk of chunks) {
52
- out.set(chunk, idx);
53
- idx += chunk.byteLength;
54
- }
55
- return out;
56
- }
57
-
58
- export class WasiHttp {
59
- requestCnt = 1;
60
- responseCnt = 1;
61
- fieldsCnt = 1;
62
- futureCnt = 1;
63
- /** @type {Map<number,OutgoingRequest>} */ requests = new Map();
64
- /** @type {Map<number,IncomingResponse>} */ responses = new Map();
65
- /** @type {Map<number,Fields>} */ fields = new Map();
66
- /** @type {Map<number,Future>} */ futures = new Map();
67
-
68
- /**
69
- *
70
- * @param {import('../common/io.js').Io} io
71
- * @returns
72
- */
73
- constructor(io) {
74
- const http = this;
75
-
76
- class OutgoingRequest {
77
- /** @type {number} */ id;
78
- bodyFinished = false;
79
- /** @type {Method} */ method = { tag: 'get' };
80
- /** @type {Scheme | undefined} */ scheme = { tag: 'HTTP' };
81
- pathWithQuery = undefined;
82
- authority = undefined;
83
- /** @type {number | undefined} */ headers = undefined;
84
- chunks = [];
85
- body = io.createStream(this);
86
- constructor() {
87
- http.requests.set(this.id = http.requestCnt++, this);
88
- }
89
- write (bytes) {
90
- this.chunks.push(bytes);
91
- }
92
- }
93
- class IncomingResponse {
94
- /** @type {number} */ id;
95
- bodyFinished = false;
96
- status = 0;
97
- chunks = [];
98
- body = io.createStream(this);
99
- /** @type {number | undefined} */ headers = undefined;
100
- constructor() {
101
- http.responses.set(this.id = http.responseCnt++, this);
102
- }
103
- read (_len) {
104
- if (this.chunks.length === 0)
105
- return [new Uint8Array([]), this.bodyFinished ? 'ended' : 'open'];
106
- if (this.chunks.length === 1)
107
- return [this.chunks[0], this.bodyFinished ? 'ended' : 'open'];
108
- return [this.chunks.shift(), 'open'];
109
- }
110
- }
111
-
112
- class Future {
113
- /** @type {number} */ id;
114
- /** @type {number} */ responseId;
115
-
116
- constructor(responseId) {
117
- http.futures.set(this.id = http.futureCnt++, this);
118
- this.responseId = responseId;
119
- }
120
- }
121
-
122
- class Fields {
123
- /** @type {number} */ id;
124
- /** @type {Map<string, Uint8Array[]>} */ fields;
125
-
126
- constructor(fields) {
127
- http.fields.set(this.id = http.fieldsCnt++, this);
128
- const encoder = new TextEncoder();
129
- this.fields = new Map(fields.map(([k, v]) => [k, encoder.encode(v)]));
130
- }
131
- }
132
-
133
- this.incomingHandler = {
134
- // TODO
135
- handle () {
136
-
137
- }
138
- };
139
-
140
- this.outgoingHandler = {
141
- /**
142
- * @param {OutgoingRequest} requestId
143
- * @param {RequestOptions | undefined} options
144
- * @returns {FutureIncomingResponse}
145
- */
146
- handle (requestId, _options) {
147
- const request = http.requests.get(requestId);
148
- if (!request) throw Error("not found!");
149
-
150
- const response = new IncomingResponse();
151
-
152
- const scheme = request.scheme.tag === "HTTP" ? "http://" : "https://";
153
-
154
- const url = scheme + request.authority + request.pathWithQuery;
155
- const headers = {
156
- "host": request.authority,
157
- };
158
- if (request.headers) {
159
- const requestHeaders = http.fields.get(request.headers);
160
- const decoder = new TextDecoder();
161
- for (const [key, value] of requestHeaders.fields.entries()) {
162
- headers[key] = decoder.decode(value);
163
- }
164
- }
165
-
166
- const res = send({
167
- method: request.method.tag,
168
- uri: url,
169
- headers: headers,
170
- params: [],
171
- body: combineChunks(request.chunks),
172
- });
173
-
174
- response.status = res.status;
175
- if (res.headers && res.headers.length > 0) {
176
- response.headers = types.newFields(res.headers);
177
- }
178
- http.responses.set(response.id, response);
179
- response.chunks = [res.body];
180
-
181
- const future = new Future(response.id);
182
- return future.id;
183
- }
184
- };
185
-
186
- const types = this.types = {
187
- /**
188
- * @param {Fields} fields
189
- */
190
- dropFields(fields) {
191
- http.fields.delete(fields);
192
- },
193
-
194
- /**
195
- * @param {[string, string][]} entries
196
- * @returns {Fields}
197
- */
198
- newFields(entries) {
199
- return new Fields(entries).id;
200
- },
201
-
202
- fieldsGet(_fields, _name) {
203
- console.log("[types] Fields get");
204
- },
205
- fieldsSet(_fields, _name, _value) {
206
- console.log("[types] Fields set");
207
- },
208
- fieldsDelete(_fields, _name) {
209
- console.log("[types] Fields delete");
210
- },
211
- fieldsAppend(_fields, _name, _value) {
212
- console.log("[types] Fields append");
213
- },
214
-
215
- /**
216
- * @param {Fields} fields
217
- * @returns {[string, Uint8Array][]}
218
- */
219
- fieldsEntries(fields) {
220
- const activeFields = http.fields.get(fields);
221
- return activeFields ? Array.from(activeFields.fields) : [];
222
- },
223
-
224
- fieldsClone(_fields) {
225
- console.log("[types] Fields clone");
226
- },
227
- finishIncomingStream(s) {
228
- io.getStream(s).bodyFinished = true;
229
- },
230
- finishOutgoingStream(s, _trailers) {
231
- io.getStream(s).bodyFinished = true;
232
- },
233
- dropIncomingRequest(_req) {
234
- console.log("[types] Drop incoming request");
235
- },
236
-
237
- /**
238
- * @param {OutgoingRequest} request
239
- */
240
- dropOutgoingRequest(request) {
241
- http.requests.delete(request);
242
- },
243
-
244
- incomingRequestMethod(_req) {
245
- console.log("[types] Incoming request method");
246
- },
247
- incomingRequestPathWithQuery(_req) {
248
- console.log("[types] Incoming request path with query");
249
- },
250
- incomingRequestScheme(_req) {
251
- console.log("[types] Incoming request scheme");
252
- },
253
- incomingRequestAuthority(_req) {
254
- console.log("[types] Incoming request authority");
255
- },
256
- incomingRequestHeaders(_req) {
257
- console.log("[types] Incoming request headers");
258
- },
259
- incomingRequestConsume(_req) {
260
- console.log("[types] Incoming request consume");
261
- },
262
-
263
- /**
264
- * @param {Method} method
265
- * @param {string | undefined} pathWithQuery
266
- * @param {Scheme | undefined} scheme
267
- * @param {string | undefined} authority
268
- * @param {Headers} headers
269
- * @returns {number}
270
- */
271
- newOutgoingRequest(method, pathWithQuery, scheme, authority, headers) {
272
- const req = new OutgoingRequest();
273
- req.pathWithQuery = pathWithQuery;
274
- req.authority = authority;
275
- req.method = method;
276
- req.headers = headers;
277
- req.scheme = scheme;
278
- return req.id;
279
- },
280
-
281
- /**
282
- * @param {OutgoingRequest} request
283
- * @returns {OutgoingStream}
284
- */
285
- outgoingRequestWrite(request) {
286
- return http.requests.get(request).body;
287
- },
288
-
289
- dropResponseOutparam(_res) {
290
- console.log("[types] Drop response outparam");
291
- },
292
- setResponseOutparam(_response) {
293
- console.log("[types] Set response outparam");
294
- },
295
-
296
- /**
297
- * @param {IncomingResponse} response
298
- */
299
- dropIncomingResponse(response) {
300
- http.responses.delete(response);
301
- },
302
-
303
- dropOutgoingResponse(_res) {
304
- console.log("[types] Drop outgoing response");
305
- },
306
-
307
- /**
308
- * @param {IncomingResponse} response
309
- * @returns {StatusCode}
310
- */
311
- incomingResponseStatus(response) {
312
- const r = http.responses.get(response);
313
- return r.status;
314
- },
315
-
316
- /**
317
- * @param {IncomingResponse} response
318
- * @returns {Headers}
319
- */
320
- incomingResponseHeaders(response) {
321
- const r = http.responses.get(response);
322
- return r.headers ?? 0;
323
- },
324
-
325
- /**
326
- * @param {IncomingResponse} response
327
- * @returns {IncomingStream}
328
- */
329
- incomingResponseConsume(response) {
330
- const r = http.responses.get(response);
331
- return r.body;
332
- },
333
-
334
- newOutgoingResponse(_statusCode, _headers) {
335
- console.log("[types] New outgoing response");
336
- },
337
- outgoingResponseWrite(_res) {
338
- console.log("[types] Outgoing response write");
339
- },
340
-
341
-
342
- /**
343
- * @param {FutureIncomingResponse} future
344
- */
345
- dropFutureIncomingResponse(future) {
346
- return http.futures.delete(future);
347
- },
348
-
349
- /**
350
- * @param {FutureIncomingResponse} future
351
- * @returns {Result<IncomingResponse, Error> | undefined}
352
- */
353
- futureIncomingResponseGet(future) {
354
- const f = http.futures.get(future);
355
- if (!f) {
356
- return {
357
- tag: "err",
358
- val: UnexpectedError(`no such future ${f}`),
359
- };
360
- }
361
- // For now this will assume the future will return
362
- // the response immediately
363
- const response = f.responseId;
364
- const r = http.responses.get(response);
365
- if (!r) {
366
- return {
367
- tag: "err",
368
- val: UnexpectedError(`no such response ${response}`),
369
- };
370
- }
371
- return {
372
- tag: "ok",
373
- val: response,
374
- };
375
- },
376
-
377
- listenToFutureIncomingResponse(_f) {
378
- console.log("[types] Listen to future incoming response");
379
- }
380
- };
381
- }
382
- }
@@ -1,9 +0,0 @@
1
- export const poll = {
2
- dropPollable (pollable) {
3
- console.log(`[poll] Drop (${pollable})`);
4
- },
5
- pollOneoff (input) {
6
- console.log(`[poll] Oneoff (${input})`);
7
- return [];
8
- }
9
- };
File without changes
File without changes