import { args_get, args_sizes_get, environ_get, environ_sizes_get, proc_exit, fd_write, fd_close, fd_read, clock_time_get, clockid, errnoToString, fd } from "bindings/wasi_snapshot_preview1"; import { E_INDEXOUTOFRANGE } from "util/error"; // @ts-ignore: decorator @lazy const iobuf = memory.data(4 * sizeof()); export namespace process { // @ts-ignore: decorator @lazy export const arch = sizeof() == 4 ? "wasm32" : "wasm64"; // @ts-ignore: decorator @lazy export const platform = "wasm"; // @ts-ignore: decorator @lazy export const argv = lazyArgv(); // @ts-ignore: decorator @lazy export const env = lazyEnv(); // @ts-ignore: decorator @lazy export var exitCode = 0; export function exit(code: i32 = exitCode): void { proc_exit(code); } // @ts-ignore: decorator @lazy export const stdin = changetype(0); // @ts-ignore: decorator @lazy export const stdout = changetype(1); // @ts-ignore: decorator @lazy export const stderr = changetype(2); export function time(): i64 { var err = clock_time_get(clockid.REALTIME, 1000000, iobuf); if (err) throw new Error(errnoToString(err)); return load(iobuf) / 1000000; } export function hrtime(): u64 { var err = clock_time_get(clockid.MONOTONIC, 0, iobuf); if (err) throw new Error(errnoToString(err)); return load(iobuf); } } function lazyArgv(): string[] { var err = args_sizes_get(iobuf, iobuf + sizeof()); if (err) throw new Error(errnoToString(err)); var count = load(iobuf); var ptrsSize = count * sizeof(); var dataSize = load(iobuf, sizeof()); var bufSize = ptrsSize + dataSize; var buf = __alloc(bufSize); err = args_get(buf, buf + ptrsSize); if (err) throw new Error(errnoToString(err)); var count32 = count; var argv = new Array(count32); for (let i = 0; i < count32; ++i) { let ptr = load(buf + i * sizeof()); let str = String.UTF8.decodeUnsafe(ptr, ptr + bufSize - buf, true); argv[i] = str; } __free(buf); return argv; } function lazyEnv(): Map { var err = environ_sizes_get(iobuf, iobuf + 4); if (err) throw new Error(errnoToString(err)); var count = load(iobuf); var ptrsSize = count * sizeof(); var dataSize = load(iobuf, sizeof()); var bufSize = ptrsSize + dataSize; var buf = __alloc(bufSize); err = environ_get(buf, buf + ptrsSize); if (err) throw new Error(errnoToString(err)); var env = new Map(); for (let i: usize = 0; i < count; ++i) { let ptr = load(buf + i * sizeof()); let str = String.UTF8.decodeUnsafe(ptr, ptr + bufSize - buf, true); let pos = str.indexOf("="); if (~pos) { env.set(str.substring(0, pos), str.substring(pos + 1)); // __dispose(changetype(str)); } else { env.set(str, ""); } } __free(buf); return env; } @unmanaged abstract class Stream { close(): void { var err = fd_close(changetype(this)); if (err) throw new Error(errnoToString(err)); } } @unmanaged abstract class WritableStream extends Stream { write(data: T): void { if (isString()) { writeString(changetype(this), changetype(data)); } else if (data instanceof ArrayBuffer) { writeBuffer(changetype(this), data); } else { ERROR("String or ArrayBuffer expected"); } } } @unmanaged abstract class ReadableStream extends Stream { read(buffer: ArrayBuffer, offset: isize = 0): i32 { var end = buffer.byteLength; if (offset < 0 || offset > end) { throw new Error(E_INDEXOUTOFRANGE); } store(iobuf, changetype(buffer) + offset); store(iobuf, end - offset, sizeof()); var err = fd_read(changetype(this), iobuf, 1, iobuf + 2 * sizeof()); if (err) throw new Error(errnoToString(err)); return load(iobuf, 2 * sizeof()); } } function writeBuffer(fd: fd, data: ArrayBuffer): void { store(iobuf, changetype(data)); store(iobuf, data.byteLength, sizeof()); var err = fd_write(fd, iobuf, 1, iobuf + 2 * sizeof()); if (err) throw new Error(errnoToString(err)); } function writeString(fd: fd, data: string): void { var char2 = -1; var char3 = -1; var char4 = -1; switch (data.length) { case 4: { // "null" char4 = load(changetype(data), 6); if (char4 >= 0x80) break; } case 3: { // "ms\n" char3 = load(changetype(data), 4); if (char3 >= 0x80) break; } case 2: { // "\r\n" char2 = load(changetype(data), 2); if (char2 >= 0x80) break; } case 1: { // "\n" let char1 = load(changetype(data)); if (char1 >= 0x80) break; store(iobuf, iobuf + 2 * sizeof()); store(iobuf, 1 + i32(char2 != -1) + i32(char3 != -1) + i32(char4 != -1), sizeof()); store(iobuf, char1 | char2 << 8 | char3 << 16 | char4 << 24, 2 * sizeof()); let err = fd_write(fd, iobuf, 1, iobuf + 3 * sizeof()); if (err) throw new Error(errnoToString(err)); } case 0: return; } var utf8len = String.UTF8.byteLength(data); var utf8buf = __alloc(utf8len); assert(String.UTF8.encodeUnsafe(changetype(data), data.length, utf8buf) == utf8len); store(iobuf, utf8buf); store(iobuf, utf8len, sizeof()); var err = fd_write(fd, iobuf, 1, iobuf + 2 * sizeof()); __free(utf8buf); if (err) throw new Error(errnoToString(err)); }