@bytecodealliance/preview2-shim 0.0.13 → 0.0.15
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 +2 -2
- package/lib/browser/cli.js +21 -6
- package/lib/browser/filesystem.js +204 -20
- package/lib/browser/http.js +4 -7
- package/lib/browser/io.js +89 -19
- package/lib/browser/logging.js +2 -2
- package/lib/browser/poll.js +48 -4
- package/lib/http/error.js +1 -1
- package/lib/http/make-request.js +4 -3
- package/lib/http/wasi-http.js +88 -53
- package/lib/nodejs/cli.js +17 -7
- package/lib/nodejs/http.js +4 -7
- package/lib/nodejs/io.js +16 -5
- package/lib/nodejs/logging.js +2 -2
- package/package.json +4 -1
- package/types/interfaces/wasi-cli-environment.d.ts +22 -0
- package/types/interfaces/wasi-cli-exit.d.ts +7 -0
- package/types/interfaces/wasi-cli-run.d.ts +6 -0
- package/types/interfaces/wasi-cli-stderr.d.ts +5 -0
- package/types/interfaces/wasi-cli-stdin.d.ts +5 -0
- package/types/interfaces/wasi-cli-stdout.d.ts +5 -0
- package/types/interfaces/wasi-cli-terminal-input.d.ts +13 -0
- package/types/interfaces/wasi-cli-terminal-output.d.ts +13 -0
- package/types/interfaces/wasi-cli-terminal-stderr.d.ts +9 -0
- package/types/interfaces/wasi-cli-terminal-stdin.d.ts +9 -0
- package/types/interfaces/wasi-cli-terminal-stdout.d.ts +9 -0
- package/types/interfaces/wasi-clocks-monotonic-clock.d.ts +24 -0
- package/types/interfaces/wasi-clocks-timezone.d.ts +71 -0
- package/types/interfaces/wasi-clocks-wall-clock.d.ts +31 -0
- package/types/interfaces/wasi-filesystem-preopens.d.ts +8 -0
- package/types/interfaces/wasi-filesystem-types.d.ts +843 -0
- package/types/interfaces/wasi-io-streams.d.ts +274 -0
- package/types/interfaces/wasi-poll-poll.d.ts +39 -0
- package/types/interfaces/wasi-random-insecure-seed.d.ts +22 -0
- package/types/interfaces/wasi-random-insecure.d.ts +20 -0
- package/types/interfaces/wasi-random-random.d.ts +22 -0
- package/types/interfaces/wasi-sockets-instance-network.d.ts +8 -0
- package/types/interfaces/wasi-sockets-ip-name-lookup.d.ts +76 -0
- package/types/interfaces/wasi-sockets-network.d.ts +180 -0
- package/types/interfaces/wasi-sockets-tcp-create-socket.d.ts +33 -0
- package/types/interfaces/wasi-sockets-tcp.d.ts +298 -0
- package/types/interfaces/wasi-sockets-udp-create-socket.d.ts +33 -0
- package/types/interfaces/wasi-sockets-udp.d.ts +228 -0
- package/types/wasi-cli-command.d.ts +29 -0
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 |
|
|
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
|
|
19
|
+
| CLI | :heavy_check_mark: | :heavy_check_mark: |
|
|
20
20
|
|
|
21
21
|
# License
|
|
22
22
|
|
package/lib/browser/cli.js
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
import { _setCwd as fsSetCwd } from './filesystem.js';
|
|
2
|
+
|
|
3
|
+
let _env = [], _args = [], _cwd = null;
|
|
2
4
|
export function _setEnv (envObj) {
|
|
3
5
|
_env = Object.entries(envObj);
|
|
4
6
|
}
|
|
7
|
+
export function _setArgs (args) {
|
|
8
|
+
_args = args;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function _setCwd (cwd) {
|
|
12
|
+
fsSetCwd(_cwd = cwd);
|
|
13
|
+
}
|
|
5
14
|
|
|
6
15
|
export const environment = {
|
|
7
16
|
getEnvironment () {
|
|
8
|
-
if (!_env) _env = [];
|
|
9
17
|
return _env;
|
|
18
|
+
},
|
|
19
|
+
getArguments () {
|
|
20
|
+
return _args;
|
|
21
|
+
},
|
|
22
|
+
initialCwd () {
|
|
23
|
+
return _cwd;
|
|
10
24
|
}
|
|
11
25
|
};
|
|
12
26
|
|
|
13
27
|
class ComponentExit extends Error {
|
|
14
|
-
constructor(
|
|
15
|
-
super(`Component exited ${
|
|
16
|
-
this.
|
|
28
|
+
constructor(ok) {
|
|
29
|
+
super(`Component exited ${ok ? 'successfully' : 'with error'}`);
|
|
30
|
+
this.exitError = true;
|
|
31
|
+
this.ok = ok;
|
|
17
32
|
}
|
|
18
33
|
}
|
|
19
34
|
|
|
20
35
|
export const exit = {
|
|
21
36
|
exit (status) {
|
|
22
|
-
throw new ComponentExit(status.tag === 'err' ?
|
|
37
|
+
throw new ComponentExit(status.tag === 'err' ? true : false);
|
|
23
38
|
}
|
|
24
39
|
};
|
|
25
40
|
|
|
@@ -1,16 +1,145 @@
|
|
|
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
|
+
|
|
1
108
|
export const preopens = {
|
|
2
109
|
getDirectories () {
|
|
3
|
-
return
|
|
110
|
+
return _preopens;
|
|
4
111
|
}
|
|
5
112
|
}
|
|
6
113
|
|
|
7
114
|
export const types = {
|
|
8
115
|
readViaStream(fd, offset) {
|
|
9
|
-
|
|
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
|
+
});
|
|
10
127
|
},
|
|
11
128
|
|
|
12
129
|
writeViaStream(fd, offset) {
|
|
13
|
-
|
|
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
|
+
});
|
|
14
143
|
},
|
|
15
144
|
|
|
16
145
|
appendViaStream(fd) {
|
|
@@ -30,7 +159,12 @@ export const types = {
|
|
|
30
159
|
},
|
|
31
160
|
|
|
32
161
|
getType(fd) {
|
|
33
|
-
|
|
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';
|
|
34
168
|
},
|
|
35
169
|
|
|
36
170
|
setFlags(fd, flags) {
|
|
@@ -46,15 +180,22 @@ export const types = {
|
|
|
46
180
|
},
|
|
47
181
|
|
|
48
182
|
read(fd, length, offset) {
|
|
49
|
-
|
|
183
|
+
const descriptor = getDescriptor(fd);
|
|
184
|
+
const source = getSource(descriptor.entry);
|
|
185
|
+
return [source.slice(offset, offset + length), offset + length >= source.byteLength];
|
|
50
186
|
},
|
|
51
187
|
|
|
52
188
|
write(fd, buffer, offset) {
|
|
53
|
-
|
|
189
|
+
const descriptor = getDescriptor(fd);
|
|
190
|
+
if (offset !== 0) throw 'invalid-seek';
|
|
191
|
+
descriptor.entry.source = buffer;
|
|
192
|
+
return buffer.byteLength;
|
|
54
193
|
},
|
|
55
194
|
|
|
56
195
|
readDirectory(fd) {
|
|
57
|
-
|
|
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)));
|
|
58
199
|
},
|
|
59
200
|
|
|
60
201
|
sync(fd) {
|
|
@@ -62,15 +203,50 @@ export const types = {
|
|
|
62
203
|
},
|
|
63
204
|
|
|
64
205
|
createDirectoryAt(fd, path) {
|
|
65
|
-
|
|
206
|
+
const entry = getChildEntry(fd, path, { create: true, directory: true });
|
|
207
|
+
if (entry.source) throw 'exist';
|
|
66
208
|
},
|
|
67
209
|
|
|
68
210
|
stat(fd) {
|
|
69
|
-
|
|
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
|
+
}
|
|
70
229
|
},
|
|
71
230
|
|
|
72
231
|
statAt(fd, pathFlags, path) {
|
|
73
|
-
|
|
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
|
+
};
|
|
74
250
|
},
|
|
75
251
|
|
|
76
252
|
setTimesAt(fd) {
|
|
@@ -81,8 +257,8 @@ export const types = {
|
|
|
81
257
|
console.log(`[filesystem] LINK AT`, fd);
|
|
82
258
|
},
|
|
83
259
|
|
|
84
|
-
openAt(fd) {
|
|
85
|
-
|
|
260
|
+
openAt(fd, _pathFlags, path, openFlags, _descriptorFlags, _modes) {
|
|
261
|
+
return createChildDescriptor(fd, path, openFlags);
|
|
86
262
|
},
|
|
87
263
|
|
|
88
264
|
readlinkAt(fd) {
|
|
@@ -134,23 +310,31 @@ export const types = {
|
|
|
134
310
|
},
|
|
135
311
|
|
|
136
312
|
dropDescriptor(fd) {
|
|
137
|
-
|
|
313
|
+
if (fd < _preopens.length + 3)
|
|
314
|
+
return;
|
|
315
|
+
delete descriptorTable[fd];
|
|
138
316
|
},
|
|
139
317
|
|
|
140
|
-
readDirectoryEntry(
|
|
141
|
-
|
|
318
|
+
readDirectoryEntry(sid) {
|
|
319
|
+
return getStream(sid).next();
|
|
142
320
|
},
|
|
143
321
|
|
|
144
|
-
dropDirectoryEntryStream(
|
|
145
|
-
|
|
322
|
+
dropDirectoryEntryStream(sid) {
|
|
323
|
+
dropStream(sid);
|
|
146
324
|
},
|
|
147
325
|
|
|
148
326
|
metadataHash(fd) {
|
|
149
|
-
|
|
327
|
+
const descriptor = getDescriptor(fd);
|
|
328
|
+
let upper = BigInt(0);
|
|
329
|
+
upper += BigInt(descriptor.mtime || 0);
|
|
330
|
+
return { upper, lower: BigInt(0) };
|
|
150
331
|
},
|
|
151
332
|
|
|
152
|
-
metadataHashAt(fd,
|
|
153
|
-
|
|
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) };
|
|
154
338
|
}
|
|
155
339
|
};
|
|
156
340
|
|
package/lib/browser/http.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UnexpectedError } from "../http/error.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @param {import("
|
|
4
|
+
* @param {import("../../types/interfaces/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
|
-
|
|
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,
|
|
104
|
+
newOutgoingRequest(_method, _pathWithQuery, _scheme, _authority, _headers) {
|
|
108
105
|
console.log("[types] New outgoing request");
|
|
109
106
|
},
|
|
110
107
|
outgoingRequestWrite(_req) {
|
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
|
-
|
|
75
|
+
return getStream(s).read(len);
|
|
4
76
|
},
|
|
5
77
|
blockingRead(s, len) {
|
|
6
|
-
|
|
78
|
+
return getStream(s).read(len);
|
|
7
79
|
},
|
|
8
80
|
skip(s, _len) {
|
|
9
81
|
console.log(`[streams] Skip ${s}`);
|
|
@@ -17,24 +89,22 @@ export const streams = {
|
|
|
17
89
|
dropInputStream(s) {
|
|
18
90
|
console.log(`[streams] Drop input stream ${s}`);
|
|
19
91
|
},
|
|
92
|
+
checkWrite(_s) {
|
|
93
|
+
// TODO: implement
|
|
94
|
+
return 1000000n;
|
|
95
|
+
},
|
|
20
96
|
write(s, buf) {
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
process.stderr.write(buf);
|
|
33
|
-
return [BigInt(buf.byteLength), 'ended'];
|
|
34
|
-
}
|
|
35
|
-
default:
|
|
36
|
-
throw new Error(`TODO: write ${s}`);
|
|
37
|
-
}
|
|
97
|
+
getStream(s).write(buf);
|
|
98
|
+
},
|
|
99
|
+
blockingWriteAndFlush(s, buf) {
|
|
100
|
+
// TODO: implement
|
|
101
|
+
return streams.write(s, buf);
|
|
102
|
+
},
|
|
103
|
+
flush(s) {
|
|
104
|
+
return streams.blockingFlush(s);
|
|
105
|
+
},
|
|
106
|
+
blockingFlush(_s) {
|
|
107
|
+
// TODO: implement
|
|
38
108
|
},
|
|
39
109
|
writeZeroes(s, _len) {
|
|
40
110
|
console.log(`[streams] Write zeroes ${s}`);
|
package/lib/browser/logging.js
CHANGED
|
@@ -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
|
|
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`);
|
package/lib/browser/poll.js
CHANGED
|
@@ -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
|
-
|
|
46
|
+
const entry = polls[pollable];
|
|
47
|
+
watching.delete(entry);
|
|
48
|
+
delete polls[pollable];
|
|
4
49
|
},
|
|
5
|
-
pollOneoff (
|
|
6
|
-
|
|
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("
|
|
2
|
+
/** @type { import("../../types/interfaces/wasi-http-types").ErrorUnexpectedError } */
|
|
3
3
|
payload;
|
|
4
4
|
constructor(message = "unexpected-error") {
|
|
5
5
|
super(message);
|
package/lib/http/make-request.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { runAsWorker } from "./synckit/index.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @param {import("
|
|
4
|
+
* @param {import("../../types/interfaces/wasi-http-types").Request} req
|
|
5
5
|
* @returns {Promise<string>}
|
|
6
6
|
*/
|
|
7
7
|
async function makeRequest(req) {
|
|
@@ -11,18 +11,19 @@ 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({
|
|
17
18
|
status: resp.status,
|
|
18
|
-
headers: Array.from(resp.headers
|
|
19
|
+
headers: Array.from(resp.headers),
|
|
19
20
|
body:
|
|
20
21
|
arrayBuffer.byteLength > 0
|
|
21
22
|
? Buffer.from(arrayBuffer).toString("base64")
|
|
22
23
|
: undefined,
|
|
23
24
|
});
|
|
24
25
|
} catch (err) {
|
|
25
|
-
return err.
|
|
26
|
+
return JSON.stringify({ message: err.toString() });
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|