@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.
- package/README.md +2 -2
- package/lib/browser/cli.js +87 -0
- package/lib/browser/filesystem.js +216 -18
- package/lib/browser/http.js +4 -7
- package/lib/browser/index.js +2 -2
- package/lib/browser/io.js +76 -17
- 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 +3 -2
- package/lib/http/wasi-http.js +52 -40
- package/lib/nodejs/cli.js +75 -0
- package/lib/nodejs/filesystem.js +93 -3
- package/lib/nodejs/http.js +4 -7
- package/lib/nodejs/index.js +2 -2
- package/lib/nodejs/logging.js +2 -2
- package/package.json +1 -1
- package/types/{imports/environment.d.ts → exports/wasi-cli-environment.d.ts} +6 -1
- package/types/{imports/exit.d.ts → exports/wasi-cli-exit.d.ts} +2 -2
- package/types/exports/wasi-cli-run.d.ts +6 -0
- package/types/exports/wasi-cli-stderr.d.ts +5 -0
- package/types/exports/wasi-cli-stdin.d.ts +5 -0
- package/types/exports/wasi-cli-stdout.d.ts +5 -0
- package/types/exports/wasi-cli-terminal-input.d.ts +13 -0
- package/types/exports/wasi-cli-terminal-output.d.ts +13 -0
- package/types/exports/wasi-cli-terminal-stderr.d.ts +9 -0
- package/types/exports/wasi-cli-terminal-stdin.d.ts +9 -0
- package/types/exports/wasi-cli-terminal-stdout.d.ts +9 -0
- package/types/{imports/monotonic-clock.d.ts → exports/wasi-clocks-monotonic-clock.d.ts} +2 -2
- package/types/{imports/timezone.d.ts → exports/wasi-clocks-timezone.d.ts} +15 -15
- package/types/{imports/wall-clock.d.ts → exports/wasi-clocks-wall-clock.d.ts} +1 -1
- package/types/exports/wasi-filesystem-preopens.d.ts +8 -0
- package/types/{imports/filesystem.d.ts → exports/wasi-filesystem-types.d.ts} +293 -307
- package/types/exports/wasi-http-incoming-handler.d.ts +3 -3
- package/types/exports/wasi-http-outgoing-handler.d.ts +9 -0
- package/types/{imports/types.d.ts → exports/wasi-http-types.d.ts} +40 -41
- package/types/exports/wasi-io-streams.d.ts +220 -0
- package/types/{imports/poll.d.ts → exports/wasi-poll-poll.d.ts} +6 -8
- package/types/{imports/insecure-seed.d.ts → exports/wasi-random-insecure-seed.d.ts} +1 -1
- package/types/exports/wasi-random-insecure.d.ts +20 -0
- package/types/exports/wasi-random-random.d.ts +22 -0
- package/types/{imports/instance-network.d.ts → exports/wasi-sockets-instance-network.d.ts} +2 -2
- package/types/{imports/ip-name-lookup.d.ts → exports/wasi-sockets-ip-name-lookup.d.ts} +9 -9
- package/types/{imports/network.d.ts → exports/wasi-sockets-network.d.ts} +43 -75
- package/types/{imports/tcp-create-socket.d.ts → exports/wasi-sockets-tcp-create-socket.d.ts} +5 -5
- package/types/{imports/tcp.d.ts → exports/wasi-sockets-tcp.d.ts} +38 -38
- package/types/{imports/udp-create-socket.d.ts → exports/wasi-sockets-udp-create-socket.d.ts} +5 -5
- package/types/{imports/udp.d.ts → exports/wasi-sockets-udp.d.ts} +41 -32
- package/types/imports/wasi-cli-environment.d.ts +22 -0
- package/types/imports/wasi-cli-exit.d.ts +7 -0
- package/types/imports/wasi-cli-stderr.d.ts +5 -0
- package/types/imports/wasi-cli-stdin.d.ts +5 -0
- package/types/imports/wasi-cli-stdout.d.ts +5 -0
- package/types/imports/wasi-cli-terminal-input.d.ts +13 -0
- package/types/imports/wasi-cli-terminal-output.d.ts +13 -0
- package/types/imports/wasi-cli-terminal-stderr.d.ts +9 -0
- package/types/imports/wasi-cli-terminal-stdin.d.ts +9 -0
- package/types/imports/wasi-cli-terminal-stdout.d.ts +9 -0
- package/types/imports/wasi-clocks-monotonic-clock.d.ts +24 -0
- package/types/imports/wasi-clocks-timezone.d.ts +71 -0
- package/types/imports/wasi-clocks-wall-clock.d.ts +31 -0
- package/types/imports/wasi-filesystem-preopens.d.ts +8 -0
- package/types/imports/wasi-filesystem-types.d.ts +843 -0
- package/types/imports/wasi-http-outgoing-handler.d.ts +9 -0
- package/types/imports/wasi-http-types.d.ts +118 -0
- package/types/imports/wasi-io-streams.d.ts +220 -0
- package/types/imports/wasi-poll-poll.d.ts +39 -0
- package/types/imports/wasi-random-insecure-seed.d.ts +22 -0
- package/types/imports/{insecure.d.ts → wasi-random-insecure.d.ts} +1 -1
- package/types/imports/{random.d.ts → wasi-random-random.d.ts} +1 -1
- package/types/imports/wasi-sockets-instance-network.d.ts +8 -0
- package/types/imports/wasi-sockets-ip-name-lookup.d.ts +76 -0
- package/types/imports/wasi-sockets-network.d.ts +180 -0
- package/types/imports/wasi-sockets-tcp-create-socket.d.ts +33 -0
- package/types/imports/wasi-sockets-tcp.d.ts +285 -0
- package/types/imports/wasi-sockets-udp-create-socket.d.ts +33 -0
- package/types/imports/wasi-sockets-udp.d.ts +228 -0
- package/types/wasi-cli-command.d.ts +29 -0
- package/types/wasi-http-proxy.d.ts +13 -0
- package/lib/browser/cli-base.js +0 -48
- package/lib/nodejs/cli-base.js +0 -99
- package/types/imports/handler.d.ts +0 -40
- package/types/imports/outgoing-handler.d.ts +0 -9
- package/types/imports/preopens.d.ts +0 -12
- package/types/imports/stderr.d.ts +0 -5
- package/types/imports/stdin.d.ts +0 -5
- package/types/imports/stdout.d.ts +0 -5
- package/types/imports/streams.d.ts +0 -180
- package/types/wasi-command.d.ts +0 -23
- package/types/wasi-proxy.d.ts +0 -10
- 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 |
|
|
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
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
135
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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 {
|
|
341
|
+
export { types as filesystemTypes }
|
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/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
|
-
|
|
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/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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}`);
|
|
@@ -18,23 +90,10 @@ export const streams = {
|
|
|
18
90
|
console.log(`[streams] Drop input stream ${s}`);
|
|
19
91
|
},
|
|
20
92
|
write(s, buf) {
|
|
21
|
-
|
|
93
|
+
return [BigInt(getStream(s).write(buf)), 'ended'];
|
|
22
94
|
},
|
|
23
95
|
blockingWrite(s, buf) {
|
|
24
|
-
|
|
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}`);
|
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/imports/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/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.
|
|
26
|
+
return JSON.stringify({ message: err.toString() });
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|