aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-01-28 23:23:26 -0800
committerGravatar GitHub <noreply@github.com> 2023-01-28 23:23:26 -0800
commitf087388ebc6314c2852d553f4f4ea3074369dfbe (patch)
tree935a0c205b3eccca29f3bcc5e3db18f7fdc4469d /src
parent48eb0c12ab2c568d7ff706c2b0a6616d428032c8 (diff)
downloadbun-f087388ebc6314c2852d553f4f4ea3074369dfbe.tar.gz
bun-f087388ebc6314c2852d553f4f4ea3074369dfbe.tar.zst
bun-f087388ebc6314c2852d553f4f4ea3074369dfbe.zip
Support running WASI (WebAssembly) files using `bun run` (#1929)
* another micro bench * Support running WASI --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/api/.gitignore1
-rw-r--r--src/bun.js/module_loader.zig87
-rw-r--r--src/bun.js/wasi-runner.js49
-rw-r--r--src/bun.js/wasi.exports.js2177
-rw-r--r--src/bundler.zig13
-rw-r--r--src/cli.zig2
-rw-r--r--src/cli/run_command.zig4
-rw-r--r--src/deps/.gitignore1
-rw-r--r--src/logger.zig7
-rw-r--r--src/string_immutable.zig11
10 files changed, 2348 insertions, 4 deletions
diff --git a/src/api/.gitignore b/src/api/.gitignore
new file mode 100644
index 000000000..19e1bced9
--- /dev/null
+++ b/src/api/.gitignore
@@ -0,0 +1 @@
+*.wasm
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig
index 485a5c59a..0038526a1 100644
--- a/src/bun.js/module_loader.zig
+++ b/src/bun.js/module_loader.zig
@@ -982,6 +982,25 @@ pub const ModuleLoader = struct {
return error.ParseError;
};
+ if (parse_result.loader == .wasm) {
+ const wasm_result = transpileSourceCode(
+ jsc_vm,
+ specifier,
+ display_specifier,
+ referrer,
+ path,
+ .wasm,
+ log,
+ &parse_result.source,
+ ret,
+ promise_ptr,
+ source_code_printer,
+ globalObject,
+ flags,
+ );
+ return wasm_result;
+ }
+
if (jsc_vm.bundler.log.errors > 0) {
return error.ParseError;
}
@@ -1180,6 +1199,55 @@ pub const ModuleLoader = struct {
// .tag = ResolvedSource.Tag.wasm,
// };
// },
+ .wasm => {
+ if (strings.eqlComptime(referrer, "undefined") and strings.eqlLong(jsc_vm.main, path.text, true)) {
+ if (virtual_source) |source| {
+ if (globalObject) |globalThis| {
+ // attempt to avoid reading the WASM file twice.
+ var encoded = JSC.EncodedJSValue{
+ .asPtr = globalThis,
+ };
+ const globalValue = @intToEnum(JSC.JSValue, encoded.asInt64);
+ globalValue.put(
+ globalThis,
+ JSC.ZigString.static("wasmSourceBytes"),
+ JSC.ArrayBuffer.create(globalThis, source.contents, .Uint8Array),
+ );
+ }
+ }
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ strings.append3(
+ bun.default_allocator,
+ JSC.Node.fs.constants_string,
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./wasi.exports.js")),
+ jsModuleFromFile(jsc_vm.load_builtins_from_path, "wasi-runner.js"),
+ ) catch unreachable,
+ ),
+ .specifier = ZigString.init(display_specifier),
+ .source_url = ZigString.init(path.text),
+ .hash = 0,
+ };
+ }
+
+ return transpileSourceCode(
+ jsc_vm,
+ specifier,
+ display_specifier,
+ referrer,
+ path,
+ .file,
+ log,
+ virtual_source,
+ ret,
+ promise_ptr,
+ source_code_printer,
+ globalObject,
+ flags,
+ );
+ },
+
else => {
var stack_buf = std.heap.stackFallback(4096, jsc_vm.allocator);
var allocator = stack_buf.get();
@@ -1910,6 +1978,21 @@ pub const ModuleLoader = struct {
.hash = 0,
};
},
+ .@"node:wasi" => {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(
+ strings.append(
+ bun.default_allocator,
+ JSC.Node.fs.constants_string,
+ @as(string, jsModuleFromFile(jsc_vm.load_builtins_from_path, "./wasi.exports.js")),
+ ) catch unreachable,
+ ),
+ .specifier = ZigString.init("node:wasi"),
+ .source_url = ZigString.init("node:wasi"),
+ .hash = 0,
+ };
+ },
.@"node:http" => {
return ResolvedSource{
.allocator = null,
@@ -2084,6 +2167,7 @@ pub const HardcodedModule = enum {
depd,
undici,
ws,
+ @"node:wasi",
/// Already resolved modules go in here.
/// This does not remap the module name, it is just a hash table.
/// Do not put modules that have aliases in here
@@ -2130,6 +2214,7 @@ pub const HardcodedModule = enum {
.{ "node:url", HardcodedModule.@"node:url" },
.{ "node:util", HardcodedModule.@"node:util" },
.{ "node:util/types", HardcodedModule.@"node:util/types" },
+ .{ "node:wasi", HardcodedModule.@"node:wasi" },
.{ "node:zlib", HardcodedModule.@"node:zlib" },
.{ "undici", HardcodedModule.undici },
.{ "ws", HardcodedModule.ws },
@@ -2192,6 +2277,7 @@ pub const HardcodedModule = enum {
.{ "node:url", "node:url" },
.{ "node:util", "node:util" },
.{ "node:util/types", "node:util/types" },
+ .{ "node:wasi", "node:wasi" },
.{ "node:zlib", "node:zlib" },
.{ "os", "node:os" },
.{ "path", "node:path" },
@@ -2216,6 +2302,7 @@ pub const HardcodedModule = enum {
.{ "url", "node:url" },
.{ "util", "node:util" },
.{ "util/types", "node:util/types" },
+ .{ "wasi", "node:wasi" },
.{ "ws", "ws" },
.{ "ws/lib/websocket", "ws" },
.{ "zlib", "node:zlib" },
diff --git a/src/bun.js/wasi-runner.js b/src/bun.js/wasi-runner.js
new file mode 100644
index 000000000..24ff0a678
--- /dev/null
+++ b/src/bun.js/wasi-runner.js
@@ -0,0 +1,49 @@
+/** --- WASI */
+// wasi is imported into the top of this file
+
+const filePath = process.argv.at(1);
+if (!filePath) {
+ var err = new Error(
+ "To run a wasm file with Bun, the first argument must be a path to a .wasm file",
+ );
+ err.name = "WasmFileNotFound";
+ throw err;
+}
+
+// The module specifier is the resolved path to the wasm file
+
+var {
+ WASM_CWD = process.cwd(),
+ WASM_ROOT_DIR = "/",
+ WASM_ENV_STR = undefined,
+ WASM_USE_ASYNC_INIT = "",
+} = process.env;
+
+var env = process.env;
+if (WASM_ENV_STR?.length) {
+ env = JSON.parse(WASM_ENV_STR);
+}
+
+const wasi = new WASI({
+ args: process.argv.slice(1),
+ env,
+ preopens: {
+ ".": WASM_CWD || process.cwd(),
+ "/": WASM_ROOT_DIR || "/",
+ },
+});
+
+let source = globalThis.wasmSourceBytes;
+if (!source) {
+ const fs = Bun.fs();
+ const file = import.meta.path;
+ source = fs.readFileSync(file);
+}
+
+const wasm = new WebAssembly.Module(source);
+const instance = !WASM_USE_ASYNC_INIT
+ ? new WebAssembly.Instance(wasm, wasi.getImports(wasm))
+ : await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
+wasi.start(instance);
+
+process.exit(0);
diff --git a/src/bun.js/wasi.exports.js b/src/bun.js/wasi.exports.js
new file mode 100644
index 000000000..060310a9c
--- /dev/null
+++ b/src/bun.js/wasi.exports.js
@@ -0,0 +1,2177 @@
+// HUGE thanks to @williamstein and https://github.com/sagemathinc/cowasm/tree/main/packages/wasi-js
+// This code is mostly a copy of wasi-js
+// Eventually we will implement this in native code, but this is just a quick hack to get WASI working.
+
+/** **/
+// constants is injected into the top of this file
+const nodeFsConstants = constants;
+
+var __getOwnPropNames = Object.getOwnPropertyNames;
+
+var __commonJS = (cb, mod) =>
+ function __require2() {
+ return (
+ mod ||
+ (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod),
+ mod.exports
+ );
+ };
+
+// node_modules/wasi-js/dist/types.js
+var require_types = __commonJS({
+ "node_modules/wasi-js/dist/types.js"(exports) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.WASIKillError = exports.WASIExitError = exports.WASIError = void 0;
+ var WASIError = class extends Error {
+ constructor(errno) {
+ super();
+ this.errno = errno;
+ Object.setPrototypeOf(this, WASIError.prototype);
+ }
+ };
+ exports.WASIError = WASIError;
+ var WASIExitError = class extends Error {
+ constructor(code) {
+ super(`WASI Exit error: ${code}`);
+ this.code = code;
+ Object.setPrototypeOf(this, WASIExitError.prototype);
+ }
+ };
+ exports.WASIExitError = WASIExitError;
+ var WASIKillError = class extends Error {
+ constructor(signal) {
+ super(`WASI Kill signal: ${signal}`);
+ this.signal = signal;
+ Object.setPrototypeOf(this, WASIKillError.prototype);
+ }
+ };
+ exports.WASIKillError = WASIKillError;
+ },
+});
+
+// node_modules/wasi-js/dist/constants.js
+var require_constants = __commonJS({
+ "node_modules/wasi-js/dist/constants.js"(exports) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.WASI_ENOMSG =
+ exports.WASI_ENOMEM =
+ exports.WASI_ENOLINK =
+ exports.WASI_ENOLCK =
+ exports.WASI_ENOEXEC =
+ exports.WASI_ENOENT =
+ exports.WASI_ENODEV =
+ exports.WASI_ENOBUFS =
+ exports.WASI_ENFILE =
+ exports.WASI_ENETUNREACH =
+ exports.WASI_ENETRESET =
+ exports.WASI_ENETDOWN =
+ exports.WASI_ENAMETOOLONG =
+ exports.WASI_EMULTIHOP =
+ exports.WASI_EMSGSIZE =
+ exports.WASI_EMLINK =
+ exports.WASI_EMFILE =
+ exports.WASI_ELOOP =
+ exports.WASI_EISDIR =
+ exports.WASI_EISCONN =
+ exports.WASI_EIO =
+ exports.WASI_EINVAL =
+ exports.WASI_EINTR =
+ exports.WASI_EINPROGRESS =
+ exports.WASI_EILSEQ =
+ exports.WASI_EIDRM =
+ exports.WASI_EHOSTUNREACH =
+ exports.WASI_EFBIG =
+ exports.WASI_EFAULT =
+ exports.WASI_EEXIST =
+ exports.WASI_EDQUOT =
+ exports.WASI_EDOM =
+ exports.WASI_EDESTADDRREQ =
+ exports.WASI_EDEADLK =
+ exports.WASI_ECONNRESET =
+ exports.WASI_ECONNREFUSED =
+ exports.WASI_ECONNABORTED =
+ exports.WASI_ECHILD =
+ exports.WASI_ECANCELED =
+ exports.WASI_EBUSY =
+ exports.WASI_EBADMSG =
+ exports.WASI_EBADF =
+ exports.WASI_EALREADY =
+ exports.WASI_EAGAIN =
+ exports.WASI_EAFNOSUPPORT =
+ exports.WASI_EADDRNOTAVAIL =
+ exports.WASI_EADDRINUSE =
+ exports.WASI_EACCES =
+ exports.WASI_E2BIG =
+ exports.WASI_ESUCCESS =
+ void 0;
+ exports.WASI_SIGVTALRM =
+ exports.WASI_SIGUSR2 =
+ exports.WASI_SIGUSR1 =
+ exports.WASI_SIGURG =
+ exports.WASI_SIGTTOU =
+ exports.WASI_SIGTTIN =
+ exports.WASI_SIGTSTP =
+ exports.WASI_SIGTRAP =
+ exports.WASI_SIGTERM =
+ exports.WASI_SIGSTOP =
+ exports.WASI_SIGSEGV =
+ exports.WASI_SIGQUIT =
+ exports.WASI_SIGPIPE =
+ exports.WASI_SIGKILL =
+ exports.WASI_SIGINT =
+ exports.WASI_SIGILL =
+ exports.WASI_SIGHUP =
+ exports.WASI_SIGFPE =
+ exports.WASI_SIGCONT =
+ exports.WASI_SIGCHLD =
+ exports.WASI_SIGBUS =
+ exports.WASI_SIGALRM =
+ exports.WASI_SIGABRT =
+ exports.WASI_ENOTCAPABLE =
+ exports.WASI_EXDEV =
+ exports.WASI_ETXTBSY =
+ exports.WASI_ETIMEDOUT =
+ exports.WASI_ESTALE =
+ exports.WASI_ESRCH =
+ exports.WASI_ESPIPE =
+ exports.WASI_EROFS =
+ exports.WASI_ERANGE =
+ exports.WASI_EPROTOTYPE =
+ exports.WASI_EPROTONOSUPPORT =
+ exports.WASI_EPROTO =
+ exports.WASI_EPIPE =
+ exports.WASI_EPERM =
+ exports.WASI_EOWNERDEAD =
+ exports.WASI_EOVERFLOW =
+ exports.WASI_ENXIO =
+ exports.WASI_ENOTTY =
+ exports.WASI_ENOTSUP =
+ exports.WASI_ENOTSOCK =
+ exports.WASI_ENOTRECOVERABLE =
+ exports.WASI_ENOTEMPTY =
+ exports.WASI_ENOTDIR =
+ exports.WASI_ENOTCONN =
+ exports.WASI_ENOSYS =
+ exports.WASI_ENOSPC =
+ exports.WASI_ENOPROTOOPT =
+ void 0;
+ exports.RIGHTS_REGULAR_FILE_BASE =
+ exports.RIGHTS_CHARACTER_DEVICE_INHERITING =
+ exports.RIGHTS_CHARACTER_DEVICE_BASE =
+ exports.RIGHTS_BLOCK_DEVICE_INHERITING =
+ exports.RIGHTS_BLOCK_DEVICE_BASE =
+ exports.RIGHTS_ALL =
+ exports.WASI_RIGHT_SOCK_SHUTDOWN =
+ exports.WASI_RIGHT_POLL_FD_READWRITE =
+ exports.WASI_RIGHT_PATH_UNLINK_FILE =
+ exports.WASI_RIGHT_PATH_REMOVE_DIRECTORY =
+ exports.WASI_RIGHT_PATH_SYMLINK =
+ exports.WASI_RIGHT_FD_FILESTAT_SET_TIMES =
+ exports.WASI_RIGHT_FD_FILESTAT_SET_SIZE =
+ exports.WASI_RIGHT_FD_FILESTAT_GET =
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_TIMES =
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_SIZE =
+ exports.WASI_RIGHT_PATH_FILESTAT_GET =
+ exports.WASI_RIGHT_PATH_RENAME_TARGET =
+ exports.WASI_RIGHT_PATH_RENAME_SOURCE =
+ exports.WASI_RIGHT_PATH_READLINK =
+ exports.WASI_RIGHT_FD_READDIR =
+ exports.WASI_RIGHT_PATH_OPEN =
+ exports.WASI_RIGHT_PATH_LINK_TARGET =
+ exports.WASI_RIGHT_PATH_LINK_SOURCE =
+ exports.WASI_RIGHT_PATH_CREATE_FILE =
+ exports.WASI_RIGHT_PATH_CREATE_DIRECTORY =
+ exports.WASI_RIGHT_FD_ALLOCATE =
+ exports.WASI_RIGHT_FD_ADVISE =
+ exports.WASI_RIGHT_FD_WRITE =
+ exports.WASI_RIGHT_FD_TELL =
+ exports.WASI_RIGHT_FD_SYNC =
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS =
+ exports.WASI_RIGHT_FD_SEEK =
+ exports.WASI_RIGHT_FD_READ =
+ exports.WASI_RIGHT_FD_DATASYNC =
+ exports.WASI_FDFLAG_SYNC =
+ exports.WASI_FDFLAG_RSYNC =
+ exports.WASI_FDFLAG_NONBLOCK =
+ exports.WASI_FDFLAG_DSYNC =
+ exports.WASI_FDFLAG_APPEND =
+ exports.WASI_FILETYPE_SYMBOLIC_LINK =
+ exports.WASI_FILETYPE_SOCKET_STREAM =
+ exports.WASI_FILETYPE_SOCKET_DGRAM =
+ exports.WASI_FILETYPE_REGULAR_FILE =
+ exports.WASI_FILETYPE_DIRECTORY =
+ exports.WASI_FILETYPE_CHARACTER_DEVICE =
+ exports.WASI_FILETYPE_BLOCK_DEVICE =
+ exports.WASI_FILETYPE_UNKNOWN =
+ exports.WASI_SIGXFSZ =
+ exports.WASI_SIGXCPU =
+ void 0;
+ exports.SIGNAL_MAP =
+ exports.ERROR_MAP =
+ exports.WASI_WHENCE_END =
+ exports.WASI_WHENCE_CUR =
+ exports.WASI_WHENCE_SET =
+ exports.WASI_STDERR_FILENO =
+ exports.WASI_STDOUT_FILENO =
+ exports.WASI_STDIN_FILENO =
+ exports.WASI_DIRCOOKIE_START =
+ exports.WASI_PREOPENTYPE_DIR =
+ exports.WASI_O_TRUNC =
+ exports.WASI_O_EXCL =
+ exports.WASI_O_DIRECTORY =
+ exports.WASI_O_CREAT =
+ exports.WASI_FILESTAT_SET_MTIM_NOW =
+ exports.WASI_FILESTAT_SET_MTIM =
+ exports.WASI_FILESTAT_SET_ATIM_NOW =
+ exports.WASI_FILESTAT_SET_ATIM =
+ exports.WASI_EVENTTYPE_FD_WRITE =
+ exports.WASI_EVENTTYPE_FD_READ =
+ exports.WASI_EVENTTYPE_CLOCK =
+ exports.WASI_CLOCK_THREAD_CPUTIME_ID =
+ exports.WASI_CLOCK_PROCESS_CPUTIME_ID =
+ exports.WASI_CLOCK_MONOTONIC =
+ exports.WASI_CLOCK_REALTIME =
+ exports.RIGHTS_TTY_INHERITING =
+ exports.RIGHTS_TTY_BASE =
+ exports.RIGHTS_SOCKET_INHERITING =
+ exports.RIGHTS_SOCKET_BASE =
+ exports.RIGHTS_DIRECTORY_INHERITING =
+ exports.RIGHTS_DIRECTORY_BASE =
+ exports.RIGHTS_REGULAR_FILE_INHERITING =
+ void 0;
+ exports.WASI_ESUCCESS = 0;
+ exports.WASI_E2BIG = 1;
+ exports.WASI_EACCES = 2;
+ exports.WASI_EADDRINUSE = 3;
+ exports.WASI_EADDRNOTAVAIL = 4;
+ exports.WASI_EAFNOSUPPORT = 5;
+ exports.WASI_EAGAIN = 6;
+ exports.WASI_EALREADY = 7;
+ exports.WASI_EBADF = 8;
+ exports.WASI_EBADMSG = 9;
+ exports.WASI_EBUSY = 10;
+ exports.WASI_ECANCELED = 11;
+ exports.WASI_ECHILD = 12;
+ exports.WASI_ECONNABORTED = 13;
+ exports.WASI_ECONNREFUSED = 14;
+ exports.WASI_ECONNRESET = 15;
+ exports.WASI_EDEADLK = 16;
+ exports.WASI_EDESTADDRREQ = 17;
+ exports.WASI_EDOM = 18;
+ exports.WASI_EDQUOT = 19;
+ exports.WASI_EEXIST = 20;
+ exports.WASI_EFAULT = 21;
+ exports.WASI_EFBIG = 22;
+ exports.WASI_EHOSTUNREACH = 23;
+ exports.WASI_EIDRM = 24;
+ exports.WASI_EILSEQ = 25;
+ exports.WASI_EINPROGRESS = 26;
+ exports.WASI_EINTR = 27;
+ exports.WASI_EINVAL = 28;
+ exports.WASI_EIO = 29;
+ exports.WASI_EISCONN = 30;
+ exports.WASI_EISDIR = 31;
+ exports.WASI_ELOOP = 32;
+ exports.WASI_EMFILE = 33;
+ exports.WASI_EMLINK = 34;
+ exports.WASI_EMSGSIZE = 35;
+ exports.WASI_EMULTIHOP = 36;
+ exports.WASI_ENAMETOOLONG = 37;
+ exports.WASI_ENETDOWN = 38;
+ exports.WASI_ENETRESET = 39;
+ exports.WASI_ENETUNREACH = 40;
+ exports.WASI_ENFILE = 41;
+ exports.WASI_ENOBUFS = 42;
+ exports.WASI_ENODEV = 43;
+ exports.WASI_ENOENT = 44;
+ exports.WASI_ENOEXEC = 45;
+ exports.WASI_ENOLCK = 46;
+ exports.WASI_ENOLINK = 47;
+ exports.WASI_ENOMEM = 48;
+ exports.WASI_ENOMSG = 49;
+ exports.WASI_ENOPROTOOPT = 50;
+ exports.WASI_ENOSPC = 51;
+ exports.WASI_ENOSYS = 52;
+ exports.WASI_ENOTCONN = 53;
+ exports.WASI_ENOTDIR = 54;
+ exports.WASI_ENOTEMPTY = 55;
+ exports.WASI_ENOTRECOVERABLE = 56;
+ exports.WASI_ENOTSOCK = 57;
+ exports.WASI_ENOTSUP = 58;
+ exports.WASI_ENOTTY = 59;
+ exports.WASI_ENXIO = 60;
+ exports.WASI_EOVERFLOW = 61;
+ exports.WASI_EOWNERDEAD = 62;
+ exports.WASI_EPERM = 63;
+ exports.WASI_EPIPE = 64;
+ exports.WASI_EPROTO = 65;
+ exports.WASI_EPROTONOSUPPORT = 66;
+ exports.WASI_EPROTOTYPE = 67;
+ exports.WASI_ERANGE = 68;
+ exports.WASI_EROFS = 69;
+ exports.WASI_ESPIPE = 70;
+ exports.WASI_ESRCH = 71;
+ exports.WASI_ESTALE = 72;
+ exports.WASI_ETIMEDOUT = 73;
+ exports.WASI_ETXTBSY = 74;
+ exports.WASI_EXDEV = 75;
+ exports.WASI_ENOTCAPABLE = 76;
+ exports.WASI_SIGABRT = 0;
+ exports.WASI_SIGALRM = 1;
+ exports.WASI_SIGBUS = 2;
+ exports.WASI_SIGCHLD = 3;
+ exports.WASI_SIGCONT = 4;
+ exports.WASI_SIGFPE = 5;
+ exports.WASI_SIGHUP = 6;
+ exports.WASI_SIGILL = 7;
+ exports.WASI_SIGINT = 8;
+ exports.WASI_SIGKILL = 9;
+ exports.WASI_SIGPIPE = 10;
+ exports.WASI_SIGQUIT = 11;
+ exports.WASI_SIGSEGV = 12;
+ exports.WASI_SIGSTOP = 13;
+ exports.WASI_SIGTERM = 14;
+ exports.WASI_SIGTRAP = 15;
+ exports.WASI_SIGTSTP = 16;
+ exports.WASI_SIGTTIN = 17;
+ exports.WASI_SIGTTOU = 18;
+ exports.WASI_SIGURG = 19;
+ exports.WASI_SIGUSR1 = 20;
+ exports.WASI_SIGUSR2 = 21;
+ exports.WASI_SIGVTALRM = 22;
+ exports.WASI_SIGXCPU = 23;
+ exports.WASI_SIGXFSZ = 24;
+ exports.WASI_FILETYPE_UNKNOWN = 0;
+ exports.WASI_FILETYPE_BLOCK_DEVICE = 1;
+ exports.WASI_FILETYPE_CHARACTER_DEVICE = 2;
+ exports.WASI_FILETYPE_DIRECTORY = 3;
+ exports.WASI_FILETYPE_REGULAR_FILE = 4;
+ exports.WASI_FILETYPE_SOCKET_DGRAM = 5;
+ exports.WASI_FILETYPE_SOCKET_STREAM = 6;
+ exports.WASI_FILETYPE_SYMBOLIC_LINK = 7;
+ exports.WASI_FDFLAG_APPEND = 1;
+ exports.WASI_FDFLAG_DSYNC = 2;
+ exports.WASI_FDFLAG_NONBLOCK = 4;
+ exports.WASI_FDFLAG_RSYNC = 8;
+ exports.WASI_FDFLAG_SYNC = 16;
+ exports.WASI_RIGHT_FD_DATASYNC = BigInt(1);
+ exports.WASI_RIGHT_FD_READ = BigInt(2);
+ exports.WASI_RIGHT_FD_SEEK = BigInt(4);
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS = BigInt(8);
+ exports.WASI_RIGHT_FD_SYNC = BigInt(16);
+ exports.WASI_RIGHT_FD_TELL = BigInt(32);
+ exports.WASI_RIGHT_FD_WRITE = BigInt(64);
+ exports.WASI_RIGHT_FD_ADVISE = BigInt(128);
+ exports.WASI_RIGHT_FD_ALLOCATE = BigInt(256);
+ exports.WASI_RIGHT_PATH_CREATE_DIRECTORY = BigInt(512);
+ exports.WASI_RIGHT_PATH_CREATE_FILE = BigInt(1024);
+ exports.WASI_RIGHT_PATH_LINK_SOURCE = BigInt(2048);
+ exports.WASI_RIGHT_PATH_LINK_TARGET = BigInt(4096);
+ exports.WASI_RIGHT_PATH_OPEN = BigInt(8192);
+ exports.WASI_RIGHT_FD_READDIR = BigInt(16384);
+ exports.WASI_RIGHT_PATH_READLINK = BigInt(32768);
+ exports.WASI_RIGHT_PATH_RENAME_SOURCE = BigInt(65536);
+ exports.WASI_RIGHT_PATH_RENAME_TARGET = BigInt(131072);
+ exports.WASI_RIGHT_PATH_FILESTAT_GET = BigInt(262144);
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_SIZE = BigInt(524288);
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_TIMES = BigInt(1048576);
+ exports.WASI_RIGHT_FD_FILESTAT_GET = BigInt(2097152);
+ exports.WASI_RIGHT_FD_FILESTAT_SET_SIZE = BigInt(4194304);
+ exports.WASI_RIGHT_FD_FILESTAT_SET_TIMES = BigInt(8388608);
+ exports.WASI_RIGHT_PATH_SYMLINK = BigInt(16777216);
+ exports.WASI_RIGHT_PATH_REMOVE_DIRECTORY = BigInt(33554432);
+ exports.WASI_RIGHT_PATH_UNLINK_FILE = BigInt(67108864);
+ exports.WASI_RIGHT_POLL_FD_READWRITE = BigInt(134217728);
+ exports.WASI_RIGHT_SOCK_SHUTDOWN = BigInt(268435456);
+ exports.RIGHTS_ALL =
+ exports.WASI_RIGHT_FD_DATASYNC |
+ exports.WASI_RIGHT_FD_READ |
+ exports.WASI_RIGHT_FD_SEEK |
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS |
+ exports.WASI_RIGHT_FD_SYNC |
+ exports.WASI_RIGHT_FD_TELL |
+ exports.WASI_RIGHT_FD_WRITE |
+ exports.WASI_RIGHT_FD_ADVISE |
+ exports.WASI_RIGHT_FD_ALLOCATE |
+ exports.WASI_RIGHT_PATH_CREATE_DIRECTORY |
+ exports.WASI_RIGHT_PATH_CREATE_FILE |
+ exports.WASI_RIGHT_PATH_LINK_SOURCE |
+ exports.WASI_RIGHT_PATH_LINK_TARGET |
+ exports.WASI_RIGHT_PATH_OPEN |
+ exports.WASI_RIGHT_FD_READDIR |
+ exports.WASI_RIGHT_PATH_READLINK |
+ exports.WASI_RIGHT_PATH_RENAME_SOURCE |
+ exports.WASI_RIGHT_PATH_RENAME_TARGET |
+ exports.WASI_RIGHT_PATH_FILESTAT_GET |
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_SIZE |
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_TIMES |
+ exports.WASI_RIGHT_FD_FILESTAT_GET |
+ exports.WASI_RIGHT_FD_FILESTAT_SET_TIMES |
+ exports.WASI_RIGHT_FD_FILESTAT_SET_SIZE |
+ exports.WASI_RIGHT_PATH_SYMLINK |
+ exports.WASI_RIGHT_PATH_UNLINK_FILE |
+ exports.WASI_RIGHT_PATH_REMOVE_DIRECTORY |
+ exports.WASI_RIGHT_POLL_FD_READWRITE |
+ exports.WASI_RIGHT_SOCK_SHUTDOWN;
+ exports.RIGHTS_BLOCK_DEVICE_BASE = exports.RIGHTS_ALL;
+ exports.RIGHTS_BLOCK_DEVICE_INHERITING = exports.RIGHTS_ALL;
+ exports.RIGHTS_CHARACTER_DEVICE_BASE = exports.RIGHTS_ALL;
+ exports.RIGHTS_CHARACTER_DEVICE_INHERITING = exports.RIGHTS_ALL;
+ exports.RIGHTS_REGULAR_FILE_BASE =
+ exports.WASI_RIGHT_FD_DATASYNC |
+ exports.WASI_RIGHT_FD_READ |
+ exports.WASI_RIGHT_FD_SEEK |
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS |
+ exports.WASI_RIGHT_FD_SYNC |
+ exports.WASI_RIGHT_FD_TELL |
+ exports.WASI_RIGHT_FD_WRITE |
+ exports.WASI_RIGHT_FD_ADVISE |
+ exports.WASI_RIGHT_FD_ALLOCATE |
+ exports.WASI_RIGHT_FD_FILESTAT_GET |
+ exports.WASI_RIGHT_FD_FILESTAT_SET_SIZE |
+ exports.WASI_RIGHT_FD_FILESTAT_SET_TIMES |
+ exports.WASI_RIGHT_POLL_FD_READWRITE;
+ exports.RIGHTS_REGULAR_FILE_INHERITING = BigInt(0);
+ exports.RIGHTS_DIRECTORY_BASE =
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS |
+ exports.WASI_RIGHT_FD_SYNC |
+ exports.WASI_RIGHT_FD_ADVISE |
+ exports.WASI_RIGHT_PATH_CREATE_DIRECTORY |
+ exports.WASI_RIGHT_PATH_CREATE_FILE |
+ exports.WASI_RIGHT_PATH_LINK_SOURCE |
+ exports.WASI_RIGHT_PATH_LINK_TARGET |
+ exports.WASI_RIGHT_PATH_OPEN |
+ exports.WASI_RIGHT_FD_READDIR |
+ exports.WASI_RIGHT_PATH_READLINK |
+ exports.WASI_RIGHT_PATH_RENAME_SOURCE |
+ exports.WASI_RIGHT_PATH_RENAME_TARGET |
+ exports.WASI_RIGHT_PATH_FILESTAT_GET |
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_SIZE |
+ exports.WASI_RIGHT_PATH_FILESTAT_SET_TIMES |
+ exports.WASI_RIGHT_FD_FILESTAT_GET |
+ exports.WASI_RIGHT_FD_FILESTAT_SET_TIMES |
+ exports.WASI_RIGHT_PATH_SYMLINK |
+ exports.WASI_RIGHT_PATH_UNLINK_FILE |
+ exports.WASI_RIGHT_PATH_REMOVE_DIRECTORY |
+ exports.WASI_RIGHT_POLL_FD_READWRITE;
+ exports.RIGHTS_DIRECTORY_INHERITING =
+ exports.RIGHTS_DIRECTORY_BASE | exports.RIGHTS_REGULAR_FILE_BASE;
+ exports.RIGHTS_SOCKET_BASE =
+ exports.WASI_RIGHT_FD_READ |
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS |
+ exports.WASI_RIGHT_FD_WRITE |
+ exports.WASI_RIGHT_FD_FILESTAT_GET |
+ exports.WASI_RIGHT_POLL_FD_READWRITE |
+ exports.WASI_RIGHT_SOCK_SHUTDOWN;
+ exports.RIGHTS_SOCKET_INHERITING = exports.RIGHTS_ALL;
+ exports.RIGHTS_TTY_BASE =
+ exports.WASI_RIGHT_FD_READ |
+ exports.WASI_RIGHT_FD_FDSTAT_SET_FLAGS |
+ exports.WASI_RIGHT_FD_WRITE |
+ exports.WASI_RIGHT_FD_FILESTAT_GET |
+ exports.WASI_RIGHT_POLL_FD_READWRITE;
+ exports.RIGHTS_TTY_INHERITING = BigInt(0);
+ exports.WASI_CLOCK_REALTIME = 0;
+ exports.WASI_CLOCK_MONOTONIC = 1;
+ exports.WASI_CLOCK_PROCESS_CPUTIME_ID = 2;
+ exports.WASI_CLOCK_THREAD_CPUTIME_ID = 3;
+ exports.WASI_EVENTTYPE_CLOCK = 0;
+ exports.WASI_EVENTTYPE_FD_READ = 1;
+ exports.WASI_EVENTTYPE_FD_WRITE = 2;
+ exports.WASI_FILESTAT_SET_ATIM = 1 << 0;
+ exports.WASI_FILESTAT_SET_ATIM_NOW = 1 << 1;
+ exports.WASI_FILESTAT_SET_MTIM = 1 << 2;
+ exports.WASI_FILESTAT_SET_MTIM_NOW = 1 << 3;
+ exports.WASI_O_CREAT = 1 << 0;
+ exports.WASI_O_DIRECTORY = 1 << 1;
+ exports.WASI_O_EXCL = 1 << 2;
+ exports.WASI_O_TRUNC = 1 << 3;
+ exports.WASI_PREOPENTYPE_DIR = 0;
+ exports.WASI_DIRCOOKIE_START = 0;
+ exports.WASI_STDIN_FILENO = 0;
+ exports.WASI_STDOUT_FILENO = 1;
+ exports.WASI_STDERR_FILENO = 2;
+ exports.WASI_WHENCE_SET = 0;
+ exports.WASI_WHENCE_CUR = 1;
+ exports.WASI_WHENCE_END = 2;
+ exports.ERROR_MAP = {
+ E2BIG: exports.WASI_E2BIG,
+ EACCES: exports.WASI_EACCES,
+ EADDRINUSE: exports.WASI_EADDRINUSE,
+ EADDRNOTAVAIL: exports.WASI_EADDRNOTAVAIL,
+ EAFNOSUPPORT: exports.WASI_EAFNOSUPPORT,
+ EALREADY: exports.WASI_EALREADY,
+ EAGAIN: exports.WASI_EAGAIN,
+ EBADF: exports.WASI_EBADF,
+ EBADMSG: exports.WASI_EBADMSG,
+ EBUSY: exports.WASI_EBUSY,
+ ECANCELED: exports.WASI_ECANCELED,
+ ECHILD: exports.WASI_ECHILD,
+ ECONNABORTED: exports.WASI_ECONNABORTED,
+ ECONNREFUSED: exports.WASI_ECONNREFUSED,
+ ECONNRESET: exports.WASI_ECONNRESET,
+ EDEADLOCK: exports.WASI_EDEADLK,
+ EDESTADDRREQ: exports.WASI_EDESTADDRREQ,
+ EDOM: exports.WASI_EDOM,
+ EDQUOT: exports.WASI_EDQUOT,
+ EEXIST: exports.WASI_EEXIST,
+ EFAULT: exports.WASI_EFAULT,
+ EFBIG: exports.WASI_EFBIG,
+ EHOSTDOWN: exports.WASI_EHOSTUNREACH,
+ EHOSTUNREACH: exports.WASI_EHOSTUNREACH,
+ EIDRM: exports.WASI_EIDRM,
+ EILSEQ: exports.WASI_EILSEQ,
+ EINPROGRESS: exports.WASI_EINPROGRESS,
+ EINTR: exports.WASI_EINTR,
+ EINVAL: exports.WASI_EINVAL,
+ EIO: exports.WASI_EIO,
+ EISCONN: exports.WASI_EISCONN,
+ EISDIR: exports.WASI_EISDIR,
+ ELOOP: exports.WASI_ELOOP,
+ EMFILE: exports.WASI_EMFILE,
+ EMLINK: exports.WASI_EMLINK,
+ EMSGSIZE: exports.WASI_EMSGSIZE,
+ EMULTIHOP: exports.WASI_EMULTIHOP,
+ ENAMETOOLONG: exports.WASI_ENAMETOOLONG,
+ ENETDOWN: exports.WASI_ENETDOWN,
+ ENETRESET: exports.WASI_ENETRESET,
+ ENETUNREACH: exports.WASI_ENETUNREACH,
+ ENFILE: exports.WASI_ENFILE,
+ ENOBUFS: exports.WASI_ENOBUFS,
+ ENODEV: exports.WASI_ENODEV,
+ ENOENT: exports.WASI_ENOENT,
+ ENOEXEC: exports.WASI_ENOEXEC,
+ ENOLCK: exports.WASI_ENOLCK,
+ ENOLINK: exports.WASI_ENOLINK,
+ ENOMEM: exports.WASI_ENOMEM,
+ ENOMSG: exports.WASI_ENOMSG,
+ ENOPROTOOPT: exports.WASI_ENOPROTOOPT,
+ ENOSPC: exports.WASI_ENOSPC,
+ ENOSYS: exports.WASI_ENOSYS,
+ ENOTCONN: exports.WASI_ENOTCONN,
+ ENOTDIR: exports.WASI_ENOTDIR,
+ ENOTEMPTY: exports.WASI_ENOTEMPTY,
+ ENOTRECOVERABLE: exports.WASI_ENOTRECOVERABLE,
+ ENOTSOCK: exports.WASI_ENOTSOCK,
+ ENOTTY: exports.WASI_ENOTTY,
+ ENXIO: exports.WASI_ENXIO,
+ EOVERFLOW: exports.WASI_EOVERFLOW,
+ EOWNERDEAD: exports.WASI_EOWNERDEAD,
+ EPERM: exports.WASI_EPERM,
+ EPIPE: exports.WASI_EPIPE,
+ EPROTO: exports.WASI_EPROTO,
+ EPROTONOSUPPORT: exports.WASI_EPROTONOSUPPORT,
+ EPROTOTYPE: exports.WASI_EPROTOTYPE,
+ ERANGE: exports.WASI_ERANGE,
+ EROFS: exports.WASI_EROFS,
+ ESPIPE: exports.WASI_ESPIPE,
+ ESRCH: exports.WASI_ESRCH,
+ ESTALE: exports.WASI_ESTALE,
+ ETIMEDOUT: exports.WASI_ETIMEDOUT,
+ ETXTBSY: exports.WASI_ETXTBSY,
+ EXDEV: exports.WASI_EXDEV,
+ };
+ exports.SIGNAL_MAP = {
+ [exports.WASI_SIGHUP]: "SIGHUP",
+ [exports.WASI_SIGINT]: "SIGINT",
+ [exports.WASI_SIGQUIT]: "SIGQUIT",
+ [exports.WASI_SIGILL]: "SIGILL",
+ [exports.WASI_SIGTRAP]: "SIGTRAP",
+ [exports.WASI_SIGABRT]: "SIGABRT",
+ [exports.WASI_SIGBUS]: "SIGBUS",
+ [exports.WASI_SIGFPE]: "SIGFPE",
+ [exports.WASI_SIGKILL]: "SIGKILL",
+ [exports.WASI_SIGUSR1]: "SIGUSR1",
+ [exports.WASI_SIGSEGV]: "SIGSEGV",
+ [exports.WASI_SIGUSR2]: "SIGUSR2",
+ [exports.WASI_SIGPIPE]: "SIGPIPE",
+ [exports.WASI_SIGALRM]: "SIGALRM",
+ [exports.WASI_SIGTERM]: "SIGTERM",
+ [exports.WASI_SIGCHLD]: "SIGCHLD",
+ [exports.WASI_SIGCONT]: "SIGCONT",
+ [exports.WASI_SIGSTOP]: "SIGSTOP",
+ [exports.WASI_SIGTSTP]: "SIGTSTP",
+ [exports.WASI_SIGTTIN]: "SIGTTIN",
+ [exports.WASI_SIGTTOU]: "SIGTTOU",
+ [exports.WASI_SIGURG]: "SIGURG",
+ [exports.WASI_SIGXCPU]: "SIGXCPU",
+ [exports.WASI_SIGXFSZ]: "SIGXFSZ",
+ [exports.WASI_SIGVTALRM]: "SIGVTALRM",
+ };
+ },
+});
+
+// node_modules/wasi-js/dist/wasi.js
+var require_wasi = __commonJS({
+ "node_modules/wasi-js/dist/wasi.js"(exports) {
+ var __importDefault =
+ (exports && exports.__importDefault) ||
+ function (mod) {
+ return mod && mod.__esModule ? mod : { default: mod };
+ };
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.SOCKET_DEFAULT_RIGHTS = void 0;
+ var log = () => {};
+ var logOpen = () => {};
+ var SC_OPEN_MAX = 32768;
+ var types_1 = require_types();
+
+ var constants_1 = require_constants();
+ var STDIN_DEFAULT_RIGHTS =
+ constants_1.WASI_RIGHT_FD_DATASYNC |
+ constants_1.WASI_RIGHT_FD_READ |
+ constants_1.WASI_RIGHT_FD_SYNC |
+ constants_1.WASI_RIGHT_FD_ADVISE |
+ constants_1.WASI_RIGHT_FD_FILESTAT_GET |
+ constants_1.WASI_RIGHT_POLL_FD_READWRITE;
+ var STDOUT_DEFAULT_RIGHTS =
+ constants_1.WASI_RIGHT_FD_DATASYNC |
+ constants_1.WASI_RIGHT_FD_WRITE |
+ constants_1.WASI_RIGHT_FD_SYNC |
+ constants_1.WASI_RIGHT_FD_ADVISE |
+ constants_1.WASI_RIGHT_FD_FILESTAT_GET |
+ constants_1.WASI_RIGHT_POLL_FD_READWRITE;
+ var STDERR_DEFAULT_RIGHTS = STDOUT_DEFAULT_RIGHTS;
+ exports.SOCKET_DEFAULT_RIGHTS =
+ constants_1.WASI_RIGHT_FD_DATASYNC |
+ constants_1.WASI_RIGHT_FD_READ |
+ constants_1.WASI_RIGHT_FD_WRITE |
+ constants_1.WASI_RIGHT_FD_ADVISE |
+ constants_1.WASI_RIGHT_FD_FILESTAT_GET |
+ constants_1.WASI_RIGHT_POLL_FD_READWRITE |
+ constants_1.WASI_RIGHT_FD_FDSTAT_SET_FLAGS;
+ var msToNs = (ms) => {
+ const msInt = Math.trunc(ms);
+ const decimal = BigInt(Math.round((ms - msInt) * 1e6));
+ const ns = BigInt(msInt) * BigInt(1e6);
+ return ns + decimal;
+ };
+ var nsToMs = (ns) => {
+ if (typeof ns === "number") {
+ ns = Math.trunc(ns);
+ }
+ const nsInt = BigInt(ns);
+ return Number(nsInt / BigInt(1e6));
+ };
+ var wrap =
+ (f) =>
+ (...args) => {
+ try {
+ return f(...args);
+ } catch (err) {
+ let e = err;
+ while (e.prev != null) {
+ e = e.prev;
+ }
+ if (e?.code && typeof e?.code === "string") {
+ return constants_1.ERROR_MAP[e.code] || constants_1.WASI_EINVAL;
+ }
+ if (e instanceof types_1.WASIError) {
+ return e.errno;
+ }
+ throw e;
+ }
+ };
+ var stat = (wasi, fd) => {
+ const entry = wasi.FD_MAP.get(fd);
+ if (!entry) {
+ throw new types_1.WASIError(constants_1.WASI_EBADF);
+ }
+ if (entry.filetype === void 0) {
+ const stats = wasi.fstatSync(entry.real);
+ const { filetype, rightsBase, rightsInheriting } =
+ translateFileAttributes(wasi, fd, stats);
+ entry.filetype = filetype;
+ if (!entry.rights) {
+ entry.rights = {
+ base: rightsBase,
+ inheriting: rightsInheriting,
+ };
+ }
+ }
+ return entry;
+ };
+ var translateFileAttributes = (wasi, fd, stats) => {
+ switch (true) {
+ case stats.isBlockDevice():
+ return {
+ filetype: constants_1.WASI_FILETYPE_BLOCK_DEVICE,
+ rightsBase: constants_1.RIGHTS_BLOCK_DEVICE_BASE,
+ rightsInheriting: constants_1.RIGHTS_BLOCK_DEVICE_INHERITING,
+ };
+ case stats.isCharacterDevice(): {
+ const filetype = constants_1.WASI_FILETYPE_CHARACTER_DEVICE;
+ if (fd !== void 0 && wasi.bindings.isTTY(fd)) {
+ return {
+ filetype,
+ rightsBase: constants_1.RIGHTS_TTY_BASE,
+ rightsInheriting: constants_1.RIGHTS_TTY_INHERITING,
+ };
+ }
+ return {
+ filetype,
+ rightsBase: constants_1.RIGHTS_CHARACTER_DEVICE_BASE,
+ rightsInheriting: constants_1.RIGHTS_CHARACTER_DEVICE_INHERITING,
+ };
+ }
+ case stats.isDirectory():
+ return {
+ filetype: constants_1.WASI_FILETYPE_DIRECTORY,
+ rightsBase: constants_1.RIGHTS_DIRECTORY_BASE,
+ rightsInheriting: constants_1.RIGHTS_DIRECTORY_INHERITING,
+ };
+ case stats.isFIFO():
+ return {
+ filetype: constants_1.WASI_FILETYPE_SOCKET_STREAM,
+ rightsBase: constants_1.RIGHTS_SOCKET_BASE,
+ rightsInheriting: constants_1.RIGHTS_SOCKET_INHERITING,
+ };
+ case stats.isFile():
+ return {
+ filetype: constants_1.WASI_FILETYPE_REGULAR_FILE,
+ rightsBase: constants_1.RIGHTS_REGULAR_FILE_BASE,
+ rightsInheriting: constants_1.RIGHTS_REGULAR_FILE_INHERITING,
+ };
+ case stats.isSocket():
+ return {
+ filetype: constants_1.WASI_FILETYPE_SOCKET_STREAM,
+ rightsBase: constants_1.RIGHTS_SOCKET_BASE,
+ rightsInheriting: constants_1.RIGHTS_SOCKET_INHERITING,
+ };
+ case stats.isSymbolicLink():
+ return {
+ filetype: constants_1.WASI_FILETYPE_SYMBOLIC_LINK,
+ rightsBase: BigInt(0),
+ rightsInheriting: BigInt(0),
+ };
+ default:
+ return {
+ filetype: constants_1.WASI_FILETYPE_UNKNOWN,
+ rightsBase: BigInt(0),
+ rightsInheriting: BigInt(0),
+ };
+ }
+ };
+ var warnedAboutSleep = false;
+
+ var defaultConfig;
+ function getDefaults() {
+ if (defaultConfig) return defaultConfig;
+
+ const defaultBindings = {
+ hrtime: () => process.hrtime.bigint(),
+ exit: (code) => {
+ process.exit(code);
+ },
+ kill: (signal) => {
+ process.kill(process.pid, signal);
+ },
+ randomFillSync: (array) => crypto.getRandomValues(array),
+ isTTY: (fd) => import.meta.require("node:tty").isatty(fd),
+ fs: Bun.fs(),
+ path: import.meta.require("node:path"),
+ };
+
+ return (defaultConfig = {
+ args: [],
+ env: {},
+ preopens: {},
+ bindings: defaultBindings,
+ sleep: (ms) => {
+ Bun.sleepSync(ms);
+ },
+ });
+ }
+
+ var WASI = class WASI {
+ constructor(wasiConfig = {}) {
+ const defaultConfig = getDefaults();
+ this.lastStdin = 0;
+ this.sleep = wasiConfig.sleep || defaultConfig.sleep;
+ this.getStdin = wasiConfig.getStdin;
+ this.sendStdout = wasiConfig.sendStdout;
+ this.sendStderr = wasiConfig.sendStderr;
+ let preopens = wasiConfig.preopens ?? defaultConfig.preopens;
+ this.env = wasiConfig.env ?? defaultConfig.env;
+
+ const args = wasiConfig.args ?? defaultConfig.args;
+ this.memory = void 0;
+ this.view = void 0;
+ this.bindings = wasiConfig.bindings || defaultConfig.bindings;
+ const bindings = this.bindings;
+ const fs = bindings.fs;
+ this.FD_MAP = /* @__PURE__ */ new Map([
+ [
+ constants_1.WASI_STDIN_FILENO,
+ {
+ real: 0,
+ filetype: constants_1.WASI_FILETYPE_CHARACTER_DEVICE,
+ rights: {
+ base: STDIN_DEFAULT_RIGHTS,
+ inheriting: BigInt(0),
+ },
+ path: "/dev/stdin",
+ },
+ ],
+ [
+ constants_1.WASI_STDOUT_FILENO,
+ {
+ real: 1,
+ filetype: constants_1.WASI_FILETYPE_CHARACTER_DEVICE,
+ rights: {
+ base: STDOUT_DEFAULT_RIGHTS,
+ inheriting: BigInt(0),
+ },
+ path: "/dev/stdout",
+ },
+ ],
+ [
+ constants_1.WASI_STDERR_FILENO,
+ {
+ real: 2,
+ filetype: constants_1.WASI_FILETYPE_CHARACTER_DEVICE,
+ rights: {
+ base: STDERR_DEFAULT_RIGHTS,
+ inheriting: BigInt(0),
+ },
+ path: "/dev/stderr",
+ },
+ ],
+ ]);
+ const path = bindings.path;
+ for (const [k, v] of Object.entries(preopens)) {
+ const real = fs.openSync(v, nodeFsConstants.O_RDONLY);
+ const newfd = this.getUnusedFileDescriptor();
+ this.FD_MAP.set(newfd, {
+ real,
+ filetype: constants_1.WASI_FILETYPE_DIRECTORY,
+ rights: {
+ base: constants_1.RIGHTS_DIRECTORY_BASE,
+ inheriting: constants_1.RIGHTS_DIRECTORY_INHERITING,
+ },
+ fakePath: k,
+ path: v,
+ });
+ }
+ const getiovs = (iovs, iovsLen) => {
+ this.refreshMemory();
+
+ const { view, memory } = this;
+ const { buffer } = memory;
+ const { byteLength } = buffer;
+
+ if (iovsLen === 1) {
+ const ptr = iovs;
+ const buf = view.getUint32(ptr, true);
+ let bufLen = view.getUint32(ptr + 4, true);
+
+ if (bufLen > byteLength - buf) {
+ console.log({
+ buf,
+ bufLen,
+ total_memory: byteLength,
+ });
+ log("getiovs: warning -- truncating buffer to fit in memory");
+ bufLen = Math.min(bufLen, Math.max(0, byteLength - buf));
+ }
+ try {
+ return [new Uint8Array(buffer, buf, bufLen)];
+ } catch (err) {
+ console.warn("WASI.getiovs -- invalid buffer", err);
+ throw new types_1.WASIError(constants_1.WASI_EINVAL);
+ }
+ }
+
+ // Avoid referencing Array because materializing the Array constructor can show up in profiling
+ const buffers = [];
+ buffers.length = iovsLen;
+
+ for (let i = 0, ptr = iovs; i < iovsLen; i++, ptr += 8) {
+ const buf = view.getUint32(ptr, true);
+ let bufLen = view.getUint32(ptr + 4, true);
+
+ if (bufLen > byteLength - buf) {
+ console.log({
+ buf,
+ bufLen,
+ total_memory: byteLength,
+ });
+ log("getiovs: warning -- truncating buffer to fit in memory");
+ bufLen = Math.min(bufLen, Math.max(0, byteLength - buf));
+ }
+ try {
+ buffers[i] = new Uint8Array(buffer, buf, bufLen);
+ } catch (err) {
+ console.warn("WASI.getiovs -- invalid buffer", err);
+ throw new types_1.WASIError(constants_1.WASI_EINVAL);
+ }
+ }
+ return buffers;
+ };
+ const CHECK_FD = (fd, rights) => {
+ const stats = stat(this, fd);
+ if (
+ rights !== BigInt(0) &&
+ (stats.rights.base & rights) === BigInt(0)
+ ) {
+ throw new types_1.WASIError(constants_1.WASI_EPERM);
+ }
+ return stats;
+ };
+ const CPUTIME_START = bindings.hrtime();
+ const now = (clockId) => {
+ switch (clockId) {
+ case constants_1.WASI_CLOCK_MONOTONIC:
+ return bindings.hrtime();
+ case constants_1.WASI_CLOCK_REALTIME:
+ return msToNs(Date.now());
+ case constants_1.WASI_CLOCK_PROCESS_CPUTIME_ID:
+ case constants_1.WASI_CLOCK_THREAD_CPUTIME_ID:
+ return bindings.hrtime() - CPUTIME_START;
+ default:
+ return null;
+ }
+ };
+ this.wasiImport = {
+ args_get: (argv, argvBuf) => {
+ this.refreshMemory();
+ let coffset = argv;
+ let offset = argvBuf;
+ args.forEach((a) => {
+ this.view.setUint32(coffset, offset, true);
+ coffset += 4;
+ offset += Buffer.from(this.memory.buffer).write(`${a}\0`, offset);
+ });
+ return constants_1.WASI_ESUCCESS;
+ },
+ args_sizes_get: (argc, argvBufSize) => {
+ this.refreshMemory();
+ this.view.setUint32(argc, args.length, true);
+ const size = args.reduce(
+ (acc, a) => acc + Buffer.byteLength(a) + 1,
+ 0,
+ );
+ this.view.setUint32(argvBufSize, size, true);
+ return constants_1.WASI_ESUCCESS;
+ },
+ environ_get: (environ, environBuf) => {
+ this.refreshMemory();
+ let coffset = environ;
+ let offset = environBuf;
+ Object.entries(this.env).forEach(([key, value]) => {
+ this.view.setUint32(coffset, offset, true);
+ coffset += 4;
+ offset += Buffer.from(this.memory.buffer).write(
+ `${key}=${value}\0`,
+ offset,
+ );
+ });
+ return constants_1.WASI_ESUCCESS;
+ },
+ environ_sizes_get: (environCount, environBufSize) => {
+ this.refreshMemory();
+ const envProcessed = Object.entries(this.env).map(
+ ([key, value]) => `${key}=${value}\0`,
+ );
+ const size = envProcessed.reduce(
+ (acc, e) => acc + Buffer.byteLength(e),
+ 0,
+ );
+ this.view.setUint32(environCount, envProcessed.length, true);
+ this.view.setUint32(environBufSize, size, true);
+ return constants_1.WASI_ESUCCESS;
+ },
+ clock_res_get: (clockId, resolution) => {
+ let res;
+ switch (clockId) {
+ case constants_1.WASI_CLOCK_MONOTONIC:
+ case constants_1.WASI_CLOCK_PROCESS_CPUTIME_ID:
+ case constants_1.WASI_CLOCK_THREAD_CPUTIME_ID: {
+ res = BigInt(1);
+ break;
+ }
+ case constants_1.WASI_CLOCK_REALTIME: {
+ res = BigInt(1e3);
+ break;
+ }
+ }
+ if (!res) {
+ throw Error("invalid clockId");
+ }
+ this.view.setBigUint64(resolution, res);
+ return constants_1.WASI_ESUCCESS;
+ },
+ clock_time_get: (clockId, _precision, time) => {
+ this.refreshMemory();
+ const n = now(clockId);
+ if (n === null) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.view.setBigUint64(time, BigInt(n), true);
+ return constants_1.WASI_ESUCCESS;
+ },
+ fd_advise: wrap((fd, _offset, _len, _advice) => {
+ CHECK_FD(fd, constants_1.WASI_RIGHT_FD_ADVISE);
+ return constants_1.WASI_ENOSYS;
+ }),
+ fd_allocate: wrap((fd, _offset, _len) => {
+ CHECK_FD(fd, constants_1.WASI_RIGHT_FD_ALLOCATE);
+ return constants_1.WASI_ENOSYS;
+ }),
+ fd_close: wrap((fd) => {
+ const stats = CHECK_FD(fd, BigInt(0));
+ fs.closeSync(stats.real);
+ this.FD_MAP.delete(fd);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_datasync: wrap((fd) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_DATASYNC);
+ fs.fdatasyncSync(stats.real);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_fdstat_get: wrap((fd, bufPtr) => {
+ const stats = CHECK_FD(fd, BigInt(0));
+ this.refreshMemory();
+ if (stats.filetype == null) {
+ throw Error("stats.filetype must be set");
+ }
+ this.view.setUint8(bufPtr, stats.filetype);
+ this.view.setUint16(bufPtr + 2, 0, true);
+ this.view.setUint16(bufPtr + 4, 0, true);
+ this.view.setBigUint64(bufPtr + 8, BigInt(stats.rights.base), true);
+ this.view.setBigUint64(
+ bufPtr + 8 + 8,
+ BigInt(stats.rights.inheriting),
+ true,
+ );
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_fdstat_set_flags: wrap((fd, flags) => {
+ CHECK_FD(fd, constants_1.WASI_RIGHT_FD_FDSTAT_SET_FLAGS);
+ if (this.wasiImport.sock_fcntlSetFlags(fd, flags) == 0) {
+ return constants_1.WASI_ESUCCESS;
+ }
+ return constants_1.WASI_ENOSYS;
+ }),
+ fd_fdstat_set_rights: wrap((fd, fsRightsBase, fsRightsInheriting) => {
+ const stats = CHECK_FD(fd, BigInt(0));
+ const nrb = stats.rights.base | fsRightsBase;
+ if (nrb > stats.rights.base) {
+ return constants_1.WASI_EPERM;
+ }
+ const nri = stats.rights.inheriting | fsRightsInheriting;
+ if (nri > stats.rights.inheriting) {
+ return constants_1.WASI_EPERM;
+ }
+ stats.rights.base = fsRightsBase;
+ stats.rights.inheriting = fsRightsInheriting;
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_filestat_get: wrap((fd, bufPtr) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_FILESTAT_GET);
+ const rstats = this.fstatSync(stats.real);
+ this.refreshMemory();
+ this.view.setBigUint64(bufPtr, BigInt(rstats.dev), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, BigInt(rstats.ino), true);
+ bufPtr += 8;
+ if (stats.filetype == null) {
+ throw Error("stats.filetype must be set");
+ }
+ this.view.setUint8(bufPtr, stats.filetype);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, BigInt(rstats.nlink), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, BigInt(rstats.size), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, msToNs(rstats.atimeMs), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, msToNs(rstats.mtimeMs), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, msToNs(rstats.ctimeMs), true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_filestat_set_size: wrap((fd, stSize) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_FD_FILESTAT_SET_SIZE,
+ );
+ fs.ftruncateSync(stats.real, Number(stSize));
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_filestat_set_times: wrap((fd, stAtim, stMtim, fstflags) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_FD_FILESTAT_SET_TIMES,
+ );
+ const rstats = this.fstatSync(stats.real);
+ let atim = rstats.atime;
+ let mtim = rstats.mtime;
+ const n = nsToMs(now(constants_1.WASI_CLOCK_REALTIME));
+ const atimflags =
+ constants_1.WASI_FILESTAT_SET_ATIM |
+ constants_1.WASI_FILESTAT_SET_ATIM_NOW;
+ if ((fstflags & atimflags) === atimflags) {
+ return constants_1.WASI_EINVAL;
+ }
+ const mtimflags =
+ constants_1.WASI_FILESTAT_SET_MTIM |
+ constants_1.WASI_FILESTAT_SET_MTIM_NOW;
+ if ((fstflags & mtimflags) === mtimflags) {
+ return constants_1.WASI_EINVAL;
+ }
+ if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_ATIM) ===
+ constants_1.WASI_FILESTAT_SET_ATIM
+ ) {
+ atim = nsToMs(stAtim);
+ } else if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_ATIM_NOW) ===
+ constants_1.WASI_FILESTAT_SET_ATIM_NOW
+ ) {
+ atim = n;
+ }
+ if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_MTIM) ===
+ constants_1.WASI_FILESTAT_SET_MTIM
+ ) {
+ mtim = nsToMs(stMtim);
+ } else if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_MTIM_NOW) ===
+ constants_1.WASI_FILESTAT_SET_MTIM_NOW
+ ) {
+ mtim = n;
+ }
+ fs.futimesSync(stats.real, new Date(atim), new Date(mtim));
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_prestat_get: wrap((fd, bufPtr) => {
+ const stats = CHECK_FD(fd, BigInt(0));
+ this.refreshMemory();
+ this.view.setUint8(bufPtr, constants_1.WASI_PREOPENTYPE_DIR);
+ this.view.setUint32(
+ bufPtr + 4,
+ Buffer.byteLength(stats.fakePath ?? stats.path ?? ""),
+ true,
+ );
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_prestat_dir_name: wrap((fd, pathPtr, pathLen) => {
+ const stats = CHECK_FD(fd, BigInt(0));
+ this.refreshMemory();
+ Buffer.from(this.memory.buffer).write(
+ stats.fakePath ?? stats.path ?? "",
+ pathPtr,
+ pathLen,
+ "utf8",
+ );
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_pwrite: wrap((fd, iovs, iovsLen, offset, nwritten) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_FD_WRITE | constants_1.WASI_RIGHT_FD_SEEK,
+ );
+ let written = 0;
+ getiovs(iovs, iovsLen).forEach((iov) => {
+ let w = 0;
+ while (w < iov.byteLength) {
+ w += fs.writeSync(
+ stats.real,
+ iov,
+ w,
+ iov.byteLength - w,
+ Number(offset) + written + w,
+ );
+ }
+ written += w;
+ });
+ this.view.setUint32(nwritten, written, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_write: wrap((fd, iovs, iovsLen, nwritten) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_WRITE);
+ const IS_STDOUT = fd == constants_1.WASI_STDOUT_FILENO;
+ const IS_STDERR = fd == constants_1.WASI_STDERR_FILENO;
+ let written = 0;
+ getiovs(iovs, iovsLen).forEach((iov) => {
+ if (iov.byteLength == 0) return;
+ if (IS_STDOUT && this.sendStdout != null) {
+ this.sendStdout(iov);
+ written += iov.byteLength;
+ } else if (IS_STDERR && this.sendStderr != null) {
+ this.sendStderr(iov);
+ written += iov.byteLength;
+ } else {
+ let w = 0;
+ while (w < iov.byteLength) {
+ const i = fs.writeSync(
+ stats.real,
+ iov,
+ w,
+ iov.byteLength - w,
+ stats.offset ? Number(stats.offset) : null,
+ );
+ if (stats.offset) stats.offset += BigInt(i);
+ w += i;
+ }
+ written += w;
+ }
+ });
+ this.view.setUint32(nwritten, written, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_pread: wrap((fd, iovs, iovsLen, offset, nread) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_FD_READ | constants_1.WASI_RIGHT_FD_SEEK,
+ );
+ let read = 0;
+ outer: for (const iov of getiovs(iovs, iovsLen)) {
+ let r = 0;
+ while (r < iov.byteLength) {
+ const length = iov.byteLength - r;
+ const rr = fs.readSync(
+ stats.real,
+ iov,
+ r,
+ iov.byteLength - r,
+ Number(offset) + read + r,
+ );
+ r += rr;
+ read += rr;
+ if (rr === 0 || rr < length) {
+ break outer;
+ }
+ }
+ read += r;
+ }
+ this.view.setUint32(nread, read, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_read: wrap((fd, iovs, iovsLen, nread) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_READ);
+ const IS_STDIN = fd == constants_1.WASI_STDIN_FILENO;
+ let read = 0;
+ outer: for (const iov of getiovs(iovs, iovsLen)) {
+ let r = 0;
+ while (r < iov.byteLength) {
+ let length = iov.byteLength - r;
+ let position =
+ IS_STDIN || stats.offset === void 0
+ ? null
+ : Number(stats.offset);
+ let rr = 0;
+ if (IS_STDIN) {
+ if (this.getStdin != null) {
+ if (this.stdinBuffer == null) {
+ this.stdinBuffer = this.getStdin();
+ }
+ if (this.stdinBuffer != null) {
+ rr = this.stdinBuffer.copy(iov);
+ if (rr == this.stdinBuffer.length) {
+ this.stdinBuffer = void 0;
+ } else {
+ this.stdinBuffer = this.stdinBuffer.slice(rr);
+ }
+ if (rr > 0) {
+ this.lastStdin = new Date().valueOf();
+ }
+ }
+ } else {
+ if (this.sleep == null && !warnedAboutSleep) {
+ warnedAboutSleep = true;
+ console.log(
+ "(cpu waiting for stdin: please define a way to sleep!) ",
+ );
+ }
+ try {
+ rr = fs.readSync(stats.real, iov, r, length, position);
+ } catch (_err) {}
+ if (rr == 0) {
+ this.shortPause();
+ } else {
+ this.lastStdin = new Date().valueOf();
+ }
+ }
+ } else {
+ rr = fs.readSync(stats.real, iov, r, length, position);
+ }
+ if (stats.filetype == constants_1.WASI_FILETYPE_REGULAR_FILE) {
+ stats.offset =
+ (stats.offset ? stats.offset : BigInt(0)) + BigInt(rr);
+ }
+ r += rr;
+ read += rr;
+ if (rr === 0 || rr < length) {
+ break outer;
+ }
+ }
+ }
+ this.view.setUint32(nread, read, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_readdir: wrap((fd, bufPtr, bufLen, cookie, bufusedPtr) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_READDIR);
+ this.refreshMemory();
+ const entries = fs.readdirSync(stats.path, { withFileTypes: true });
+ const startPtr = bufPtr;
+ for (let i = Number(cookie); i < entries.length; i += 1) {
+ const entry = entries[i];
+ let nameLength = Buffer.byteLength(entry.name);
+ if (bufPtr - startPtr > bufLen) {
+ break;
+ }
+ this.view.setBigUint64(bufPtr, BigInt(i + 1), true);
+ bufPtr += 8;
+ if (bufPtr - startPtr > bufLen) {
+ break;
+ }
+ const rstats = fs.lstatSync(path.resolve(stats.path, entry.name));
+ this.view.setBigUint64(bufPtr, BigInt(rstats.ino), true);
+ bufPtr += 8;
+ if (bufPtr - startPtr > bufLen) {
+ break;
+ }
+ this.view.setUint32(bufPtr, nameLength, true);
+ bufPtr += 4;
+ if (bufPtr - startPtr > bufLen) {
+ break;
+ }
+ let filetype;
+ switch (true) {
+ case rstats.isBlockDevice():
+ filetype = constants_1.WASI_FILETYPE_BLOCK_DEVICE;
+ break;
+ case rstats.isCharacterDevice():
+ filetype = constants_1.WASI_FILETYPE_CHARACTER_DEVICE;
+ break;
+ case rstats.isDirectory():
+ filetype = constants_1.WASI_FILETYPE_DIRECTORY;
+ break;
+ case rstats.isFIFO():
+ filetype = constants_1.WASI_FILETYPE_SOCKET_STREAM;
+ break;
+ case rstats.isFile():
+ filetype = constants_1.WASI_FILETYPE_REGULAR_FILE;
+ break;
+ case rstats.isSocket():
+ filetype = constants_1.WASI_FILETYPE_SOCKET_STREAM;
+ break;
+ case rstats.isSymbolicLink():
+ filetype = constants_1.WASI_FILETYPE_SYMBOLIC_LINK;
+ break;
+ default:
+ filetype = constants_1.WASI_FILETYPE_UNKNOWN;
+ break;
+ }
+ this.view.setUint8(bufPtr, filetype);
+ bufPtr += 1;
+ bufPtr += 3;
+ if (bufPtr + nameLength >= startPtr + bufLen) {
+ break;
+ }
+ let memory_buffer = Buffer.from(this.memory.buffer);
+ memory_buffer.write(entry.name, bufPtr);
+ bufPtr += nameLength;
+ }
+ const bufused = bufPtr - startPtr;
+ this.view.setUint32(bufusedPtr, Math.min(bufused, bufLen), true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_renumber: wrap((from, to) => {
+ CHECK_FD(from, BigInt(0));
+ CHECK_FD(to, BigInt(0));
+ fs.closeSync(this.FD_MAP.get(from).real);
+ this.FD_MAP.set(from, this.FD_MAP.get(to));
+ this.FD_MAP.delete(to);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_seek: wrap((fd, offset, whence, newOffsetPtr) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_SEEK);
+ this.refreshMemory();
+ switch (whence) {
+ case constants_1.WASI_WHENCE_CUR:
+ stats.offset =
+ (stats.offset ? stats.offset : BigInt(0)) + BigInt(offset);
+ break;
+ case constants_1.WASI_WHENCE_END:
+ const { size } = this.fstatSync(stats.real);
+ stats.offset = BigInt(size) + BigInt(offset);
+ break;
+ case constants_1.WASI_WHENCE_SET:
+ stats.offset = BigInt(offset);
+ break;
+ }
+ if (stats.offset == null) {
+ throw Error("stats.offset must be defined");
+ }
+ this.view.setBigUint64(newOffsetPtr, stats.offset, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_tell: wrap((fd, offsetPtr) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_TELL);
+ this.refreshMemory();
+ if (!stats.offset) {
+ stats.offset = BigInt(0);
+ }
+ this.view.setBigUint64(offsetPtr, stats.offset, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ fd_sync: wrap((fd) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_FD_SYNC);
+ fs.fsyncSync(stats.real);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ path_create_directory: wrap((fd, pathPtr, pathLen) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_PATH_CREATE_DIRECTORY,
+ );
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ fs.mkdirSync(path.resolve(stats.path, p));
+ return constants_1.WASI_ESUCCESS;
+ }),
+ path_filestat_get: wrap((fd, flags, pathPtr, pathLen, bufPtr) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_PATH_FILESTAT_GET,
+ );
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ let rstats;
+ if (flags) {
+ rstats = fs.statSync(path.resolve(stats.path, p));
+ } else {
+ rstats = fs.lstatSync(path.resolve(stats.path, p));
+ }
+ this.view.setBigUint64(bufPtr, BigInt(rstats.dev), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, BigInt(rstats.ino), true);
+ bufPtr += 8;
+ this.view.setUint8(
+ bufPtr,
+ translateFileAttributes(this, void 0, rstats).filetype,
+ );
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, BigInt(rstats.nlink), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, BigInt(rstats.size), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, msToNs(rstats.atimeMs), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, msToNs(rstats.mtimeMs), true);
+ bufPtr += 8;
+ this.view.setBigUint64(bufPtr, msToNs(rstats.ctimeMs), true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ path_filestat_set_times: wrap(
+ (fd, _dirflags, pathPtr, pathLen, stAtim, stMtim, fstflags) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_PATH_FILESTAT_SET_TIMES,
+ );
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const rstats = this.fstatSync(stats.real);
+ let atim = rstats.atime;
+ let mtim = rstats.mtime;
+ const n = nsToMs(now(constants_1.WASI_CLOCK_REALTIME));
+ const atimflags =
+ constants_1.WASI_FILESTAT_SET_ATIM |
+ constants_1.WASI_FILESTAT_SET_ATIM_NOW;
+ if ((fstflags & atimflags) === atimflags) {
+ return constants_1.WASI_EINVAL;
+ }
+ const mtimflags =
+ constants_1.WASI_FILESTAT_SET_MTIM |
+ constants_1.WASI_FILESTAT_SET_MTIM_NOW;
+ if ((fstflags & mtimflags) === mtimflags) {
+ return constants_1.WASI_EINVAL;
+ }
+ if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_ATIM) ===
+ constants_1.WASI_FILESTAT_SET_ATIM
+ ) {
+ atim = nsToMs(stAtim);
+ } else if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_ATIM_NOW) ===
+ constants_1.WASI_FILESTAT_SET_ATIM_NOW
+ ) {
+ atim = n;
+ }
+ if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_MTIM) ===
+ constants_1.WASI_FILESTAT_SET_MTIM
+ ) {
+ mtim = nsToMs(stMtim);
+ } else if (
+ (fstflags & constants_1.WASI_FILESTAT_SET_MTIM_NOW) ===
+ constants_1.WASI_FILESTAT_SET_MTIM_NOW
+ ) {
+ mtim = n;
+ }
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ fs.utimesSync(
+ path.resolve(stats.path, p),
+ new Date(atim),
+ new Date(mtim),
+ );
+ return constants_1.WASI_ESUCCESS;
+ },
+ ),
+ path_link: wrap(
+ (
+ oldFd,
+ _oldFlags,
+ oldPath,
+ oldPathLen,
+ newFd,
+ newPath,
+ newPathLen,
+ ) => {
+ const ostats = CHECK_FD(
+ oldFd,
+ constants_1.WASI_RIGHT_PATH_LINK_SOURCE,
+ );
+ const nstats = CHECK_FD(
+ newFd,
+ constants_1.WASI_RIGHT_PATH_LINK_TARGET,
+ );
+ if (!ostats.path || !nstats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const op = Buffer.from(
+ this.memory.buffer,
+ oldPath,
+ oldPathLen,
+ ).toString();
+ const np = Buffer.from(
+ this.memory.buffer,
+ newPath,
+ newPathLen,
+ ).toString();
+ fs.linkSync(
+ path.resolve(ostats.path, op),
+ path.resolve(nstats.path, np),
+ );
+ return constants_1.WASI_ESUCCESS;
+ },
+ ),
+ path_open: wrap(
+ (
+ dirfd,
+ _dirflags,
+ pathPtr,
+ pathLen,
+ oflags,
+ fsRightsBase,
+ fsRightsInheriting,
+ fsFlags,
+ fdPtr,
+ ) => {
+ try {
+ const stats = CHECK_FD(dirfd, constants_1.WASI_RIGHT_PATH_OPEN);
+ fsRightsBase = BigInt(fsRightsBase);
+ fsRightsInheriting = BigInt(fsRightsInheriting);
+ const read =
+ (fsRightsBase &
+ (constants_1.WASI_RIGHT_FD_READ |
+ constants_1.WASI_RIGHT_FD_READDIR)) !==
+ BigInt(0);
+ const write =
+ (fsRightsBase &
+ (constants_1.WASI_RIGHT_FD_DATASYNC |
+ constants_1.WASI_RIGHT_FD_WRITE |
+ constants_1.WASI_RIGHT_FD_ALLOCATE |
+ constants_1.WASI_RIGHT_FD_FILESTAT_SET_SIZE)) !==
+ BigInt(0);
+ let noflags;
+ if (write && read) {
+ noflags = nodeFsConstants.O_RDWR;
+ } else if (read) {
+ noflags = nodeFsConstants.O_RDONLY;
+ } else if (write) {
+ noflags = nodeFsConstants.O_WRONLY;
+ }
+ let neededBase =
+ fsRightsBase | constants_1.WASI_RIGHT_PATH_OPEN;
+ let neededInheriting = fsRightsBase | fsRightsInheriting;
+ if ((oflags & constants_1.WASI_O_CREAT) !== 0) {
+ noflags |= nodeFsConstants.O_CREAT;
+ neededBase |= constants_1.WASI_RIGHT_PATH_CREATE_FILE;
+ }
+ if ((oflags & constants_1.WASI_O_DIRECTORY) !== 0) {
+ noflags |= nodeFsConstants.O_DIRECTORY;
+ }
+ if ((oflags & constants_1.WASI_O_EXCL) !== 0) {
+ noflags |= nodeFsConstants.O_EXCL;
+ }
+ if ((oflags & constants_1.WASI_O_TRUNC) !== 0) {
+ noflags |= nodeFsConstants.O_TRUNC;
+ neededBase |= constants_1.WASI_RIGHT_PATH_FILESTAT_SET_SIZE;
+ }
+ if ((fsFlags & constants_1.WASI_FDFLAG_APPEND) !== 0) {
+ noflags |= nodeFsConstants.O_APPEND;
+ }
+ if ((fsFlags & constants_1.WASI_FDFLAG_DSYNC) !== 0) {
+ if (nodeFsConstants.O_DSYNC) {
+ noflags |= nodeFsConstants.O_DSYNC;
+ } else {
+ noflags |= nodeFsConstants.O_SYNC;
+ }
+ neededInheriting |= constants_1.WASI_RIGHT_FD_DATASYNC;
+ }
+ if ((fsFlags & constants_1.WASI_FDFLAG_NONBLOCK) !== 0) {
+ noflags |= nodeFsConstants.O_NONBLOCK;
+ }
+ if ((fsFlags & constants_1.WASI_FDFLAG_RSYNC) !== 0) {
+ if (nodeFsConstants.O_RSYNC) {
+ noflags |= nodeFsConstants.O_RSYNC;
+ } else {
+ noflags |= nodeFsConstants.O_SYNC;
+ }
+ neededInheriting |= constants_1.WASI_RIGHT_FD_SYNC;
+ }
+ if ((fsFlags & constants_1.WASI_FDFLAG_SYNC) !== 0) {
+ noflags |= nodeFsConstants.O_SYNC;
+ neededInheriting |= constants_1.WASI_RIGHT_FD_SYNC;
+ }
+ if (
+ write &&
+ (noflags &
+ (nodeFsConstants.O_APPEND | nodeFsConstants.O_TRUNC)) ===
+ 0
+ ) {
+ neededInheriting |= constants_1.WASI_RIGHT_FD_SEEK;
+ }
+ this.refreshMemory();
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ if (p == "dev/tty") {
+ this.view.setUint32(
+ fdPtr,
+ constants_1.WASI_STDIN_FILENO,
+ true,
+ );
+ return constants_1.WASI_ESUCCESS;
+ }
+ logOpen("path_open", p);
+ if (p.startsWith("proc/")) {
+ throw new types_1.WASIError(constants_1.WASI_EBADF);
+ }
+ const fullUnresolved = path.resolve(stats.path, p);
+ let full;
+ try {
+ full = fs.realpathSync(fullUnresolved);
+ } catch (e) {
+ if (e?.code === "ENOENT") {
+ full = fullUnresolved;
+ } else {
+ throw e;
+ }
+ }
+ let isDirectory;
+ if (write) {
+ try {
+ isDirectory = fs.statSync(full).isDirectory();
+ } catch (_err) {}
+ }
+ let realfd;
+ if (!write && isDirectory) {
+ realfd = fs.openSync(full, nodeFsConstants.O_RDONLY);
+ } else {
+ realfd = fs.openSync(full, noflags);
+ }
+ const newfd = this.getUnusedFileDescriptor();
+ this.FD_MAP.set(newfd, {
+ real: realfd,
+ filetype: void 0,
+ rights: {
+ base: neededBase,
+ inheriting: neededInheriting,
+ },
+ path: full,
+ });
+ stat(this, newfd);
+ this.view.setUint32(fdPtr, newfd, true);
+ } catch (e) {
+ console.error(e);
+ }
+ return constants_1.WASI_ESUCCESS;
+ },
+ ),
+ path_readlink: wrap((fd, pathPtr, pathLen, buf, bufLen, bufused) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_PATH_READLINK);
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ const full = path.resolve(stats.path, p);
+ const r = fs.readlinkSync(full);
+ const used = Buffer.from(this.memory.buffer).write(r, buf, bufLen);
+ this.view.setUint32(bufused, used, true);
+ return constants_1.WASI_ESUCCESS;
+ }),
+ path_remove_directory: wrap((fd, pathPtr, pathLen) => {
+ const stats = CHECK_FD(
+ fd,
+ constants_1.WASI_RIGHT_PATH_REMOVE_DIRECTORY,
+ );
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ fs.rmdirSync(path.resolve(stats.path, p));
+ return constants_1.WASI_ESUCCESS;
+ }),
+ path_rename: wrap(
+ (oldFd, oldPath, oldPathLen, newFd, newPath, newPathLen) => {
+ const ostats = CHECK_FD(
+ oldFd,
+ constants_1.WASI_RIGHT_PATH_RENAME_SOURCE,
+ );
+ const nstats = CHECK_FD(
+ newFd,
+ constants_1.WASI_RIGHT_PATH_RENAME_TARGET,
+ );
+ if (!ostats.path || !nstats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const op = Buffer.from(
+ this.memory.buffer,
+ oldPath,
+ oldPathLen,
+ ).toString();
+ const np = Buffer.from(
+ this.memory.buffer,
+ newPath,
+ newPathLen,
+ ).toString();
+ fs.renameSync(
+ path.resolve(ostats.path, op),
+ path.resolve(nstats.path, np),
+ );
+ return constants_1.WASI_ESUCCESS;
+ },
+ ),
+ path_symlink: wrap((oldPath, oldPathLen, fd, newPath, newPathLen) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_PATH_SYMLINK);
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const op = Buffer.from(
+ this.memory.buffer,
+ oldPath,
+ oldPathLen,
+ ).toString();
+ const np = Buffer.from(
+ this.memory.buffer,
+ newPath,
+ newPathLen,
+ ).toString();
+ fs.symlinkSync(op, path.resolve(stats.path, np));
+ return constants_1.WASI_ESUCCESS;
+ }),
+ path_unlink_file: wrap((fd, pathPtr, pathLen) => {
+ const stats = CHECK_FD(fd, constants_1.WASI_RIGHT_PATH_UNLINK_FILE);
+ if (!stats.path) {
+ return constants_1.WASI_EINVAL;
+ }
+ this.refreshMemory();
+ const p = Buffer.from(
+ this.memory.buffer,
+ pathPtr,
+ pathLen,
+ ).toString();
+ fs.unlinkSync(path.resolve(stats.path, p));
+ return constants_1.WASI_ESUCCESS;
+ }),
+ poll_oneoff: (sin, sout, nsubscriptions, neventsPtr) => {
+ let nevents = 0;
+ let name = "";
+ let waitTimeNs = BigInt(0);
+ let fd = -1;
+ let fd_type = "read";
+ let fd_timeout_ms = 0;
+ const startNs = BigInt(bindings.hrtime());
+ this.refreshMemory();
+ let last_sin = sin;
+ for (let i = 0; i < nsubscriptions; i += 1) {
+ const userdata = this.view.getBigUint64(sin, true);
+ sin += 8;
+ const type = this.view.getUint8(sin);
+ sin += 1;
+ sin += 7;
+ if (log.enabled) {
+ if (type == constants_1.WASI_EVENTTYPE_CLOCK) {
+ name = "poll_oneoff (type=WASI_EVENTTYPE_CLOCK): ";
+ } else if (type == constants_1.WASI_EVENTTYPE_FD_READ) {
+ name = "poll_oneoff (type=WASI_EVENTTYPE_FD_READ): ";
+ } else {
+ name = "poll_oneoff (type=WASI_EVENTTYPE_FD_WRITE): ";
+ }
+ log(name);
+ }
+ switch (type) {
+ case constants_1.WASI_EVENTTYPE_CLOCK: {
+ const clockid = this.view.getUint32(sin, true);
+ sin += 4;
+ sin += 4;
+ const timeout = this.view.getBigUint64(sin, true);
+ sin += 8;
+ sin += 8;
+ const subclockflags = this.view.getUint16(sin, true);
+ sin += 2;
+ sin += 6;
+ const absolute = subclockflags === 1;
+ if (log.enabled) {
+ log(name, { clockid, timeout, absolute });
+ }
+ if (!absolute) {
+ fd_timeout_ms = Number(timeout / BigInt(1e6));
+ }
+ let e = constants_1.WASI_ESUCCESS;
+ const t = now(clockid);
+ if (t == null) {
+ e = constants_1.WASI_EINVAL;
+ } else {
+ const end = absolute ? timeout : t + timeout;
+ const waitNs = end - t;
+ if (waitNs > waitTimeNs) {
+ waitTimeNs = waitNs;
+ }
+ }
+ this.view.setBigUint64(sout, userdata, true);
+ sout += 8;
+ this.view.setUint16(sout, e, true);
+ sout += 2;
+ this.view.setUint8(sout, constants_1.WASI_EVENTTYPE_CLOCK);
+ sout += 1;
+ sout += 5;
+ nevents += 1;
+ break;
+ }
+ case constants_1.WASI_EVENTTYPE_FD_READ:
+ case constants_1.WASI_EVENTTYPE_FD_WRITE: {
+ fd = this.view.getUint32(sin, true);
+ fd_type =
+ type == constants_1.WASI_EVENTTYPE_FD_READ
+ ? "read"
+ : "write";
+ sin += 4;
+ log(name, "fd =", fd);
+ sin += 28;
+ this.view.setBigUint64(sout, userdata, true);
+ sout += 8;
+ this.view.setUint16(sout, constants_1.WASI_ENOSYS, true);
+ sout += 2;
+ this.view.setUint8(sout, type);
+ sout += 1;
+ sout += 5;
+ nevents += 1;
+ if (
+ fd == constants_1.WASI_STDIN_FILENO &&
+ constants_1.WASI_EVENTTYPE_FD_READ == type
+ ) {
+ this.shortPause();
+ }
+ break;
+ }
+ default:
+ return constants_1.WASI_EINVAL;
+ }
+ if (sin - last_sin != 48) {
+ console.warn("*** BUG in wasi-js in poll_oneoff ", {
+ i,
+ sin,
+ last_sin,
+ diff: sin - last_sin,
+ });
+ }
+ last_sin = sin;
+ }
+ this.view.setUint32(neventsPtr, nevents, true);
+ if (nevents == 2 && fd >= 0) {
+ const r = this.wasiImport.sock_pollSocket(
+ fd,
+ fd_type,
+ fd_timeout_ms,
+ );
+ if (r != constants_1.WASI_ENOSYS) {
+ return r;
+ }
+ }
+ if (waitTimeNs > 0) {
+ waitTimeNs -= BigInt(bindings.hrtime()) - startNs;
+ if (waitTimeNs >= 1e6) {
+ if (this.sleep == null && !warnedAboutSleep) {
+ warnedAboutSleep = true;
+ console.log(
+ "(100% cpu burning waiting for stdin: please define a way to sleep!) ",
+ );
+ }
+ if (this.sleep != null) {
+ const ms = nsToMs(waitTimeNs);
+ this.sleep(ms);
+ } else {
+ const end = BigInt(bindings.hrtime()) + waitTimeNs;
+ while (BigInt(bindings.hrtime()) < end) {}
+ }
+ }
+ }
+ return constants_1.WASI_ESUCCESS;
+ },
+ proc_exit: (rval) => {
+ bindings.exit(rval);
+ return constants_1.WASI_ESUCCESS;
+ },
+ proc_raise: (sig) => {
+ if (!(sig in constants_1.SIGNAL_MAP)) {
+ return constants_1.WASI_EINVAL;
+ }
+ bindings.kill(constants_1.SIGNAL_MAP[sig]);
+ return constants_1.WASI_ESUCCESS;
+ },
+ random_get: (bufPtr, bufLen) => {
+ this.refreshMemory();
+ crypto.getRandomValues(this.memory.buffer, bufPtr, bufLen);
+ return bufLen;
+ },
+ sched_yield() {
+ return constants_1.WASI_ESUCCESS;
+ },
+ sock_recv() {
+ return constants_1.WASI_ENOSYS;
+ },
+ sock_send() {
+ return constants_1.WASI_ENOSYS;
+ },
+ sock_shutdown() {
+ return constants_1.WASI_ENOSYS;
+ },
+ sock_fcntlSetFlags(_fd, _flags) {
+ return constants_1.WASI_ENOSYS;
+ },
+ sock_pollSocket(_fd, _eventtype, _timeout_ms) {
+ return constants_1.WASI_ENOSYS;
+ },
+ };
+ if (log.enabled) {
+ Object.keys(this.wasiImport).forEach((key) => {
+ const prevImport = this.wasiImport[key];
+ this.wasiImport[key] = function (...args2) {
+ log(key, args2);
+ try {
+ let result = prevImport(...args2);
+ log("result", result);
+ return result;
+ } catch (e) {
+ log("error: ", e);
+ throw e;
+ }
+ };
+ });
+ }
+ }
+ getState() {
+ return { env: this.env, FD_MAP: this.FD_MAP, bindings: bindings };
+ }
+ setState(state) {
+ this.env = state.env;
+ this.FD_MAP = state.FD_MAP;
+ bindings = state.bindings;
+ }
+ fstatSync(real_fd) {
+ if (real_fd <= 2) {
+ try {
+ return bindings.fs.fstatSync(real_fd);
+ } catch (_) {
+ const now = new Date();
+ return {
+ dev: 0,
+ mode: 8592,
+ nlink: 1,
+ uid: 0,
+ gid: 0,
+ rdev: 0,
+ blksize: 65536,
+ ino: 0,
+ size: 0,
+ blocks: 0,
+ atimeMs: now.valueOf(),
+ mtimeMs: now.valueOf(),
+ ctimeMs: now.valueOf(),
+ birthtimeMs: 0,
+ atime: new Date(),
+ mtime: new Date(),
+ ctime: new Date(),
+ birthtime: new Date(0),
+ };
+ }
+ }
+ return bindings.fs.fstatSync(real_fd);
+ }
+ shortPause() {
+ if (this.sleep == null) return;
+ const now = new Date().valueOf();
+ if (now - this.lastStdin > 2e3) {
+ this.sleep(50);
+ }
+ }
+ getUnusedFileDescriptor(start = 3) {
+ let fd = start;
+ while (this.FD_MAP.has(fd)) {
+ fd += 1;
+ }
+ if (fd > SC_OPEN_MAX) {
+ throw Error("no available file descriptors");
+ }
+ return fd;
+ }
+ refreshMemory() {
+ if (!this.view || this.view.buffer.byteLength === 0) {
+ this.view = new DataView(this.memory.buffer);
+ }
+ }
+ setMemory(memory) {
+ this.memory = memory;
+ }
+ start(instance, memory) {
+ const exports2 = instance.exports;
+ if (exports2 === null || typeof exports2 !== "object") {
+ throw new Error(
+ `instance.exports must be an Object. Received ${exports2}.`,
+ );
+ }
+ if (memory == null) {
+ memory = exports2.memory;
+ if (!(memory instanceof WebAssembly.Memory)) {
+ throw new Error(
+ `instance.exports.memory must be a WebAssembly.Memory. Recceived ${memory}.`,
+ );
+ }
+ }
+ this.setMemory(memory);
+ if (exports2._start) {
+ exports2._start();
+ }
+ }
+ getImports(module2) {
+ let namespace = null;
+ const imports = WebAssembly.Module.imports(module2);
+
+ for (let imp of imports) {
+ if (imp.kind !== "function") {
+ continue;
+ }
+ if (!imp.module.startsWith("wasi_")) {
+ continue;
+ }
+
+ namespace = imp.module;
+ break;
+ }
+
+ switch (namespace) {
+ case "wasi_unstable":
+ return {
+ wasi_unstable: this.wasiImport,
+ };
+ case "wasi_snapshot_preview1":
+ return {
+ wasi_snapshot_preview1: this.wasiImport,
+ };
+ default: {
+ throw new Error(
+ "No WASI namespace found. Only wasi_unstable and wasi_snapshot_preview1 are supported.\n\nList of imports:\n\n" +
+ imports
+ .map(
+ ({ name, kind, module }) => `${module}:${name} (${kind})`,
+ )
+ .join("\n") +
+ "\n",
+ );
+ }
+ }
+ }
+ initWasiFdInfo() {
+ if (this.env["WASI_FD_INFO"] != null) {
+ const fdInfo = JSON.parse(this.env["WASI_FD_INFO"]);
+ for (const wasi_fd in fdInfo) {
+ console.log(wasi_fd);
+ const fd = parseInt(wasi_fd);
+ if (this.FD_MAP.has(fd)) {
+ continue;
+ }
+ const real = fdInfo[wasi_fd];
+ try {
+ this.fstatSync(real);
+ } catch (_err) {
+ console.log("discarding ", { wasi_fd, real });
+ continue;
+ }
+ const file = {
+ real,
+ filetype: constants_1.WASI_FILETYPE_SOCKET_STREAM,
+ rights: {
+ base: STDIN_DEFAULT_RIGHTS,
+ inheriting: BigInt(0),
+ },
+ };
+ this.FD_MAP.set(fd, file);
+ }
+ console.log("after initWasiFdInfo: ", this.FD_MAP);
+ console.log("fdInfo = ", fdInfo);
+ } else {
+ console.log("no WASI_FD_INFO");
+ }
+ }
+ };
+ exports.default = WASI;
+ },
+});
+const WASIExport = require_wasi();
+const WASI = WASIExport.default;
+WASIExport[Symbol.for("CommonJS")] = 0;
+export { WASIExport as WASI };
+export default WASIExport;
diff --git a/src/bundler.zig b/src/bundler.zig
index ec3de573b..336723da3 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -1404,6 +1404,17 @@ pub const Bundler = struct {
.ts,
.tsx,
=> {
+ // wasm magic number
+ if (source.isWebAssembly()) {
+ return ParseResult{
+ .source = source,
+ .input_fd = input_fd,
+ .loader = .wasm,
+ .empty = true,
+ .ast = js_ast.Ast.empty,
+ };
+ }
+
const platform = bundler.options.platform;
var jsx = this_parse.jsx;
@@ -1518,7 +1529,7 @@ pub const Bundler = struct {
},
.wasm => {
if (bundler.options.platform.isBun()) {
- if (source.contents.len < 4 or @bitCast(u32, source.contents[0..4].*) != @bitCast(u32, [4]u8{ 0, 'a', 's', 'm' })) {
+ if (!source.isWebAssembly()) {
bundler.log.addErrorFmt(
null,
logger.Loc.Empty,
diff --git a/src/cli.zig b/src/cli.zig
index 01adffee8..4b4f87ae9 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -1243,7 +1243,7 @@ pub const Command = struct {
const force_using_bun = ctx.debug.run_in_bun;
var did_check = false;
if (default_loader) |loader| {
- if (loader.isJavaScriptLike()) {
+ if (loader.isJavaScriptLike() or loader == .wasm) {
was_js_like = true;
if (maybeOpenWithBunJS(&ctx)) {
return;
diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig
index dc0138310..b6784cdf2 100644
--- a/src/cli/run_command.zig
+++ b/src/cli/run_command.zig
@@ -857,7 +857,7 @@ pub const RunCommand = struct {
possibly_open_with_bun_js: {
if (!force_using_bun) {
if (options.defaultLoaders.get(std.fs.path.extension(script_name_to_search))) |load| {
- if (!load.isJavaScriptLike())
+ if (!(load.isJavaScriptLike() or load == .wasm))
break :possibly_open_with_bun_js;
} else {
break :possibly_open_with_bun_js;
@@ -898,9 +898,9 @@ pub const RunCommand = struct {
};
var shebang: string = shebang_buf[0..shebang_size];
+
shebang = std.mem.trim(u8, shebang, " \r\n\t");
if (shebang.len == 0) break :possibly_open_with_bun_js;
-
if (strings.hasPrefixComptime(shebang, "#!")) {
const first_arg: string = if (std.os.argv.len > 0) bun.span(std.os.argv[0]) else "";
const filename = std.fs.path.basename(first_arg);
diff --git a/src/deps/.gitignore b/src/deps/.gitignore
new file mode 100644
index 000000000..19e1bced9
--- /dev/null
+++ b/src/deps/.gitignore
@@ -0,0 +1 @@
+*.wasm
diff --git a/src/logger.zig b/src/logger.zig
index 5e4e92406..bd2c81c31 100644
--- a/src/logger.zig
+++ b/src/logger.zig
@@ -1144,6 +1144,13 @@ pub const Source = struct {
contents: string,
contents_is_recycled: bool = false,
+ pub fn isWebAssembly(this: *const Source) bool {
+ if (this.contents.len < 4) return false;
+
+ const bytes = @bitCast(u32, this.contents[0..4].*);
+ return bytes == 0x6d736100; // "\0asm"
+ }
+
pub const ErrorPosition = struct {
line_start: usize,
line_end: usize,
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index db00508e1..b02cf1249 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -838,6 +838,17 @@ pub inline fn append(allocator: std.mem.Allocator, self: string, other: string)
return buf;
}
+pub inline fn append3(allocator: std.mem.Allocator, self: string, other: string, third: string) ![]u8 {
+ var buf = try allocator.alloc(u8, self.len + other.len + third.len);
+ if (self.len > 0)
+ @memcpy(buf.ptr, self.ptr, self.len);
+ if (other.len > 0)
+ @memcpy(buf.ptr + self.len, other.ptr, other.len);
+ if (third.len > 0)
+ @memcpy(buf.ptr + self.len + other.len, third.ptr, third.len);
+ return buf;
+}
+
pub inline fn joinBuf(out: []u8, parts: anytype, comptime parts_len: usize) []u8 {
var remain = out;
var count: usize = 0;