@tybys/wasm-util 0.1.0

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.
@@ -0,0 +1,889 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WASI = void 0;
4
+ const path_1 = require("./path");
5
+ const types_1 = require("./types");
6
+ const fd_1 = require("./fd");
7
+ const error_1 = require("./error");
8
+ const util_1 = require("./util");
9
+ const rights_1 = require("./rights");
10
+ const memory_1 = require("../memory");
11
+ function copyMemory(targets, src) {
12
+ if (targets.length === 0 || src.length === 0)
13
+ return 0;
14
+ let copied = 0;
15
+ let left = src.length - copied;
16
+ for (let i = 0; i < targets.length; ++i) {
17
+ const target = targets[i];
18
+ if (left < target.length) {
19
+ target.set(src.subarray(copied, copied + left), 0);
20
+ copied += left;
21
+ left = 0;
22
+ return copied;
23
+ }
24
+ target.set(src.subarray(copied, copied + target.length), 0);
25
+ copied += target.length;
26
+ left -= target.length;
27
+ }
28
+ return copied;
29
+ }
30
+ const _memory = new WeakMap();
31
+ const _wasi = new WeakMap();
32
+ const _fs = new WeakMap();
33
+ function getMemory(wasi) {
34
+ return _memory.get(wasi);
35
+ }
36
+ function getFs(wasi) {
37
+ const fs = _fs.get(wasi);
38
+ if (!fs)
39
+ throw new Error('filesystem is unavailable');
40
+ return fs;
41
+ }
42
+ function handleError(err) {
43
+ if (err instanceof error_1.WasiError) {
44
+ if (process.env.NODE_ENV !== 'production') {
45
+ console.warn(err);
46
+ }
47
+ return err.errno;
48
+ }
49
+ switch (err.code) {
50
+ case 'ENOENT': return types_1.WasiErrno.ENOENT;
51
+ case 'EBADF': return types_1.WasiErrno.EBADF;
52
+ case 'EINVAL': return types_1.WasiErrno.EINVAL;
53
+ case 'EPERM': return types_1.WasiErrno.EPERM;
54
+ case 'EPROTO': return types_1.WasiErrno.EPROTO;
55
+ case 'EEXIST': return types_1.WasiErrno.EEXIST;
56
+ case 'ENOTDIR': return types_1.WasiErrno.ENOTDIR;
57
+ case 'EMFILE': return types_1.WasiErrno.EMFILE;
58
+ case 'EACCES': return types_1.WasiErrno.EACCES;
59
+ case 'EISDIR': return types_1.WasiErrno.EISDIR;
60
+ case 'ENOTEMPTY': return types_1.WasiErrno.ENOTEMPTY;
61
+ case 'ENOSYS': return types_1.WasiErrno.ENOSYS;
62
+ }
63
+ throw err;
64
+ }
65
+ function defineName(name, f) {
66
+ Object.defineProperty(f, 'name', { value: name });
67
+ return f;
68
+ }
69
+ function syscallWrap(name, f) {
70
+ return defineName(name, function () {
71
+ if (process.env.NODE_DEBUG_NATIVE === 'wasi') {
72
+ const args = Array.prototype.slice.call(arguments);
73
+ let debugArgs = [`${name}(${Array.from({ length: arguments.length }).map(() => '%d').join(', ')})`];
74
+ debugArgs = debugArgs.concat(args);
75
+ console.debug.apply(console, debugArgs);
76
+ }
77
+ let r;
78
+ try {
79
+ r = f.apply(this, arguments);
80
+ }
81
+ catch (err) {
82
+ return handleError(err);
83
+ }
84
+ if ((0, util_1.isPromiseLike)(r)) {
85
+ return r.then(_ => _, handleError);
86
+ }
87
+ return r;
88
+ });
89
+ }
90
+ function resolvePath(fs, fileDescriptor, path, flags) {
91
+ let resolvedPath = (0, path_1.resolve)(fileDescriptor.realPath, path);
92
+ if ((flags & 1) === 1) {
93
+ try {
94
+ resolvedPath = fs.readlinkSync(resolvedPath);
95
+ }
96
+ catch (err) {
97
+ if (err.code !== 'EINVAL' && err.code !== 'ENOENT') {
98
+ throw err;
99
+ }
100
+ }
101
+ }
102
+ return resolvedPath;
103
+ }
104
+ const encoder = new TextEncoder();
105
+ const decoder = new TextDecoder();
106
+ function readStdin() {
107
+ const value = window.prompt();
108
+ if (value === null)
109
+ return new Uint8Array();
110
+ const buffer = new TextEncoder().encode(value + '\n');
111
+ return buffer;
112
+ }
113
+ class WASI {
114
+ constructor(args, env, preopens, stdio, filesystem, print, printErr) {
115
+ this._setMemory = function _setMemory(m) {
116
+ if (!(m instanceof WebAssembly.Memory)) {
117
+ throw new TypeError('"instance.exports.memory" property must be a WebAssembly.Memory');
118
+ }
119
+ _memory.set(this, (0, memory_1.extendMemory)(m));
120
+ };
121
+ this.args_get = syscallWrap('args_get', function (argv, argv_buf) {
122
+ argv = Number(argv);
123
+ argv_buf = Number(argv_buf);
124
+ if (argv === 0 || argv_buf === 0) {
125
+ return types_1.WasiErrno.EINVAL;
126
+ }
127
+ const { HEAPU8, view } = getMemory(this);
128
+ const wasi = _wasi.get(this);
129
+ const args = wasi.args;
130
+ for (let i = 0; i < args.length; ++i) {
131
+ const arg = args[i];
132
+ view.setInt32(argv, argv_buf, true);
133
+ argv += 4;
134
+ const data = encoder.encode(arg + '\0');
135
+ HEAPU8.set(data, argv_buf);
136
+ argv_buf += data.length;
137
+ }
138
+ return types_1.WasiErrno.ESUCCESS;
139
+ });
140
+ this.args_sizes_get = syscallWrap('args_sizes_get', function (argc, argv_buf_size) {
141
+ argc = Number(argc);
142
+ argv_buf_size = Number(argv_buf_size);
143
+ if (argc === 0 || argv_buf_size === 0) {
144
+ return types_1.WasiErrno.EINVAL;
145
+ }
146
+ const { view } = getMemory(this);
147
+ const wasi = _wasi.get(this);
148
+ const args = wasi.args;
149
+ view.setUint32(argc, args.length, true);
150
+ view.setUint32(argv_buf_size, encoder.encode(args.join('\0') + '\0').length, true);
151
+ return types_1.WasiErrno.ESUCCESS;
152
+ });
153
+ this.environ_get = syscallWrap('environ_get', function (environ, environ_buf) {
154
+ environ = Number(environ);
155
+ environ_buf = Number(environ_buf);
156
+ if (environ === 0 || environ_buf === 0) {
157
+ return types_1.WasiErrno.EINVAL;
158
+ }
159
+ const { HEAPU8, view } = getMemory(this);
160
+ const wasi = _wasi.get(this);
161
+ const env = wasi.env;
162
+ for (let i = 0; i < env.length; ++i) {
163
+ const pair = env[i];
164
+ view.setInt32(environ, environ_buf, true);
165
+ environ += 4;
166
+ const data = encoder.encode(pair + '\0');
167
+ HEAPU8.set(data, environ_buf);
168
+ environ_buf += data.length;
169
+ }
170
+ return types_1.WasiErrno.ESUCCESS;
171
+ });
172
+ this.environ_sizes_get = syscallWrap('environ_sizes_get', function (len, buflen) {
173
+ len = Number(len);
174
+ buflen = Number(buflen);
175
+ if (len === 0 || buflen === 0) {
176
+ return types_1.WasiErrno.EINVAL;
177
+ }
178
+ const { view } = getMemory(this);
179
+ const wasi = _wasi.get(this);
180
+ view.setUint32(len, wasi.env.length, true);
181
+ view.setUint32(buflen, encoder.encode(wasi.env.join('\0') + '\0').length, true);
182
+ return types_1.WasiErrno.ESUCCESS;
183
+ });
184
+ this.clock_res_get = syscallWrap('clock_res_get', function (id, resolution) {
185
+ resolution = Number(resolution);
186
+ if (resolution === 0) {
187
+ return types_1.WasiErrno.EINVAL;
188
+ }
189
+ const { view } = getMemory(this);
190
+ switch (id) {
191
+ case types_1.WasiClockid.REALTIME:
192
+ view.setBigUint64(resolution, BigInt(1000000), true);
193
+ return types_1.WasiErrno.ESUCCESS;
194
+ case types_1.WasiClockid.MONOTONIC:
195
+ case types_1.WasiClockid.PROCESS_CPUTIME_ID:
196
+ case types_1.WasiClockid.THREAD_CPUTIME_ID:
197
+ view.setBigUint64(resolution, BigInt(1000), true);
198
+ return types_1.WasiErrno.ESUCCESS;
199
+ default: return types_1.WasiErrno.EINVAL;
200
+ }
201
+ });
202
+ this.clock_time_get = syscallWrap('clock_time_get', function (id, _percision, time) {
203
+ time = Number(time);
204
+ if (time === 0) {
205
+ return types_1.WasiErrno.EINVAL;
206
+ }
207
+ const { view } = getMemory(this);
208
+ switch (id) {
209
+ case types_1.WasiClockid.REALTIME:
210
+ view.setBigUint64(time, BigInt(Date.now()) * BigInt(1000000), true);
211
+ return types_1.WasiErrno.ESUCCESS;
212
+ case types_1.WasiClockid.MONOTONIC:
213
+ case types_1.WasiClockid.PROCESS_CPUTIME_ID:
214
+ case types_1.WasiClockid.THREAD_CPUTIME_ID: {
215
+ const t = performance.now();
216
+ const s = Math.trunc(t);
217
+ const ms = Math.floor((t - s) * 1000);
218
+ const result = BigInt(s) * BigInt(1000000000) + BigInt(ms) * BigInt(1000000);
219
+ view.setBigUint64(time, result, true);
220
+ return types_1.WasiErrno.ESUCCESS;
221
+ }
222
+ default: return types_1.WasiErrno.EINVAL;
223
+ }
224
+ });
225
+ this.fd_advise = syscallWrap('fd_advise', function (_fd, _offset, _len, _advice) {
226
+ return types_1.WasiErrno.ENOSYS;
227
+ });
228
+ this.fd_allocate = syscallWrap('fd_allocate', function (fd, offset, len) {
229
+ const wasi = _wasi.get(this);
230
+ const fs = getFs(this);
231
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_ALLOCATE, BigInt(0));
232
+ const stat = fs.fstatSync(fileDescriptor.fd, { bigint: true });
233
+ if (stat.size < offset + len) {
234
+ fs.truncateSync(fileDescriptor.fd, Number(offset + len));
235
+ }
236
+ return types_1.WasiErrno.ESUCCESS;
237
+ });
238
+ this.fd_close = syscallWrap('fd_close', function (fd) {
239
+ const wasi = _wasi.get(this);
240
+ const fileDescriptor = wasi.fds.get(fd, BigInt(0), BigInt(0));
241
+ const fs = getFs(this);
242
+ fs.closeSync(fileDescriptor.fd);
243
+ wasi.fds.remove(fd);
244
+ return types_1.WasiErrno.ESUCCESS;
245
+ });
246
+ this.fd_datasync = syscallWrap('fd_datasync', function (fd) {
247
+ const wasi = _wasi.get(this);
248
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_DATASYNC, BigInt(0));
249
+ const fs = getFs(this);
250
+ fs.fdatasyncSync(fileDescriptor.fd);
251
+ return types_1.WasiErrno.ESUCCESS;
252
+ });
253
+ this.fd_fdstat_get = syscallWrap('fd_fdstat_get', function (fd, fdstat) {
254
+ fdstat = Number(fdstat);
255
+ if (fdstat === 0) {
256
+ return types_1.WasiErrno.EINVAL;
257
+ }
258
+ const wasi = _wasi.get(this);
259
+ const fileDescriptor = wasi.fds.get(fd, BigInt(0), BigInt(0));
260
+ const { view } = getMemory(this);
261
+ view.setUint16(fdstat, fileDescriptor.type, true);
262
+ view.setUint16(fdstat + 2, 0, true);
263
+ view.setBigUint64(fdstat + 8, fileDescriptor.rightsBase, true);
264
+ view.setBigUint64(fdstat + 16, fileDescriptor.rightsInheriting, true);
265
+ return types_1.WasiErrno.ESUCCESS;
266
+ });
267
+ this.fd_fdstat_set_flags = syscallWrap('fd_fdstat_set_flags', function (_fd, _flags) {
268
+ return types_1.WasiErrno.ENOSYS;
269
+ });
270
+ this.fd_fdstat_set_rights = syscallWrap('fd_fdstat_set_rights', function (fd, rightsBase, rightsInheriting) {
271
+ const wasi = _wasi.get(this);
272
+ const fileDescriptor = wasi.fds.get(fd, BigInt(0), BigInt(0));
273
+ if ((rightsBase | fileDescriptor.rightsBase) > fileDescriptor.rightsBase) {
274
+ return types_1.WasiErrno.ENOTCAPABLE;
275
+ }
276
+ if ((rightsInheriting | fileDescriptor.rightsInheriting) >
277
+ fileDescriptor.rightsInheriting) {
278
+ return types_1.WasiErrno.ENOTCAPABLE;
279
+ }
280
+ fileDescriptor.rightsBase = rightsBase;
281
+ fileDescriptor.rightsInheriting = rightsInheriting;
282
+ return types_1.WasiErrno.ESUCCESS;
283
+ });
284
+ this.fd_filestat_get = syscallWrap('fd_filestat_get', function (fd, buf) {
285
+ buf = Number(buf);
286
+ if (buf === 0)
287
+ return types_1.WasiErrno.EINVAL;
288
+ const wasi = _wasi.get(this);
289
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_FILESTAT_GET, BigInt(0));
290
+ const fs = getFs(this);
291
+ const stat = fs.fstatSync(fileDescriptor.fd, { bigint: true });
292
+ const { view } = getMemory(this);
293
+ (0, fd_1.toFileStat)(view, buf, stat);
294
+ return types_1.WasiErrno.ESUCCESS;
295
+ });
296
+ this.fd_filestat_set_size = syscallWrap('fd_filestat_set_size', function (fd, size) {
297
+ const wasi = _wasi.get(this);
298
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_FILESTAT_SET_SIZE, BigInt(0));
299
+ const fs = getFs(this);
300
+ fs.ftruncateSync(fileDescriptor.fd, Number(size));
301
+ return types_1.WasiErrno.ESUCCESS;
302
+ });
303
+ this.fd_filestat_set_times = syscallWrap('fd_filestat_set_times', function (fd, atim, mtim, flags) {
304
+ const wasi = _wasi.get(this);
305
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_FILESTAT_SET_TIMES, BigInt(0));
306
+ if ((flags & types_1.WasiFstFlag.SET_ATIM_NOW) === types_1.WasiFstFlag.SET_ATIM_NOW) {
307
+ atim = BigInt(Date.now() * 1000000);
308
+ }
309
+ if ((flags & types_1.WasiFstFlag.SET_MTIM_NOW) === types_1.WasiFstFlag.SET_MTIM_NOW) {
310
+ mtim = BigInt(Date.now() * 1000000);
311
+ }
312
+ const fs = getFs(this);
313
+ fs.futimesSync(fileDescriptor.fd, Number(atim), Number(mtim));
314
+ return types_1.WasiErrno.ESUCCESS;
315
+ });
316
+ this.fd_pread = syscallWrap('fd_pread', function (fd, iovs, iovslen, offset, size) {
317
+ iovs = Number(iovs);
318
+ size = Number(size);
319
+ if (iovs === 0 || size === 0) {
320
+ return types_1.WasiErrno.EINVAL;
321
+ }
322
+ const { HEAPU8, view } = getMemory(this);
323
+ const wasi = _wasi.get(this);
324
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READ | types_1.WasiRights.FD_SEEK, BigInt(0));
325
+ let totalSize = 0;
326
+ const ioVecs = Array.from({ length: Number(iovslen) }, (_, i) => {
327
+ const offset = iovs + (i * 8);
328
+ const buf = view.getInt32(offset, true);
329
+ const bufLen = view.getUint32(offset + 4, true);
330
+ totalSize += bufLen;
331
+ return HEAPU8.subarray(buf, buf + bufLen);
332
+ });
333
+ let nread = 0;
334
+ const buffer = new Uint8Array(totalSize);
335
+ buffer._isBuffer = true;
336
+ const fs = getFs(this);
337
+ const bytesRead = fs.readSync(fileDescriptor.fd, buffer, 0, buffer.length, Number(offset));
338
+ nread = buffer ? copyMemory(ioVecs, buffer.subarray(0, bytesRead)) : 0;
339
+ view.setUint32(size, nread, true);
340
+ return types_1.WasiErrno.ESUCCESS;
341
+ });
342
+ this.fd_prestat_get = syscallWrap('fd_prestat_get', function (fd, prestat) {
343
+ prestat = Number(prestat);
344
+ if (prestat === 0) {
345
+ return types_1.WasiErrno.EINVAL;
346
+ }
347
+ const wasi = _wasi.get(this);
348
+ let fileDescriptor;
349
+ try {
350
+ fileDescriptor = wasi.fds.get(fd, BigInt(0), BigInt(0));
351
+ }
352
+ catch (err) {
353
+ if (err instanceof error_1.WasiError)
354
+ return err.errno;
355
+ throw err;
356
+ }
357
+ if (fileDescriptor.preopen !== 1)
358
+ return types_1.WasiErrno.EINVAL;
359
+ const { view } = getMemory(this);
360
+ // preopen type is dir(0)
361
+ view.setUint32(prestat, 0, true);
362
+ view.setUint32(prestat + 4, encoder.encode(fileDescriptor.path).length + 1, true);
363
+ return types_1.WasiErrno.ESUCCESS;
364
+ });
365
+ this.fd_prestat_dir_name = syscallWrap('fd_prestat_dir_name', function (fd, path, path_len) {
366
+ path = Number(path);
367
+ path_len = Number(path_len);
368
+ if (path === 0) {
369
+ return types_1.WasiErrno.EINVAL;
370
+ }
371
+ const wasi = _wasi.get(this);
372
+ const fileDescriptor = wasi.fds.get(fd, BigInt(0), BigInt(0));
373
+ if (fileDescriptor.preopen !== 1)
374
+ return types_1.WasiErrno.EBADF;
375
+ const buffer = encoder.encode(fileDescriptor.path + '\0');
376
+ const size = buffer.length;
377
+ if (size > path_len)
378
+ return types_1.WasiErrno.ENOBUFS;
379
+ const { HEAPU8 } = getMemory(this);
380
+ HEAPU8.set(buffer, path);
381
+ return types_1.WasiErrno.ESUCCESS;
382
+ });
383
+ this.fd_pwrite = syscallWrap('fd_pwrite', function (fd, iovs, iovslen, offset, size) {
384
+ iovs = Number(iovs);
385
+ size = Number(size);
386
+ if (iovs === 0 || size === 0) {
387
+ return types_1.WasiErrno.EINVAL;
388
+ }
389
+ const { HEAPU8, view } = getMemory(this);
390
+ const wasi = _wasi.get(this);
391
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_WRITE | types_1.WasiRights.FD_SEEK, BigInt(0));
392
+ const buffer = (0, fd_1.concatBuffer)(Array.from({ length: Number(iovslen) }, (_, i) => {
393
+ const offset = iovs + (i * 8);
394
+ const buf = view.getInt32(offset, true);
395
+ const bufLen = view.getUint32(offset + 4, true);
396
+ return HEAPU8.subarray(buf, buf + bufLen);
397
+ }));
398
+ const fs = getFs(this);
399
+ const nwritten = fs.writeSync(fileDescriptor.fd, buffer, 0, buffer.length, Number(offset));
400
+ view.setUint32(size, nwritten, true);
401
+ return types_1.WasiErrno.ESUCCESS;
402
+ });
403
+ this.fd_read = syscallWrap('fd_read', function (fd, iovs, iovslen, size) {
404
+ iovs = Number(iovs);
405
+ size = Number(size);
406
+ if (iovs === 0 || size === 0) {
407
+ return types_1.WasiErrno.EINVAL;
408
+ }
409
+ const { HEAPU8, view } = getMemory(this);
410
+ const wasi = _wasi.get(this);
411
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READ, BigInt(0));
412
+ let totalSize = 0;
413
+ const ioVecs = Array.from({ length: Number(iovslen) }, (_, i) => {
414
+ const offset = iovs + (i * 8);
415
+ const buf = view.getInt32(offset, true);
416
+ const bufLen = view.getUint32(offset + 4, true);
417
+ totalSize += bufLen;
418
+ return HEAPU8.subarray(buf, buf + bufLen);
419
+ });
420
+ let buffer;
421
+ let nread = 0;
422
+ if (fd === 0) {
423
+ buffer = readStdin();
424
+ nread = buffer ? copyMemory(ioVecs, buffer) : 0;
425
+ }
426
+ else {
427
+ buffer = new Uint8Array(totalSize);
428
+ buffer._isBuffer = true;
429
+ const fs = getFs(this);
430
+ const bytesRead = fs.readSync(fileDescriptor.fd, buffer, 0, buffer.length, Number(fileDescriptor.pos));
431
+ nread = buffer ? copyMemory(ioVecs, buffer.subarray(0, bytesRead)) : 0;
432
+ fileDescriptor.pos += BigInt(nread);
433
+ }
434
+ view.setUint32(size, nread, true);
435
+ return types_1.WasiErrno.ESUCCESS;
436
+ });
437
+ this.fd_seek = syscallWrap('fd_seek', function (fd, offset, whence, newOffset) {
438
+ newOffset = Number(newOffset);
439
+ if (newOffset === 0) {
440
+ return types_1.WasiErrno.EINVAL;
441
+ }
442
+ if (fd === 0 || fd === 1 || fd === 2)
443
+ return types_1.WasiErrno.ESUCCESS;
444
+ const wasi = _wasi.get(this);
445
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_SEEK, BigInt(0));
446
+ const r = fileDescriptor.seek(offset, whence);
447
+ const { view } = getMemory(this);
448
+ view.setBigUint64(newOffset, r, true);
449
+ return types_1.WasiErrno.ESUCCESS;
450
+ });
451
+ this.fd_readdir = syscallWrap('fd_readdir', function (fd, buf, buf_len, cookie, bufused) {
452
+ buf = Number(buf);
453
+ buf_len = Number(buf_len);
454
+ bufused = Number(bufused);
455
+ if (buf === 0 || bufused === 0)
456
+ return types_1.WasiErrno.ESUCCESS;
457
+ const wasi = _wasi.get(this);
458
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READDIR, BigInt(0));
459
+ const fs = getFs(this);
460
+ const entries = fs.readdirSync(fileDescriptor.realPath, { withFileTypes: true });
461
+ const { HEAPU8, view } = getMemory(this);
462
+ let bufferUsed = 0;
463
+ for (let i = Number(cookie); i < entries.length; i++) {
464
+ const nameData = encoder.encode(entries[i].name);
465
+ const entryInfo = fs.statSync((0, path_1.resolve)(fileDescriptor.realPath, entries[i].name), { bigint: true });
466
+ const entryData = new Uint8Array(24 + nameData.byteLength);
467
+ const entryView = new DataView(entryData.buffer);
468
+ entryView.setBigUint64(0, BigInt(i + 1), true);
469
+ entryView.setBigUint64(8, BigInt(entryInfo.ino ? entryInfo.ino : 0), true);
470
+ entryView.setUint32(16, nameData.byteLength, true);
471
+ let type;
472
+ if (entries[i].isFile()) {
473
+ type = types_1.WasiFileType.REGULAR_FILE;
474
+ }
475
+ else if (entries[i].isDirectory()) {
476
+ type = types_1.WasiFileType.DIRECTORY;
477
+ }
478
+ else if (entries[i].isSymbolicLink()) {
479
+ type = types_1.WasiFileType.SYMBOLIC_LINK;
480
+ }
481
+ else if (entries[i].isCharacterDevice()) {
482
+ type = types_1.WasiFileType.CHARACTER_DEVICE;
483
+ }
484
+ else if (entries[i].isBlockDevice()) {
485
+ type = types_1.WasiFileType.BLOCK_DEVICE;
486
+ }
487
+ else if (entries[i].isSocket()) {
488
+ type = types_1.WasiFileType.SOCKET_STREAM;
489
+ }
490
+ else {
491
+ type = types_1.WasiFileType.UNKNOWN;
492
+ }
493
+ entryView.setUint8(20, type);
494
+ entryData.set(nameData, 24);
495
+ const data = entryData.slice(0, Math.min(entryData.length, buf_len - bufferUsed));
496
+ HEAPU8.set(data, buf + bufferUsed);
497
+ bufferUsed += data.byteLength;
498
+ }
499
+ view.setUint32(bufused, bufferUsed, true);
500
+ return types_1.WasiErrno.ESUCCESS;
501
+ });
502
+ this.fd_renumber = syscallWrap('fd_renumber', function (from, to) {
503
+ const wasi = _wasi.get(this);
504
+ wasi.fds.renumber(to, from);
505
+ return types_1.WasiErrno.ESUCCESS;
506
+ });
507
+ this.fd_sync = syscallWrap('fd_sync', function (fd) {
508
+ const wasi = _wasi.get(this);
509
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_SYNC, BigInt(0));
510
+ const fs = getFs(this);
511
+ fs.fsyncSync(fileDescriptor.fd);
512
+ return types_1.WasiErrno.ESUCCESS;
513
+ });
514
+ this.fd_tell = syscallWrap('fd_tell', function (fd, offset) {
515
+ const wasi = _wasi.get(this);
516
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_TELL, BigInt(0));
517
+ const pos = BigInt(fileDescriptor.pos);
518
+ const { view } = getMemory(this);
519
+ view.setBigUint64(Number(offset), pos, true);
520
+ return types_1.WasiErrno.ESUCCESS;
521
+ });
522
+ this.fd_write = syscallWrap('fd_write', function (fd, iovs, iovslen, size) {
523
+ iovs = Number(iovs);
524
+ size = Number(size);
525
+ if (iovs === 0 || size === 0) {
526
+ return types_1.WasiErrno.EINVAL;
527
+ }
528
+ const { HEAPU8, view } = getMemory(this);
529
+ const wasi = _wasi.get(this);
530
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_WRITE, BigInt(0));
531
+ const buffer = (0, fd_1.concatBuffer)(Array.from({ length: Number(iovslen) }, (_, i) => {
532
+ const offset = iovs + (i * 8);
533
+ const buf = view.getInt32(offset, true);
534
+ const bufLen = view.getUint32(offset + 4, true);
535
+ return HEAPU8.subarray(buf, buf + bufLen);
536
+ }));
537
+ let nwritten;
538
+ if (fd === 1 || fd === 2) {
539
+ nwritten = fileDescriptor.write(buffer);
540
+ }
541
+ else {
542
+ const fs = getFs(this);
543
+ nwritten = fs.writeSync(fileDescriptor.fd, buffer, 0, buffer.length, Number(fileDescriptor.pos));
544
+ fileDescriptor.pos += BigInt(nwritten);
545
+ }
546
+ view.setUint32(size, nwritten, true);
547
+ return types_1.WasiErrno.ESUCCESS;
548
+ });
549
+ this.path_create_directory = syscallWrap('path_create_directory', function (fd, path, path_len) {
550
+ path = Number(path);
551
+ path_len = Number(path_len);
552
+ if (path === 0) {
553
+ return types_1.WasiErrno.EINVAL;
554
+ }
555
+ const { HEAPU8 } = getMemory(this);
556
+ const wasi = _wasi.get(this);
557
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_CREATE_DIRECTORY, BigInt(0));
558
+ let pathString = decoder.decode(HEAPU8.subarray(path, path + path_len));
559
+ pathString = (0, path_1.resolve)(fileDescriptor.realPath, pathString);
560
+ const fs = getFs(this);
561
+ fs.mkdirSync(pathString);
562
+ return types_1.WasiErrno.ESUCCESS;
563
+ });
564
+ this.path_filestat_get = syscallWrap('path_filestat_get', function (fd, flags, path, path_len, filestat) {
565
+ path = Number(path);
566
+ path_len = Number(path_len);
567
+ filestat = Number(filestat);
568
+ if (path === 0 || filestat === 0) {
569
+ return types_1.WasiErrno.EINVAL;
570
+ }
571
+ const { HEAPU8, view } = getMemory(this);
572
+ const wasi = _wasi.get(this);
573
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_FILESTAT_GET, BigInt(0));
574
+ let pathString = decoder.decode(HEAPU8.subarray(path, path + path_len));
575
+ const fs = getFs(this);
576
+ pathString = (0, path_1.resolve)(fileDescriptor.realPath, pathString);
577
+ let stat;
578
+ if ((flags & 1) === 1) {
579
+ stat = fs.statSync(pathString, { bigint: true });
580
+ }
581
+ else {
582
+ stat = fs.lstatSync(pathString, { bigint: true });
583
+ }
584
+ (0, fd_1.toFileStat)(view, filestat, stat);
585
+ return types_1.WasiErrno.ESUCCESS;
586
+ });
587
+ this.path_filestat_set_times = syscallWrap('path_filestat_set_times', function (fd, flags, path, path_len, atim, mtim, fst_flags) {
588
+ path = Number(path);
589
+ path_len = Number(path_len);
590
+ if (path === 0)
591
+ return types_1.WasiErrno.EINVAL;
592
+ if ((fst_flags) & ~(types_1.WasiFstFlag.SET_ATIM |
593
+ types_1.WasiFstFlag.SET_ATIM_NOW |
594
+ types_1.WasiFstFlag.SET_MTIM |
595
+ types_1.WasiFstFlag.SET_MTIM_NOW)) {
596
+ return types_1.WasiErrno.EINVAL;
597
+ }
598
+ const { HEAPU8 } = getMemory(this);
599
+ const wasi = _wasi.get(this);
600
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_FILESTAT_SET_TIMES, BigInt(0));
601
+ const fs = getFs(this);
602
+ const resolvedPath = resolvePath(fs, fileDescriptor, decoder.decode(HEAPU8.subarray(path, path + path_len)), flags);
603
+ if ((fst_flags & types_1.WasiFstFlag.SET_ATIM_NOW) === types_1.WasiFstFlag.SET_ATIM_NOW) {
604
+ atim = BigInt(Date.now() * 1000000);
605
+ }
606
+ if ((fst_flags & types_1.WasiFstFlag.SET_MTIM_NOW) === types_1.WasiFstFlag.SET_MTIM_NOW) {
607
+ mtim = BigInt(Date.now() * 1000000);
608
+ }
609
+ fs.utimesSync(resolvedPath, Number(atim), Number(mtim));
610
+ return types_1.WasiErrno.ESUCCESS;
611
+ });
612
+ this.path_link = syscallWrap('path_link', function (old_fd, old_flags, old_path, old_path_len, new_fd, new_path, new_path_len) {
613
+ old_path = Number(old_path);
614
+ old_path_len = Number(old_path_len);
615
+ new_path = Number(new_path);
616
+ new_path_len = Number(new_path_len);
617
+ if (old_path === 0 || new_path === 0) {
618
+ return types_1.WasiErrno.EINVAL;
619
+ }
620
+ const wasi = _wasi.get(this);
621
+ let oldWrap;
622
+ let newWrap;
623
+ if (old_fd === new_fd) {
624
+ oldWrap = newWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_LINK_SOURCE | types_1.WasiRights.PATH_LINK_TARGET, BigInt(0));
625
+ }
626
+ else {
627
+ oldWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_LINK_SOURCE, BigInt(0));
628
+ newWrap = wasi.fds.get(new_fd, types_1.WasiRights.PATH_LINK_TARGET, BigInt(0));
629
+ }
630
+ const { HEAPU8 } = getMemory(this);
631
+ const fs = getFs(this);
632
+ const resolvedOldPath = resolvePath(fs, oldWrap, decoder.decode(HEAPU8.subarray(old_path, old_path + old_path_len)), old_flags);
633
+ const resolvedNewPath = (0, path_1.resolve)(newWrap.realPath, decoder.decode(HEAPU8.subarray(new_path, new_path + new_path_len)));
634
+ fs.linkSync(resolvedOldPath, resolvedNewPath);
635
+ return types_1.WasiErrno.ESUCCESS;
636
+ });
637
+ this.path_open = syscallWrap('path_open', function (dirfd, dirflags, path, path_len, o_flags, fs_rights_base, fs_rights_inheriting, fs_flags, fd) {
638
+ path = Number(path);
639
+ fd = Number(fd);
640
+ if (path === 0 || fd === 0) {
641
+ return types_1.WasiErrno.EINVAL;
642
+ }
643
+ path_len = Number(path_len);
644
+ fs_rights_base = BigInt(fs_rights_base);
645
+ fs_rights_base = BigInt(fs_rights_base);
646
+ const read = (fs_rights_base & (types_1.WasiRights.FD_READ |
647
+ types_1.WasiRights.FD_READDIR)) !== BigInt(0);
648
+ const write = (fs_rights_base & (types_1.WasiRights.FD_DATASYNC |
649
+ types_1.WasiRights.FD_WRITE |
650
+ types_1.WasiRights.FD_ALLOCATE |
651
+ types_1.WasiRights.FD_FILESTAT_SET_SIZE)) !== BigInt(0);
652
+ let flags = write ? read ? types_1.FileControlFlag.O_RDWR : types_1.FileControlFlag.O_WRONLY : types_1.FileControlFlag.O_RDONLY;
653
+ let needed_base = types_1.WasiRights.PATH_OPEN;
654
+ let needed_inheriting = fs_rights_base | fs_rights_inheriting;
655
+ if ((o_flags & types_1.WasiFileControlFlag.O_CREAT) !== 0) {
656
+ flags |= types_1.FileControlFlag.O_CREAT;
657
+ needed_base |= types_1.WasiRights.PATH_CREATE_FILE;
658
+ }
659
+ if ((o_flags & types_1.WasiFileControlFlag.O_DIRECTORY) !== 0) {
660
+ flags |= types_1.FileControlFlag.O_DIRECTORY;
661
+ }
662
+ if ((o_flags & types_1.WasiFileControlFlag.O_EXCL) !== 0) {
663
+ flags |= types_1.FileControlFlag.O_EXCL;
664
+ }
665
+ if ((o_flags & types_1.WasiFileControlFlag.O_TRUNC) !== 0) {
666
+ flags |= types_1.FileControlFlag.O_TRUNC;
667
+ needed_base |= types_1.WasiRights.PATH_FILESTAT_SET_SIZE;
668
+ }
669
+ if ((fs_flags & types_1.WasiFdFlag.APPEND) !== 0) {
670
+ flags |= types_1.FileControlFlag.O_APPEND;
671
+ }
672
+ if ((fs_flags & types_1.WasiFdFlag.DSYNC) !== 0) {
673
+ // flags |= FileControlFlag.O_DSYNC;
674
+ needed_inheriting |= types_1.WasiRights.FD_DATASYNC;
675
+ }
676
+ if ((fs_flags & types_1.WasiFdFlag.NONBLOCK) !== 0) {
677
+ flags |= types_1.FileControlFlag.O_NONBLOCK;
678
+ }
679
+ if ((fs_flags & types_1.WasiFdFlag.RSYNC) !== 0) {
680
+ flags |= types_1.FileControlFlag.O_SYNC;
681
+ needed_inheriting |= types_1.WasiRights.FD_SYNC;
682
+ }
683
+ if ((fs_flags & types_1.WasiFdFlag.SYNC) !== 0) {
684
+ flags |= types_1.FileControlFlag.O_SYNC;
685
+ needed_inheriting |= types_1.WasiRights.FD_SYNC;
686
+ }
687
+ if (write && (flags & (types_1.FileControlFlag.O_APPEND | types_1.FileControlFlag.O_TRUNC)) === 0) {
688
+ needed_inheriting |= types_1.WasiRights.FD_SEEK;
689
+ }
690
+ const wasi = _wasi.get(this);
691
+ const fileDescriptor = wasi.fds.get(dirfd, needed_base, needed_inheriting);
692
+ const memory = getMemory(this);
693
+ const HEAPU8 = memory.HEAPU8;
694
+ const pathString = decoder.decode(HEAPU8.subarray(path, path + path_len));
695
+ const fs = getFs(this);
696
+ const resolved_path = resolvePath(fs, fileDescriptor, pathString, dirflags);
697
+ const r = fs.openSync(resolved_path, flags, 0o666);
698
+ const filetype = wasi.fds.getFileTypeByFd(r);
699
+ if ((o_flags & types_1.WasiFileControlFlag.O_DIRECTORY) !== 0 && filetype !== types_1.WasiFileType.DIRECTORY) {
700
+ return types_1.WasiErrno.ENOTDIR;
701
+ }
702
+ const { base: max_base, inheriting: max_inheriting } = (0, rights_1.getRights)(wasi.fds.stdio, r, flags, filetype);
703
+ const wrap = wasi.fds.insert(r, resolved_path, resolved_path, filetype, fs_rights_base & max_base, fs_rights_inheriting & max_inheriting, 0);
704
+ const stat = fs.fstatSync(r, { bigint: true });
705
+ if (stat.isFile()) {
706
+ wrap.size = stat.size;
707
+ if ((flags & types_1.FileControlFlag.O_APPEND) !== 0) {
708
+ wrap.pos = stat.size;
709
+ }
710
+ }
711
+ const view = memory.view;
712
+ view.setInt32(fd, wrap.id, true);
713
+ return types_1.WasiErrno.ESUCCESS;
714
+ });
715
+ this.path_readlink = syscallWrap('path_readlink', function (fd, path, path_len, buf, buf_len, bufused) {
716
+ path = Number(path);
717
+ path_len = Number(path_len);
718
+ buf = Number(buf);
719
+ buf_len = Number(buf_len);
720
+ bufused = Number(bufused);
721
+ if (path === 0 || buf === 0 || bufused === 0) {
722
+ return types_1.WasiErrno.EINVAL;
723
+ }
724
+ const { HEAPU8, view } = getMemory(this);
725
+ const wasi = _wasi.get(this);
726
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_READLINK, BigInt(0));
727
+ let pathString = decoder.decode(HEAPU8.subarray(path, path + path_len));
728
+ pathString = (0, path_1.resolve)(fileDescriptor.realPath, pathString);
729
+ const fs = getFs(this);
730
+ const link = fs.readlinkSync(pathString);
731
+ const linkData = encoder.encode(link);
732
+ const len = Math.min(linkData.length, buf_len);
733
+ if (len >= buf_len)
734
+ return types_1.WasiErrno.ENOBUFS;
735
+ HEAPU8.set(linkData.subarray(0, len), buf);
736
+ HEAPU8[buf + len] = 0;
737
+ view.setUint32(bufused, len + 1, true);
738
+ return types_1.WasiErrno.ESUCCESS;
739
+ });
740
+ this.path_remove_directory = syscallWrap('path_remove_directory', function (fd, path, path_len) {
741
+ path = Number(path);
742
+ path_len = Number(path_len);
743
+ if (path === 0) {
744
+ return types_1.WasiErrno.EINVAL;
745
+ }
746
+ const { HEAPU8 } = getMemory(this);
747
+ const wasi = _wasi.get(this);
748
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_REMOVE_DIRECTORY, BigInt(0));
749
+ let pathString = decoder.decode(HEAPU8.subarray(path, path + path_len));
750
+ pathString = (0, path_1.resolve)(fileDescriptor.realPath, pathString);
751
+ const fs = getFs(this);
752
+ fs.rmdirSync(pathString);
753
+ return types_1.WasiErrno.ESUCCESS;
754
+ });
755
+ this.path_rename = syscallWrap('path_rename', function (old_fd, old_path, old_path_len, new_fd, new_path, new_path_len) {
756
+ old_path = Number(old_path);
757
+ old_path_len = Number(old_path_len);
758
+ new_path = Number(new_path);
759
+ new_path_len = Number(new_path_len);
760
+ if (old_path === 0 || new_path === 0) {
761
+ return types_1.WasiErrno.EINVAL;
762
+ }
763
+ const wasi = _wasi.get(this);
764
+ let oldWrap;
765
+ let newWrap;
766
+ if (old_fd === new_fd) {
767
+ oldWrap = newWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_RENAME_SOURCE | types_1.WasiRights.PATH_RENAME_TARGET, BigInt(0));
768
+ }
769
+ else {
770
+ oldWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_RENAME_SOURCE, BigInt(0));
771
+ newWrap = wasi.fds.get(new_fd, types_1.WasiRights.PATH_RENAME_TARGET, BigInt(0));
772
+ }
773
+ const { HEAPU8 } = getMemory(this);
774
+ const resolvedOldPath = (0, path_1.resolve)(oldWrap.realPath, decoder.decode(HEAPU8.subarray(old_path, old_path + old_path_len)));
775
+ const resolvedNewPath = (0, path_1.resolve)(newWrap.realPath, decoder.decode(HEAPU8.subarray(new_path, new_path + new_path_len)));
776
+ const fs = getFs(this);
777
+ fs.renameSync(resolvedOldPath, resolvedNewPath);
778
+ return types_1.WasiErrno.ESUCCESS;
779
+ });
780
+ this.path_symlink = syscallWrap('path_symlink', function (old_path, old_path_len, fd, new_path, new_path_len) {
781
+ old_path = Number(old_path);
782
+ old_path_len = Number(old_path_len);
783
+ new_path = Number(new_path);
784
+ new_path_len = Number(new_path_len);
785
+ if (old_path === 0 || new_path === 0) {
786
+ return types_1.WasiErrno.EINVAL;
787
+ }
788
+ const { HEAPU8 } = getMemory(this);
789
+ const wasi = _wasi.get(this);
790
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_SYMLINK, BigInt(0));
791
+ const oldPath = decoder.decode(HEAPU8.subarray(old_path, old_path + old_path_len));
792
+ let newPath = decoder.decode(HEAPU8.subarray(new_path, new_path + new_path_len));
793
+ newPath = (0, path_1.resolve)(fileDescriptor.realPath, newPath);
794
+ const fs = getFs(this);
795
+ fs.symlinkSync(oldPath, newPath);
796
+ return types_1.WasiErrno.ESUCCESS;
797
+ });
798
+ this.path_unlink_file = syscallWrap('path_unlink_file', function (fd, path, path_len) {
799
+ path = Number(path);
800
+ path_len = Number(path_len);
801
+ if (path === 0) {
802
+ return types_1.WasiErrno.EINVAL;
803
+ }
804
+ const { HEAPU8 } = getMemory(this);
805
+ const wasi = _wasi.get(this);
806
+ const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_UNLINK_FILE, BigInt(0));
807
+ let pathString = decoder.decode(HEAPU8.subarray(path, path + path_len));
808
+ pathString = (0, path_1.resolve)(fileDescriptor.realPath, pathString);
809
+ const fs = getFs(this);
810
+ fs.unlinkSync(pathString);
811
+ return types_1.WasiErrno.ESUCCESS;
812
+ });
813
+ this.poll_oneoff = syscallWrap('poll_oneoff', function (_in, _out, _sub, _nevents) {
814
+ return types_1.WasiErrno.ENOSYS;
815
+ });
816
+ this.proc_exit = syscallWrap('proc_exit', function (_rval) {
817
+ return types_1.WasiErrno.ESUCCESS;
818
+ });
819
+ this.proc_raise = syscallWrap('proc_raise', function (_sig) {
820
+ return types_1.WasiErrno.ENOSYS;
821
+ });
822
+ this.sched_yield = syscallWrap('sched_yield', function () {
823
+ return types_1.WasiErrno.ESUCCESS;
824
+ });
825
+ this.random_get = typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function'
826
+ ? syscallWrap('random_get', function (buf, buf_len) {
827
+ buf = Number(buf);
828
+ if (buf === 0) {
829
+ return types_1.WasiErrno.EINVAL;
830
+ }
831
+ buf_len = Number(buf_len);
832
+ const { HEAPU8 } = getMemory(this);
833
+ let pos;
834
+ const stride = 65536;
835
+ for (pos = 0; pos + stride < buf_len; pos += stride) {
836
+ crypto.getRandomValues(HEAPU8.subarray(buf + pos, buf + pos + stride));
837
+ }
838
+ crypto.getRandomValues(HEAPU8.subarray(buf + pos, buf + buf_len));
839
+ return types_1.WasiErrno.ESUCCESS;
840
+ })
841
+ : syscallWrap('random_get', function (buf, buf_len) {
842
+ buf = Number(buf);
843
+ if (buf === 0) {
844
+ return types_1.WasiErrno.EINVAL;
845
+ }
846
+ buf_len = Number(buf_len);
847
+ const { view } = getMemory(this);
848
+ for (let i = buf; i < buf + buf_len; ++i) {
849
+ view.setUint8(i, Math.floor(Math.random() * 256));
850
+ }
851
+ return types_1.WasiErrno.ESUCCESS;
852
+ });
853
+ this.sock_recv = syscallWrap('sock_recv', function () {
854
+ return types_1.WasiErrno.ENOTSUP;
855
+ });
856
+ this.sock_send = syscallWrap('sock_send', function () {
857
+ return types_1.WasiErrno.ENOTSUP;
858
+ });
859
+ this.sock_shutdown = syscallWrap('sock_shutdown', function () {
860
+ return types_1.WasiErrno.ENOTSUP;
861
+ });
862
+ const fs = filesystem ? filesystem.fs : undefined;
863
+ const fds = new fd_1.FileDescriptorTable({
864
+ size: 3,
865
+ in: stdio[0],
866
+ out: stdio[1],
867
+ err: stdio[2],
868
+ fs,
869
+ print,
870
+ printErr
871
+ });
872
+ _wasi.set(this, {
873
+ fds,
874
+ args,
875
+ env
876
+ });
877
+ if (fs)
878
+ _fs.set(this, fs);
879
+ if (preopens.length > 0) {
880
+ for (let i = 0; i < preopens.length; ++i) {
881
+ const realPath = fs.realpathSync(preopens[i].realPath, 'utf8');
882
+ const fd = fs.openSync(realPath, 'r', 0o666);
883
+ fds.insertPreopen(fd, preopens[i].mappedPath, realPath);
884
+ }
885
+ }
886
+ }
887
+ }
888
+ exports.WASI = WASI;
889
+ //# sourceMappingURL=preview1.js.map