@bytecodealliance/preview2-shim 0.0.12 → 0.0.14

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 (91) hide show
  1. package/README.md +2 -2
  2. package/lib/browser/cli.js +87 -0
  3. package/lib/browser/filesystem.js +216 -18
  4. package/lib/browser/http.js +4 -7
  5. package/lib/browser/index.js +2 -2
  6. package/lib/browser/io.js +76 -17
  7. package/lib/browser/logging.js +2 -2
  8. package/lib/browser/poll.js +48 -4
  9. package/lib/http/error.js +1 -1
  10. package/lib/http/make-request.js +3 -2
  11. package/lib/http/wasi-http.js +52 -40
  12. package/lib/nodejs/cli.js +75 -0
  13. package/lib/nodejs/filesystem.js +93 -3
  14. package/lib/nodejs/http.js +4 -7
  15. package/lib/nodejs/index.js +2 -2
  16. package/lib/nodejs/logging.js +2 -2
  17. package/package.json +1 -1
  18. package/types/{imports/environment.d.ts → exports/wasi-cli-environment.d.ts} +6 -1
  19. package/types/{imports/exit.d.ts → exports/wasi-cli-exit.d.ts} +2 -2
  20. package/types/exports/wasi-cli-run.d.ts +6 -0
  21. package/types/exports/wasi-cli-stderr.d.ts +5 -0
  22. package/types/exports/wasi-cli-stdin.d.ts +5 -0
  23. package/types/exports/wasi-cli-stdout.d.ts +5 -0
  24. package/types/exports/wasi-cli-terminal-input.d.ts +13 -0
  25. package/types/exports/wasi-cli-terminal-output.d.ts +13 -0
  26. package/types/exports/wasi-cli-terminal-stderr.d.ts +9 -0
  27. package/types/exports/wasi-cli-terminal-stdin.d.ts +9 -0
  28. package/types/exports/wasi-cli-terminal-stdout.d.ts +9 -0
  29. package/types/{imports/monotonic-clock.d.ts → exports/wasi-clocks-monotonic-clock.d.ts} +2 -2
  30. package/types/{imports/timezone.d.ts → exports/wasi-clocks-timezone.d.ts} +15 -15
  31. package/types/{imports/wall-clock.d.ts → exports/wasi-clocks-wall-clock.d.ts} +1 -1
  32. package/types/exports/wasi-filesystem-preopens.d.ts +8 -0
  33. package/types/{imports/filesystem.d.ts → exports/wasi-filesystem-types.d.ts} +293 -307
  34. package/types/exports/wasi-http-incoming-handler.d.ts +3 -3
  35. package/types/exports/wasi-http-outgoing-handler.d.ts +9 -0
  36. package/types/{imports/types.d.ts → exports/wasi-http-types.d.ts} +40 -41
  37. package/types/exports/wasi-io-streams.d.ts +220 -0
  38. package/types/{imports/poll.d.ts → exports/wasi-poll-poll.d.ts} +6 -8
  39. package/types/{imports/insecure-seed.d.ts → exports/wasi-random-insecure-seed.d.ts} +1 -1
  40. package/types/exports/wasi-random-insecure.d.ts +20 -0
  41. package/types/exports/wasi-random-random.d.ts +22 -0
  42. package/types/{imports/instance-network.d.ts → exports/wasi-sockets-instance-network.d.ts} +2 -2
  43. package/types/{imports/ip-name-lookup.d.ts → exports/wasi-sockets-ip-name-lookup.d.ts} +9 -9
  44. package/types/{imports/network.d.ts → exports/wasi-sockets-network.d.ts} +43 -75
  45. package/types/{imports/tcp-create-socket.d.ts → exports/wasi-sockets-tcp-create-socket.d.ts} +5 -5
  46. package/types/{imports/tcp.d.ts → exports/wasi-sockets-tcp.d.ts} +38 -38
  47. package/types/{imports/udp-create-socket.d.ts → exports/wasi-sockets-udp-create-socket.d.ts} +5 -5
  48. package/types/{imports/udp.d.ts → exports/wasi-sockets-udp.d.ts} +41 -32
  49. package/types/imports/wasi-cli-environment.d.ts +22 -0
  50. package/types/imports/wasi-cli-exit.d.ts +7 -0
  51. package/types/imports/wasi-cli-stderr.d.ts +5 -0
  52. package/types/imports/wasi-cli-stdin.d.ts +5 -0
  53. package/types/imports/wasi-cli-stdout.d.ts +5 -0
  54. package/types/imports/wasi-cli-terminal-input.d.ts +13 -0
  55. package/types/imports/wasi-cli-terminal-output.d.ts +13 -0
  56. package/types/imports/wasi-cli-terminal-stderr.d.ts +9 -0
  57. package/types/imports/wasi-cli-terminal-stdin.d.ts +9 -0
  58. package/types/imports/wasi-cli-terminal-stdout.d.ts +9 -0
  59. package/types/imports/wasi-clocks-monotonic-clock.d.ts +24 -0
  60. package/types/imports/wasi-clocks-timezone.d.ts +71 -0
  61. package/types/imports/wasi-clocks-wall-clock.d.ts +31 -0
  62. package/types/imports/wasi-filesystem-preopens.d.ts +8 -0
  63. package/types/imports/wasi-filesystem-types.d.ts +843 -0
  64. package/types/imports/wasi-http-outgoing-handler.d.ts +9 -0
  65. package/types/imports/wasi-http-types.d.ts +118 -0
  66. package/types/imports/wasi-io-streams.d.ts +220 -0
  67. package/types/imports/wasi-poll-poll.d.ts +39 -0
  68. package/types/imports/wasi-random-insecure-seed.d.ts +22 -0
  69. package/types/imports/{insecure.d.ts → wasi-random-insecure.d.ts} +1 -1
  70. package/types/imports/{random.d.ts → wasi-random-random.d.ts} +1 -1
  71. package/types/imports/wasi-sockets-instance-network.d.ts +8 -0
  72. package/types/imports/wasi-sockets-ip-name-lookup.d.ts +76 -0
  73. package/types/imports/wasi-sockets-network.d.ts +180 -0
  74. package/types/imports/wasi-sockets-tcp-create-socket.d.ts +33 -0
  75. package/types/imports/wasi-sockets-tcp.d.ts +285 -0
  76. package/types/imports/wasi-sockets-udp-create-socket.d.ts +33 -0
  77. package/types/imports/wasi-sockets-udp.d.ts +228 -0
  78. package/types/wasi-cli-command.d.ts +29 -0
  79. package/types/wasi-http-proxy.d.ts +13 -0
  80. package/lib/browser/cli-base.js +0 -48
  81. package/lib/nodejs/cli-base.js +0 -99
  82. package/types/imports/handler.d.ts +0 -40
  83. package/types/imports/outgoing-handler.d.ts +0 -9
  84. package/types/imports/preopens.d.ts +0 -12
  85. package/types/imports/stderr.d.ts +0 -5
  86. package/types/imports/stdin.d.ts +0 -5
  87. package/types/imports/stdout.d.ts +0 -5
  88. package/types/imports/streams.d.ts +0 -180
  89. package/types/wasi-command.d.ts +0 -23
  90. package/types/wasi-proxy.d.ts +0 -10
  91. package/types/wasi-reactor.d.ts +0 -23
package/README.md CHANGED
@@ -10,13 +10,13 @@ Currently supports Node.js and browser versions, but alternative implementations
10
10
  | --------------- | ----------------------------:|-----------------------------:|
11
11
  | Clocks | Pending timezone, poll | Pending timezone, poll |
12
12
  | Filesystem | Basic read support | :x: |
13
- | HTTP | :x: | :x: |
13
+ | HTTP | Experimental support | Experimental support |
14
14
  | IO | Basic FS Streams | :x: |
15
15
  | Logging | :heavy_check_mark: | :heavy_check_mark: |
16
16
  | Poll | :x: | :x: |
17
17
  | Random | :heavy_check_mark: | :heavy_check_mark: |
18
18
  | Sockets | :x: | :x: |
19
- | CLI Base | :heavy_check_mark: | :heavy_check_mark: |
19
+ | CLI | :heavy_check_mark: | :heavy_check_mark: |
20
20
 
21
21
  # License
22
22
 
@@ -0,0 +1,87 @@
1
+ import { _setCwd as fsSetCwd } from './filesystem.js';
2
+
3
+ let _env = [], _args = [], _cwd = null;
4
+ export function _setEnv (envObj) {
5
+ _env = Object.entries(envObj);
6
+ }
7
+ export function _setArgs (args) {
8
+ _args = args;
9
+ }
10
+
11
+ export function _setCwd (cwd) {
12
+ fsSetCwd(_cwd = cwd);
13
+ }
14
+
15
+ export const environment = {
16
+ getEnvironment () {
17
+ return _env;
18
+ },
19
+ getArguments () {
20
+ return _args;
21
+ },
22
+ initialCwd () {
23
+ return _cwd;
24
+ }
25
+ };
26
+
27
+ class ComponentExit extends Error {
28
+ constructor(ok) {
29
+ super(`Component exited ${ok ? 'successfully' : 'with error'}`);
30
+ this.exitError = true;
31
+ this.ok = ok;
32
+ }
33
+ }
34
+
35
+ export const exit = {
36
+ exit (status) {
37
+ throw new ComponentExit(status.tag === 'err' ? true : false);
38
+ }
39
+ };
40
+
41
+ export const stdin = {
42
+ getStdin () {
43
+ return 0;
44
+ }
45
+ };
46
+
47
+ export const stdout = {
48
+ getStdout () {
49
+ return 1;
50
+ }
51
+ };
52
+
53
+ export const stderr = {
54
+ getStderr () {
55
+ return 2;
56
+ }
57
+ };
58
+
59
+ export const terminalInput = {
60
+ dropTerminalInput () {
61
+
62
+ }
63
+ };
64
+
65
+ export const terminalOutput = {
66
+ dropTerminalOutput () {
67
+
68
+ }
69
+ };
70
+
71
+ export const terminalStderr = {
72
+ getTerminalStderr () {
73
+ return 0;
74
+ }
75
+ };
76
+
77
+ export const terminalStdin = {
78
+ getTerminalStdin () {
79
+ return 1;
80
+ }
81
+ };
82
+
83
+ export const terminalStdout = {
84
+ getTerminalStdout () {
85
+ return 2;
86
+ }
87
+ };
@@ -1,10 +1,145 @@
1
- export const filesystem = {
1
+ import { createStream, getStream, dropStream } from './io.js';
2
+ import { environment } from './cli.js';
3
+
4
+ let _preopens = [[3, '/']], _rootPreopen = _preopens[0];
5
+
6
+ export function _setPreopens (preopens) {
7
+ _preopens = preopens;
8
+ descriptorCnt = 3 + _preopens.length;
9
+ _rootPreopen = _preopens.find(preopen => preopen[1] === '/');
10
+ }
11
+
12
+ let _cwd = null;
13
+
14
+ export function _setCwd (cwd) {
15
+ _cwd = cwd;
16
+ }
17
+
18
+ export function _setFileData (fileData) {
19
+ _fileData = fileData;
20
+ _setPreopens(Object.keys(fileData).map((key) => {
21
+ const fd = descriptorCnt++;
22
+ descriptorTable[fd] = { entry: fileData[key] };
23
+ return [fd, key];
24
+ }));
25
+ const cwd = environment.initialCwd();
26
+ _setCwd(cwd || '/');
27
+ }
28
+
29
+ export function _getFileData () {
30
+ return JSON.stringify(_fileData);
31
+ }
32
+
33
+ let _fileData = {};
34
+
35
+ let descriptorCnt = 4;
36
+ const descriptorTable = {
37
+ 0: { stream: 0 },
38
+ 1: { stream: 1 },
39
+ 2: { stream: 2 },
40
+ 3: { entry: { dir: {} } },
41
+ };
42
+
43
+ const timeZero = {
44
+ seconds: BigInt(0),
45
+ nanoseconds: 0
46
+ };
47
+
48
+ function getDescriptor (fd) {
49
+ const descriptor = descriptorTable[fd];
50
+ if (!descriptor) throw 'bad-descriptor';
51
+ return descriptor;
52
+ }
53
+
54
+ function getChildEntry (fd, subpath, openFlags) {
55
+ if (subpath === '.' && _rootPreopen && _rootPreopen[0] === fd) {
56
+ subpath = _cwd;
57
+ if (subpath.startsWith('/'))
58
+ subpath = subpath.slice(1);
59
+ }
60
+ let entry = getDescriptor(fd)?.entry;
61
+ let segmentIdx;
62
+ do {
63
+ if (!entry || !entry.dir) throw 'not-directory';
64
+ segmentIdx = subpath.indexOf('/');
65
+ const segment = segmentIdx === -1 ? subpath : subpath.slice(0, segmentIdx);
66
+ if (segment === '.' || segment === '') return entry;
67
+ if (segment === '..') throw 'no-entry';
68
+ if (!entry.dir[segment] && openFlags.create)
69
+ entry = entry.dir[segment] = openFlags.directory ? { dir: {} } : { source: new Uint8Array([]) };
70
+ else
71
+ entry = entry.dir[segment];
72
+ } while (segmentIdx !== -1)
73
+ if (!entry) throw 'no-entry';
74
+ return entry;
75
+ }
76
+
77
+ function createChildDescriptor (fd, subpath, openFlags) {
78
+ const entry = getChildEntry(fd, subpath, openFlags);
79
+ const childFd = descriptorCnt++;
80
+ descriptorTable[childFd] = { entry };
81
+ return childFd;
82
+ }
83
+
84
+ function getSource (fileEntry) {
85
+ if (typeof fileEntry.source === 'string') {
86
+ fileEntry.source = new TextEncoder().encode(fileEntry.source);
87
+ }
88
+ return fileEntry.source;
89
+ }
90
+
91
+ class DirStream {
92
+ constructor (entries) {
93
+ this.idx = 0;
94
+ this.entries = entries;
95
+ }
96
+ next () {
97
+ if (this.idx === this.entries.length)
98
+ return null;
99
+ const [name, entry] = this.entries[this.idx];
100
+ this.idx += 1;
101
+ return {
102
+ name,
103
+ type: entry.dir ? 'directory' : 'regular-file'
104
+ };
105
+ }
106
+ }
107
+
108
+ export const preopens = {
109
+ getDirectories () {
110
+ return _preopens;
111
+ }
112
+ }
113
+
114
+ export const types = {
2
115
  readViaStream(fd, offset) {
3
- console.log(`[filesystem] READ STREAM ${fd} ${offset}`);
116
+ const descriptor = getDescriptor(fd);
117
+ const source = getSource(descriptor.entry);
118
+ return createStream({
119
+ i: Number(offset),
120
+ source,
121
+ read (len) {
122
+ const bytes = this.source.slice(this.i, this.i + Number(len));
123
+ this.i += bytes.byteLength;
124
+ return [bytes, this.i === this.source.byteLength ? 'ended' : 'open'];
125
+ }
126
+ });
4
127
  },
5
128
 
6
129
  writeViaStream(fd, offset) {
7
- console.log(`[filesystem] WRITE STREAM ${fd} ${offset}`);
130
+ const descriptor = getDescriptor(fd);
131
+ return createStream({
132
+ i: Number(offset),
133
+ entry: descriptor.entry,
134
+ write (buf) {
135
+ const newSource = new Uint8Array(buf.byteLength + this.entry.source.byteLength);
136
+ newSource.set(this.entry.source, 0);
137
+ newSource.set(buf, this.i);
138
+ this.i += buf.byteLength;
139
+ this.entry.source = newSource;
140
+ return buf.byteLength;
141
+ }
142
+ });
8
143
  },
9
144
 
10
145
  appendViaStream(fd) {
@@ -24,7 +159,12 @@ export const filesystem = {
24
159
  },
25
160
 
26
161
  getType(fd) {
27
- console.log(`[filesystem] GET TYPE ${fd}`);
162
+ if (fd < 3) return 'fifo';
163
+ const descriptor = getDescriptor(fd);
164
+ if (descriptor.stream) return 'fifo';
165
+ if (descriptor.entry.dir) return 'directory';
166
+ if (descriptor.entry.source) return 'regular-file';
167
+ return 'unknown';
28
168
  },
29
169
 
30
170
  setFlags(fd, flags) {
@@ -40,15 +180,22 @@ export const filesystem = {
40
180
  },
41
181
 
42
182
  read(fd, length, offset) {
43
- console.log(`[filesystem] READ`, fd, length, offset);
183
+ const descriptor = getDescriptor(fd);
184
+ const source = getSource(descriptor.entry);
185
+ return [source.slice(offset, offset + length), offset + length >= source.byteLength];
44
186
  },
45
187
 
46
188
  write(fd, buffer, offset) {
47
- console.log(`[filesystem] WRITE`, fd, buffer, offset);
189
+ const descriptor = getDescriptor(fd);
190
+ if (offset !== 0) throw 'invalid-seek';
191
+ descriptor.entry.source = buffer;
192
+ return buffer.byteLength;
48
193
  },
49
194
 
50
195
  readDirectory(fd) {
51
- console.log(`[filesystem] READ DIR`, fd);
196
+ const descriptor = getDescriptor(fd);
197
+ if (!descriptor?.entry?.dir) throw 'bad-descriptor';
198
+ return createStream(new DirStream(Object.entries(descriptor.entry.dir).sort(([a], [b]) => a > b ? 1 : -1)));
52
199
  },
53
200
 
54
201
  sync(fd) {
@@ -56,15 +203,50 @@ export const filesystem = {
56
203
  },
57
204
 
58
205
  createDirectoryAt(fd, path) {
59
- console.log(`[filesystem] CREATE DIRECTORY`, fd, path);
206
+ const entry = getChildEntry(fd, path, { create: true, directory: true });
207
+ if (entry.source) throw 'exist';
60
208
  },
61
209
 
62
210
  stat(fd) {
63
- console.log(`[filesystem] STAT`, fd);
211
+ const descriptor = getDescriptor(fd);
212
+ let type = 'unknown', size = BigInt(0);
213
+ if (descriptor.entry.source) {
214
+ type = 'directory';
215
+ }
216
+ else if (descriptor.entry.dir) {
217
+ type = 'regular-file';
218
+ const source = getSource(descriptor.entry);
219
+ size = BigInt(source.byteLength);
220
+ }
221
+ return {
222
+ type,
223
+ linkCount: BigInt(0),
224
+ size,
225
+ dataAccessTimestamp: timeZero,
226
+ dataModificationTimestamp: timeZero,
227
+ statusChangeTimestamp: timeZero,
228
+ }
64
229
  },
65
230
 
66
231
  statAt(fd, pathFlags, path) {
67
- console.log(`[filesystem] STAT`, fd, pathFlags, path);
232
+ const entry = getChildEntry(fd, path);
233
+ let type = 'unknown', size = BigInt(0);
234
+ if (entry.source) {
235
+ type = 'regular-file';
236
+ const source = getSource(entry);
237
+ size = BigInt(source.byteLength);
238
+ }
239
+ else if (entry.dir) {
240
+ type = 'directory';
241
+ }
242
+ return {
243
+ type,
244
+ linkCount: BigInt(0),
245
+ size,
246
+ dataAccessTimestamp: timeZero,
247
+ dataModificationTimestamp: timeZero,
248
+ statusChangeTimestamp: timeZero,
249
+ };
68
250
  },
69
251
 
70
252
  setTimesAt(fd) {
@@ -75,8 +257,8 @@ export const filesystem = {
75
257
  console.log(`[filesystem] LINK AT`, fd);
76
258
  },
77
259
 
78
- openAt(fd) {
79
- console.log(`[filesystem] OPEN AT ${fd}`);
260
+ openAt(fd, _pathFlags, path, openFlags, _descriptorFlags, _modes) {
261
+ return createChildDescriptor(fd, path, openFlags);
80
262
  },
81
263
 
82
264
  readlinkAt(fd) {
@@ -128,16 +310,32 @@ export const filesystem = {
128
310
  },
129
311
 
130
312
  dropDescriptor(fd) {
131
- console.log(`[filesystem] DROP DESCRIPTOR`, fd);
313
+ if (fd < _preopens.length + 3)
314
+ return;
315
+ delete descriptorTable[fd];
316
+ },
317
+
318
+ readDirectoryEntry(sid) {
319
+ return getStream(sid).next();
320
+ },
321
+
322
+ dropDirectoryEntryStream(sid) {
323
+ dropStream(sid);
132
324
  },
133
325
 
134
- readDirectoryEntry(stream) {
135
- console.log(`[filesystem] READ DIRECTRY ENTRY`, stream);
326
+ metadataHash(fd) {
327
+ const descriptor = getDescriptor(fd);
328
+ let upper = BigInt(0);
329
+ upper += BigInt(descriptor.mtime || 0);
330
+ return { upper, lower: BigInt(0) };
136
331
  },
137
332
 
138
- dropDirectoryEntryStream(stream) {
139
- console.log(`[filesystem] DROP DIRECTORY ENTRY`, stream);
333
+ metadataHashAt(fd, _pathFlags, _path) {
334
+ const descriptor = getDescriptor(fd);
335
+ let upper = BigInt(0);
336
+ upper += BigInt(descriptor.mtime || 0);
337
+ return { upper, lower: BigInt(0) };
140
338
  }
141
339
  };
142
340
 
143
- export { filesystem as filesystemFilesystem }
341
+ export { types as filesystemTypes }
@@ -1,7 +1,7 @@
1
1
  import { UnexpectedError } from "../http/error.js";
2
2
 
3
3
  /**
4
- * @param {import("../types/imports/types").Request} req
4
+ * @param {import("../../types/imports/wasi-http-types").Request} req
5
5
  * @returns {string}
6
6
  */
7
7
  export function send(req) {
@@ -86,11 +86,8 @@ export const types = {
86
86
  incomingRequestMethod(_req) {
87
87
  console.log("[types] Incoming request method");
88
88
  },
89
- incomingRequestPath(_req) {
90
- console.log("[types] Incoming request path");
91
- },
92
- incomingRequestQuery(_req) {
93
- console.log("[types] Incoming request query");
89
+ incomingRequestPathWithQuery(_req) {
90
+ console.log("[types] Incoming request path with query");
94
91
  },
95
92
  incomingRequestScheme(_req) {
96
93
  console.log("[types] Incoming request scheme");
@@ -104,7 +101,7 @@ export const types = {
104
101
  incomingRequestConsume(_req) {
105
102
  console.log("[types] Incoming request consume");
106
103
  },
107
- newOutgoingRequest(_method, _path, _query, _scheme, _authority, _headers) {
104
+ newOutgoingRequest(_method, _pathWithQuery, _scheme, _authority, _headers) {
108
105
  console.log("[types] New outgoing request");
109
106
  },
110
107
  outgoingRequestWrite(_req) {
@@ -6,7 +6,7 @@ import * as logging from "./logging.js";
6
6
  import * as poll from "./poll.js";
7
7
  import * as random from "./random.js";
8
8
  import * as sockets from "./sockets.js";
9
- import * as cliBase from "./cli-base.js";
9
+ import * as cli from "./cli.js";
10
10
 
11
11
  export const importObject = {
12
12
  clocks,
@@ -17,7 +17,7 @@ export const importObject = {
17
17
  poll,
18
18
  random,
19
19
  sockets,
20
- cliBase,
20
+ cli,
21
21
  };
22
22
 
23
23
  export { WasiHttp } from "../http/wasi-http.js";
package/lib/browser/io.js CHANGED
@@ -1,9 +1,81 @@
1
+ // buffer until the next newline
2
+ class NewlineBufferStream {
3
+ constructor (handler) {
4
+ this.bufferLen = 0;
5
+ this.bufferCapacity = 1024;
6
+ this.buffer = new Uint8Array(1024);
7
+ this.handler = handler;
8
+ }
9
+ write (bytes) {
10
+ const newlineIdx = bytes.lastIndexOf(10);
11
+ if (newlineIdx === -1) {
12
+ this.#addToBuffer(bytes);
13
+ } else {
14
+ this.#addToBuffer(bytes.slice(0, newlineIdx + 1));
15
+ this.handler(new TextDecoder().decode(this.buffer.slice(0, this.bufferLen)));
16
+ this.bufferLen = 0;
17
+ this.#addToBuffer(bytes.slice(newlineIdx + 1));
18
+ }
19
+ }
20
+ #addToBuffer (bytes) {
21
+ if (bytes.byteLength + this.bufferLen > this.bufferCapacity) {
22
+ this.bufferCapacity *= 2;
23
+ const buffer = new Uint8Array(this.bufferCapacity);
24
+ buffer.set(this.buffer);
25
+ this.buffer = buffer;
26
+ }
27
+ this.buffer.set(bytes, this.bufferLen);
28
+ this.bufferLen += bytes.byteLength;
29
+ }
30
+ }
31
+
32
+ class IgnoreStream {
33
+ read () {
34
+ return [new Uint8Array([]), 'ended'];
35
+ }
36
+ write () {}
37
+ }
38
+
39
+ export function createStream (stream) {
40
+ streamEntries[streamCnt] = stream;
41
+ return streamCnt++;
42
+ }
43
+
44
+ export function getStream (sid) {
45
+ const stream = streamEntries[sid];
46
+ if (!stream) throw new Error();
47
+ return stream;
48
+ }
49
+
50
+ export function dropStream (sid) {
51
+ delete streamEntries[sid];
52
+ }
53
+
54
+ let streamCnt = 3;
55
+ const streamEntries = {
56
+ 0: new IgnoreStream(),
57
+ 1: new NewlineBufferStream(console.log.bind(console)),
58
+ 2: new NewlineBufferStream(console.error.bind(console)),
59
+ };
60
+
61
+ export function _setStdout (stdout) {
62
+ streamEntries[1] = stdout;
63
+ }
64
+
65
+ export function _setStderr (stderr) {
66
+ streamEntries[2] = stderr;
67
+ }
68
+
69
+ export function _setStdin (stdin) {
70
+ streamEntries[0] = stdin;
71
+ }
72
+
1
73
  export const streams = {
2
74
  read(s, len) {
3
- console.log(`[streams] Read ${s} ${len}`);
75
+ return getStream(s).read(len);
4
76
  },
5
77
  blockingRead(s, len) {
6
- console.log(`[streams] Blocking read ${s} ${len}`);
78
+ return getStream(s).read(len);
7
79
  },
8
80
  skip(s, _len) {
9
81
  console.log(`[streams] Skip ${s}`);
@@ -18,23 +90,10 @@ export const streams = {
18
90
  console.log(`[streams] Drop input stream ${s}`);
19
91
  },
20
92
  write(s, buf) {
21
- streams.blockingWrite(s, buf);
93
+ return [BigInt(getStream(s).write(buf)), 'ended'];
22
94
  },
23
95
  blockingWrite(s, buf) {
24
- switch (s) {
25
- case 0:
26
- throw new Error(`TODO: write stdin`);
27
- case 1: {
28
- process.stdout.write(buf);
29
- return [BigInt(buf.byteLength), 'ended'];
30
- }
31
- case 2: {
32
- process.stderr.write(buf);
33
- return [BigInt(buf.byteLength), 'ended'];
34
- }
35
- default:
36
- throw new Error(`TODO: write ${s}`);
37
- }
96
+ return [BigInt(getStream(s).write(buf)), 'ended'];
38
97
  },
39
98
  writeZeroes(s, _len) {
40
99
  console.log(`[streams] Write zeroes ${s}`);
@@ -1,8 +1,8 @@
1
- const levels = ["trace", "debug", "info", "warn", "error"];
1
+ const levels = ["trace", "debug", "info", "warn", "error", "critical"];
2
2
 
3
3
  let logLevel = levels.indexOf("warn");
4
4
 
5
- export const handler = {
5
+ export const logging = {
6
6
  log(level, context, msg) {
7
7
  if (logLevel > levels.indexOf(level)) return;
8
8
  console[level](`(${context}) ${msg}\n`);
@@ -1,9 +1,53 @@
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
+
1
44
  export const poll = {
2
45
  dropPollable (pollable) {
3
- console.log(`[poll] Drop (${pollable})`);
46
+ const entry = polls[pollable];
47
+ watching.delete(entry);
48
+ delete polls[pollable];
4
49
  },
5
- pollOneoff (input) {
6
- console.log(`[poll] Oneoff (${input})`);
7
- return [];
50
+ pollOneoff (from) {
51
+ return from.map(pollable => polls[pollable].settled);
8
52
  }
9
53
  };
package/lib/http/error.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export class UnexpectedError extends Error {
2
- /** @type { import("../types/http").HttpErrorUnexpectedError } */
2
+ /** @type { import("../../types/imports/wasi-http-types").ErrorUnexpectedError } */
3
3
  payload;
4
4
  constructor(message = "unexpected-error") {
5
5
  super(message);
@@ -1,7 +1,7 @@
1
1
  import { runAsWorker } from "./synckit/index.js";
2
2
 
3
3
  /**
4
- * @param {import("../types/imports/types").Request} req
4
+ * @param {import("../../types/imports/wasi-http-types").Request} req
5
5
  * @returns {Promise<string>}
6
6
  */
7
7
  async function makeRequest(req) {
@@ -11,6 +11,7 @@ async function makeRequest(req) {
11
11
  method: req.method.toString(),
12
12
  headers,
13
13
  body: req.body && req.body.length > 0 ? req.body : undefined,
14
+ redirect: "manual",
14
15
  });
15
16
  let arrayBuffer = await resp.arrayBuffer();
16
17
  return JSON.stringify({
@@ -22,7 +23,7 @@ async function makeRequest(req) {
22
23
  : undefined,
23
24
  });
24
25
  } catch (err) {
25
- return err.message;
26
+ return JSON.stringify({ message: err.toString() });
26
27
  }
27
28
  }
28
29