diff options
author | 2023-09-14 21:26:37 -0700 | |
---|---|---|
committer | 2023-09-14 21:26:37 -0700 | |
commit | ced69d38180e963da1206f9932db76666cec9f72 (patch) | |
tree | a4c4462ff8747adc7d092891b1c299dfbb0ecc4a | |
parent | b262b0153a2d9667fcb47a970e8027d3b54f8a0a (diff) | |
download | bun-ced69d38180e963da1206f9932db76666cec9f72.tar.gz bun-ced69d38180e963da1206f9932db76666cec9f72.tar.zst bun-ced69d38180e963da1206f9932db76666cec9f72.zip |
async-ify all node:fs functions (#5360)
* async all node:fs functions
* draw the rest of the owl
* LLVM & Clang 16
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r-- | .github/workflows/bun-mac-aarch64.yml | 12 | ||||
-rw-r--r-- | .github/workflows/bun-mac-x64-baseline.yml | 12 | ||||
-rw-r--r-- | .github/workflows/bun-mac-x64.yml | 12 | ||||
-rwxr-xr-x | .scripts/postinstall.sh | 2 | ||||
-rw-r--r-- | Dockerfile | 12 | ||||
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | bench/snippets/write.node.mjs | 5 | ||||
-rw-r--r-- | docs/project/development.md | 14 | ||||
-rw-r--r-- | packages/bun-usockets/src/context.c | 3 | ||||
-rw-r--r-- | packages/bun-usockets/src/crypto/openssl.c | 2 | ||||
-rw-r--r-- | packages/bun-usockets/src/eventing/epoll_kqueue.c | 4 | ||||
-rw-r--r-- | packages/bun-usockets/src/libusockets.h | 1 | ||||
-rw-r--r-- | packages/bun-usockets/src/socket.c | 53 | ||||
-rw-r--r-- | src/bun.js/event_loop.zig | 241 | ||||
-rw-r--r-- | src/bun.js/node/node_fs.zig | 2222 | ||||
-rw-r--r-- | src/bun.js/node/node_fs_binding.zig | 62 | ||||
-rw-r--r-- | src/bun.js/node/types.zig | 80 | ||||
-rw-r--r-- | src/js/node/fs.js | 74 | ||||
-rw-r--r-- | src/js/node/fs.promises.ts | 107 | ||||
-rw-r--r-- | src/js/out/InternalModuleRegistryConstants.h | 12 | ||||
-rw-r--r-- | test/js/node/fs/fs.test.ts | 13 |
21 files changed, 1402 insertions, 1553 deletions
diff --git a/.github/workflows/bun-mac-aarch64.yml b/.github/workflows/bun-mac-aarch64.yml index 214cec702..c13007167 100644 --- a/.github/workflows/bun-mac-aarch64.yml +++ b/.github/workflows/bun-mac-aarch64.yml @@ -172,11 +172,11 @@ jobs: OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps run: | - brew install ccache rust llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force + brew install ccache rust llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH - brew link --overwrite llvm@15 + echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH + brew link --overwrite llvm@16 - name: ccache uses: hendrikmuhs/ccache-action@v1.2 with: @@ -290,10 +290,10 @@ jobs: OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps run: | - brew install rust ccache llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force + brew install rust ccache llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH - brew link --overwrite llvm@15 + echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH + brew link --overwrite llvm@16 - name: ccache uses: hendrikmuhs/ccache-action@v1.2 with: diff --git a/.github/workflows/bun-mac-x64-baseline.yml b/.github/workflows/bun-mac-x64-baseline.yml index 8b96a3e7d..b8a5aeacc 100644 --- a/.github/workflows/bun-mac-x64-baseline.yml +++ b/.github/workflows/bun-mac-x64-baseline.yml @@ -172,11 +172,11 @@ jobs: OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps run: | - brew install ccache rust llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force + brew install ccache rust llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH - brew link --overwrite llvm@15 + echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH + brew link --overwrite llvm@16 - name: ccache (dependencies) uses: hendrikmuhs/ccache-action@v1.2 if: matrix.dependencies @@ -291,10 +291,10 @@ jobs: OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps run: | - brew install ccache rust llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force + brew install ccache rust llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH - brew link --overwrite llvm@15 + echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH + brew link --overwrite llvm@16 - name: ccache (link) uses: hendrikmuhs/ccache-action@v1.2 with: diff --git a/.github/workflows/bun-mac-x64.yml b/.github/workflows/bun-mac-x64.yml index 937fb9a50..3b4e3c450 100644 --- a/.github/workflows/bun-mac-x64.yml +++ b/.github/workflows/bun-mac-x64.yml @@ -172,10 +172,10 @@ jobs: OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps run: | - brew install rust ccache llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force + brew install rust ccache llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH - brew link --overwrite llvm@15 + echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH + brew link --overwrite llvm@16 - name: Download WebKit if: matrix.compile_obj env: @@ -293,10 +293,10 @@ jobs: OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps run: | - brew install rust ccache llvm@15 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force + brew install rust ccache llvm@16 pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config esbuild --force echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH - brew link --overwrite llvm@15 + echo "$(brew --prefix llvm@16)/bin" >> $GITHUB_PATH + brew link --overwrite llvm@16 - name: Download WebKit env: CPU_TARGET: ${{ matrix.cpu }} diff --git a/.scripts/postinstall.sh b/.scripts/postinstall.sh index 05ecb3203..eedb9bbfc 100755 --- a/.scripts/postinstall.sh +++ b/.scripts/postinstall.sh @@ -10,4 +10,4 @@ fi # sets up vscode C++ intellisense rm -f .vscode/clang++ -ln -s $(which clang++-15 || which clang++) .vscode/clang++ 2>/dev/null +ln -s $(which clang++-16 || which clang++) .vscode/clang++ 2>/dev/null diff --git a/Dockerfile b/Dockerfile index d0f13b431..f8ecac00c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ RUN install_packages ca-certificates curl wget lsb-release software-properties-c RUN wget https://apt.llvm.org/llvm.sh && \ chmod +x llvm.sh && \ - ./llvm.sh 15 + ./llvm.sh 16 RUN install_packages \ cmake \ @@ -49,8 +49,8 @@ RUN install_packages \ xz-utils \ bash tar gzip ccache -ENV CXX=clang++-15 -ENV CC=clang-15 +ENV CXX=clang++-16 +ENV CC=clang-16 RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \ install_packages nodejs && \ @@ -72,10 +72,10 @@ ARG ZIG_FILENAME ENV WEBKIT_OUT_DIR=${WEBKIT_DIR} ENV BUILDARCH=${BUILDARCH} -ENV AR=/usr/bin/llvm-ar-15 +ENV AR=/usr/bin/llvm-ar-16 ENV ZIG "${ZIG_PATH}/zig" ENV PATH="$ZIG/bin:$PATH" -ENV LD=lld-15 +ENV LD=lld-16 RUN mkdir -p $BUN_DIR $BUN_DEPS_OUT_DIR @@ -157,7 +157,7 @@ COPY src/deps/lol-html ${BUN_DIR}/src/deps/lol-html ENV CCACHE_DIR=/ccache -RUN --mount=type=cache,target=/ccache export PATH=$PATH:$HOME/.cargo/bin && export CC=$(which clang-15) && cd ${BUN_DIR} && \ +RUN --mount=type=cache,target=/ccache export PATH=$PATH:$HOME/.cargo/bin && export CC=$(which clang-16) && cd ${BUN_DIR} && \ make lolhtml && rm -rf src/deps/lol-html Makefile FROM bun-base as mimalloc @@ -82,8 +82,8 @@ ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make # This is easier to happen than you'd expect. # Using realpath here causes issues because clang uses clang++ as a symlink # so if that's resolved, it won't build for C++ -REAL_CC = $(shell which clang-15 2>/dev/null || which clang 2>/dev/null) -REAL_CXX = $(shell which clang++-15 2>/dev/null || which clang++ 2>/dev/null) +REAL_CC = $(shell which clang-16 2>/dev/null || which clang 2>/dev/null) +REAL_CXX = $(shell which clang++-16 2>/dev/null || which clang++ 2>/dev/null) CLANG_FORMAT = $(shell which clang-format-15 2>/dev/null || which clang-format 2>/dev/null) CC = $(REAL_CC) @@ -108,14 +108,14 @@ CC_WITH_CCACHE = $(CCACHE_PATH) $(CC) ifeq ($(OS_NAME),darwin) # Find LLVM ifeq ($(wildcard $(LLVM_PREFIX)),) - LLVM_PREFIX = $(shell brew --prefix llvm@15) + LLVM_PREFIX = $(shell brew --prefix llvm@16) endif ifeq ($(wildcard $(LLVM_PREFIX)),) LLVM_PREFIX = $(shell brew --prefix llvm) endif ifeq ($(wildcard $(LLVM_PREFIX)),) # This is kinda ugly, but I can't find a better way to error :( - LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@15' or set LLVM_PREFIX=/path/to/llvm") + LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@16' or set LLVM_PREFIX=/path/to/llvm") endif LDFLAGS += -L$(LLVM_PREFIX)/lib @@ -155,7 +155,7 @@ CMAKE_FLAGS_WITHOUT_RELEASE = -DCMAKE_C_COMPILER=$(CC) \ -DCMAKE_OSX_DEPLOYMENT_TARGET=$(MIN_MACOS_VERSION) \ $(CMAKE_CXX_COMPILER_LAUNCHER_FLAG) \ -DCMAKE_AR=$(AR) \ - -DCMAKE_RANLIB=$(which llvm-15-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) + -DCMAKE_RANLIB=$(which llvm-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) @@ -664,7 +664,7 @@ endif .PHONY: assert-deps assert-deps: @echo "Checking if the required utilities are available..." - @if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@15"; exit 1; fi + @if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@16"; exit 1; fi @cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1) @$(PYTHON) --version >/dev/null 2>&1 || (echo -e "ERROR: python is required."; exit 1) @$(ESBUILD) --version >/dev/null 2>&1 || (echo -e "ERROR: esbuild is required."; exit 1) diff --git a/bench/snippets/write.node.mjs b/bench/snippets/write.node.mjs index 14bceb23f..f59c98aef 100644 --- a/bench/snippets/write.node.mjs +++ b/bench/snippets/write.node.mjs @@ -9,9 +9,8 @@ bench("writeFile(/tmp/foo.txt, short string)", async () => { await writeFile("/tmp/foo.txt", "short string", "utf8"); }); -const buffer = Buffer.from("short string"); bench("writeFile(/tmp/foo.txt, Buffer.from(short string))", async () => { - await writeFile("/tmp/foo.txt", buffer); + await writeFile("/tmp/foo.txt", Buffer.from("short string")); }); const fd = openSync("/tmp/foo.txt", "w"); @@ -22,7 +21,7 @@ bench("write(fd, short string)", () => { }); bench("write(fd, Uint8Array(short string))", () => { - const bytesWritten = write(fd, buffer); + const bytesWritten = write(fd, Buffer.from("short string")); if (bytesWritten !== 12) throw new Error("wrote !== 12"); }); diff --git a/docs/project/development.md b/docs/project/development.md index ce9ef1ded..f2903e024 100644 --- a/docs/project/development.md +++ b/docs/project/development.md @@ -32,12 +32,12 @@ $ proto install bun ## Install LLVM -Bun requires LLVM 15 and Clang 15 (`clang` is part of LLVM). This version requirement is to match WebKit (precompiled), as mismatching versions will cause memory allocation failures at runtime. In most cases, you can install LLVM through your system package manager: +Bun requires LLVM 16 and Clang 16 (`clang` is part of LLVM). This version requirement is to match WebKit (precompiled), as mismatching versions will cause memory allocation failures at runtime. In most cases, you can install LLVM through your system package manager: {% codetabs %} ```bash#macOS (Homebrew) -$ brew install llvm@15 +$ brew install llvm@16 ``` ```bash#Ubuntu/Debian @@ -54,10 +54,10 @@ $ sudo pacman -S llvm15 clang15 lld If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.7). -Make sure LLVM 15 is in your path: +Make sure LLVM 16 is in your path: ```bash -$ which clang-15 +$ which clang-16 ``` If not, run this to manually link it: @@ -66,9 +66,9 @@ If not, run this to manually link it: ```bash#macOS (Homebrew) # use fish_add_path if you're using fish -$ export PATH="$PATH:$(brew --prefix llvm@15)/bin" -$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@15)/lib" -$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@15)/include" +$ export PATH="$PATH:$(brew --prefix llvm@16)/bin" +$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@16)/lib" +$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@16)/include" ``` ```bash#Arch diff --git a/packages/bun-usockets/src/context.c b/packages/bun-usockets/src/context.c index a4d243e85..9e0dd5356 100644 --- a/packages/bun-usockets/src/context.c +++ b/packages/bun-usockets/src/context.c @@ -29,6 +29,7 @@ int default_is_low_prio_handler(struct us_socket_t *s) { unsigned short us_socket_context_timestamp(int ssl, struct us_socket_context_t *context) { return context->timestamp; } +int us_internal_raw_root_certs(struct us_cert_string_t** out); int us_raw_root_certs(struct us_cert_string_t**out){ return us_internal_raw_root_certs(out); } @@ -568,7 +569,7 @@ void *us_socket_context_ext(int ssl, struct us_socket_context_t *context) { void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_context_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data) { #ifndef LIBUS_NO_SSL if (ssl) { - us_internal_on_ssl_handshake((struct us_internal_ssl_socket_context_t *) context, on_handshake, custom_data); + us_internal_on_ssl_handshake((struct us_internal_ssl_socket_context_t *) context, (void (*)(struct us_internal_ssl_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data))on_handshake, custom_data); return; } #endif diff --git a/packages/bun-usockets/src/crypto/openssl.c b/packages/bun-usockets/src/crypto/openssl.c index 0b55ca866..a03bf3520 100644 --- a/packages/bun-usockets/src/crypto/openssl.c +++ b/packages/bun-usockets/src/crypto/openssl.c @@ -45,7 +45,7 @@ void *sni_find(void *sni, const char *hostname); #include "./root_certs.h" #include <stdatomic.h> -static const root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]); +static const size_t root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]); static X509* root_cert_instances[root_certs_size] = {NULL}; static atomic_flag root_cert_instances_lock = ATOMIC_FLAG_INIT; static atomic_bool root_cert_instances_initialized = 0; diff --git a/packages/bun-usockets/src/eventing/epoll_kqueue.c b/packages/bun-usockets/src/eventing/epoll_kqueue.c index 7ab2be826..df694dd04 100644 --- a/packages/bun-usockets/src/eventing/epoll_kqueue.c +++ b/packages/bun-usockets/src/eventing/epoll_kqueue.c @@ -35,8 +35,8 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs); /* Pointer tags are used to indicate a Bun pointer versus a uSockets pointer */ #define UNSET_BITS_49_UNTIL_64 0x0000FFFFFFFFFFFF #define CLEAR_POINTER_TAG(p) ((void *) ((uintptr_t) (p) & UNSET_BITS_49_UNTIL_64)) -#define LIKELY(cond) __builtin_expect((uint64_t)(void*)cond, 1) -#define UNLIKELY(cond) __builtin_expect((uint64_t)(void*)cond, 0) +#define LIKELY(cond) __builtin_expect((uint64_t)(void*)(cond), 1) +#define UNLIKELY(cond) __builtin_expect((uint64_t)(void*)(cond), 0) #ifdef LIBUS_USE_EPOLL #define GET_READY_POLL(loop, index) (struct us_poll_t *) loop->ready_polls[index].data.ptr diff --git a/packages/bun-usockets/src/libusockets.h b/packages/bun-usockets/src/libusockets.h index 5f4563605..e0a427ce5 100644 --- a/packages/bun-usockets/src/libusockets.h +++ b/packages/bun-usockets/src/libusockets.h @@ -386,7 +386,6 @@ void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *le /* Bun extras */ struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds); struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd); -struct us_socket_t *us_socket_detach(int ssl, struct us_socket_t *s); struct us_socket_t *us_socket_attach(int ssl, LIBUS_SOCKET_DESCRIPTOR client_fd, struct us_socket_context_t *ctx, int flags, int socket_ext_size); struct us_socket_t *us_socket_wrap_with_tls(int ssl, struct us_socket_t *s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size); int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more); diff --git a/packages/bun-usockets/src/socket.c b/packages/bun-usockets/src/socket.c index 5f5a91acb..ce5203ccb 100644 --- a/packages/bun-usockets/src/socket.c +++ b/packages/bun-usockets/src/socket.c @@ -140,59 +140,6 @@ struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s, int code, vo return s; } -// This function is the same as us_socket_close but: -// - does not emit on_close event -// - does not close -struct us_socket_t *us_socket_detach(int ssl, struct us_socket_t *s) { - if (!us_socket_is_closed(0, s)) { - if (s->low_prio_state == 1) { - /* Unlink this socket from the low-priority queue */ - if (!s->prev) s->context->loop->data.low_prio_head = s->next; - else s->prev->next = s->next; - - if (s->next) s->next->prev = s->prev; - - s->prev = 0; - s->next = 0; - s->low_prio_state = 0; - } else { - us_internal_socket_context_unlink(s->context, s); - } - us_poll_stop((struct us_poll_t *) s, s->context->loop); - - /* Link this socket to the close-list and let it be deleted after this iteration */ - s->next = s->context->loop->data.closed_head; - s->context->loop->data.closed_head = s; - - /* Any socket with prev = context is marked as closed */ - s->prev = (struct us_socket_t *) s->context; - - return s; - } - return s; -} - -// This function is used for moving a socket between two different event loops -struct us_socket_t *us_socket_attach(int ssl, LIBUS_SOCKET_DESCRIPTOR client_fd, struct us_socket_context_t *ctx, int flags, int socket_ext_size) { - struct us_poll_t *accepted_p = us_create_poll(ctx->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + socket_ext_size); - us_poll_init(accepted_p, client_fd, POLL_TYPE_SOCKET); - us_poll_start(accepted_p, ctx->loop, flags); - - struct us_socket_t *s = (struct us_socket_t *) accepted_p; - - s->context = ctx; - s->timeout = 0; - s->low_prio_state = 0; - - /* We always use nodelay */ - bsd_socket_nodelay(client_fd, 1); - us_internal_socket_context_link(ctx, s); - - if (ctx->on_open) ctx->on_open(s, 0, 0, 0); - - return s; -} - struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds) { #ifdef LIBUS_USE_LIBUV return 0; diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index c7de557f4..ed9d5b195 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -303,6 +303,48 @@ const PollPendingModulesTask = JSC.ModuleLoader.AsyncModule.Queue; // const PromiseTask = JSInternalPromise.Completion.PromiseTask; const GetAddrInfoRequestTask = JSC.DNS.GetAddrInfoRequest.Task; const JSCDeferredWorkTask = JSCScheduler.JSCDeferredWorkTask; + +const Stat = JSC.Node.Async.stat; +const Lstat = JSC.Node.Async.lstat; +const Fstat = JSC.Node.Async.fstat; +const Open = JSC.Node.Async.open; +const ReadFile = JSC.Node.Async.readFile; +const WriteFile = JSC.Node.Async.writeFile; +const CopyFile = JSC.Node.Async.copyFile; +const Read = JSC.Node.Async.read; +const Write = JSC.Node.Async.write; +const Truncate = JSC.Node.Async.truncate; +const FTruncate = JSC.Node.Async.ftruncate; +const Readdir = JSC.Node.Async.readdir; +const Readv = JSC.Node.Async.readv; +const Writev = JSC.Node.Async.writev; +const Close = JSC.Node.Async.close; +const Rm = JSC.Node.Async.rm; +const Rmdir = JSC.Node.Async.rmdir; +const Chown = JSC.Node.Async.chown; +const FChown = JSC.Node.Async.fchown; +const Utimes = JSC.Node.Async.utimes; +const Lutimes = JSC.Node.Async.lutimes; +const Chmod = JSC.Node.Async.chmod; +const Fchmod = JSC.Node.Async.fchmod; +const Link = JSC.Node.Async.link; +const Symlink = JSC.Node.Async.symlink; +const Readlink = JSC.Node.Async.readlink; +const Realpath = JSC.Node.Async.realpath; +const Mkdir = JSC.Node.Async.mkdir; +const Fsync = JSC.Node.Async.fsync; +const Rename = JSC.Node.Async.rename; +const Fdatasync = JSC.Node.Async.fdatasync; +const Access = JSC.Node.Async.access; +const AppendFile = JSC.Node.Async.appendFile; +const Mkdtemp = JSC.Node.Async.mkdtemp; +const Exists = JSC.Node.Async.exists; +const Futimes = JSC.Node.Async.futimes; +const Lchmod = JSC.Node.Async.lchmod; +const Lchown = JSC.Node.Async.lchown; +const Unlink = JSC.Node.Async.unlink; + +// Task.get(ReadFileTask) -> ?ReadFileTask pub const Task = TaggedPointerUnion(.{ FetchTasklet, Microtask, @@ -321,9 +363,45 @@ pub const Task = TaggedPointerUnion(.{ GetAddrInfoRequestTask, FSWatchTask, JSCDeferredWorkTask, - - // PromiseTask, - // TimeoutTasklet, + Stat, + Lstat, + Fstat, + Open, + ReadFile, + WriteFile, + CopyFile, + Read, + Write, + Truncate, + FTruncate, + Readdir, + Close, + Rm, + Rmdir, + Chown, + FChown, + Utimes, + Lutimes, + Chmod, + Fchmod, + Link, + Symlink, + Readlink, + Realpath, + Mkdir, + Fsync, + Fdatasync, + Writev, + Readv, + Rename, + Access, + AppendFile, + Mkdtemp, + Exists, + Futimes, + Lchmod, + Lchown, + Unlink, }); const UnboundedQueue = @import("./unbounded_queue.zig").UnboundedQueue; pub const ConcurrentTask = struct { @@ -535,7 +613,6 @@ pub const EventLoop = struct { } extern fn JSC__JSGlobalObject__drainMicrotasks(*JSC.JSGlobalObject) void; fn drainMicrotasksWithGlobal(this: *EventLoop, globalObject: *JSC.JSGlobalObject) void { - JSC.markBinding(@src()); JSC__JSGlobalObject__drainMicrotasks(globalObject); this.drainDeferredTasks(); } @@ -662,6 +739,162 @@ pub const EventLoop = struct { any.runFromJS(); any.deinit(); }, + @field(Task.Tag, typeBaseName(@typeName(Stat))) => { + var any: *Stat = task.get(Stat).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Lstat))) => { + var any: *Lstat = task.get(Lstat).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Fstat))) => { + var any: *Fstat = task.get(Fstat).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Open))) => { + var any: *Open = task.get(Open).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(ReadFile))) => { + var any: *ReadFile = task.get(ReadFile).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(WriteFile))) => { + var any: *WriteFile = task.get(WriteFile).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(CopyFile))) => { + var any: *CopyFile = task.get(CopyFile).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Read))) => { + var any: *Read = task.get(Read).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Write))) => { + var any: *Write = task.get(Write).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Truncate))) => { + var any: *Truncate = task.get(Truncate).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Writev))) => { + var any: *Writev = task.get(Writev).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Readv))) => { + var any: *Readv = task.get(Readv).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Rename))) => { + var any: *Rename = task.get(Rename).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(FTruncate))) => { + var any: *FTruncate = task.get(FTruncate).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Readdir))) => { + var any: *Readdir = task.get(Readdir).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Close))) => { + var any: *Close = task.get(Close).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Rm))) => { + var any: *Rm = task.get(Rm).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Rmdir))) => { + var any: *Rmdir = task.get(Rmdir).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Chown))) => { + var any: *Chown = task.get(Chown).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(FChown))) => { + var any: *FChown = task.get(FChown).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Utimes))) => { + var any: *Utimes = task.get(Utimes).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Lutimes))) => { + var any: *Lutimes = task.get(Lutimes).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Chmod))) => { + var any: *Chmod = task.get(Chmod).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Fchmod))) => { + var any: *Fchmod = task.get(Fchmod).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Link))) => { + var any: *Link = task.get(Link).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Symlink))) => { + var any: *Symlink = task.get(Symlink).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Readlink))) => { + var any: *Readlink = task.get(Readlink).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Realpath))) => { + var any: *Realpath = task.get(Realpath).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Mkdir))) => { + var any: *Mkdir = task.get(Mkdir).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Fsync))) => { + var any: *Fsync = task.get(Fsync).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Fdatasync))) => { + var any: *Fdatasync = task.get(Fdatasync).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Access))) => { + var any: *Access = task.get(Access).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(AppendFile))) => { + var any: *AppendFile = task.get(AppendFile).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Mkdtemp))) => { + var any: *Mkdtemp = task.get(Mkdtemp).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Exists))) => { + var any: *Exists = task.get(Exists).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Futimes))) => { + var any: *Futimes = task.get(Futimes).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Lchmod))) => { + var any: *Lchmod = task.get(Lchmod).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Lchown))) => { + var any: *Lchown = task.get(Lchown).?; + any.runFromJSThread(); + }, + @field(Task.Tag, typeBaseName(@typeName(Unlink))) => { + var any: *Unlink = task.get(Unlink).?; + any.runFromJSThread(); + }, else => if (Environment.allow_assert) { bun.Output.prettyln("\nUnexpected tag: {s}\n", .{@tagName(task.tag())}); } else { diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index d9e3ed119..752d0e2fb 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -55,468 +55,147 @@ else // TODO: 0; +const SliceWithUnderlyingStringOrBuffer = JSC.Node.SliceWithUnderlyingStringOrBuffer; const ArrayBuffer = JSC.MarkedArrayBuffer; const Buffer = JSC.Buffer; const FileSystemFlags = JSC.Node.FileSystemFlags; +pub const Async = struct { + pub const access = NewAsyncFSTask(Return.Access, Arguments.Access, NodeFS.access); + pub const appendFile = NewAsyncFSTask(Return.AppendFile, Arguments.AppendFile, NodeFS.appendFile); + pub const chmod = NewAsyncFSTask(Return.Chmod, Arguments.Chmod, NodeFS.chmod); + pub const chown = NewAsyncFSTask(Return.Chown, Arguments.Chown, NodeFS.chown); + pub const close = NewAsyncFSTask(Return.Close, Arguments.Close, NodeFS.close); + pub const copyFile = NewAsyncFSTask(Return.CopyFile, Arguments.CopyFile, NodeFS.copyFile); + pub const exists = NewAsyncFSTask(Return.Exists, Arguments.Exists, NodeFS.exists); + pub const fchmod = NewAsyncFSTask(Return.Fchmod, Arguments.FChmod, NodeFS.fchmod); + pub const fchown = NewAsyncFSTask(Return.Fchown, Arguments.Fchown, NodeFS.fchown); + pub const fdatasync = NewAsyncFSTask(Return.Fdatasync, Arguments.FdataSync, NodeFS.fdatasync); + pub const fstat = NewAsyncFSTask(Return.Fstat, Arguments.Fstat, NodeFS.fstat); + pub const fsync = NewAsyncFSTask(Return.Fsync, Arguments.Fsync, NodeFS.fsync); + pub const ftruncate = NewAsyncFSTask(Return.Ftruncate, Arguments.FTruncate, NodeFS.ftruncate); + pub const futimes = NewAsyncFSTask(Return.Futimes, Arguments.Futimes, NodeFS.futimes); + pub const lchmod = NewAsyncFSTask(Return.Lchmod, Arguments.LCHmod, NodeFS.lchmod); + pub const lchown = NewAsyncFSTask(Return.Lchown, Arguments.LChown, NodeFS.lchown); + pub const link = NewAsyncFSTask(Return.Link, Arguments.Link, NodeFS.link); + pub const lstat = NewAsyncFSTask(Return.Stat, Arguments.Stat, NodeFS.lstat); + pub const lutimes = NewAsyncFSTask(Return.Lutimes, Arguments.Lutimes, NodeFS.lutimes); + pub const mkdir = NewAsyncFSTask(Return.Mkdir, Arguments.Mkdir, NodeFS.mkdir); + pub const mkdtemp = NewAsyncFSTask(Return.Mkdtemp, Arguments.MkdirTemp, NodeFS.mkdtemp); + pub const open = NewAsyncFSTask(Return.Open, Arguments.Open, NodeFS.open); + pub const read = NewAsyncFSTask(Return.Read, Arguments.Read, NodeFS.read); + pub const readdir = NewAsyncFSTask(Return.Readdir, Arguments.Readdir, NodeFS.readdir); + pub const readFile = NewAsyncFSTask(Return.ReadFile, Arguments.ReadFile, NodeFS.readFile); + pub const readlink = NewAsyncFSTask(Return.Readlink, Arguments.Readlink, NodeFS.readlink); + pub const readv = NewAsyncFSTask(Return.Readv, Arguments.Readv, NodeFS.readv); + pub const realpath = NewAsyncFSTask(Return.Realpath, Arguments.Realpath, NodeFS.realpath); + pub const rename = NewAsyncFSTask(Return.Rename, Arguments.Rename, NodeFS.rename); + pub const rm = NewAsyncFSTask(Return.Rm, Arguments.Rm, NodeFS.rm); + pub const rmdir = NewAsyncFSTask(Return.Rmdir, Arguments.RmDir, NodeFS.rmdir); + pub const stat = NewAsyncFSTask(Return.Stat, Arguments.Stat, NodeFS.stat); + pub const symlink = NewAsyncFSTask(Return.Symlink, Arguments.Symlink, NodeFS.symlink); + pub const truncate = NewAsyncFSTask(Return.Truncate, Arguments.Truncate, NodeFS.truncate); + pub const unlink = NewAsyncFSTask(Return.Unlink, Arguments.Unlink, NodeFS.unlink); + pub const utimes = NewAsyncFSTask(Return.Utimes, Arguments.Utimes, NodeFS.utimes); + pub const write = NewAsyncFSTask(Return.Write, Arguments.Write, NodeFS.write); + pub const writeFile = NewAsyncFSTask(Return.WriteFile, Arguments.WriteFile, NodeFS.writeFile); + pub const writev = NewAsyncFSTask(Return.Writev, Arguments.Writev, NodeFS.writev); + + pub const cp = AsyncCpTask; + + fn NewAsyncFSTask(comptime ReturnType: type, comptime ArgumentType: type, comptime Function: anytype) type { + return struct { + promise: JSC.JSPromise.Strong, + args: ArgumentType, + globalObject: *JSC.JSGlobalObject, + task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, + result: JSC.Maybe(ReturnType), + ref: JSC.PollRef = .{}, + tracker: JSC.AsyncTaskTracker, + + pub const Task = @This(); + + pub fn create( + globalObject: *JSC.JSGlobalObject, + args: ArgumentType, + vm: *JSC.VirtualMachine, + ) JSC.JSValue { + var task = bun.default_allocator.create(Task) catch @panic("out of memory"); + task.* = Task{ + .promise = JSC.JSPromise.Strong.init(globalObject), + .args = args, + .result = undefined, + .globalObject = globalObject, + .tracker = JSC.AsyncTaskTracker.init(vm), + }; + task.ref.ref(vm); + task.args.toThreadSafe(); + task.tracker.didSchedule(globalObject); + JSC.WorkPool.schedule(&task.task); -pub const AsyncReaddirTask = struct { - promise: JSC.JSPromise.Strong, - args: Arguments.Readdir, - globalObject: *JSC.JSGlobalObject, - task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, - result: JSC.Maybe(Return.Readdir), - ref: JSC.PollRef = .{}, - arena: bun.ArenaAllocator, - tracker: JSC.AsyncTaskTracker, - - pub fn create(globalObject: *JSC.JSGlobalObject, readdir_args: Arguments.Readdir, vm: *JSC.VirtualMachine, arena: bun.ArenaAllocator) JSC.JSValue { - var task = bun.default_allocator.create(AsyncReaddirTask) catch @panic("out of memory"); - task.* = AsyncReaddirTask{ - .promise = JSC.JSPromise.Strong.init(globalObject), - .args = readdir_args, - .result = undefined, - .globalObject = globalObject, - .arena = arena, - .tracker = JSC.AsyncTaskTracker.init(vm), - }; - task.ref.ref(vm); - task.args.path.toThreadSafe(); - task.tracker.didSchedule(globalObject); - JSC.WorkPool.schedule(&task.task); - - return task.promise.value(); - } - - fn workPoolCallback(task: *JSC.WorkPoolTask) void { - var this: *AsyncReaddirTask = @fieldParentPtr(AsyncReaddirTask, "task", task); - - var node_fs = NodeFS{}; - this.result = node_fs.readdir(this.args, .promise); - - if (this.result == .err) { - this.result.err.path = bun.default_allocator.dupe(u8, this.result.err.path) catch ""; - } - - this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, runFromJSThread)); - } - - fn runFromJSThread(this: *AsyncReaddirTask) void { - var globalObject = this.globalObject; - - var success = @as(JSC.Maybe(Return.Readdir).Tag, this.result) == .result; - const result = switch (this.result) { - .err => |err| err.toJSC(globalObject), - .result => |res| brk: { - var exceptionref: JSC.C.JSValueRef = null; - const out = JSC.JSValue.c(JSC.To.JS.withType(Return.Readdir, res, globalObject, &exceptionref)); - const exception = JSC.JSValue.c(exceptionref); - if (exception != .zero) { - success = false; - break :brk exception; - } - - break :brk out; - }, - }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); - promise_value.ensureStillAlive(); - - const tracker = this.tracker; - this.deinit(); - - tracker.willDispatch(globalObject); - defer tracker.didDispatch(globalObject); - switch (success) { - false => { - promise.reject(globalObject, result); - }, - true => { - promise.resolve(globalObject, result); - }, - } - } - - pub fn deinit(this: *AsyncReaddirTask) void { - this.ref.unref(this.globalObject.bunVM()); - this.args.deinitAndUnprotect(); - this.promise.strong.deinit(); - this.arena.deinit(); - bun.default_allocator.destroy(this); - } -}; - -pub const AsyncStatTask = struct { - promise: JSC.JSPromise.Strong, - args: Arguments.Stat, - globalObject: *JSC.JSGlobalObject, - task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, - result: JSC.Maybe(Return.Stat), - ref: JSC.PollRef = .{}, - is_lstat: bool = false, - arena: bun.ArenaAllocator, - tracker: JSC.AsyncTaskTracker, - - pub fn create( - globalObject: *JSC.JSGlobalObject, - readdir_args: Arguments.Stat, - vm: *JSC.VirtualMachine, - is_lstat: bool, - arena: bun.ArenaAllocator, - ) JSC.JSValue { - var task = bun.default_allocator.create(AsyncStatTask) catch @panic("out of memory"); - task.* = AsyncStatTask{ - .promise = JSC.JSPromise.Strong.init(globalObject), - .args = readdir_args, - .result = undefined, - .globalObject = globalObject, - .is_lstat = is_lstat, - .tracker = JSC.AsyncTaskTracker.init(vm), - .arena = arena, - }; - task.ref.ref(vm); - task.args.path.toThreadSafe(); - task.tracker.didSchedule(globalObject); - - JSC.WorkPool.schedule(&task.task); - - return task.promise.value(); - } - - fn workPoolCallback(task: *JSC.WorkPoolTask) void { - var this: *AsyncStatTask = @fieldParentPtr(AsyncStatTask, "task", task); - - var node_fs = NodeFS{}; - this.result = if (this.is_lstat) - node_fs.lstat(this.args, .promise) - else - node_fs.stat(this.args, .promise); - - this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, runFromJSThread)); - } - - fn runFromJSThread(this: *AsyncStatTask) void { - var globalObject = this.globalObject; - var success = @as(JSC.Maybe(Return.Lstat).Tag, this.result) == .result; - const result = switch (this.result) { - .err => |err| err.toJSC(globalObject), - .result => |res| brk: { - var exceptionref: JSC.C.JSValueRef = null; - const out = JSC.JSValue.c(JSC.To.JS.withType(Return.Lstat, res, globalObject, &exceptionref)); - const exception = JSC.JSValue.c(exceptionref); - if (exception != .zero) { - success = false; - break :brk exception; - } - - break :brk out; - }, - }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); - promise_value.ensureStillAlive(); - - const tracker = this.tracker; - tracker.willDispatch(globalObject); - defer tracker.didDispatch(globalObject); - - this.deinit(); - switch (success) { - false => { - promise.reject(globalObject, result); - }, - true => { - promise.resolve(globalObject, result); - }, - } - } - - pub fn deinit(this: *AsyncStatTask) void { - this.ref.unref(this.globalObject.bunVM()); - this.args.deinitAndUnprotect(); - this.promise.strong.deinit(); - this.arena.deinit(); - bun.default_allocator.destroy(this); - } -}; - -pub const AsyncRealpathTask = struct { - promise: JSC.JSPromise.Strong, - args: Arguments.Realpath, - globalObject: *JSC.JSGlobalObject, - task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, - result: JSC.Maybe(Return.Realpath), - ref: JSC.PollRef = .{}, - arena: bun.ArenaAllocator, - tracker: JSC.AsyncTaskTracker, - - pub fn create( - globalObject: *JSC.JSGlobalObject, - args: Arguments.Realpath, - vm: *JSC.VirtualMachine, - arena: bun.ArenaAllocator, - ) JSC.JSValue { - var task = bun.default_allocator.create(AsyncRealpathTask) catch @panic("out of memory"); - task.* = AsyncRealpathTask{ - .promise = JSC.JSPromise.Strong.init(globalObject), - .args = args, - .result = undefined, - .globalObject = globalObject, - .arena = arena, - .tracker = JSC.AsyncTaskTracker.init(vm), - }; - task.ref.ref(vm); - task.args.path.toThreadSafe(); - task.tracker.didSchedule(globalObject); - JSC.WorkPool.schedule(&task.task); - - return task.promise.value(); - } - - fn workPoolCallback(task: *JSC.WorkPoolTask) void { - var this: *AsyncRealpathTask = @fieldParentPtr(AsyncRealpathTask, "task", task); + return task.promise.value(); + } - var node_fs = NodeFS{}; - this.result = node_fs.realpath(this.args, .promise); + fn workPoolCallback(task: *JSC.WorkPoolTask) void { + var this: *Task = @fieldParentPtr(Task, "task", task); - if (this.result == .err) { - this.result.err.path = bun.default_allocator.dupe(u8, this.result.err.path) catch ""; - } + var node_fs = NodeFS{}; + this.result = Function(&node_fs, this.args, .promise); - this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, runFromJSThread)); - } - - fn runFromJSThread(this: *AsyncRealpathTask) void { - var globalObject = this.globalObject; - var success = @as(JSC.Maybe(Return.Realpath).Tag, this.result) == .result; - const result = switch (this.result) { - .err => |err| err.toJSC(globalObject), - .result => |res| brk: { - var exceptionref: JSC.C.JSValueRef = null; - const out = JSC.JSValue.c(JSC.To.JS.withType(Return.Realpath, res, globalObject, &exceptionref)); - const exception = JSC.JSValue.c(exceptionref); - if (exception != .zero) { - success = false; - break :brk exception; + if (this.result == .err) { + this.result.err.path = bun.default_allocator.dupe(u8, this.result.err.path) catch ""; + std.mem.doNotOptimizeAway(&node_fs); } - break :brk out; - }, - }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); - promise_value.ensureStillAlive(); - - const tracker = this.tracker; - tracker.willDispatch(globalObject); - defer tracker.didDispatch(globalObject); - - this.deinit(); - switch (success) { - false => { - promise.reject(globalObject, result); - }, - true => { - promise.resolve(globalObject, result); - }, - } - } - - pub fn deinit(this: *AsyncRealpathTask) void { - if (this.result == .err) { - bun.default_allocator.free(this.result.err.path); - } - - this.ref.unref(this.globalObject.bunVM()); - this.args.deinitAndUnprotect(); - this.promise.strong.deinit(); - this.arena.deinit(); - bun.default_allocator.destroy(this); - } -}; - -pub const AsyncReadFileTask = struct { - promise: JSC.JSPromise.Strong, - args: Arguments.ReadFile, - globalObject: *JSC.JSGlobalObject, - task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, - result: JSC.Maybe(Return.ReadFile), - ref: JSC.PollRef = .{}, - arena: bun.ArenaAllocator, - tracker: JSC.AsyncTaskTracker, - - pub fn create( - globalObject: *JSC.JSGlobalObject, - args: Arguments.ReadFile, - vm: *JSC.VirtualMachine, - arena: bun.ArenaAllocator, - ) JSC.JSValue { - var task = bun.default_allocator.create(AsyncReadFileTask) catch @panic("out of memory"); - task.* = AsyncReadFileTask{ - .promise = JSC.JSPromise.Strong.init(globalObject), - .args = args, - .result = undefined, - .globalObject = globalObject, - .arena = arena, - .tracker = JSC.AsyncTaskTracker.init(vm), - }; - task.ref.ref(vm); - task.args.path.toThreadSafe(); - task.tracker.didSchedule(globalObject); - JSC.WorkPool.schedule(&task.task); - - return task.promise.value(); - } - - fn workPoolCallback(task: *JSC.WorkPoolTask) void { - var this: *AsyncReadFileTask = @fieldParentPtr(AsyncReadFileTask, "task", task); - - var node_fs = NodeFS{}; - this.result = node_fs.readFile(this.args, .promise); - - if (this.result == .err) { - this.result.err.path = bun.default_allocator.dupe(u8, this.result.err.path) catch ""; - } - - this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, runFromJSThread)); - } + this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.create(JSC.Task.init(this))); + } - fn runFromJSThread(this: *AsyncReadFileTask) void { - var globalObject = this.globalObject; + pub fn runFromJSThread(this: *Task) void { + var globalObject = this.globalObject; + var success = @as(JSC.Maybe(ReturnType).Tag, this.result) == .result; + const result = switch (this.result) { + .err => |err| err.toJSC(globalObject), + .result => |res| brk: { + var exceptionref: JSC.C.JSValueRef = null; + const out = JSC.JSValue.c(JSC.To.JS.withType(ReturnType, res, globalObject, &exceptionref)); + const exception = JSC.JSValue.c(exceptionref); + if (exception != .zero) { + success = false; + break :brk exception; + } - var success = @as(JSC.Maybe(Return.ReadFile).Tag, this.result) == .result; - const result = switch (this.result) { - .err => |err| err.toJSC(globalObject), - .result => |res| brk: { - var exceptionref: JSC.C.JSValueRef = null; - const out = JSC.JSValue.c(JSC.To.JS.withType(Return.ReadFile, res, globalObject, &exceptionref)); - const exception = JSC.JSValue.c(exceptionref); - if (exception != .zero) { - success = false; - break :brk exception; + break :brk out; + }, + }; + var promise_value = this.promise.value(); + var promise = this.promise.get(); + promise_value.ensureStillAlive(); + + const tracker = this.tracker; + tracker.willDispatch(globalObject); + defer tracker.didDispatch(globalObject); + + this.deinit(); + switch (success) { + false => { + promise.reject(globalObject, result); + }, + true => { + promise.resolve(globalObject, result); + }, } + } - break :brk out; - }, - }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); - promise_value.ensureStillAlive(); - - const tracker = this.tracker; - tracker.willDispatch(globalObject); - defer tracker.didDispatch(globalObject); - - this.deinit(); - switch (success) { - false => { - promise.reject(globalObject, result); - }, - true => { - promise.resolve(globalObject, result); - }, - } - } - - pub fn deinit(this: *AsyncReadFileTask) void { - this.ref.unref(this.globalObject.bunVM()); - this.args.deinitAndUnprotect(); - this.promise.strong.deinit(); - this.arena.deinit(); - bun.default_allocator.destroy(this); - } -}; - -pub const AsyncCopyFileTask = struct { - promise: JSC.JSPromise.Strong, - args: Arguments.CopyFile, - globalObject: *JSC.JSGlobalObject, - task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, - result: JSC.Maybe(Return.CopyFile), - ref: JSC.PollRef = .{}, - arena: bun.ArenaAllocator, - tracker: JSC.AsyncTaskTracker, - - pub fn create( - globalObject: *JSC.JSGlobalObject, - copyfile_args: Arguments.CopyFile, - vm: *JSC.VirtualMachine, - arena: bun.ArenaAllocator, - ) JSC.JSValue { - var task = bun.default_allocator.create(AsyncCopyFileTask) catch @panic("out of memory"); - task.* = AsyncCopyFileTask{ - .promise = JSC.JSPromise.Strong.init(globalObject), - .args = copyfile_args, - .result = undefined, - .globalObject = globalObject, - .tracker = JSC.AsyncTaskTracker.init(vm), - .arena = arena, - }; - task.ref.ref(vm); - task.args.src.toThreadSafe(); - task.args.dest.toThreadSafe(); - task.tracker.didSchedule(globalObject); - - JSC.WorkPool.schedule(&task.task); - - return task.promise.value(); - } - - fn workPoolCallback(task: *JSC.WorkPoolTask) void { - var this: *AsyncCopyFileTask = @fieldParentPtr(AsyncCopyFileTask, "task", task); - - var node_fs = NodeFS{}; - this.result = node_fs.copyFile(this.args, .promise); - - if (this.result == .err) { - this.result.err.path = bun.default_allocator.dupe(u8, this.result.err.path) catch ""; - } - - this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, runFromJSThread)); - } - - fn runFromJSThread(this: *AsyncCopyFileTask) void { - var globalObject = this.globalObject; - var success = @as(JSC.Maybe(Return.CopyFile).Tag, this.result) == .result; - const result = switch (this.result) { - .err => |err| err.toJSC(globalObject), - .result => |res| brk: { - var exceptionref: JSC.C.JSValueRef = null; - const out = JSC.JSValue.c(JSC.To.JS.withType(Return.CopyFile, res, globalObject, &exceptionref)); - const exception = JSC.JSValue.c(exceptionref); - if (exception != .zero) { - success = false; - break :brk exception; + pub fn deinit(this: *Task) void { + if (this.result == .err) { + bun.default_allocator.free(this.result.err.path); } - break :brk out; - }, + this.ref.unref(this.globalObject.bunVM()); + this.args.deinit(); + this.promise.strong.deinit(); + bun.default_allocator.destroy(this); + } }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); - promise_value.ensureStillAlive(); - - const tracker = this.tracker; - tracker.willDispatch(globalObject); - defer tracker.didDispatch(globalObject); - - this.deinit(); - switch (success) { - false => { - promise.reject(globalObject, result); - }, - true => { - promise.resolve(globalObject, result); - }, - } - } - - pub fn deinit(this: *AsyncCopyFileTask) void { - this.ref.unref(this.globalObject.bunVM()); - this.args.deinit(); - this.promise.strong.deinit(); - this.arena.deinit(); - bun.default_allocator.destroy(this); } }; @@ -710,6 +389,16 @@ pub const Arguments = struct { this.new_path.deinit(); } + pub fn deinitAndUnprotect(this: @This()) void { + this.old_path.deinitAndUnprotect(); + this.new_path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.old_path.toThreadSafe(); + this.new_path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Rename { const old_path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -748,8 +437,16 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: *@This()) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Truncate { - const path = PathOrFileDescriptor.fromJS(ctx, arguments, arguments.arena.allocator(), exception) orelse { + const path = PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator, exception) orelse { if (exception.* == null) { JSC.throwInvalidArguments( "path must be a string or TypedArray", @@ -783,6 +480,21 @@ pub const Arguments = struct { pub fn deinit(_: *const @This()) void {} + pub fn deinitAndUnprotect(this: *const @This()) void { + this.buffers.value.unprotect(); + this.buffers.buffers.deinit(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.buffers.value.protect(); + + var clone = bun.default_allocator.dupe(std.os.iovec, this.buffers.buffers.items) catch @panic("out of memory"); + this.buffers.buffers.deinit(); + this.buffers.buffers.items = clone; + this.buffers.buffers.capacity = clone.len; + this.buffers.buffers.allocator = bun.default_allocator; + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Writev { const fd_value = arguments.nextEat() orelse { if (exception.* == null) { @@ -855,7 +567,23 @@ pub const Arguments = struct { buffers: JSC.Node.VectorArrayBuffer, position: ?u52 = 0, - pub fn deinit(_: *const @This()) void {} + pub fn deinit(this: *const @This()) void { + _ = this; + } + + pub fn deinitAndUnprotect(this: *const @This()) void { + this.buffers.value.unprotect(); + this.buffers.buffers.deinit(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.buffers.value.protect(); + var clone = bun.default_allocator.dupe(std.os.iovec, this.buffers.buffers.items) catch @panic("out of memory"); + this.buffers.buffers.deinit(); + this.buffers.buffers.items = clone; + this.buffers.buffers.capacity = clone.len; + this.buffers.buffers.allocator = bun.default_allocator; + } pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Readv { const fd_value = arguments.nextEat() orelse { @@ -932,6 +660,14 @@ pub const Arguments = struct { _ = this; } + pub fn deinitAndUnprotect(this: *@This()) void { + _ = this; + } + + pub fn toThreadSafe(this: *const @This()) void { + _ = this; + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?FTruncate { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -982,6 +718,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: *@This()) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Chown { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1040,6 +784,8 @@ pub const Arguments = struct { pub fn deinit(_: @This()) void {} + pub fn toThreadSafe(_: *const @This()) void {} + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Fchown { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -1114,6 +860,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: *@This()) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Lutimes { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1189,6 +943,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn toThreadSafe(this: *@This()) void { + this.path.toThreadSafe(); + } + + pub fn deinitAndUnprotect(this: *@This()) void { + this.path.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Chmod { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1234,6 +996,10 @@ pub const Arguments = struct { fd: FileDescriptor, mode: Mode = 0x777, + pub fn deinit(_: *const @This()) void {} + + pub fn toThreadSafe(_: *const @This()) void {} + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?FChmod { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -1303,6 +1069,10 @@ pub const Arguments = struct { this.path.deinitAndUnprotect(); } + pub fn toThreadSafe(this: *Stat) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Stat { const path = PathLike.fromJSWithAllocator(ctx, arguments, bun.default_allocator, exception) orelse { if (exception.* == null) { @@ -1356,6 +1126,8 @@ pub const Arguments = struct { pub fn deinit(_: @This()) void {} + pub fn toThreadSafe(_: *@This()) void {} + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Fstat { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -1412,6 +1184,16 @@ pub const Arguments = struct { this.new_path.deinit(); } + pub fn deinitAndUnprotect(this: *Link) void { + this.old_path.deinitAndUnprotect(); + this.new_path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *Link) void { + this.old_path.toThreadSafe(); + this.new_path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Link { const old_path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1454,6 +1236,16 @@ pub const Arguments = struct { this.new_path.deinit(); } + pub fn deinitAndUnprotect(this: Symlink) void { + this.old_path.deinitAndUnprotect(); + this.new_path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *@This()) void { + this.old_path.toThreadSafe(); + this.new_path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Symlink { const old_path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1512,6 +1304,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: *Readlink) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *Readlink) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Readlink { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1560,6 +1360,10 @@ pub const Arguments = struct { this.path.deinitAndUnprotect(); } + pub fn toThreadSafe(this: *Realpath) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Realpath { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1599,6 +1403,18 @@ pub const Arguments = struct { pub const Unlink = struct { path: PathLike, + pub fn deinit(this: Unlink) void { + this.path.deinit(); + } + + pub fn deinitAndUnprotect(this: *Unlink) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *Unlink) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Unlink { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1620,13 +1436,7 @@ pub const Arguments = struct { } }; - pub const Rm = struct { - path: PathLike, - force: bool = false, - max_retries: u32 = 0, - recursive: bool = false, - retry_delay: c_uint = 100, - }; + pub const Rm = RmDir; pub const RmDir = struct { path: PathLike, @@ -1637,6 +1447,14 @@ pub const Arguments = struct { recursive: bool = false, retry_delay: c_uint = 100, + pub fn deinitAndUnprotect(this: *RmDir) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *RmDir) void { + this.path.toThreadSafe(); + } + pub fn deinit(this: RmDir) void { this.path.deinit(); } @@ -1701,6 +1519,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: *Mkdir) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *Mkdir) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: *JSC.JSGlobalObject, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Mkdir { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1752,10 +1578,18 @@ pub const Arguments = struct { this.prefix.deinit(); } + pub fn deinitAndUnprotect(this: *MkdirTemp) void { + this.prefix.deinit(); + } + + pub fn toThreadSafe(this: *MkdirTemp) void { + this.prefix.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?MkdirTemp { const prefix_value = arguments.next() orelse return MkdirTemp{}; - var prefix = JSC.Node.SliceOrBuffer.fromJS(ctx, arguments.arena.allocator(), prefix_value) orelse { + var prefix = JSC.Node.SliceOrBuffer.fromJS(ctx, bun.default_allocator, prefix_value) orelse { if (exception.* == null) { JSC.throwInvalidArguments( "prefix must be a string or TypedArray", @@ -1810,6 +1644,10 @@ pub const Arguments = struct { this.path.deinitAndUnprotect(); } + pub fn toThreadSafe(this: *Readdir) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Readdir { const path = PathLike.fromJSWithAllocator(ctx, arguments, bun.default_allocator, exception) orelse { if (exception.* == null) { @@ -1864,6 +1702,7 @@ pub const Arguments = struct { fd: FileDescriptor, pub fn deinit(_: Close) void {} + pub fn toThreadSafe(_: Close) void {} pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Close { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { @@ -1905,6 +1744,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: Open) void { + this.path.deinitAndUnprotect(); + } + + pub fn toThreadSafe(this: *Open) void { + this.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Open { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1971,6 +1818,10 @@ pub const Arguments = struct { pub fn deinit(_: Futimes) void {} + pub fn toThreadSafe(self: *const @This()) void { + _ = self; + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Futimes { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -2052,42 +1903,6 @@ pub const Arguments = struct { } }; - pub const FSync = struct { - fd: FileDescriptor, - - pub fn deinit(_: FSync) void {} - - pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?FSync { - const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - if (exception.* == null) { - JSC.throwInvalidArguments( - "File descriptor is required", - .{}, - ctx, - exception, - ); - } - return null; - }, exception) orelse { - if (exception.* == null) { - JSC.throwInvalidArguments( - "fd must be a number", - .{}, - ctx, - exception, - ); - } - return null; - }; - - if (exception.* != null) return null; - - return FSync{ - .fd = fd, - }; - } - }; - /// Write `buffer` to the file specified by `fd`. If `buffer` is a normal object, it /// must have an own `toString` function property. /// @@ -2114,7 +1929,7 @@ pub const Arguments = struct { /// pub const Write = struct { fd: FileDescriptor, - buffer: StringOrBuffer, + buffer: JSC.Node.SliceWithUnderlyingStringOrBuffer, // buffer_val: JSC.JSValue = JSC.JSValue.zero, offset: u64 = 0, length: u64 = std.math.maxInt(u64), @@ -2123,6 +1938,10 @@ pub const Arguments = struct { pub fn deinit(_: Write) void {} + pub fn toThreadSafe(self: *@This()) void { + self.buffer.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Write { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -2150,7 +1969,7 @@ pub const Arguments = struct { if (exception.* != null) return null; - const buffer = StringOrBuffer.fromJS(ctx.ptr(), arguments.arena.allocator(), arguments.next() orelse { + const buffer = SliceWithUnderlyingStringOrBuffer.fromJS(ctx.ptr(), bun.default_allocator, arguments.next() orelse { if (exception.* == null) { JSC.throwInvalidArguments( "data is required", @@ -2177,7 +1996,7 @@ pub const Arguments = struct { .fd = fd, .buffer = buffer, .encoding = switch (buffer) { - .string => Encoding.utf8, + .SliceWithUnderlyingString => Encoding.utf8, .buffer => Encoding.buffer, }, }; @@ -2190,7 +2009,7 @@ pub const Arguments = struct { var current = current_; switch (buffer) { // fs.write(fd, string[, position[, encoding]], callback) - .string => { + .SliceWithUnderlyingString => { if (current.isNumber()) { args.position = current.to(i52); arguments.eat(); @@ -2239,6 +2058,14 @@ pub const Arguments = struct { pub fn deinit(_: Read) void {} + pub fn toThreadSafe(this: Read) void { + this.buffer.buffer.value.protect(); + } + + pub fn deinitAndUnprotect(this: *Read) void { + this.buffer.buffer.value.unprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Read { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -2377,6 +2204,10 @@ pub const Arguments = struct { self.path.deinitAndUnprotect(); } + pub fn toThreadSafe(self: *ReadFile) void { + self.path.toThreadSafe(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?ReadFile { const path = PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator, exception) orelse { if (exception.* == null) { @@ -2463,8 +2294,16 @@ pub const Arguments = struct { self.file.deinit(); } + pub fn toThreadSafe(self: *WriteFile) void { + self.file.toThreadSafe(); + } + + pub fn deinitAndUnprotect(self: *WriteFile) void { + self.file.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?WriteFile { - const file = PathOrFileDescriptor.fromJS(ctx, arguments, arguments.arena.allocator(), exception) orelse { + const file = PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator, exception) orelse { if (exception.* == null) { JSC.throwInvalidArguments( "path must be a string or a file descriptor", @@ -2478,7 +2317,7 @@ pub const Arguments = struct { if (exception.* != null) return null; - const data = StringOrBuffer.fromJS(ctx.ptr(), arguments.arena.allocator(), arguments.next() orelse { + const data = StringOrBuffer.fromJS(ctx.ptr(), bun.default_allocator, arguments.next() orelse { if (exception.* == null) { JSC.throwInvalidArguments( "data is required", @@ -2673,6 +2512,18 @@ pub const Arguments = struct { } } + pub fn toThreadSafe(this: *Exists) void { + if (this.path) |*path| { + path.toThreadSafe(); + } + } + + pub fn deinitAndUnprotect(this: *Exists) void { + if (this.path) |*path| { + path.deinitAndUnprotect(); + } + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Exists { return Exists{ .path = PathLike.fromJS(ctx, arguments, exception), @@ -2688,6 +2539,14 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn toThreadSafe(this: *Access) void { + this.path.toThreadSafe(); + } + + pub fn deinitAndUnprotect(this: *Access) void { + this.path.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Access { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -3002,6 +2861,9 @@ pub const Arguments = struct { fd: FileDescriptor, pub fn deinit(_: FdataSync) void {} + pub fn toThreadSafe(self: *const @This()) void { + _ = self; + } pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?FdataSync { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { @@ -3039,11 +2901,21 @@ pub const Arguments = struct { dest: PathLike, mode: Constants.Copyfile, - fn deinit(this: CopyFile) void { + pub fn deinit(this: CopyFile) void { this.src.deinit(); this.dest.deinit(); } + pub fn toThreadSafe(this: *CopyFile) void { + this.src.toThreadSafe(); + this.dest.toThreadSafe(); + } + + pub fn deinitAndUnprotect(this: *CopyFile) void { + this.src.deinitAndUnprotect(); + this.dest.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?CopyFile { const src = PathLike.fromJSWithAllocator(ctx, arguments, bun.default_allocator, exception) orelse { if (exception.* == null) { @@ -3196,6 +3068,9 @@ pub const Arguments = struct { pub const Fsync = struct { fd: FileDescriptor, + pub fn deinit(_: Fsync) void {} + pub fn toThreadSafe(_: *const @This()) void {} + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Fsync { const fd = JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { if (exception.* == null) { @@ -3411,69 +3286,49 @@ pub const NodeFS = struct { } pub fn appendFile(this: *NodeFS, args: Arguments.AppendFile, comptime flavor: Flavor) Maybe(Return.AppendFile) { + _ = flavor; var data = args.data.slice(); switch (args.file) { .fd => |fd| { - switch (comptime flavor) { - .sync => { - while (data.len > 0) { - const written = switch (Syscall.write(fd, data)) { - .result => |result| result, - .err => |err| return .{ .err = err }, - }; - data = data[written..]; - } - - return Maybe(Return.AppendFile).success; - }, - else => { - @compileError("Not implemented yet"); - }, + while (data.len > 0) { + const written = switch (Syscall.write(fd, data)) { + .result => |result| result, + .err => |err| return .{ .err = err }, + }; + data = data[written..]; } + + return Maybe(Return.AppendFile).success; }, .path => |path_| { const path = path_.sliceZ(&this.sync_error_buf); - switch (comptime flavor) { - .sync => { - const fd = switch (Syscall.open(path, @intFromEnum(FileSystemFlags.a), 0o000666)) { - .result => |result| result, - .err => |err| return .{ .err = err }, - }; - defer { - _ = Syscall.close(fd); - } + const fd = switch (Syscall.open(path, @intFromEnum(FileSystemFlags.a), 0o000666)) { + .result => |result| result, + .err => |err| return .{ .err = err }, + }; - while (data.len > 0) { - const written = switch (Syscall.write(fd, data)) { - .result => |result| result, - .err => |err| return .{ .err = err }, - }; - data = data[written..]; - } + defer { + _ = Syscall.close(fd); + } - return Maybe(Return.AppendFile).success; - }, - else => { - @compileError("Not implemented yet"); - }, + while (data.len > 0) { + const written = switch (Syscall.write(fd, data)) { + .result => |result| result, + .err => |err| return .{ .err = err }, + }; + data = data[written..]; } + + return Maybe(Return.AppendFile).success; }, } - - return Maybe(Return.AppendFile).todo; } pub fn close(_: *NodeFS, args: Arguments.Close, comptime flavor: Flavor) Maybe(Return.Close) { - switch (comptime flavor) { - .sync => { - return if (Syscall.close(args.fd)) |err| .{ .err = err } else Maybe(Return.Close).success; - }, - else => {}, - } - - return .{ .err = Syscall.Error.todo }; + _ = flavor; + return if (Syscall.close(args.fd)) |err| .{ .err = err } else Maybe(Return.Close).success; } // since we use a 64 KB stack buffer, we should not let this function get inlined @@ -3714,132 +3569,92 @@ pub const NodeFS = struct { } pub fn exists(this: *NodeFS, args: Arguments.Exists, comptime flavor: Flavor) Maybe(Return.Exists) { + _ = flavor; const Ret = Maybe(Return.Exists); - switch (comptime flavor) { - .sync => { - const path = args.path orelse return Ret{ .result = false }; - const slice = path.sliceZ(&this.sync_error_buf); - // access() may not work correctly on NFS file systems with UID - // mapping enabled, because UID mapping is done on the server and - // hidden from the client, which checks permissions. Similar - // problems can occur to FUSE mounts. - const rc = (system.access(slice, std.os.F_OK)); - return Ret{ .result = rc == 0 }; - }, - else => {}, - } - - return Ret.todo; + const path = args.path orelse return Ret{ .result = false }; + const slice = path.sliceZ(&this.sync_error_buf); + // access() may not work correctly on NFS file systems with UID + // mapping enabled, because UID mapping is done on the server and + // hidden from the client, which checks permissions. Similar + // problems can occur to FUSE mounts. + const rc = (system.access(slice, std.os.F_OK)); + return Ret{ .result = rc == 0 }; } pub fn chown(this: *NodeFS, args: Arguments.Chown, comptime flavor: Flavor) Maybe(Return.Chown) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fchmod).todo; } const path = args.path.sliceZ(&this.sync_error_buf); - switch (comptime flavor) { - .sync => return Syscall.chown(path, args.uid, args.gid), - else => {}, - } - - return Maybe(Return.Chown).todo; + return Syscall.chown(path, args.uid, args.gid); } /// This should almost never be async pub fn chmod(this: *NodeFS, args: Arguments.Chmod, comptime flavor: Flavor) Maybe(Return.Chmod) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fchmod).todo; } const path = args.path.sliceZ(&this.sync_error_buf); - switch (comptime flavor) { - .sync => { - return Maybe(Return.Chmod).errnoSysP(C.chmod(path, args.mode), .chmod, path) orelse - Maybe(Return.Chmod).success; - }, - else => {}, - } - - return Maybe(Return.Chmod).todo; + return Maybe(Return.Chmod).errnoSysP(C.chmod(path, args.mode), .chmod, path) orelse + Maybe(Return.Chmod).success; } /// This should almost never be async pub fn fchmod(_: *NodeFS, args: Arguments.FChmod, comptime flavor: Flavor) Maybe(Return.Fchmod) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fchmod).todo; } - switch (comptime flavor) { - .sync => { - return Syscall.fchmod(args.fd, args.mode); - }, - else => {}, - } - - return Maybe(Return.Fchmod).todo; + return Syscall.fchmod(args.fd, args.mode); } pub fn fchown(_: *NodeFS, args: Arguments.Fchown, comptime flavor: Flavor) Maybe(Return.Fchown) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fchown).todo; } - switch (comptime flavor) { - .sync => { - return Maybe(Return.Fchown).errnoSys(C.fchown(args.fd, args.uid, args.gid), .fchown) orelse - Maybe(Return.Fchown).success; - }, - else => {}, - } - - return Maybe(Return.Fchown).todo; + return Maybe(Return.Fchown).errnoSys(C.fchown(args.fd, args.uid, args.gid), .fchown) orelse + Maybe(Return.Fchown).success; } pub fn fdatasync(_: *NodeFS, args: Arguments.FdataSync, comptime flavor: Flavor) Maybe(Return.Fdatasync) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fdatasync).todo; } - switch (comptime flavor) { - .sync => return Maybe(Return.Fdatasync).errnoSys(system.fdatasync(args.fd), .fdatasync) orelse - Maybe(Return.Fdatasync).success, - else => {}, - } - - return Maybe(Return.Fdatasync).todo; + return Maybe(Return.Fdatasync).errnoSys(system.fdatasync(args.fd), .fdatasync) orelse + Maybe(Return.Fdatasync).success; } pub fn fstat(_: *NodeFS, args: Arguments.Fstat, comptime flavor: Flavor) Maybe(Return.Fstat) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fstat).todo; } - switch (comptime flavor) { - .sync => { - if (comptime Environment.isPosix) { - return switch (Syscall.fstat(args.fd)) { - .result => |result| Maybe(Return.Fstat){ .result = Stats.init(result, false) }, - .err => |err| Maybe(Return.Fstat){ .err = err }, - }; - } - }, - else => {}, + if (comptime Environment.isPosix) { + return switch (Syscall.fstat(args.fd)) { + .result => |result| Maybe(Return.Fstat){ .result = Stats.init(result, false) }, + .err => |err| Maybe(Return.Fstat){ .err = err }, + }; } return Maybe(Return.Fstat).todo; } pub fn fsync(_: *NodeFS, args: Arguments.Fsync, comptime flavor: Flavor) Maybe(Return.Fsync) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Fsync).todo; } - switch (comptime flavor) { - .sync => return Maybe(Return.Fsync).errnoSys(system.fsync(args.fd), .fsync) orelse - Maybe(Return.Fsync).success, - else => {}, - } - - return Maybe(Return.Fsync).todo; + return Maybe(Return.Fsync).errnoSys(system.fsync(args.fd), .fsync) orelse + Maybe(Return.Fsync).success; } pub fn ftruncateSync(args: Arguments.FTruncate) Maybe(Return.Ftruncate) { @@ -3847,14 +3662,11 @@ pub const NodeFS = struct { } pub fn ftruncate(_: *NodeFS, args: Arguments.FTruncate, comptime flavor: Flavor) Maybe(Return.Ftruncate) { - switch (comptime flavor) { - .sync => return ftruncateSync(args), - else => {}, - } - - return Maybe(Return.Ftruncate).todo; + _ = flavor; + return ftruncateSync(args); } pub fn futimes(_: *NodeFS, args: Arguments.Futimes, comptime flavor: Flavor) Maybe(Return.Futimes) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Futimes).todo; } @@ -3870,66 +3682,43 @@ pub const NodeFS = struct { }, }; - switch (comptime flavor) { - .sync => return if (Maybe(Return.Futimes).errnoSys(system.futimens(args.fd, ×), .futimens)) |err| - err - else - Maybe(Return.Futimes).success, - else => {}, - } - - return Maybe(Return.Futimes).todo; + return if (Maybe(Return.Futimes).errnoSys(system.futimens(args.fd, ×), .futimens)) |err| + err + else + Maybe(Return.Futimes).success; } pub fn lchmod(this: *NodeFS, args: Arguments.LCHmod, comptime flavor: Flavor) Maybe(Return.Lchmod) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Lchmod).todo; } const path = args.path.sliceZ(&this.sync_error_buf); - switch (comptime flavor) { - .sync => { - return Maybe(Return.Lchmod).errnoSysP(C.lchmod(path, args.mode), .lchmod, path) orelse - Maybe(Return.Lchmod).success; - }, - else => {}, - } - - return Maybe(Return.Lchmod).todo; + return Maybe(Return.Lchmod).errnoSysP(C.lchmod(path, args.mode), .lchmod, path) orelse + Maybe(Return.Lchmod).success; } pub fn lchown(this: *NodeFS, args: Arguments.LChown, comptime flavor: Flavor) Maybe(Return.Lchown) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Lchown).todo; } const path = args.path.sliceZ(&this.sync_error_buf); - switch (comptime flavor) { - .sync => { - return Maybe(Return.Lchown).errnoSysP(C.lchown(path, args.uid, args.gid), .lchown, path) orelse - Maybe(Return.Lchown).success; - }, - else => {}, - } - - return Maybe(Return.Lchown).todo; + return Maybe(Return.Lchown).errnoSysP(C.lchown(path, args.uid, args.gid), .lchown, path) orelse + Maybe(Return.Lchown).success; } pub fn link(this: *NodeFS, args: Arguments.Link, comptime flavor: Flavor) Maybe(Return.Link) { + _ = flavor; var new_path_buf: [bun.MAX_PATH_BYTES]u8 = undefined; const from = args.old_path.sliceZ(&this.sync_error_buf); const to = args.new_path.sliceZ(&new_path_buf); - switch (comptime flavor) { - .sync => { - return Maybe(Return.Link).errnoSysP(system.link(from, to, 0), .link, from) orelse - Maybe(Return.Link).success; - }, - else => {}, - } - - return Maybe(Return.Link).todo; + return Maybe(Return.Link).errnoSysP(system.link(from, to, 0), .link, from) orelse + Maybe(Return.Link).success; } pub fn lstat(this: *NodeFS, args: Arguments.Lstat, comptime flavor: Flavor) Maybe(Return.Lstat) { if (comptime Environment.isWindows) { @@ -3957,158 +3746,146 @@ pub const NodeFS = struct { } // Node doesn't absolute the path so we don't have to either fn mkdirNonRecursive(this: *NodeFS, args: Arguments.Mkdir, comptime flavor: Flavor) Maybe(Return.Mkdir) { - switch (comptime flavor) { - .sync => { - const path = args.path.sliceZ(&this.sync_error_buf); - return switch (Syscall.mkdir(path, args.mode)) { - .result => Maybe(Return.Mkdir){ .result = bun.String.empty }, - .err => |err| Maybe(Return.Mkdir){ .err = err }, - }; - }, - else => {}, - } + _ = flavor; - return Maybe(Return.Mkdir).todo; + const path = args.path.sliceZ(&this.sync_error_buf); + return switch (Syscall.mkdir(path, args.mode)) { + .result => Maybe(Return.Mkdir){ .result = bun.String.empty }, + .err => |err| Maybe(Return.Mkdir){ .err = err }, + }; } // TODO: windows // TODO: verify this works correctly with unicode codepoints pub fn mkdirRecursive(this: *NodeFS, args: Arguments.Mkdir, comptime flavor: Flavor) Maybe(Return.Mkdir) { + _ = flavor; const Option = Maybe(Return.Mkdir); if (comptime Environment.isWindows) return Option.todo; - switch (comptime flavor) { - // The sync version does no allocation except when returning the path - .sync => { - var buf: [bun.MAX_PATH_BYTES]u8 = undefined; - const path = args.path.sliceZWithForceCopy(&buf, true); - const len = @as(u16, @truncate(path.len)); - - // First, attempt to create the desired directory - // If that fails, then walk back up the path until we have a match - switch (Syscall.mkdir(path, args.mode)) { - .err => |err| { - switch (err.getErrno()) { - else => { - @memcpy(this.sync_error_buf[0..len], path[0..len]); - return .{ .err = err.withPath(this.sync_error_buf[0..len]) }; - }, + var buf: [bun.MAX_PATH_BYTES]u8 = undefined; + const path = args.path.sliceZWithForceCopy(&buf, true); + const len = @as(u16, @truncate(path.len)); - .EXIST => { - return Option{ .result = bun.String.empty }; - }, - // continue - .NOENT => {}, - } + // First, attempt to create the desired directory + // If that fails, then walk back up the path until we have a match + switch (Syscall.mkdir(path, args.mode)) { + .err => |err| { + switch (err.getErrno()) { + else => { + @memcpy(this.sync_error_buf[0..len], path[0..len]); + return .{ .err = err.withPath(this.sync_error_buf[0..len]) }; }, - .result => { - return Option{ - .result = if (args.path == .slice_with_underlying_string) - args.path.slice_with_underlying_string.underlying - else - bun.String.create(args.path.slice()), - }; + + .EXIST => { + return Option{ .result = bun.String.empty }; }, + // continue + .NOENT => {}, } + }, + .result => { + return Option{ + .result = if (args.path == .slice_with_underlying_string) + args.path.slice_with_underlying_string.underlying + else + bun.String.create(args.path.slice()), + }; + }, + } - var working_mem = &this.sync_error_buf; - @memcpy(working_mem[0..len], path[0..len]); + var working_mem = &this.sync_error_buf; + @memcpy(working_mem[0..len], path[0..len]); - var i: u16 = len - 1; + var i: u16 = len - 1; - // iterate backwards until creating the directory works successfully - while (i > 0) : (i -= 1) { - if (path[i] == std.fs.path.sep) { - working_mem[i] = 0; - var parent: [:0]u8 = working_mem[0..i :0]; + // iterate backwards until creating the directory works successfully + while (i > 0) : (i -= 1) { + if (path[i] == std.fs.path.sep) { + working_mem[i] = 0; + var parent: [:0]u8 = working_mem[0..i :0]; - switch (Syscall.mkdir(parent, args.mode)) { - .err => |err| { - working_mem[i] = std.fs.path.sep; - switch (err.getErrno()) { - .EXIST => { - // Handle race condition - break; - }, - .NOENT => { - continue; - }, - else => return .{ .err = err.withPath(parent) }, - } - }, - .result => { - // We found a parent that worked - working_mem[i] = std.fs.path.sep; + switch (Syscall.mkdir(parent, args.mode)) { + .err => |err| { + working_mem[i] = std.fs.path.sep; + switch (err.getErrno()) { + .EXIST => { + // Handle race condition break; }, - } - } - } - var first_match: u16 = i; - i += 1; - // after we find one that works, we go forward _after_ the first working directory - while (i < len) : (i += 1) { - if (path[i] == std.fs.path.sep) { - working_mem[i] = 0; - var parent: [:0]u8 = working_mem[0..i :0]; - - switch (Syscall.mkdir(parent, args.mode)) { - .err => |err| { - working_mem[i] = std.fs.path.sep; - switch (err.getErrno()) { - .EXIST => { - if (Environment.allow_assert) std.debug.assert(false); - continue; - }, - else => return .{ .err = err }, - } - }, - - .result => { - working_mem[i] = std.fs.path.sep; + .NOENT => { + continue; }, + else => return .{ .err = err.withPath(parent) }, } - } + }, + .result => { + // We found a parent that worked + working_mem[i] = std.fs.path.sep; + break; + }, } + } + } + var first_match: u16 = i; + i += 1; + // after we find one that works, we go forward _after_ the first working directory + while (i < len) : (i += 1) { + if (path[i] == std.fs.path.sep) { + working_mem[i] = 0; + var parent: [:0]u8 = working_mem[0..i :0]; - working_mem[len] = 0; - - // Our final directory will not have a trailing separator - // so we have to create it once again - switch (Syscall.mkdir(working_mem[0..len :0], args.mode)) { + switch (Syscall.mkdir(parent, args.mode)) { .err => |err| { + working_mem[i] = std.fs.path.sep; switch (err.getErrno()) { - // handle the race condition .EXIST => { - var display_path = bun.String.empty; - if (first_match != std.math.maxInt(u16)) { - display_path = bun.String.create(working_mem[0..first_match]); - } - return Option{ .result = display_path }; - }, - - // NOENT shouldn't happen here - else => return .{ - .err = err.withPath(path), + if (Environment.allow_assert) std.debug.assert(false); + continue; }, + else => return .{ .err = err }, } }, + .result => { - return Option{ - .result = if (first_match != std.math.maxInt(u16)) - bun.String.create(working_mem[0..first_match]) - else if (args.path == .slice_with_underlying_string) - args.path.slice_with_underlying_string.underlying - else - bun.String.create(args.path.slice()), - }; + working_mem[i] = std.fs.path.sep; }, } - }, - else => {}, + } } - return Maybe(Return.Mkdir).todo; + working_mem[len] = 0; + + // Our final directory will not have a trailing separator + // so we have to create it once again + switch (Syscall.mkdir(working_mem[0..len :0], args.mode)) { + .err => |err| { + switch (err.getErrno()) { + // handle the race condition + .EXIST => { + var display_path = bun.String.empty; + if (first_match != std.math.maxInt(u16)) { + display_path = bun.String.create(working_mem[0..first_match]); + } + return Option{ .result = display_path }; + }, + + // NOENT shouldn't happen here + else => return .{ + .err = err.withPath(path), + }, + } + }, + .result => { + return Option{ + .result = if (first_match != std.math.maxInt(u16)) + bun.String.create(working_mem[0..first_match]) + else if (args.path == .slice_with_underlying_string) + args.path.slice_with_underlying_string.underlying + else + bun.String.create(args.path.slice()), + }; + }, + } } pub fn mkdtemp(this: *NodeFS, args: Arguments.MkdirTemp, comptime _: Flavor) Maybe(Return.Mkdtemp) { @@ -4136,75 +3913,54 @@ pub const NodeFS = struct { return .{ .err = Syscall.Error{ .errno = @as(Syscall.Error.Int, @truncate(@intFromEnum(errno))), .syscall = .mkdtemp } }; } pub fn open(this: *NodeFS, args: Arguments.Open, comptime flavor: Flavor) Maybe(Return.Open) { - switch (comptime flavor) { - // The sync version does no allocation except when returning the path - .sync => { - const path = args.path.sliceZ(&this.sync_error_buf); - return switch (Syscall.open(path, @intFromEnum(args.flags), args.mode)) { - .err => |err| .{ - .err = err.withPath(args.path.slice()), - }, - .result => |fd| .{ .result = fd }, - }; + _ = flavor; + const path = args.path.sliceZ(&this.sync_error_buf); + return switch (Syscall.open(path, @intFromEnum(args.flags), args.mode)) { + .err => |err| .{ + .err = err.withPath(args.path.slice()), }, - else => {}, - } - - return Maybe(Return.Open).todo; + .result => |fd| .{ .result = fd }, + }; } pub fn openDir(_: *NodeFS, _: Arguments.OpenDir, comptime _: Flavor) Maybe(Return.OpenDir) { return Maybe(Return.OpenDir).todo; } fn _read(_: *NodeFS, args: Arguments.Read, comptime flavor: Flavor) Maybe(Return.Read) { + _ = flavor; if (Environment.allow_assert) std.debug.assert(args.position == null); + var buf = args.buffer.slice(); + buf = buf[@min(args.offset, buf.len)..]; + buf = buf[0..@min(buf.len, args.length)]; - switch (comptime flavor) { - // The sync version does no allocation except when returning the path - .sync => { - var buf = args.buffer.slice(); - buf = buf[@min(args.offset, buf.len)..]; - buf = buf[0..@min(buf.len, args.length)]; - - return switch (Syscall.read(args.fd, buf)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ - .result = .{ - .bytes_read = @as(u52, @truncate(amt)), - }, - }, - }; + return switch (Syscall.read(args.fd, buf)) { + .err => |err| .{ + .err = err, }, - else => {}, - } - - return Maybe(Return.Read).todo; + .result => |amt| .{ + .result = .{ + .bytes_read = @as(u52, @truncate(amt)), + }, + }, + }; } fn _pread(_: *NodeFS, args: Arguments.Read, comptime flavor: Flavor) Maybe(Return.Read) { - switch (comptime flavor) { - .sync => { - var buf = args.buffer.slice(); - buf = buf[@min(args.offset, buf.len)..]; - buf = buf[0..@min(buf.len, args.length)]; - - return switch (Syscall.pread(args.fd, buf, args.position.?)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ - .result = .{ - .bytes_read = @as(u52, @truncate(amt)), - }, - }, - }; - }, - else => {}, - } + _ = flavor; + var buf = args.buffer.slice(); + buf = buf[@min(args.offset, buf.len)..]; + buf = buf[0..@min(buf.len, args.length)]; - return Maybe(Return.Read).todo; + return switch (Syscall.pread(args.fd, buf, args.position.?)) { + .err => |err| .{ + .err = err, + }, + .result => |amt| .{ + .result = .{ + .bytes_read = @as(u52, @truncate(amt)), + }, + }, + }; } pub fn read(this: *NodeFS, args: Arguments.Read, comptime flavor: Flavor) Maybe(Return.Read) { @@ -4236,127 +3992,91 @@ pub const NodeFS = struct { return if (args.position != null) _pwrite(this, args, flavor) else _write(this, args, flavor); } fn _write(_: *NodeFS, args: Arguments.Write, comptime flavor: Flavor) Maybe(Return.Write) { - switch (comptime flavor) { - .sync => { - var buf = args.buffer.slice(); - buf = buf[@min(args.offset, buf.len)..]; - buf = buf[0..@min(buf.len, args.length)]; - - return switch (Syscall.write(args.fd, buf)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ - .result = .{ - .bytes_written = @as(u52, @truncate(amt)), - }, - }, - }; - }, - else => {}, - } + _ = flavor; + + var buf = args.buffer.slice(); + buf = buf[@min(args.offset, buf.len)..]; + buf = buf[0..@min(buf.len, args.length)]; - return Maybe(Return.Write).todo; + return switch (Syscall.write(args.fd, buf)) { + .err => |err| .{ + .err = err, + }, + .result => |amt| .{ + .result = .{ + .bytes_written = @as(u52, @truncate(amt)), + }, + }, + }; } fn _pwrite(_: *NodeFS, args: Arguments.Write, comptime flavor: Flavor) Maybe(Return.Write) { + _ = flavor; const position = args.position.?; - switch (comptime flavor) { - .sync => { - var buf = args.buffer.slice(); - buf = buf[@min(args.offset, buf.len)..]; - buf = buf[0..@min(args.length, buf.len)]; + var buf = args.buffer.slice(); + buf = buf[@min(args.offset, buf.len)..]; + buf = buf[0..@min(args.length, buf.len)]; - return switch (Syscall.pwrite(args.fd, buf, position)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ .result = .{ - .bytes_written = @as(u52, @truncate(amt)), - } }, - }; + return switch (Syscall.pwrite(args.fd, buf, position)) { + .err => |err| .{ + .err = err, }, - else => {}, - } - - return Maybe(Return.Write).todo; + .result => |amt| .{ .result = .{ + .bytes_written = @as(u52, @truncate(amt)), + } }, + }; } fn _preadv(_: *NodeFS, args: Arguments.Readv, comptime flavor: Flavor) Maybe(Return.Readv) { + _ = flavor; const position = args.position.?; - switch (comptime flavor) { - .sync => { - return switch (Syscall.preadv(args.fd, args.buffers.buffers.items, position)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ .result = .{ - .bytes_read = @as(u52, @truncate(amt)), - } }, - }; + return switch (Syscall.preadv(args.fd, args.buffers.buffers.items, position)) { + .err => |err| .{ + .err = err, }, - else => {}, - } - - return Maybe(Return.Write).todo; + .result => |amt| .{ .result = .{ + .bytes_read = @as(u52, @truncate(amt)), + } }, + }; } fn _readv(_: *NodeFS, args: Arguments.Readv, comptime flavor: Flavor) Maybe(Return.Readv) { - switch (comptime flavor) { - .sync => { - return switch (Syscall.readv(args.fd, args.buffers.buffers.items)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ .result = .{ - .bytes_read = @as(u52, @truncate(amt)), - } }, - }; + _ = flavor; + return switch (Syscall.readv(args.fd, args.buffers.buffers.items)) { + .err => |err| .{ + .err = err, }, - else => {}, - } - - return Maybe(Return.Write).todo; + .result => |amt| .{ .result = .{ + .bytes_read = @as(u52, @truncate(amt)), + } }, + }; } fn _pwritev(_: *NodeFS, args: Arguments.Writev, comptime flavor: Flavor) Maybe(Return.Write) { + _ = flavor; const position = args.position.?; - - switch (comptime flavor) { - .sync => { - return switch (Syscall.pwritev(args.fd, args.buffers.buffers.items, position)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ .result = .{ - .bytes_written = @as(u52, @truncate(amt)), - } }, - }; + return switch (Syscall.pwritev(args.fd, args.buffers.buffers.items, position)) { + .err => |err| .{ + .err = err, }, - else => {}, - } - - return Maybe(Return.Write).todo; + .result => |amt| .{ .result = .{ + .bytes_written = @as(u52, @truncate(amt)), + } }, + }; } fn _writev(_: *NodeFS, args: Arguments.Writev, comptime flavor: Flavor) Maybe(Return.Write) { - switch (comptime flavor) { - .sync => { - return switch (Syscall.writev(args.fd, args.buffers.buffers.items)) { - .err => |err| .{ - .err = err, - }, - .result => |amt| .{ .result = .{ - .bytes_written = @as(u52, @truncate(amt)), - } }, - }; + _ = flavor; + return switch (Syscall.writev(args.fd, args.buffers.buffers.items)) { + .err => |err| .{ + .err = err, }, - else => {}, - } - - return Maybe(Return.Write).todo; + .result => |amt| .{ .result = .{ + .bytes_written = @as(u52, @truncate(amt)), + } }, + }; } pub fn readdir(this: *NodeFS, args: Arguments.Readdir, comptime flavor: Flavor) Maybe(Return.Readdir) { @@ -4751,50 +4471,39 @@ pub const NodeFS = struct { return Maybe(Return.WriteFile).success; } - pub fn writeFile(this: *NodeFS, args: Arguments.WriteFile, comptime flavor: Flavor) Maybe(Return.WriteFile) { - switch (comptime flavor) { - .sync => return writeFileWithPathBuffer(&this.sync_error_buf, args), - else => {}, - } - - return Maybe(Return.WriteFile).todo; + pub fn writeFile(this: *NodeFS, args: Arguments.WriteFile, comptime _: Flavor) Maybe(Return.WriteFile) { + return writeFileWithPathBuffer(&this.sync_error_buf, args); } - pub fn readlink(this: *NodeFS, args: Arguments.Readlink, comptime flavor: Flavor) Maybe(Return.Readlink) { + pub fn readlink(this: *NodeFS, args: Arguments.Readlink, comptime _: Flavor) Maybe(Return.Readlink) { var outbuf: [bun.MAX_PATH_BYTES]u8 = undefined; var inbuf = &this.sync_error_buf; - switch (comptime flavor) { - .sync => { - const path = args.path.sliceZ(inbuf); - const len = switch (Syscall.readlink(path, &outbuf)) { - .err => |err| return .{ - .err = err.withPath(args.path.slice()), - }, - .result => |buf_| buf_, - }; + const path = args.path.sliceZ(inbuf); - return .{ - .result = switch (args.encoding) { - .buffer => .{ - .buffer = Buffer.fromString(outbuf[0..len], bun.default_allocator) catch unreachable, - }, - else => if (args.path == .slice_with_underlying_string and - strings.eqlLong(args.path.slice_with_underlying_string.slice(), outbuf[0..len], true)) - .{ - .BunString = args.path.slice_with_underlying_string.underlying.dupeRef(), - } - else - .{ - .BunString = bun.String.create(outbuf[0..len]), - }, - }, - }; + const len = switch (Syscall.readlink(path, &outbuf)) { + .err => |err| return .{ + .err = err.withPath(args.path.slice()), }, - else => {}, - } + .result => |buf_| buf_, + }; - return Maybe(Return.Readlink).todo; + return .{ + .result = switch (args.encoding) { + .buffer => .{ + .buffer = Buffer.fromString(outbuf[0..len], bun.default_allocator) catch unreachable, + }, + else => if (args.path == .slice_with_underlying_string and + strings.eqlLong(args.path.slice_with_underlying_string.slice(), outbuf[0..len], true)) + .{ + .BunString = args.path.slice_with_underlying_string.underlying.dupeRef(), + } + else + .{ + .BunString = bun.String.create(outbuf[0..len]), + }, + }, + }; } pub fn realpath(this: *NodeFS, args: Arguments.Realpath, comptime _: Flavor) Maybe(Return.Realpath) { var outbuf: [bun.MAX_PATH_BYTES]u8 = undefined; @@ -4857,325 +4566,309 @@ pub const NodeFS = struct { // return error.NotImplementedYet; // } pub fn rename(this: *NodeFS, args: Arguments.Rename, comptime flavor: Flavor) Maybe(Return.Rename) { + _ = flavor; var from_buf = &this.sync_error_buf; var to_buf: [bun.MAX_PATH_BYTES]u8 = undefined; - switch (comptime flavor) { - .sync => { - var from = args.old_path.sliceZ(from_buf); - var to = args.new_path.sliceZ(&to_buf); - return Syscall.rename(from, to); - }, - else => {}, - } - - return Maybe(Return.Rename).todo; + var from = args.old_path.sliceZ(from_buf); + var to = args.new_path.sliceZ(&to_buf); + return Syscall.rename(from, to); } pub fn rmdir(this: *NodeFS, args: Arguments.RmDir, comptime flavor: Flavor) Maybe(Return.Rmdir) { - switch (comptime flavor) { - .sync => { - if (comptime Environment.isMac) { - if (args.recursive) { - var dest = args.path.sliceZ(&this.sync_error_buf); - - var flags: u32 = bun.C.darwin.RemoveFileFlags.cross_mount | - bun.C.darwin.RemoveFileFlags.allow_long_paths | - bun.C.darwin.RemoveFileFlags.recursive; - - while (true) { - if (Maybe(Return.Rmdir).errnoSys(bun.C.darwin.removefileat(std.os.AT.FDCWD, dest, null, flags), .rmdir)) |errno| { - switch (@as(os.E, @enumFromInt(errno.err.errno))) { + _ = flavor; + + if (comptime Environment.isMac) { + if (args.recursive) { + var dest = args.path.sliceZ(&this.sync_error_buf); + + var flags: u32 = bun.C.darwin.RemoveFileFlags.cross_mount | + bun.C.darwin.RemoveFileFlags.allow_long_paths | + bun.C.darwin.RemoveFileFlags.recursive; + + while (true) { + if (Maybe(Return.Rmdir).errnoSys(bun.C.darwin.removefileat(std.os.AT.FDCWD, dest, null, flags), .rmdir)) |errno| { + switch (@as(os.E, @enumFromInt(errno.err.errno))) { + .AGAIN, .INTR => continue, + .NOENT => return Maybe(Return.Rmdir).success, + .MLINK => { + var copy: [bun.MAX_PATH_BYTES]u8 = undefined; + @memcpy(copy[0..dest.len], dest); + copy[dest.len] = 0; + var dest_copy = copy[0..dest.len :0]; + switch (Syscall.unlink(dest_copy).getErrno()) { .AGAIN, .INTR => continue, - .NOENT => return Maybe(Return.Rmdir).success, - .MLINK => { - var copy: [bun.MAX_PATH_BYTES]u8 = undefined; - @memcpy(copy[0..dest.len], dest); - copy[dest.len] = 0; - var dest_copy = copy[0..dest.len :0]; - switch (Syscall.unlink(dest_copy).getErrno()) { - .AGAIN, .INTR => continue, - .NOENT => return errno, - .SUCCESS => continue, - else => return errno, - } - }, - .SUCCESS => unreachable, + .NOENT => return errno, + .SUCCESS => continue, else => return errno, } - } - - return Maybe(Return.Rmdir).success; + }, + .SUCCESS => unreachable, + else => return errno, } } - return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse - Maybe(Return.Rmdir).success; - } else if (comptime Environment.isLinux) { - if (args.recursive) { - std.fs.cwd().deleteTree(args.path.slice()) catch |err| { - const errno: std.os.E = switch (err) { - error.InvalidHandle => .BADF, - error.AccessDenied => .PERM, - error.FileTooBig => .FBIG, - error.SymLinkLoop => .LOOP, - error.ProcessFdQuotaExceeded => .NFILE, - error.NameTooLong => .NAMETOOLONG, - error.SystemFdQuotaExceeded => .MFILE, - error.SystemResources => .NOMEM, - error.ReadOnlyFileSystem => .ROFS, - error.FileSystem => .IO, - error.FileBusy => .BUSY, - error.DeviceBusy => .BUSY, - - // One of the path components was not a directory. - // This error is unreachable if `sub_path` does not contain a path separator. - error.NotDir => .NOTDIR, - // On Windows, file paths must be valid Unicode. - error.InvalidUtf8 => .INVAL, - - // On Windows, file paths cannot contain these characters: - // '/', '*', '?', '"', '<', '>', '|' - error.BadPathName => .INVAL, - - else => .FAULT, - }; - return Maybe(Return.Rm){ - .err = bun.sys.Error.fromCode(errno, .rmdir), - }; - }; + return Maybe(Return.Rmdir).success; + } + } - return Maybe(Return.Rmdir).success; - } + return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse + Maybe(Return.Rmdir).success; + } else if (comptime Environment.isLinux) { + if (args.recursive) { + std.fs.cwd().deleteTree(args.path.slice()) catch |err| { + const errno: std.os.E = switch (err) { + error.InvalidHandle => .BADF, + error.AccessDenied => .PERM, + error.FileTooBig => .FBIG, + error.SymLinkLoop => .LOOP, + error.ProcessFdQuotaExceeded => .NFILE, + error.NameTooLong => .NAMETOOLONG, + error.SystemFdQuotaExceeded => .MFILE, + error.SystemResources => .NOMEM, + error.ReadOnlyFileSystem => .ROFS, + error.FileSystem => .IO, + error.FileBusy => .BUSY, + error.DeviceBusy => .BUSY, + + // One of the path components was not a directory. + // This error is unreachable if `sub_path` does not contain a path separator. + error.NotDir => .NOTDIR, + // On Windows, file paths must be valid Unicode. + error.InvalidUtf8 => .INVAL, + + // On Windows, file paths cannot contain these characters: + // '/', '*', '?', '"', '<', '>', '|' + error.BadPathName => .INVAL, + + else => .FAULT, + }; + return Maybe(Return.Rm){ + .err = bun.sys.Error.fromCode(errno, .rmdir), + }; + }; - return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse - Maybe(Return.Rmdir).success; - } - }, - else => {}, - } + return Maybe(Return.Rmdir).success; + } - return Maybe(Return.Rmdir).todo; + return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse + Maybe(Return.Rmdir).success; + } } pub fn rm(this: *NodeFS, args: Arguments.RmDir, comptime flavor: Flavor) Maybe(Return.Rm) { - switch (comptime flavor) { - .sync => { - if (comptime Environment.isMac) { - var dest = args.path.sliceZ(&this.sync_error_buf); - - while (true) { - var flags: u32 = 0; - if (args.recursive) { - flags |= bun.C.darwin.RemoveFileFlags.cross_mount; - flags |= bun.C.darwin.RemoveFileFlags.allow_long_paths; - flags |= bun.C.darwin.RemoveFileFlags.recursive; - } + _ = flavor; + + if (comptime Environment.isMac) { + var dest = args.path.sliceZ(&this.sync_error_buf); - if (Maybe(Return.Rm).errnoSys(bun.C.darwin.removefileat(std.os.AT.FDCWD, dest, null, flags), .unlink)) |errno| { - switch (@as(os.E, @enumFromInt(errno.err.errno))) { + while (true) { + var flags: u32 = 0; + if (args.recursive) { + flags |= bun.C.darwin.RemoveFileFlags.cross_mount; + flags |= bun.C.darwin.RemoveFileFlags.allow_long_paths; + flags |= bun.C.darwin.RemoveFileFlags.recursive; + } + + if (Maybe(Return.Rm).errnoSys(bun.C.darwin.removefileat(std.os.AT.FDCWD, dest, null, flags), .unlink)) |errno| { + switch (@as(os.E, @enumFromInt(errno.err.errno))) { + .AGAIN, .INTR => continue, + .NOENT => { + if (args.force) { + return Maybe(Return.Rm).success; + } + + return errno; + }, + + .MLINK => { + var copy: [bun.MAX_PATH_BYTES]u8 = undefined; + @memcpy(copy[0..dest.len], dest); + copy[dest.len] = 0; + var dest_copy = copy[0..dest.len :0]; + switch (Syscall.unlink(dest_copy).getErrno()) { .AGAIN, .INTR => continue, .NOENT => { if (args.force) { - return Maybe(Return.Rm).success; + continue; } return errno; }, - - .MLINK => { - var copy: [bun.MAX_PATH_BYTES]u8 = undefined; - @memcpy(copy[0..dest.len], dest); - copy[dest.len] = 0; - var dest_copy = copy[0..dest.len :0]; - switch (Syscall.unlink(dest_copy).getErrno()) { - .AGAIN, .INTR => continue, - .NOENT => { - if (args.force) { - continue; - } - - return errno; - }, - .SUCCESS => continue, - else => return errno, - } - }, - .SUCCESS => unreachable, + .SUCCESS => continue, else => return errno, } - } - - return Maybe(Return.Rm).success; - } - } else if (comptime Environment.isLinux or Environment.isWindows) { - if (args.recursive) { - std.fs.cwd().deleteTree(args.path.slice()) catch |err| { - const errno: E = switch (err) { - error.InvalidHandle => .BADF, - error.AccessDenied => .PERM, - error.FileTooBig => .FBIG, - error.SymLinkLoop => .LOOP, - error.ProcessFdQuotaExceeded => .NFILE, - error.NameTooLong => .NAMETOOLONG, - error.SystemFdQuotaExceeded => .MFILE, - error.SystemResources => .NOMEM, - error.ReadOnlyFileSystem => .ROFS, - error.FileSystem => .IO, - error.FileBusy => .BUSY, - error.DeviceBusy => .BUSY, - - // One of the path components was not a directory. - // This error is unreachable if `sub_path` does not contain a path separator. - error.NotDir => .NOTDIR, - // On Windows, file paths must be valid Unicode. - error.InvalidUtf8 => .INVAL, - - // On Windows, file paths cannot contain these characters: - // '/', '*', '?', '"', '<', '>', '|' - error.BadPathName => .INVAL, - - else => .FAULT, - }; - if (args.force) { - return Maybe(Return.Rm).success; - } - return Maybe(Return.Rm){ - .err = bun.sys.Error.fromCode(errno, .unlink), - }; - }; - return Maybe(Return.Rm).success; + }, + .SUCCESS => unreachable, + else => return errno, } } - if (comptime Environment.isPosix) { - var dest = args.path.osPath(&this.sync_error_buf); - std.os.unlinkZ(dest) catch |er| { - // empircally, it seems to return AccessDenied when the - // file is actually a directory on macOS. - if (args.recursive and - (er == error.IsDir or er == error.NotDir or er == error.AccessDenied)) - { - std.os.rmdirZ(dest) catch |err| { - if (args.force) { - return Maybe(Return.Rm).success; - } - - const code: E = switch (err) { - error.AccessDenied => .PERM, - error.SymLinkLoop => .LOOP, - error.NameTooLong => .NAMETOOLONG, - error.SystemResources => .NOMEM, - error.ReadOnlyFileSystem => .ROFS, - error.FileBusy => .BUSY, - error.FileNotFound => .NOENT, - error.InvalidUtf8 => .INVAL, - error.BadPathName => .INVAL, - else => .FAULT, - }; - - return .{ - .err = bun.sys.Error.fromCode( - code, - .rmdir, - ), - }; - }; - - return Maybe(Return.Rm).success; - } + return Maybe(Return.Rm).success; + } + } else if (comptime Environment.isLinux or Environment.isWindows) { + if (args.recursive) { + std.fs.cwd().deleteTree(args.path.slice()) catch |err| { + const errno: E = switch (err) { + error.InvalidHandle => .BADF, + error.AccessDenied => .PERM, + error.FileTooBig => .FBIG, + error.SymLinkLoop => .LOOP, + error.ProcessFdQuotaExceeded => .NFILE, + error.NameTooLong => .NAMETOOLONG, + error.SystemFdQuotaExceeded => .MFILE, + error.SystemResources => .NOMEM, + error.ReadOnlyFileSystem => .ROFS, + error.FileSystem => .IO, + error.FileBusy => .BUSY, + error.DeviceBusy => .BUSY, + + // One of the path components was not a directory. + // This error is unreachable if `sub_path` does not contain a path separator. + error.NotDir => .NOTDIR, + // On Windows, file paths must be valid Unicode. + error.InvalidUtf8 => .INVAL, + + // On Windows, file paths cannot contain these characters: + // '/', '*', '?', '"', '<', '>', '|' + error.BadPathName => .INVAL, + + else => .FAULT, + }; + if (args.force) { + return Maybe(Return.Rm).success; + } + return Maybe(Return.Rm){ + .err = bun.sys.Error.fromCode(errno, .unlink), + }; + }; + return Maybe(Return.Rm).success; + } + } + if (comptime Environment.isPosix) { + var dest = args.path.osPath(&this.sync_error_buf); + std.os.unlinkZ(dest) catch |er| { + // empircally, it seems to return AccessDenied when the + // file is actually a directory on macOS. + if (args.recursive and + (er == error.IsDir or er == error.NotDir or er == error.AccessDenied)) + { + std.os.rmdirZ(dest) catch |err| { if (args.force) { return Maybe(Return.Rm).success; } - { - const code: E = switch (er) { - error.AccessDenied => .PERM, - error.SymLinkLoop => .LOOP, - error.NameTooLong => .NAMETOOLONG, - error.SystemResources => .NOMEM, - error.ReadOnlyFileSystem => .ROFS, - error.FileBusy => .BUSY, - error.InvalidUtf8 => .INVAL, - error.BadPathName => .INVAL, - error.FileNotFound => .NOENT, - else => .FAULT, - }; + const code: E = switch (err) { + error.AccessDenied => .PERM, + error.SymLinkLoop => .LOOP, + error.NameTooLong => .NAMETOOLONG, + error.SystemResources => .NOMEM, + error.ReadOnlyFileSystem => .ROFS, + error.FileBusy => .BUSY, + error.FileNotFound => .NOENT, + error.InvalidUtf8 => .INVAL, + error.BadPathName => .INVAL, + else => .FAULT, + }; - return .{ - .err = bun.sys.Error.fromCode( - code, - .unlink, - ), - }; - } + return .{ + .err = bun.sys.Error.fromCode( + code, + .rmdir, + ), + }; }; return Maybe(Return.Rm).success; } - if (comptime Environment.isWindows) { - var dest = args.path.osPath(&this.sync_error_buf); - std.os.windows.DeleteFile(dest, .{ - .dir = null, - .remove_dir = brk: { - const file_attrs = std.os.windows.GetFileAttributesW(dest.ptr) catch |err| { - if (args.force) { - return Maybe(Return.Rm).success; - } + if (args.force) { + return Maybe(Return.Rm).success; + } - const code: E = switch (err) { - error.FileNotFound => .NOENT, - error.PermissionDenied => .PERM, - else => .INVAL, - }; + { + const code: E = switch (er) { + error.AccessDenied => .PERM, + error.SymLinkLoop => .LOOP, + error.NameTooLong => .NAMETOOLONG, + error.SystemResources => .NOMEM, + error.ReadOnlyFileSystem => .ROFS, + error.FileBusy => .BUSY, + error.InvalidUtf8 => .INVAL, + error.BadPathName => .INVAL, + error.FileNotFound => .NOENT, + else => .FAULT, + }; - return .{ - .err = bun.sys.Error.fromCode( - code, - .unlink, - ), - }; - }; - // TODO: check FILE_ATTRIBUTE_INVALID - break :brk (file_attrs & std.os.windows.FILE_ATTRIBUTE_DIRECTORY) != 0; - }, - }) catch |er| { - // empircally, it seems to return AccessDenied when the - // file is actually a directory on macOS. + return .{ + .err = bun.sys.Error.fromCode( + code, + .unlink, + ), + }; + } + }; + + return Maybe(Return.Rm).success; + } + if (comptime Environment.isWindows) { + var dest = args.path.osPath(&this.sync_error_buf); + std.os.windows.DeleteFile(dest, .{ + .dir = null, + .remove_dir = brk: { + const file_attrs = std.os.windows.GetFileAttributesW(dest.ptr) catch |err| { if (args.force) { return Maybe(Return.Rm).success; } - { - const code: E = switch (er) { - error.FileNotFound => .NOENT, - error.AccessDenied => .PERM, - error.NameTooLong => .INVAL, - error.FileBusy => .BUSY, - error.NotDir => .NOTDIR, - error.IsDir => .ISDIR, - error.DirNotEmpty => .INVAL, - error.NetworkNotFound => .NOENT, - else => .UNKNOWN, - }; + const code: E = switch (err) { + error.FileNotFound => .NOENT, + error.PermissionDenied => .PERM, + else => .INVAL, + }; - return .{ - .err = bun.sys.Error.fromCode( - code, - .unlink, - ), - }; - } + return .{ + .err = bun.sys.Error.fromCode( + code, + .unlink, + ), + }; }; + // TODO: check FILE_ATTRIBUTE_INVALID + break :brk (file_attrs & std.os.windows.FILE_ATTRIBUTE_DIRECTORY) != 0; + }, + }) catch |er| { + // empircally, it seems to return AccessDenied when the + // file is actually a directory on macOS. + if (args.force) { return Maybe(Return.Rm).success; } - }, - else => {}, - } - return Maybe(Return.Rm).todo; + { + const code: E = switch (er) { + error.FileNotFound => .NOENT, + error.AccessDenied => .PERM, + error.NameTooLong => .INVAL, + error.FileBusy => .BUSY, + error.NotDir => .NOTDIR, + error.IsDir => .ISDIR, + error.DirNotEmpty => .INVAL, + error.NetworkNotFound => .NOENT, + else => .UNKNOWN, + }; + + return .{ + .err = bun.sys.Error.fromCode( + code, + .unlink, + ), + }; + } + }; + + return Maybe(Return.Rm).success; + } } pub fn stat(this: *NodeFS, args: Arguments.Stat, comptime flavor: Flavor) Maybe(Return.Stat) { if (comptime Environment.isWindows) { @@ -5199,38 +4892,26 @@ pub const NodeFS = struct { } pub fn symlink(this: *NodeFS, args: Arguments.Symlink, comptime flavor: Flavor) Maybe(Return.Symlink) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Symlink).todo; } var to_buf: [bun.MAX_PATH_BYTES]u8 = undefined; - switch (comptime flavor) { - .sync => { - return Syscall.symlink( - args.old_path.sliceZ(&this.sync_error_buf), - args.new_path.sliceZ(&to_buf), - ); - }, - else => {}, - } - - return Maybe(Return.Symlink).todo; + return Syscall.symlink( + args.old_path.sliceZ(&this.sync_error_buf), + args.new_path.sliceZ(&to_buf), + ); } fn _truncate(this: *NodeFS, path: PathLike, len: JSC.WebCore.Blob.SizeType, comptime flavor: Flavor) Maybe(Return.Truncate) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Truncate).todo; } - switch (comptime flavor) { - .sync => { - return Maybe(Return.Truncate).errno(C.truncate(path.sliceZ(&this.sync_error_buf), len)) orelse - Maybe(Return.Truncate).success; - }, - else => {}, - } - - return Maybe(Return.Truncate).todo; + return Maybe(Return.Truncate).errno(C.truncate(path.sliceZ(&this.sync_error_buf), len)) orelse + Maybe(Return.Truncate).success; } pub fn truncate(this: *NodeFS, args: Arguments.Truncate, comptime flavor: Flavor) Maybe(Return.Truncate) { return switch (args.path) { @@ -5246,19 +4927,13 @@ pub const NodeFS = struct { }; } pub fn unlink(this: *NodeFS, args: Arguments.Unlink, comptime flavor: Flavor) Maybe(Return.Unlink) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Unlink).todo; } - switch (comptime flavor) { - .sync => { - return Maybe(Return.Unlink).errnoSysP(system.unlink(args.path.sliceZ(&this.sync_error_buf)), .unlink, args.path.slice()) orelse - Maybe(Return.Unlink).success; - }, - else => {}, - } - - return Maybe(Return.Unlink).todo; + return Maybe(Return.Unlink).errnoSysP(system.unlink(args.path.sliceZ(&this.sync_error_buf)), .unlink, args.path.slice()) orelse + Maybe(Return.Unlink).success; } pub fn watchFile(_: *NodeFS, args: Arguments.WatchFile, comptime flavor: Flavor) Maybe(Return.WatchFile) { std.debug.assert(flavor == .sync); @@ -5283,6 +4958,7 @@ pub const NodeFS = struct { return Maybe(Return.UnwatchFile).todo; } pub fn utimes(this: *NodeFS, args: Arguments.Utimes, comptime flavor: Flavor) Maybe(Return.Utimes) { + _ = flavor; if (comptime Environment.isWindows) { return Maybe(Return.Utimes).todo; } @@ -5300,21 +4976,13 @@ pub const NodeFS = struct { }, }; - switch (comptime flavor) { - // futimes uses the syscall version - // we use libc because here, not for a good reason - // just missing from the linux syscall interface in zig and I don't want to modify that right now - .sync => return if (Maybe(Return.Utimes).errnoSysP(std.c.utimes(args.path.sliceZ(&this.sync_error_buf), ×), .utimes, args.path.slice())) |err| - err - else - Maybe(Return.Utimes).success, - else => {}, - } - - return Maybe(Return.Utimes).todo; + return if (Maybe(Return.Utimes).errnoSysP(std.c.utimes(args.path.sliceZ(&this.sync_error_buf), ×), .utimes, args.path.slice())) |err| + err + else + Maybe(Return.Utimes).success; } - pub fn lutimes(this: *NodeFS, args: Arguments.Lutimes, comptime flavor: Flavor) Maybe(Return.Lutimes) { + pub fn lutimes(this: *NodeFS, args: Arguments.Lutimes, comptime _: Flavor) Maybe(Return.Lutimes) { if (comptime Environment.isWindows) { return Maybe(Return.Lutimes).todo; } @@ -5332,18 +5000,10 @@ pub const NodeFS = struct { }, }; - switch (comptime flavor) { - // futimes uses the syscall version - // we use libc because here, not for a good reason - // just missing from the linux syscall interface in zig and I don't want to modify that right now - .sync => return if (Maybe(Return.Lutimes).errnoSysP(C.lutimes(args.path.sliceZ(&this.sync_error_buf), ×), .lutimes, args.path.slice())) |err| - err - else - Maybe(Return.Lutimes).success, - else => {}, - } - - return Maybe(Return.Lutimes).todo; + return if (Maybe(Return.Lutimes).errnoSysP(C.lutimes(args.path.sliceZ(&this.sync_error_buf), ×), .lutimes, args.path.slice())) |err| + err + else + Maybe(Return.Lutimes).success; } pub fn watch(_: *NodeFS, args: Arguments.Watch, comptime _: Flavor) Maybe(Return.Watch) { if (comptime Environment.isWindows) { diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index b3866b557..db4d79fc9 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -67,6 +67,7 @@ fn callSync(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { args, comptime Flavor.sync, ); + switch (result) { .err => |err| { globalObject.throwValue(JSC.JSValue.c(err.toJS(globalObject))); @@ -108,14 +109,6 @@ fn call(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, ) callconv(.C) JSC.JSValue { - switch (comptime FunctionEnum) { - .readdir, .lstat, .stat, .readFile, .realpath, .copyFile, .cp => {}, - else => { - globalObject.throw("Not implemented yet", .{}); - return .zero; - }, - } - var arguments = callframe.arguments(8); var slice = ArgumentsSlice.init(globalObject.bunVM(), arguments.ptr[0..arguments.len]); @@ -142,57 +135,12 @@ fn call(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { // TODO: handle globalObject.throwValue - if (comptime FunctionEnum == .readdir) { - return JSC.Node.AsyncReaddirTask.create(globalObject, args, slice.vm, slice.arena); - } - - if (comptime FunctionEnum == .readFile) { - return JSC.Node.AsyncReadFileTask.create(globalObject, args, slice.vm, slice.arena); - } - - if (comptime FunctionEnum == .realpath) { - return JSC.Node.AsyncRealpathTask.create(globalObject, args, slice.vm, slice.arena); - } - - if (comptime FunctionEnum == .stat or FunctionEnum == .lstat) { - return JSC.Node.AsyncStatTask.create(globalObject, args, slice.vm, FunctionEnum == .lstat, slice.arena); - } - - if (comptime FunctionEnum == .copyFile) { - return JSC.Node.AsyncCopyFileTask.create(globalObject, args, slice.vm, slice.arena); - } - + const Task = @field(JSC.Node.Async, @tagName(FunctionEnum)); if (comptime FunctionEnum == .cp) { - return JSC.Node.AsyncCpTask.create(globalObject, args, slice.vm, slice.arena); + return Task.create(globalObject, args, globalObject.bunVM(), slice.arena); + } else { + return Task.create(globalObject, args, globalObject.bunVM()); } - - // defer { - // for (arguments.len) |arg| { - // JSC.C.JSValueUnprotect(ctx, arg); - // } - // slice.arena.deinit(); - // } - - // const args = if (comptime Arguments != void) - // Arguments.fromJS(ctx, &slice, exception) - // else - // Arguments{}; - // if (exception.* != null) return null; - - // const result: Maybe(Result) = Function(this, comptime Flavor.sync, args); - // switch (result) { - // .err => |err| { - // exception.* = err.toJS(ctx); - // return null; - // }, - // .result => |res| { - // return switch (comptime Result) { - // void => JSC.JSValue.jsUndefined().asRef(), - // else => res.toJS(ctx), - // }; - // }, - // } - // unreachable; } }; return NodeBindingClosure.bind; diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 35daea52c..84dc394d0 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -315,6 +315,68 @@ pub const StringOrBunStringOrBuffer = union(enum) { } }; +pub const SliceWithUnderlyingStringOrBuffer = union(enum) { + SliceWithUnderlyingString: bun.SliceWithUnderlyingString, + buffer: Buffer, + + pub fn toThreadSafe(this: *@This()) void { + switch (this.*) { + .SliceWithUnderlyingString => this.SliceWithUnderlyingString.toThreadSafe(), + else => {}, + } + } + + pub fn toJS(this: *SliceWithUnderlyingStringOrBuffer, ctx: JSC.C.JSContextRef, exception: JSC.C.ExceptionRef) JSC.C.JSValueRef { + return switch (this) { + .SliceWithUnderlyingStringOrBuffer => { + defer { + this.SliceWithUnderlyingString.deinit(); + this.SliceWithUnderlyingString.underlying = bun.String.empty; + this.SliceWithUnderlyingString.utf8 = .{}; + } + + return this.SliceWithUnderlyingString.underlying.toJS(ctx); + }, + .buffer => this.buffer.toJSObjectRef(ctx, exception), + }; + } + + pub fn slice(this: *const SliceWithUnderlyingStringOrBuffer) []const u8 { + return switch (this.*) { + .SliceWithUnderlyingString => this.SliceWithUnderlyingString.slice(), + .buffer => this.buffer.slice(), + }; + } + + pub fn fromJS(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, exception: JSC.C.ExceptionRef) ?SliceWithUnderlyingStringOrBuffer { + _ = exception; + return switch (value.jsType()) { + JSC.JSValue.JSType.String, JSC.JSValue.JSType.StringObject, JSC.JSValue.JSType.DerivedStringObject, JSC.JSValue.JSType.Object => { + var str = bun.String.tryFromJS(value, global) orelse return null; + return SliceWithUnderlyingStringOrBuffer{ .SliceWithUnderlyingString = str.toSlice(allocator) }; + }, + + .ArrayBuffer, + .Int8Array, + .Uint8Array, + .Uint8ClampedArray, + .Int16Array, + .Uint16Array, + .Int32Array, + .Uint32Array, + .Float32Array, + .Float64Array, + .BigInt64Array, + .BigUint64Array, + .DataView, + => SliceWithUnderlyingStringOrBuffer{ + .buffer = Buffer.fromArrayBuffer(global, value), + }, + else => null, + }; + } +}; + /// Like StringOrBuffer but actually returns a Node.js Buffer pub const StringOrNodeBuffer = union(Tag) { string: string, @@ -401,6 +463,20 @@ pub const SliceOrBuffer = union(Tag) { } } + pub fn toThreadSafe(this: *SliceOrBuffer) void { + var buffer: ?Buffer = null; + if (this.* == .buffer) { + buffer = this.buffer; + this.buffer.buffer.value.ensureStillAlive(); + } + defer { + if (buffer) |buf| { + buf.buffer.value.unprotect(); + } + } + this.ensureCloned(bun.default_allocator) catch unreachable; + } + pub const Tag = enum { string, buffer }; pub fn slice(this: SliceOrBuffer) []const u8 { @@ -650,6 +726,10 @@ pub const PathLike = union(Tag) { if (this.* == .slice_with_underlying_string) { this.slice_with_underlying_string.toThreadSafe(); } + + if (this.* == .buffer) { + this.buffer.buffer.value.protect(); + } } pub fn deinitAndUnprotect(this: *const PathLike) void { diff --git a/src/js/node/fs.js b/src/js/node/fs.js index b4165311f..8340c7375 100644 --- a/src/js/node/fs.js +++ b/src/js/node/fs.js @@ -109,19 +109,19 @@ class StatWatcher extends EventEmitter { } var access = function access(...args) { - callbackify(fs.accessSync, args); + callbackify(fs.access, args); }, appendFile = function appendFile(...args) { - callbackify(fs.appendFileSync, args); + callbackify(fs.appendFile, args); }, close = function close(...args) { - callbackify(fs.closeSync, args); + callbackify(fs.close, args); }, rm = function rm(...args) { - callbackify(fs.rmSync, args); + callbackify(fs.rm, args); }, rmdir = function rmdir(...args) { - callbackify(fs.rmdirSync, args); + callbackify(fs.rmdir, args); }, copyFile = function copyFile(...args) { const callback = args[args.length - 1]; @@ -133,49 +133,49 @@ var access = function access(...args) { fs.copyFile(...args).then(result => callback(null, result), callback); }, exists = function exists(...args) { - callbackify(fs.existsSync, args); + callbackify(fs.exists, args); }, chown = function chown(...args) { - callbackify(fs.chownSync, args); + callbackify(fs.chown, args); }, chmod = function chmod(...args) { - callbackify(fs.chmodSync, args); + callbackify(fs.chmod, args); }, fchmod = function fchmod(...args) { - callbackify(fs.fchmodSync, args); + callbackify(fs.fchmod, args); }, fchown = function fchown(...args) { - callbackify(fs.fchownSync, args); + callbackify(fs.fchown, args); }, fstat = function fstat(...args) { - callbackify(fs.fstatSync, args); + callbackify(fs.fstat, args); }, fsync = function fsync(...args) { - callbackify(fs.fsyncSync, args); + callbackify(fs.fsync, args); }, ftruncate = function ftruncate(...args) { - callbackify(fs.ftruncateSync, args); + callbackify(fs.ftruncate, args); }, futimes = function futimes(...args) { - callbackify(fs.futimesSync, args); + callbackify(fs.futimes, args); }, lchmod = function lchmod(...args) { - callbackify(fs.lchmodSync, args); + callbackify(fs.lchmod, args); }, lchown = function lchown(...args) { - callbackify(fs.lchownSync, args); + callbackify(fs.lchown, args); }, link = function link(...args) { - callbackify(fs.linkSync, args); + callbackify(fs.link, args); }, mkdir = function mkdir(...args) { - callbackify(fs.mkdirSync, args); + callbackify(fs.mkdir, args); }, mkdtemp = function mkdtemp(...args) { - callbackify(fs.mkdtempSync, args); + callbackify(fs.mkdtemp, args); }, open = function open(...args) { - callbackify(fs.openSync, args); + callbackify(fs.open, args); }, read = function read(fd, buffer, offsetOrOptions, length, position, callback) { let offset = offsetOrOptions; @@ -210,7 +210,7 @@ var access = function access(...args) { }); }, write = function write(...args) { - callbackify(fs.writeSync, args); + callbackify(fs.write, args); }, readdir = function readdir(...args) { const callback = args[args.length - 1]; @@ -231,10 +231,10 @@ var access = function access(...args) { fs.readFile(...args).then(result => callback(null, result), callback); }, writeFile = function writeFile(...args) { - callbackify(fs.writeFileSync, args); + callbackify(fs.writeFile, args); }, readlink = function readlink(...args) { - callbackify(fs.readlinkSync, args); + callbackify(fs.readlink, args); }, realpath = function realpath(...args) { const callback = args[args.length - 1]; @@ -246,7 +246,7 @@ var access = function access(...args) { fs.realpath(...args).then(result => callback(null, result), callback); }, rename = function rename(...args) { - callbackify(fs.renameSync, args); + callbackify(fs.rename, args); }, lstat = function lstat(...args) { const callback = args[args.length - 1]; @@ -267,19 +267,19 @@ var access = function access(...args) { fs.stat(...args).then(result => callback(null, result), callback); }, symlink = function symlink(...args) { - callbackify(fs.symlinkSync, args); + callbackify(fs.symlink, args); }, truncate = function truncate(...args) { - callbackify(fs.truncateSync, args); + callbackify(fs.truncate, args); }, unlink = function unlink(...args) { - callbackify(fs.unlinkSync, args); + callbackify(fs.unlink, args); }, utimes = function utimes(...args) { - callbackify(fs.utimesSync, args); + callbackify(fs.utimes, args); }, lutimes = function lutimes(...args) { - callbackify(fs.lutimesSync, args); + callbackify(fs.lutimes, args); }, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), @@ -406,16 +406,18 @@ function unwatchFile(filename, listener) { } function callbackify(fsFunction, args) { + const callback = args[args.length - 1]; try { - const result = fsFunction.apply(fs, args.slice(0, args.length - 1)); - const callback = args[args.length - 1]; - if (typeof callback === "function") { - queueMicrotask(() => callback(null, result)); - } + var result = fsFunction.apply(fs, args.slice(0, args.length - 1)); + result.then( + (...args) => callback(null, ...args), + err => callback(err), + ); } catch (e) { - const callback = args[args.length - 1]; if (typeof callback === "function") { - queueMicrotask(() => callback(e)); + callback(e); + } else { + throw e; } } } diff --git a/src/js/node/fs.promises.ts b/src/js/node/fs.promises.ts index 8921e42d3..91566d155 100644 --- a/src/js/node/fs.promises.ts +++ b/src/js/node/fs.promises.ts @@ -9,14 +9,6 @@ var fs = Bun.fs(); // in some cases, node swaps around arguments or makes small tweaks to the return type // this is just better than nothing. const notrace = "::bunternal::"; -var promisify = { - [notrace]: fsFunction => { - return async function (...args) { - await 1; - return fsFunction.apply(fs, args); - }; - }, -}[notrace]; function watch( filename: string | Buffer | URL, @@ -139,72 +131,57 @@ async function opendir(dir: string) { } export default { - access: promisify(fs.accessSync), - appendFile: promisify(fs.appendFileSync), - close: promisify(fs.closeSync), + access: fs.access.bind(fs), + appendFile: fs.appendFile.bind(fs), + close: fs.close.bind(fs), copyFile: fs.copyFile.bind(fs), cp, - exists: promisify(fs.existsSync), - chown: promisify(fs.chownSync), - chmod: promisify(fs.chmodSync), - fchmod: promisify(fs.fchmodSync), - fchown: promisify(fs.fchownSync), - fstat: promisify(fs.fstatSync), - fsync: promisify(fs.fsyncSync), - ftruncate: promisify(fs.ftruncateSync), - futimes: promisify(fs.futimesSync), - lchmod: promisify(fs.lchmodSync), - lchown: promisify(fs.lchownSync), - link: promisify(fs.linkSync), + exists: fs.exists.bind(fs), + chown: fs.chown.bind(fs), + chmod: fs.chmod.bind(fs), + fchmod: fs.fchmod.bind(fs), + fchown: fs.fchown.bind(fs), + fstat: fs.fstat.bind(fs), + fsync: fs.fsync.bind(fs), + ftruncate: fs.ftruncate.bind(fs), + futimes: fs.futimes.bind(fs), + lchmod: fs.lchmod.bind(fs), + lchown: fs.lchown.bind(fs), + link: fs.link.bind(fs), lstat: fs.lstat.bind(fs), - mkdir: promisify(fs.mkdirSync), - mkdtemp: promisify(fs.mkdtempSync), - open: promisify(fs.openSync), - read: promisify(fs.readSync), - write: promisify(fs.writeSync), + mkdir: fs.mkdir.bind(fs), + mkdtemp: fs.mkdtemp.bind(fs), + open: fs.open.bind(fs), + read: fs.read.bind(fs), + write: fs.write.bind(fs), readdir: fs.readdir.bind(fs), readFile: fs.readFile.bind(fs), - writeFile: promisify(fs.writeFileSync), - readlink: promisify(fs.readlinkSync), + writeFile: fs.writeFile.bind(fs), + readlink: fs.readlink.bind(fs), realpath: fs.realpath.bind(fs), - rename: promisify(fs.renameSync), + rename: fs.rename.bind(fs), stat: fs.stat.bind(fs), - symlink: promisify(fs.symlinkSync), - truncate: promisify(fs.truncateSync), - unlink: promisify(fs.unlinkSync), - utimes: promisify(fs.utimesSync), - lutimes: promisify(fs.lutimesSync), - rm: promisify(fs.rmSync), - rmdir: promisify(fs.rmdirSync), - writev: (fd, buffers, position) => { - return new Promise((resolve, reject) => { - try { - var bytesWritten = fs.writevSync(fd, buffers, position); - } catch (err) { - reject(err); - return; - } - - resolve({ - bytesWritten, - buffers, - }); - }); + symlink: fs.symlink.bind(fs), + truncate: fs.truncate.bind(fs), + unlink: fs.unlink.bind(fs), + utimes: fs.utimes.bind(fs), + lutimes: fs.lutimes.bind(fs), + rm: fs.rm.bind(fs), + rmdir: fs.rmdir.bind(fs), + writev: async (fd, buffers, position) => { + var bytesWritten = await fs.writev(fd, buffers, position); + return { + bytesWritten, + buffers, + }; }, - readv: (fd, buffers, position) => { - return new Promise((resolve, reject) => { - try { - var bytesRead = fs.readvSync(fd, buffers, position); - } catch (err) { - reject(err); - return; - } + readv: async (fd, buffers, position) => { + var bytesRead = await fs.readv(fd, buffers, position); - resolve({ - bytesRead, - buffers, - }); - }); + return { + bytesRead, + buffers, + }; }, constants, watch, diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h index 479b97638..9d5cfaf4d 100644 --- a/src/js/out/InternalModuleRegistryConstants.h +++ b/src/js/out/InternalModuleRegistryConstants.h @@ -82,11 +82,11 @@ static constexpr ASCIILiteral NodeEventsCode = "(function (){\"use strict\";// s // // -static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar getValidatedPath = function(p) {\n if (p instanceof URL)\n return Bun.fileURLToPath(p);\n if (typeof p !== \"string\")\n @throwTypeError(\"Path must be a string or URL.\");\n return (_pathModule \?\?= @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28)).resolve(p);\n}, watchFile = function(filename, options, listener) {\n if (filename = getValidatedPath(filename), typeof options === \"function\")\n listener = options, options = {};\n if (typeof listener !== \"function\")\n @throwTypeError(\"listener must be a function\");\n var stat = statWatchers.get(filename);\n if (!stat)\n stat = new StatWatcher(filename, options), statWatchers.set(filename, stat);\n return stat.addListener(\"change\", listener), stat;\n}, unwatchFile = function(filename, listener) {\n filename = getValidatedPath(filename);\n var stat = statWatchers.get(filename);\n if (!stat)\n return;\n if (listener) {\n if (stat.removeListener(\"change\", listener), stat.listenerCount(\"change\") !== 0)\n return;\n } else\n stat.removeAllListeners(\"change\");\n stat.stop(), statWatchers.delete(filename);\n}, callbackify = function(fsFunction, args) {\n try {\n const result = fsFunction.apply(fs, args.slice(0, args.length - 1)), callback = args[args.length - 1];\n if (typeof callback === \"function\")\n queueMicrotask(() => callback(null, result));\n } catch (e) {\n const callback = args[args.length - 1];\n if (typeof callback === \"function\")\n queueMicrotask(() => callback(e));\n }\n}, createReadStream = function(path, options) {\n return new ReadStream(path, options);\n}, WriteStream_handleWrite = function(er, bytes) {\n if (er)\n return WriteStream_errorOrDestroy.call(this, er);\n this.bytesWritten += bytes;\n}, WriteStream_internalClose = function(err, cb) {\n this[_writeStreamPathFastPathSymbol] = !1;\n var fd = this.fd;\n this[_fs].close(fd, (er) => {\n this.fd = null, cb(err || er);\n });\n}, WriteStream_errorOrDestroy = function(err) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n}, createWriteStream = function(path, options) {\n return new WriteStream(path, options);\n}, cpSync = function(src, dest, options) {\n if (!options)\n return fs.cpSync(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cpSync)\n lazy_cpSync = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cpSync(src, dest, options);\n }\n return fs.cpSync(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n}, cp = function(src, dest, options, callback) {\n if (typeof options === \"function\")\n callback = options, options = @undefined;\n promises.cp(src, dest, options).then(() => callback(), callback);\n}, _toUnixTimestamp = function(time, name = \"time\") {\n if (typeof time === \"string\" && +time == time)\n return +time;\n if (NumberIsFinite(time)) {\n if (time < 0)\n return DateNow() / 1000;\n return time;\n }\n if (isDate(time))\n return DatePrototypeGetTime(time) / 1000;\n @throwTypeError(`Expected ${name} to be a number or Date`);\n}, $, ReadStream, WriteStream, EventEmitter = @getInternalField(@internalModuleRegistry, 18) || @createInternalModuleById(18), promises = @getInternalField(@internalModuleRegistry, 20) || @createInternalModuleById(20), Stream = @getInternalField(@internalModuleRegistry, 37) || @createInternalModuleById(37), { isArrayBufferView } = @requireNativeModule(\"util/types\"), _writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), _fs = Symbol.for(\"#fs\"), constants = @processBindingConstants.fs, fs = Bun.fs();\n\nclass FSWatcher extends EventEmitter {\n #watcher;\n #listener;\n constructor(path, options, listener) {\n super();\n if (typeof options === \"function\")\n listener = options, options = {};\n else if (typeof options === \"string\")\n options = { encoding: options };\n if (typeof listener !== \"function\")\n listener = () => {\n };\n this.#listener = listener;\n try {\n this.#watcher = fs.watch(path, options || {}, this.#onEvent.bind(this));\n } catch (e) {\n if (!e.message\?.startsWith(\"FileNotFound\"))\n throw e;\n const notFound = new Error(`ENOENT: no such file or directory, watch '${path}'`);\n throw notFound.code = \"ENOENT\", notFound.errno = -2, notFound.path = path, notFound.syscall = \"watch\", notFound.filename = path, notFound;\n }\n }\n #onEvent(eventType, filenameOrError) {\n if (eventType === \"error\" || eventType === \"close\")\n this.emit(eventType, filenameOrError);\n else\n this.emit(\"change\", eventType, filenameOrError), this.#listener(eventType, filenameOrError);\n }\n close() {\n this.#watcher\?.close(), this.#watcher = null;\n }\n ref() {\n this.#watcher\?.ref();\n }\n unref() {\n this.#watcher\?.unref();\n }\n start() {\n }\n}\n\nclass StatWatcher extends EventEmitter {\n constructor(path, options) {\n super();\n this._handle = fs.watchFile(path, options, this.#onChange.bind(this));\n }\n #onChange(curr, prev) {\n this.emit(\"change\", curr, prev);\n }\n start() {\n }\n stop() {\n this._handle\?.close(), this._handle = null;\n }\n ref() {\n this._handle\?.ref();\n }\n unref() {\n this._handle\?.unref();\n }\n}\nvar access = function access2(...args) {\n callbackify(fs.accessSync, args);\n}, appendFile = function appendFile2(...args) {\n callbackify(fs.appendFileSync, args);\n}, close = function close2(...args) {\n callbackify(fs.closeSync, args);\n}, rm = function rm2(...args) {\n callbackify(fs.rmSync, args);\n}, rmdir = function rmdir2(...args) {\n callbackify(fs.rmdirSync, args);\n}, copyFile = function copyFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.copyFile(...args).then((result) => callback(null, result), callback);\n}, exists = function exists2(...args) {\n callbackify(fs.existsSync, args);\n}, chown = function chown2(...args) {\n callbackify(fs.chownSync, args);\n}, chmod = function chmod2(...args) {\n callbackify(fs.chmodSync, args);\n}, fchmod = function fchmod2(...args) {\n callbackify(fs.fchmodSync, args);\n}, fchown = function fchown2(...args) {\n callbackify(fs.fchownSync, args);\n}, fstat = function fstat2(...args) {\n callbackify(fs.fstatSync, args);\n}, fsync = function fsync2(...args) {\n callbackify(fs.fsyncSync, args);\n}, ftruncate = function ftruncate2(...args) {\n callbackify(fs.ftruncateSync, args);\n}, futimes = function futimes2(...args) {\n callbackify(fs.futimesSync, args);\n}, lchmod = function lchmod2(...args) {\n callbackify(fs.lchmodSync, args);\n}, lchown = function lchown2(...args) {\n callbackify(fs.lchownSync, args);\n}, link = function link2(...args) {\n callbackify(fs.linkSync, args);\n}, mkdir = function mkdir2(...args) {\n callbackify(fs.mkdirSync, args);\n}, mkdtemp = function mkdtemp2(...args) {\n callbackify(fs.mkdtempSync, args);\n}, open = function open2(...args) {\n callbackify(fs.openSync, args);\n}, read = function read2(fd, buffer, offsetOrOptions, length, position, callback) {\n let offset = offsetOrOptions, params = null;\n if (arguments.length <= 4) {\n if (arguments.length === 4)\n callback = length, params = offsetOrOptions;\n else if (arguments.length === 3) {\n if (!isArrayBufferView(buffer))\n params = buffer, { buffer = @Buffer.alloc(16384) } = params \?\? {};\n callback = offsetOrOptions;\n } else\n callback = buffer, buffer = @Buffer.alloc(16384);\n ({ offset = 0, length = buffer\?.byteLength - offset, position = null } = params \?\? {});\n }\n queueMicrotask(() => {\n try {\n var bytesRead = fs.readSync(fd, buffer, offset, length, position);\n } catch (e) {\n callback(e);\n }\n callback(null, bytesRead, buffer);\n });\n}, write = function write2(...args) {\n callbackify(fs.writeSync, args);\n}, readdir = function readdir2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readdir(...args).then((result) => callback(null, result), callback);\n}, readFile = function readFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readFile(...args).then((result) => callback(null, result), callback);\n}, writeFile = function writeFile2(...args) {\n callbackify(fs.writeFileSync, args);\n}, readlink = function readlink2(...args) {\n callbackify(fs.readlinkSync, args);\n}, realpath = function realpath2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.realpath(...args).then((result) => callback(null, result), callback);\n}, rename = function rename2(...args) {\n callbackify(fs.renameSync, args);\n}, lstat = function lstat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.lstat(...args).then((result) => callback(null, result), callback);\n}, stat = function stat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.stat(...args).then((result) => callback(null, result), callback);\n}, symlink = function symlink2(...args) {\n callbackify(fs.symlinkSync, args);\n}, truncate = function truncate2(...args) {\n callbackify(fs.truncateSync, args);\n}, unlink = function unlink2(...args) {\n callbackify(fs.unlinkSync, args);\n}, utimes = function utimes2(...args) {\n callbackify(fs.utimesSync, args);\n}, lutimes = function lutimes2(...args) {\n callbackify(fs.lutimesSync, args);\n}, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), closeSync = fs.closeSync.bind(fs), copyFileSync = fs.copyFileSync.bind(fs), existsSync = fs.existsSync.bind(fs), chownSync = fs.chownSync.bind(fs), chmodSync = fs.chmodSync.bind(fs), fchmodSync = fs.fchmodSync.bind(fs), fchownSync = fs.fchownSync.bind(fs), fstatSync = fs.fstatSync.bind(fs), fsyncSync = fs.fsyncSync.bind(fs), ftruncateSync = fs.ftruncateSync.bind(fs), futimesSync = fs.futimesSync.bind(fs), lchmodSync = fs.lchmodSync.bind(fs), lchownSync = fs.lchownSync.bind(fs), linkSync = fs.linkSync.bind(fs), lstatSync = fs.lstatSync.bind(fs), mkdirSync = fs.mkdirSync.bind(fs), mkdtempSync = fs.mkdtempSync.bind(fs), openSync = fs.openSync.bind(fs), readSync = fs.readSync.bind(fs), writeSync = fs.writeSync.bind(fs), readdirSync = fs.readdirSync.bind(fs), readFileSync = fs.readFileSync.bind(fs), writeFileSync = fs.writeFileSync.bind(fs), readlinkSync = fs.readlinkSync.bind(fs), realpathSync = fs.realpathSync.bind(fs), renameSync = fs.renameSync.bind(fs), statSync = fs.statSync.bind(fs), symlinkSync = fs.symlinkSync.bind(fs), truncateSync = fs.truncateSync.bind(fs), unlinkSync = fs.unlinkSync.bind(fs), utimesSync = fs.utimesSync.bind(fs), lutimesSync = fs.lutimesSync.bind(fs), rmSync = fs.rmSync.bind(fs), rmdirSync = fs.rmdirSync.bind(fs), writev = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.writevSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, writevSync = fs.writevSync.bind(fs), readv = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.readvSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {\n return new FSWatcher(path, options, listener);\n}, statWatchers = new Map, _pathModule, readStreamPathFastPathSymbol = Symbol.for(\"Bun.Node.readStreamPathFastPath\"), readStreamSymbol = Symbol.for(\"Bun.NodeReadStream\"), readStreamPathOrFdSymbol = Symbol.for(\"Bun.NodeReadStreamPathOrFd\"), writeStreamSymbol = Symbol.for(\"Bun.NodeWriteStream\"), writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), writeStreamPathFastPathCallSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPathCall\"), kIoDone = Symbol.for(\"kIoDone\"), defaultReadStreamOptions = {\n file: @undefined,\n fd: null,\n flags: \"r\",\n encoding: @undefined,\n mode: 438,\n autoClose: !0,\n emitClose: !0,\n start: 0,\n end: @Infinity,\n highWaterMark: 65536,\n fs: {\n read,\n open: (path, flags, mode, cb) => {\n var fd;\n try {\n fd = openSync(path, flags, mode);\n } catch (e) {\n cb(e);\n return;\n }\n cb(null, fd);\n },\n openSync,\n close\n },\n autoDestroy: !0\n}, ReadStreamClass;\nReadStream = function(InternalReadStream) {\n ReadStreamClass = InternalReadStream, Object.defineProperty(ReadStreamClass.prototype, Symbol.toStringTag, {\n value: \"ReadStream\",\n enumerable: !1\n });\n function ReadStream3(path, options) {\n return new InternalReadStream(path, options);\n }\n return ReadStream3.prototype = InternalReadStream.prototype, Object.defineProperty(ReadStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalReadStream;\n }\n });\n}(class ReadStream2 extends Stream._getNativeReadableStreamPrototype(2, Stream.Readable) {\n constructor(pathOrFd, options = defaultReadStreamOptions) {\n if (typeof options !== \"object\" || !options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n flags = defaultReadStreamOptions.flags,\n encoding = defaultReadStreamOptions.encoding,\n mode = defaultReadStreamOptions.mode,\n autoClose = defaultReadStreamOptions.autoClose,\n emitClose = defaultReadStreamOptions.emitClose,\n start = defaultReadStreamOptions.start,\n end = defaultReadStreamOptions.end,\n autoDestroy = defaultReadStreamOptions.autoClose,\n fs: fs2 = defaultReadStreamOptions.fs,\n highWaterMark = defaultReadStreamOptions.highWaterMark,\n fd = defaultReadStreamOptions.fd\n } = options;\n if (pathOrFd\?.constructor\?.name === \"URL\")\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n var tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n @throwTypeError(\"Expected options.fd to be a number\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = fd, tempThis.autoClose = !1;\n } else if (typeof pathOrFd === \"string\") {\n if (pathOrFd.startsWith(\"file://\"))\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n if (pathOrFd.length === 0)\n @throwTypeError(\"Expected path to be a non-empty string\");\n tempThis.path = tempThis.file = tempThis[readStreamPathOrFdSymbol] = pathOrFd;\n } else if (typeof pathOrFd === \"number\") {\n if (pathOrFd |= 0, pathOrFd < 0)\n @throwTypeError(\"Expected fd to be a positive integer\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = pathOrFd, tempThis.autoClose = !1;\n } else\n @throwTypeError(\"Expected a path or file descriptor\");\n if (tempThis.fd === @undefined)\n tempThis.fd = fs2.openSync(pathOrFd, flags, mode);\n var fileRef = Bun.file(tempThis.fd), stream = fileRef.stream(), native = @direct(stream);\n if (!native)\n throw new Error(\"no native readable stream\");\n var { stream: ptr } = native;\n super(ptr, {\n ...options,\n encoding,\n autoDestroy,\n autoClose,\n emitClose,\n highWaterMark\n });\n if (Object.assign(this, tempThis), this.#fileRef = fileRef, this.end = end, this._read = this.#internalRead, this.start = start, this.flags = flags, this.mode = mode, this.emitClose = emitClose, this[readStreamPathFastPathSymbol] = start === 0 && end === @Infinity && autoClose && fs2 === defaultReadStreamOptions.fs && (encoding === \"buffer\" || encoding === \"binary\" || encoding == null || encoding === \"utf-8\" || encoding === \"utf8\"), this._readableState.autoClose = autoDestroy = autoClose, this._readableState.highWaterMark = highWaterMark, start !== @undefined)\n this.pos = start;\n }\n #fileRef;\n #fs;\n file;\n path;\n fd = null;\n flags;\n mode;\n start;\n end;\n pos;\n bytesRead = 0;\n #fileSize = -1;\n _read;\n [readStreamSymbol] = !0;\n [readStreamPathOrFdSymbol];\n [readStreamPathFastPathSymbol];\n _construct(callback) {\n if (super._construct)\n super._construct(callback);\n else\n callback();\n this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n super._destroy(err, cb);\n try {\n var fd = this.fd;\n if (this[readStreamPathFastPathSymbol] = !1, !fd)\n cb(err);\n else\n this.#fs.close(fd, (er) => {\n cb(er || err);\n }), this.fd = null;\n } catch (e) {\n throw e;\n }\n }\n close(cb) {\n if (typeof cb === \"function\")\n Stream.eos(this, cb);\n this.destroy();\n }\n push(chunk) {\n var bytesRead = chunk\?.length \?\? 0;\n if (bytesRead > 0) {\n this.bytesRead += bytesRead;\n var currPos = this.pos;\n if (currPos !== @undefined) {\n if (this.bytesRead < currPos)\n return !0;\n if (currPos === this.start) {\n var n = this.bytesRead - currPos;\n chunk = chunk.slice(-n);\n var [_, ...rest] = arguments;\n if (this.pos = this.bytesRead, this.end !== @undefined && this.bytesRead > this.end)\n chunk = chunk.slice(0, this.end - this.start + 1);\n return super.push(chunk, ...rest);\n }\n var end = this.end;\n if (end !== @undefined && this.bytesRead > end) {\n chunk = chunk.slice(0, end - currPos + 1);\n var [_, ...rest] = arguments;\n return this.pos = this.bytesRead, super.push(chunk, ...rest);\n }\n this.pos = this.bytesRead;\n }\n }\n return super.push(...arguments);\n }\n #internalRead(n) {\n var { pos, end, bytesRead, fd, encoding } = this;\n if (n = pos !== @undefined \? Math.min(end - pos + 1, n) : Math.min(end - bytesRead + 1, n), n <= 0) {\n this.push(null);\n return;\n }\n if (this.#fileSize === -1 && bytesRead === 0 && pos === @undefined) {\n var stat3 = fstatSync(fd);\n if (this.#fileSize = stat3.size, this.#fileSize > 0 && n > this.#fileSize)\n n = this.#fileSize + 1;\n }\n this[kIoDone] = !1;\n var res = super._read(n);\n if (@isPromise(res)) {\n var then = res\?.then;\n if (then && @isCallable(then))\n res.then(() => {\n if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone);\n }, (er) => {\n this[kIoDone] = !0, this.#errorOrDestroy(er);\n });\n } else if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone), this.#errorOrDestroy(new Error(\"ERR_STREAM_PREMATURE_CLOSE\"));\n }\n #errorOrDestroy(err, sync = null) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n }\n pause() {\n return this[readStreamPathFastPathSymbol] = !1, super.pause();\n }\n resume() {\n return this[readStreamPathFastPathSymbol] = !1, super.resume();\n }\n unshift(...args) {\n return this[readStreamPathFastPathSymbol] = !1, super.unshift(...args);\n }\n pipe(dest, pipeOpts) {\n if (this[readStreamPathFastPathSymbol] && (pipeOpts\?.end \?\? !0) && this._readableState\?.pipes\?.length === 0) {\n if ((writeStreamPathFastPathSymbol in dest) && dest[writeStreamPathFastPathSymbol]) {\n if (dest[writeStreamPathFastPathCallSymbol](this, pipeOpts))\n return this;\n }\n }\n return this[readStreamPathFastPathSymbol] = !1, super.pipe(dest, pipeOpts);\n }\n});\nvar defaultWriteStreamOptions = {\n fd: null,\n start: @undefined,\n pos: @undefined,\n encoding: @undefined,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass = WriteStream = function WriteStream2(path, options = defaultWriteStreamOptions) {\n if (!(this instanceof WriteStream2))\n return new WriteStream2(path, options);\n if (!options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n fs: fs2 = defaultWriteStreamOptions.fs,\n start = defaultWriteStreamOptions.start,\n flags = defaultWriteStreamOptions.flags,\n mode = defaultWriteStreamOptions.mode,\n autoClose = !0,\n emitClose = !1,\n autoDestroy = autoClose,\n encoding = defaultWriteStreamOptions.encoding,\n fd = defaultWriteStreamOptions.fd,\n pos = defaultWriteStreamOptions.pos\n } = options, tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n throw new Error(\"Expected options.fd to be a number\");\n tempThis.fd = fd, tempThis[_writeStreamPathFastPathSymbol] = !1;\n } else if (typeof path === \"string\") {\n if (path.length === 0)\n @throwTypeError(\"Expected a non-empty path\");\n if (path.startsWith(\"file:\"))\n path = Bun.fileURLToPath(path);\n tempThis.path = path, tempThis.fd = null, tempThis[_writeStreamPathFastPathSymbol] = autoClose && (start === @undefined || start === 0) && fs2.write === defaultWriteStreamOptions.fs.write && fs2.close === defaultWriteStreamOptions.fs.close;\n }\n if (tempThis.fd == null)\n tempThis.fd = fs2.openSync(path, flags, mode);\n if (NativeWritable.call(this, tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n }), Object.assign(this, tempThis), typeof fs2\?.write !== \"function\")\n @throwTypeError(\"Expected fs.write to be a function\");\n if (typeof fs2\?.close !== \"function\")\n @throwTypeError(\"Expected fs.close to be a function\");\n if (typeof fs2\?.open !== \"function\")\n @throwTypeError(\"Expected fs.open to be a function\");\n if (typeof path === \"object\" && path) {\n if (path instanceof URL)\n path = Bun.fileURLToPath(path);\n }\n if (typeof path !== \"string\" && typeof fd !== \"number\")\n @throwTypeError(\"Expected a path or file descriptor\");\n if (this.start = start, this[_fs] = fs2, this.flags = flags, this.mode = mode, this.bytesWritten = 0, this[writeStreamSymbol] = !0, this[kIoDone] = !1, this.start !== @undefined)\n this.pos = this.start;\n if (encoding !== defaultWriteStreamOptions.encoding) {\n if (this.setDefaultEncoding(encoding), encoding !== \"buffer\" && encoding !== \"utf8\" && encoding !== \"utf-8\" && encoding !== \"binary\")\n this[_writeStreamPathFastPathSymbol] = !1;\n }\n return this;\n}, NativeWritable = Stream.NativeWritable, WriteStreamPrototype = WriteStream.prototype = Object.create(NativeWritable.prototype);\nObject.defineProperties(WriteStreamPrototype, {\n autoClose: {\n get() {\n return this._writableState.autoDestroy;\n },\n set(val) {\n this._writableState.autoDestroy = val;\n }\n },\n pending: {\n get() {\n return this.fd === null;\n }\n }\n});\nWriteStreamPrototype.destroySoon = WriteStreamPrototype.end;\nWriteStreamPrototype.open = function open3() {\n};\nWriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(readStream, pipeOpts) {\n if (!this[_writeStreamPathFastPathSymbol])\n return !1;\n if (this.fd !== null)\n return this[_writeStreamPathFastPathSymbol] = !1, !1;\n return this[kIoDone] = !1, readStream[kIoDone] = !1, Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then((bytesWritten) => {\n readStream[kIoDone] = this[kIoDone] = !0, this.bytesWritten += bytesWritten, readStream.bytesRead += bytesWritten, this.end(), readStream.close();\n }, (err) => {\n readStream[kIoDone] = this[kIoDone] = !0, WriteStream_errorOrDestroy.call(this, err), readStream.emit(\"error\", err);\n });\n};\nWriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {\n return this[_writeStreamPathFastPathSymbol];\n};\nWriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {\n this[_writeStreamPathFastPathSymbol] = !1;\n};\nWriteStreamPrototype._construct = function _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n};\nWriteStreamPrototype._destroy = function _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));\n return;\n }\n WriteStream_internalClose.call(this, err, cb);\n};\nWriteStreamPrototype.close = function close3(cb) {\n if (cb) {\n if (this.closed) {\n process.nextTick(cb);\n return;\n }\n this.on(\"close\", cb);\n }\n if (!this.autoClose)\n this.on(\"finish\", this.destroy);\n this.end();\n};\nWriteStreamPrototype.write = function write3(chunk, encoding, cb) {\n if (encoding \?\?= this._writableState\?.defaultEncoding, this[_writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = @Buffer.from(chunk, encoding);\n var native = this.pos === @undefined;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, WriteStream_handleWrite.call(this, err, bytes), this.emit(kIoDone), cb)\n !err \? cb() : cb(err);\n } : () => {\n };\n if (this[kIoDone] = !0, this._write)\n return this._write(chunk, encoding, callback);\n else\n return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);\n};\nWriteStreamPrototype._write = @undefined;\nWriteStreamPrototype._writev = @undefined;\nWriteStreamPrototype.end = function end(chunk, encoding, cb) {\n var native = this.pos === @undefined;\n return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);\n};\nWriteStreamPrototype._destroy = function _destroy2(err, cb) {\n this.close(err, cb);\n};\nObject.defineProperties(fs, {\n createReadStream: {\n value: createReadStream\n },\n createWriteStream: {\n value: createWriteStream\n },\n ReadStream: {\n value: ReadStream\n },\n WriteStream: {\n value: WriteStream\n }\n});\nrealpath.native = realpath;\nrealpathSync.native = realpathSync;\nvar lazy_cpSync = null;\n$ = {\n Dirent,\n FSWatcher,\n ReadStream,\n Stats,\n WriteStream,\n _toUnixTimestamp,\n access,\n accessSync,\n appendFile,\n appendFileSync,\n chmod,\n chmodSync,\n chown,\n chownSync,\n close,\n closeSync,\n constants,\n copyFile,\n copyFileSync,\n cp,\n cpSync,\n createReadStream,\n createWriteStream,\n exists,\n existsSync,\n fchmod,\n fchmodSync,\n fchown,\n fchownSync,\n fstat,\n fstatSync,\n fsync,\n fsyncSync,\n ftruncate,\n ftruncateSync,\n futimes,\n futimesSync,\n lchmod,\n lchmodSync,\n lchown,\n lchownSync,\n link,\n linkSync,\n lstat,\n lstatSync,\n lutimes,\n lutimesSync,\n mkdir,\n mkdirSync,\n mkdtemp,\n mkdtempSync,\n open,\n openSync,\n promises,\n read,\n readFile,\n readFileSync,\n readSync,\n readdir,\n readdirSync,\n readlink,\n readlinkSync,\n readv,\n readvSync,\n realpath,\n realpathSync,\n rename,\n renameSync,\n rm,\n rmSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n symlink,\n symlinkSync,\n truncate,\n truncateSync,\n unlink,\n unlinkSync,\n unwatchFile,\n utimes,\n utimesSync,\n watch,\n watchFile,\n write,\n writeFile,\n writeFileSync,\n writeSync,\n writev,\n writevSync,\n [Symbol.for(\"::bunternal::\")]: {\n ReadStreamClass,\n WriteStreamClass\n }\n};\nreturn $})\n"_s; +static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar getValidatedPath = function(p) {\n if (p instanceof URL)\n return Bun.fileURLToPath(p);\n if (typeof p !== \"string\")\n @throwTypeError(\"Path must be a string or URL.\");\n return (_pathModule \?\?= @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28)).resolve(p);\n}, watchFile = function(filename, options, listener) {\n if (filename = getValidatedPath(filename), typeof options === \"function\")\n listener = options, options = {};\n if (typeof listener !== \"function\")\n @throwTypeError(\"listener must be a function\");\n var stat = statWatchers.get(filename);\n if (!stat)\n stat = new StatWatcher(filename, options), statWatchers.set(filename, stat);\n return stat.addListener(\"change\", listener), stat;\n}, unwatchFile = function(filename, listener) {\n filename = getValidatedPath(filename);\n var stat = statWatchers.get(filename);\n if (!stat)\n return;\n if (listener) {\n if (stat.removeListener(\"change\", listener), stat.listenerCount(\"change\") !== 0)\n return;\n } else\n stat.removeAllListeners(\"change\");\n stat.stop(), statWatchers.delete(filename);\n}, callbackify = function(fsFunction, args) {\n const callback = args[args.length - 1];\n try {\n var result = fsFunction.apply(fs, args.slice(0, args.length - 1));\n result.then((...args2) => callback(null, ...args2), (err) => callback(err));\n } catch (e) {\n if (typeof callback === \"function\")\n callback(e);\n else\n throw e;\n }\n}, createReadStream = function(path, options) {\n return new ReadStream(path, options);\n}, WriteStream_handleWrite = function(er, bytes) {\n if (er)\n return WriteStream_errorOrDestroy.call(this, er);\n this.bytesWritten += bytes;\n}, WriteStream_internalClose = function(err, cb) {\n this[_writeStreamPathFastPathSymbol] = !1;\n var fd = this.fd;\n this[_fs].close(fd, (er) => {\n this.fd = null, cb(err || er);\n });\n}, WriteStream_errorOrDestroy = function(err) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n}, createWriteStream = function(path, options) {\n return new WriteStream(path, options);\n}, cpSync = function(src, dest, options) {\n if (!options)\n return fs.cpSync(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cpSync)\n lazy_cpSync = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cpSync(src, dest, options);\n }\n return fs.cpSync(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n}, cp = function(src, dest, options, callback) {\n if (typeof options === \"function\")\n callback = options, options = @undefined;\n promises.cp(src, dest, options).then(() => callback(), callback);\n}, _toUnixTimestamp = function(time, name = \"time\") {\n if (typeof time === \"string\" && +time == time)\n return +time;\n if (NumberIsFinite(time)) {\n if (time < 0)\n return DateNow() / 1000;\n return time;\n }\n if (isDate(time))\n return DatePrototypeGetTime(time) / 1000;\n @throwTypeError(`Expected ${name} to be a number or Date`);\n}, $, ReadStream, WriteStream, EventEmitter = @getInternalField(@internalModuleRegistry, 18) || @createInternalModuleById(18), promises = @getInternalField(@internalModuleRegistry, 20) || @createInternalModuleById(20), Stream = @getInternalField(@internalModuleRegistry, 37) || @createInternalModuleById(37), { isArrayBufferView } = @requireNativeModule(\"util/types\"), _writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), _fs = Symbol.for(\"#fs\"), constants = @processBindingConstants.fs, fs = Bun.fs();\n\nclass FSWatcher extends EventEmitter {\n #watcher;\n #listener;\n constructor(path, options, listener) {\n super();\n if (typeof options === \"function\")\n listener = options, options = {};\n else if (typeof options === \"string\")\n options = { encoding: options };\n if (typeof listener !== \"function\")\n listener = () => {\n };\n this.#listener = listener;\n try {\n this.#watcher = fs.watch(path, options || {}, this.#onEvent.bind(this));\n } catch (e) {\n if (!e.message\?.startsWith(\"FileNotFound\"))\n throw e;\n const notFound = new Error(`ENOENT: no such file or directory, watch '${path}'`);\n throw notFound.code = \"ENOENT\", notFound.errno = -2, notFound.path = path, notFound.syscall = \"watch\", notFound.filename = path, notFound;\n }\n }\n #onEvent(eventType, filenameOrError) {\n if (eventType === \"error\" || eventType === \"close\")\n this.emit(eventType, filenameOrError);\n else\n this.emit(\"change\", eventType, filenameOrError), this.#listener(eventType, filenameOrError);\n }\n close() {\n this.#watcher\?.close(), this.#watcher = null;\n }\n ref() {\n this.#watcher\?.ref();\n }\n unref() {\n this.#watcher\?.unref();\n }\n start() {\n }\n}\n\nclass StatWatcher extends EventEmitter {\n constructor(path, options) {\n super();\n this._handle = fs.watchFile(path, options, this.#onChange.bind(this));\n }\n #onChange(curr, prev) {\n this.emit(\"change\", curr, prev);\n }\n start() {\n }\n stop() {\n this._handle\?.close(), this._handle = null;\n }\n ref() {\n this._handle\?.ref();\n }\n unref() {\n this._handle\?.unref();\n }\n}\nvar access = function access2(...args) {\n callbackify(fs.access, args);\n}, appendFile = function appendFile2(...args) {\n callbackify(fs.appendFile, args);\n}, close = function close2(...args) {\n callbackify(fs.close, args);\n}, rm = function rm2(...args) {\n callbackify(fs.rm, args);\n}, rmdir = function rmdir2(...args) {\n callbackify(fs.rmdir, args);\n}, copyFile = function copyFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.copyFile(...args).then((result) => callback(null, result), callback);\n}, exists = function exists2(...args) {\n callbackify(fs.exists, args);\n}, chown = function chown2(...args) {\n callbackify(fs.chown, args);\n}, chmod = function chmod2(...args) {\n callbackify(fs.chmod, args);\n}, fchmod = function fchmod2(...args) {\n callbackify(fs.fchmod, args);\n}, fchown = function fchown2(...args) {\n callbackify(fs.fchown, args);\n}, fstat = function fstat2(...args) {\n callbackify(fs.fstat, args);\n}, fsync = function fsync2(...args) {\n callbackify(fs.fsync, args);\n}, ftruncate = function ftruncate2(...args) {\n callbackify(fs.ftruncate, args);\n}, futimes = function futimes2(...args) {\n callbackify(fs.futimes, args);\n}, lchmod = function lchmod2(...args) {\n callbackify(fs.lchmod, args);\n}, lchown = function lchown2(...args) {\n callbackify(fs.lchown, args);\n}, link = function link2(...args) {\n callbackify(fs.link, args);\n}, mkdir = function mkdir2(...args) {\n callbackify(fs.mkdir, args);\n}, mkdtemp = function mkdtemp2(...args) {\n callbackify(fs.mkdtemp, args);\n}, open = function open2(...args) {\n callbackify(fs.open, args);\n}, read = function read2(fd, buffer, offsetOrOptions, length, position, callback) {\n let offset = offsetOrOptions, params = null;\n if (arguments.length <= 4) {\n if (arguments.length === 4)\n callback = length, params = offsetOrOptions;\n else if (arguments.length === 3) {\n if (!isArrayBufferView(buffer))\n params = buffer, { buffer = @Buffer.alloc(16384) } = params \?\? {};\n callback = offsetOrOptions;\n } else\n callback = buffer, buffer = @Buffer.alloc(16384);\n ({ offset = 0, length = buffer\?.byteLength - offset, position = null } = params \?\? {});\n }\n queueMicrotask(() => {\n try {\n var bytesRead = fs.readSync(fd, buffer, offset, length, position);\n } catch (e) {\n callback(e);\n }\n callback(null, bytesRead, buffer);\n });\n}, write = function write2(...args) {\n callbackify(fs.write, args);\n}, readdir = function readdir2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readdir(...args).then((result) => callback(null, result), callback);\n}, readFile = function readFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readFile(...args).then((result) => callback(null, result), callback);\n}, writeFile = function writeFile2(...args) {\n callbackify(fs.writeFile, args);\n}, readlink = function readlink2(...args) {\n callbackify(fs.readlink, args);\n}, realpath = function realpath2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.realpath(...args).then((result) => callback(null, result), callback);\n}, rename = function rename2(...args) {\n callbackify(fs.rename, args);\n}, lstat = function lstat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.lstat(...args).then((result) => callback(null, result), callback);\n}, stat = function stat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.stat(...args).then((result) => callback(null, result), callback);\n}, symlink = function symlink2(...args) {\n callbackify(fs.symlink, args);\n}, truncate = function truncate2(...args) {\n callbackify(fs.truncate, args);\n}, unlink = function unlink2(...args) {\n callbackify(fs.unlink, args);\n}, utimes = function utimes2(...args) {\n callbackify(fs.utimes, args);\n}, lutimes = function lutimes2(...args) {\n callbackify(fs.lutimes, args);\n}, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), closeSync = fs.closeSync.bind(fs), copyFileSync = fs.copyFileSync.bind(fs), existsSync = fs.existsSync.bind(fs), chownSync = fs.chownSync.bind(fs), chmodSync = fs.chmodSync.bind(fs), fchmodSync = fs.fchmodSync.bind(fs), fchownSync = fs.fchownSync.bind(fs), fstatSync = fs.fstatSync.bind(fs), fsyncSync = fs.fsyncSync.bind(fs), ftruncateSync = fs.ftruncateSync.bind(fs), futimesSync = fs.futimesSync.bind(fs), lchmodSync = fs.lchmodSync.bind(fs), lchownSync = fs.lchownSync.bind(fs), linkSync = fs.linkSync.bind(fs), lstatSync = fs.lstatSync.bind(fs), mkdirSync = fs.mkdirSync.bind(fs), mkdtempSync = fs.mkdtempSync.bind(fs), openSync = fs.openSync.bind(fs), readSync = fs.readSync.bind(fs), writeSync = fs.writeSync.bind(fs), readdirSync = fs.readdirSync.bind(fs), readFileSync = fs.readFileSync.bind(fs), writeFileSync = fs.writeFileSync.bind(fs), readlinkSync = fs.readlinkSync.bind(fs), realpathSync = fs.realpathSync.bind(fs), renameSync = fs.renameSync.bind(fs), statSync = fs.statSync.bind(fs), symlinkSync = fs.symlinkSync.bind(fs), truncateSync = fs.truncateSync.bind(fs), unlinkSync = fs.unlinkSync.bind(fs), utimesSync = fs.utimesSync.bind(fs), lutimesSync = fs.lutimesSync.bind(fs), rmSync = fs.rmSync.bind(fs), rmdirSync = fs.rmdirSync.bind(fs), writev = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.writevSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, writevSync = fs.writevSync.bind(fs), readv = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.readvSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {\n return new FSWatcher(path, options, listener);\n}, statWatchers = new Map, _pathModule, readStreamPathFastPathSymbol = Symbol.for(\"Bun.Node.readStreamPathFastPath\"), readStreamSymbol = Symbol.for(\"Bun.NodeReadStream\"), readStreamPathOrFdSymbol = Symbol.for(\"Bun.NodeReadStreamPathOrFd\"), writeStreamSymbol = Symbol.for(\"Bun.NodeWriteStream\"), writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), writeStreamPathFastPathCallSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPathCall\"), kIoDone = Symbol.for(\"kIoDone\"), defaultReadStreamOptions = {\n file: @undefined,\n fd: null,\n flags: \"r\",\n encoding: @undefined,\n mode: 438,\n autoClose: !0,\n emitClose: !0,\n start: 0,\n end: @Infinity,\n highWaterMark: 65536,\n fs: {\n read,\n open: (path, flags, mode, cb) => {\n var fd;\n try {\n fd = openSync(path, flags, mode);\n } catch (e) {\n cb(e);\n return;\n }\n cb(null, fd);\n },\n openSync,\n close\n },\n autoDestroy: !0\n}, ReadStreamClass;\nReadStream = function(InternalReadStream) {\n ReadStreamClass = InternalReadStream, Object.defineProperty(ReadStreamClass.prototype, Symbol.toStringTag, {\n value: \"ReadStream\",\n enumerable: !1\n });\n function ReadStream3(path, options) {\n return new InternalReadStream(path, options);\n }\n return ReadStream3.prototype = InternalReadStream.prototype, Object.defineProperty(ReadStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalReadStream;\n }\n });\n}(class ReadStream2 extends Stream._getNativeReadableStreamPrototype(2, Stream.Readable) {\n constructor(pathOrFd, options = defaultReadStreamOptions) {\n if (typeof options !== \"object\" || !options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n flags = defaultReadStreamOptions.flags,\n encoding = defaultReadStreamOptions.encoding,\n mode = defaultReadStreamOptions.mode,\n autoClose = defaultReadStreamOptions.autoClose,\n emitClose = defaultReadStreamOptions.emitClose,\n start = defaultReadStreamOptions.start,\n end = defaultReadStreamOptions.end,\n autoDestroy = defaultReadStreamOptions.autoClose,\n fs: fs2 = defaultReadStreamOptions.fs,\n highWaterMark = defaultReadStreamOptions.highWaterMark,\n fd = defaultReadStreamOptions.fd\n } = options;\n if (pathOrFd\?.constructor\?.name === \"URL\")\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n var tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n @throwTypeError(\"Expected options.fd to be a number\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = fd, tempThis.autoClose = !1;\n } else if (typeof pathOrFd === \"string\") {\n if (pathOrFd.startsWith(\"file://\"))\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n if (pathOrFd.length === 0)\n @throwTypeError(\"Expected path to be a non-empty string\");\n tempThis.path = tempThis.file = tempThis[readStreamPathOrFdSymbol] = pathOrFd;\n } else if (typeof pathOrFd === \"number\") {\n if (pathOrFd |= 0, pathOrFd < 0)\n @throwTypeError(\"Expected fd to be a positive integer\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = pathOrFd, tempThis.autoClose = !1;\n } else\n @throwTypeError(\"Expected a path or file descriptor\");\n if (tempThis.fd === @undefined)\n tempThis.fd = fs2.openSync(pathOrFd, flags, mode);\n var fileRef = Bun.file(tempThis.fd), stream = fileRef.stream(), native = @direct(stream);\n if (!native)\n throw new Error(\"no native readable stream\");\n var { stream: ptr } = native;\n super(ptr, {\n ...options,\n encoding,\n autoDestroy,\n autoClose,\n emitClose,\n highWaterMark\n });\n if (Object.assign(this, tempThis), this.#fileRef = fileRef, this.end = end, this._read = this.#internalRead, this.start = start, this.flags = flags, this.mode = mode, this.emitClose = emitClose, this[readStreamPathFastPathSymbol] = start === 0 && end === @Infinity && autoClose && fs2 === defaultReadStreamOptions.fs && (encoding === \"buffer\" || encoding === \"binary\" || encoding == null || encoding === \"utf-8\" || encoding === \"utf8\"), this._readableState.autoClose = autoDestroy = autoClose, this._readableState.highWaterMark = highWaterMark, start !== @undefined)\n this.pos = start;\n }\n #fileRef;\n #fs;\n file;\n path;\n fd = null;\n flags;\n mode;\n start;\n end;\n pos;\n bytesRead = 0;\n #fileSize = -1;\n _read;\n [readStreamSymbol] = !0;\n [readStreamPathOrFdSymbol];\n [readStreamPathFastPathSymbol];\n _construct(callback) {\n if (super._construct)\n super._construct(callback);\n else\n callback();\n this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n super._destroy(err, cb);\n try {\n var fd = this.fd;\n if (this[readStreamPathFastPathSymbol] = !1, !fd)\n cb(err);\n else\n this.#fs.close(fd, (er) => {\n cb(er || err);\n }), this.fd = null;\n } catch (e) {\n throw e;\n }\n }\n close(cb) {\n if (typeof cb === \"function\")\n Stream.eos(this, cb);\n this.destroy();\n }\n push(chunk) {\n var bytesRead = chunk\?.length \?\? 0;\n if (bytesRead > 0) {\n this.bytesRead += bytesRead;\n var currPos = this.pos;\n if (currPos !== @undefined) {\n if (this.bytesRead < currPos)\n return !0;\n if (currPos === this.start) {\n var n = this.bytesRead - currPos;\n chunk = chunk.slice(-n);\n var [_, ...rest] = arguments;\n if (this.pos = this.bytesRead, this.end !== @undefined && this.bytesRead > this.end)\n chunk = chunk.slice(0, this.end - this.start + 1);\n return super.push(chunk, ...rest);\n }\n var end = this.end;\n if (end !== @undefined && this.bytesRead > end) {\n chunk = chunk.slice(0, end - currPos + 1);\n var [_, ...rest] = arguments;\n return this.pos = this.bytesRead, super.push(chunk, ...rest);\n }\n this.pos = this.bytesRead;\n }\n }\n return super.push(...arguments);\n }\n #internalRead(n) {\n var { pos, end, bytesRead, fd, encoding } = this;\n if (n = pos !== @undefined \? Math.min(end - pos + 1, n) : Math.min(end - bytesRead + 1, n), n <= 0) {\n this.push(null);\n return;\n }\n if (this.#fileSize === -1 && bytesRead === 0 && pos === @undefined) {\n var stat3 = fstatSync(fd);\n if (this.#fileSize = stat3.size, this.#fileSize > 0 && n > this.#fileSize)\n n = this.#fileSize + 1;\n }\n this[kIoDone] = !1;\n var res = super._read(n);\n if (@isPromise(res)) {\n var then = res\?.then;\n if (then && @isCallable(then))\n res.then(() => {\n if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone);\n }, (er) => {\n this[kIoDone] = !0, this.#errorOrDestroy(er);\n });\n } else if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone), this.#errorOrDestroy(new Error(\"ERR_STREAM_PREMATURE_CLOSE\"));\n }\n #errorOrDestroy(err, sync = null) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n }\n pause() {\n return this[readStreamPathFastPathSymbol] = !1, super.pause();\n }\n resume() {\n return this[readStreamPathFastPathSymbol] = !1, super.resume();\n }\n unshift(...args) {\n return this[readStreamPathFastPathSymbol] = !1, super.unshift(...args);\n }\n pipe(dest, pipeOpts) {\n if (this[readStreamPathFastPathSymbol] && (pipeOpts\?.end \?\? !0) && this._readableState\?.pipes\?.length === 0) {\n if ((writeStreamPathFastPathSymbol in dest) && dest[writeStreamPathFastPathSymbol]) {\n if (dest[writeStreamPathFastPathCallSymbol](this, pipeOpts))\n return this;\n }\n }\n return this[readStreamPathFastPathSymbol] = !1, super.pipe(dest, pipeOpts);\n }\n});\nvar defaultWriteStreamOptions = {\n fd: null,\n start: @undefined,\n pos: @undefined,\n encoding: @undefined,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass = WriteStream = function WriteStream2(path, options = defaultWriteStreamOptions) {\n if (!(this instanceof WriteStream2))\n return new WriteStream2(path, options);\n if (!options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n fs: fs2 = defaultWriteStreamOptions.fs,\n start = defaultWriteStreamOptions.start,\n flags = defaultWriteStreamOptions.flags,\n mode = defaultWriteStreamOptions.mode,\n autoClose = !0,\n emitClose = !1,\n autoDestroy = autoClose,\n encoding = defaultWriteStreamOptions.encoding,\n fd = defaultWriteStreamOptions.fd,\n pos = defaultWriteStreamOptions.pos\n } = options, tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n throw new Error(\"Expected options.fd to be a number\");\n tempThis.fd = fd, tempThis[_writeStreamPathFastPathSymbol] = !1;\n } else if (typeof path === \"string\") {\n if (path.length === 0)\n @throwTypeError(\"Expected a non-empty path\");\n if (path.startsWith(\"file:\"))\n path = Bun.fileURLToPath(path);\n tempThis.path = path, tempThis.fd = null, tempThis[_writeStreamPathFastPathSymbol] = autoClose && (start === @undefined || start === 0) && fs2.write === defaultWriteStreamOptions.fs.write && fs2.close === defaultWriteStreamOptions.fs.close;\n }\n if (tempThis.fd == null)\n tempThis.fd = fs2.openSync(path, flags, mode);\n if (NativeWritable.call(this, tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n }), Object.assign(this, tempThis), typeof fs2\?.write !== \"function\")\n @throwTypeError(\"Expected fs.write to be a function\");\n if (typeof fs2\?.close !== \"function\")\n @throwTypeError(\"Expected fs.close to be a function\");\n if (typeof fs2\?.open !== \"function\")\n @throwTypeError(\"Expected fs.open to be a function\");\n if (typeof path === \"object\" && path) {\n if (path instanceof URL)\n path = Bun.fileURLToPath(path);\n }\n if (typeof path !== \"string\" && typeof fd !== \"number\")\n @throwTypeError(\"Expected a path or file descriptor\");\n if (this.start = start, this[_fs] = fs2, this.flags = flags, this.mode = mode, this.bytesWritten = 0, this[writeStreamSymbol] = !0, this[kIoDone] = !1, this.start !== @undefined)\n this.pos = this.start;\n if (encoding !== defaultWriteStreamOptions.encoding) {\n if (this.setDefaultEncoding(encoding), encoding !== \"buffer\" && encoding !== \"utf8\" && encoding !== \"utf-8\" && encoding !== \"binary\")\n this[_writeStreamPathFastPathSymbol] = !1;\n }\n return this;\n}, NativeWritable = Stream.NativeWritable, WriteStreamPrototype = WriteStream.prototype = Object.create(NativeWritable.prototype);\nObject.defineProperties(WriteStreamPrototype, {\n autoClose: {\n get() {\n return this._writableState.autoDestroy;\n },\n set(val) {\n this._writableState.autoDestroy = val;\n }\n },\n pending: {\n get() {\n return this.fd === null;\n }\n }\n});\nWriteStreamPrototype.destroySoon = WriteStreamPrototype.end;\nWriteStreamPrototype.open = function open3() {\n};\nWriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(readStream, pipeOpts) {\n if (!this[_writeStreamPathFastPathSymbol])\n return !1;\n if (this.fd !== null)\n return this[_writeStreamPathFastPathSymbol] = !1, !1;\n return this[kIoDone] = !1, readStream[kIoDone] = !1, Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then((bytesWritten) => {\n readStream[kIoDone] = this[kIoDone] = !0, this.bytesWritten += bytesWritten, readStream.bytesRead += bytesWritten, this.end(), readStream.close();\n }, (err) => {\n readStream[kIoDone] = this[kIoDone] = !0, WriteStream_errorOrDestroy.call(this, err), readStream.emit(\"error\", err);\n });\n};\nWriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {\n return this[_writeStreamPathFastPathSymbol];\n};\nWriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {\n this[_writeStreamPathFastPathSymbol] = !1;\n};\nWriteStreamPrototype._construct = function _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n};\nWriteStreamPrototype._destroy = function _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));\n return;\n }\n WriteStream_internalClose.call(this, err, cb);\n};\nWriteStreamPrototype.close = function close3(cb) {\n if (cb) {\n if (this.closed) {\n process.nextTick(cb);\n return;\n }\n this.on(\"close\", cb);\n }\n if (!this.autoClose)\n this.on(\"finish\", this.destroy);\n this.end();\n};\nWriteStreamPrototype.write = function write3(chunk, encoding, cb) {\n if (encoding \?\?= this._writableState\?.defaultEncoding, this[_writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = @Buffer.from(chunk, encoding);\n var native = this.pos === @undefined;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, WriteStream_handleWrite.call(this, err, bytes), this.emit(kIoDone), cb)\n !err \? cb() : cb(err);\n } : () => {\n };\n if (this[kIoDone] = !0, this._write)\n return this._write(chunk, encoding, callback);\n else\n return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);\n};\nWriteStreamPrototype._write = @undefined;\nWriteStreamPrototype._writev = @undefined;\nWriteStreamPrototype.end = function end(chunk, encoding, cb) {\n var native = this.pos === @undefined;\n return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);\n};\nWriteStreamPrototype._destroy = function _destroy2(err, cb) {\n this.close(err, cb);\n};\nObject.defineProperties(fs, {\n createReadStream: {\n value: createReadStream\n },\n createWriteStream: {\n value: createWriteStream\n },\n ReadStream: {\n value: ReadStream\n },\n WriteStream: {\n value: WriteStream\n }\n});\nrealpath.native = realpath;\nrealpathSync.native = realpathSync;\nvar lazy_cpSync = null;\n$ = {\n Dirent,\n FSWatcher,\n ReadStream,\n Stats,\n WriteStream,\n _toUnixTimestamp,\n access,\n accessSync,\n appendFile,\n appendFileSync,\n chmod,\n chmodSync,\n chown,\n chownSync,\n close,\n closeSync,\n constants,\n copyFile,\n copyFileSync,\n cp,\n cpSync,\n createReadStream,\n createWriteStream,\n exists,\n existsSync,\n fchmod,\n fchmodSync,\n fchown,\n fchownSync,\n fstat,\n fstatSync,\n fsync,\n fsyncSync,\n ftruncate,\n ftruncateSync,\n futimes,\n futimesSync,\n lchmod,\n lchmodSync,\n lchown,\n lchownSync,\n link,\n linkSync,\n lstat,\n lstatSync,\n lutimes,\n lutimesSync,\n mkdir,\n mkdirSync,\n mkdtemp,\n mkdtempSync,\n open,\n openSync,\n promises,\n read,\n readFile,\n readFileSync,\n readSync,\n readdir,\n readdirSync,\n readlink,\n readlinkSync,\n readv,\n readvSync,\n realpath,\n realpathSync,\n rename,\n renameSync,\n rm,\n rmSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n symlink,\n symlinkSync,\n truncate,\n truncateSync,\n unlink,\n unlinkSync,\n unwatchFile,\n utimes,\n utimesSync,\n watch,\n watchFile,\n write,\n writeFile,\n writeFileSync,\n writeSync,\n writev,\n writevSync,\n [Symbol.for(\"::bunternal::\")]: {\n ReadStreamClass,\n WriteStreamClass\n }\n};\nreturn $})\n"_s; // // -static constexpr ASCIILiteral NodeFSPromisesCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.promises.ts\nvar watch = function(filename, options = {}) {\n if (filename instanceof URL)\n @throwTypeError(\"Watch URLs are not supported yet\");\n else if (@Buffer.isBuffer(filename))\n filename = filename.toString();\n else if (typeof filename !== \"string\")\n @throwTypeError(\"Expected path to be a string or Buffer\");\n let nextEventResolve = null;\n if (typeof options === \"string\")\n options = { encoding: options };\n const queue = @createFIFO(), watcher = fs.watch(filename, options || {}, (eventType, filename2) => {\n if (queue.push({ eventType, filename: filename2 }), nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n });\n return {\n [Symbol.asyncIterator]() {\n let closed = !1;\n return {\n async next() {\n while (!closed) {\n let event;\n while (event = queue.shift()) {\n if (event.eventType === \"close\")\n return closed = !0, { value: @undefined, done: !0 };\n if (event.eventType === \"error\")\n throw closed = !0, event.filename;\n return { value: event, done: !1 };\n }\n const { promise, resolve } = @Promise.withResolvers();\n nextEventResolve = resolve, await promise;\n }\n return { value: @undefined, done: !0 };\n },\n return() {\n if (!closed) {\n if (watcher.close(), closed = !0, nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n }\n return { value: @undefined, done: !0 };\n }\n };\n }\n };\n}, cp = function(src, dest, options) {\n if (!options)\n return fs.cp(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cp)\n lazy_cp = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cp(src, dest, options);\n }\n return fs.cp(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n};\nasync function opendir(dir) {\n const entries = await fs.readdir(dir, { withFileTypes: !0 });\n return new Dir(entries);\n}\nvar $, constants = @processBindingConstants.fs, fs = Bun.fs(), notrace = \"::bunternal::\", promisify = {\n [notrace]: (fsFunction) => {\n return async function(...args) {\n return await 1, fsFunction.apply(fs, args);\n };\n }\n}[notrace], lazy_cp = null;\n\nclass Dir {\n #entries;\n constructor(e) {\n this.#entries = e;\n }\n readSync() {\n return this.#entries.shift() \?\? null;\n }\n read(c) {\n if (c)\n process.nextTick(c, null, this.readSync());\n return @Promise.resolve(this.readSync());\n }\n closeSync() {\n }\n close(c) {\n if (c)\n process.nextTick(c);\n return @Promise.resolve();\n }\n *[Symbol.asyncIterator]() {\n var next;\n while (next = this.readSync())\n yield next;\n }\n}\n$ = {\n access: promisify(fs.accessSync),\n appendFile: promisify(fs.appendFileSync),\n close: promisify(fs.closeSync),\n copyFile: fs.copyFile.bind(fs),\n cp,\n exists: promisify(fs.existsSync),\n chown: promisify(fs.chownSync),\n chmod: promisify(fs.chmodSync),\n fchmod: promisify(fs.fchmodSync),\n fchown: promisify(fs.fchownSync),\n fstat: promisify(fs.fstatSync),\n fsync: promisify(fs.fsyncSync),\n ftruncate: promisify(fs.ftruncateSync),\n futimes: promisify(fs.futimesSync),\n lchmod: promisify(fs.lchmodSync),\n lchown: promisify(fs.lchownSync),\n link: promisify(fs.linkSync),\n lstat: fs.lstat.bind(fs),\n mkdir: promisify(fs.mkdirSync),\n mkdtemp: promisify(fs.mkdtempSync),\n open: promisify(fs.openSync),\n read: promisify(fs.readSync),\n write: promisify(fs.writeSync),\n readdir: fs.readdir.bind(fs),\n readFile: fs.readFile.bind(fs),\n writeFile: promisify(fs.writeFileSync),\n readlink: promisify(fs.readlinkSync),\n realpath: fs.realpath.bind(fs),\n rename: promisify(fs.renameSync),\n stat: fs.stat.bind(fs),\n symlink: promisify(fs.symlinkSync),\n truncate: promisify(fs.truncateSync),\n unlink: promisify(fs.unlinkSync),\n utimes: promisify(fs.utimesSync),\n lutimes: promisify(fs.lutimesSync),\n rm: promisify(fs.rmSync),\n rmdir: promisify(fs.rmdirSync),\n writev: (fd, buffers, position) => {\n return new @Promise((resolve, reject) => {\n try {\n var bytesWritten = fs.writevSync(fd, buffers, position);\n } catch (err) {\n reject(err);\n return;\n }\n resolve({\n bytesWritten,\n buffers\n });\n });\n },\n readv: (fd, buffers, position) => {\n return new @Promise((resolve, reject) => {\n try {\n var bytesRead = fs.readvSync(fd, buffers, position);\n } catch (err) {\n reject(err);\n return;\n }\n resolve({\n bytesRead,\n buffers\n });\n });\n },\n constants,\n watch,\n opendir\n};\nreturn $})\n"_s; +static constexpr ASCIILiteral NodeFSPromisesCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.promises.ts\nvar watch = function(filename, options = {}) {\n if (filename instanceof URL)\n @throwTypeError(\"Watch URLs are not supported yet\");\n else if (@Buffer.isBuffer(filename))\n filename = filename.toString();\n else if (typeof filename !== \"string\")\n @throwTypeError(\"Expected path to be a string or Buffer\");\n let nextEventResolve = null;\n if (typeof options === \"string\")\n options = { encoding: options };\n const queue = @createFIFO(), watcher = fs.watch(filename, options || {}, (eventType, filename2) => {\n if (queue.push({ eventType, filename: filename2 }), nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n });\n return {\n [Symbol.asyncIterator]() {\n let closed = !1;\n return {\n async next() {\n while (!closed) {\n let event;\n while (event = queue.shift()) {\n if (event.eventType === \"close\")\n return closed = !0, { value: @undefined, done: !0 };\n if (event.eventType === \"error\")\n throw closed = !0, event.filename;\n return { value: event, done: !1 };\n }\n const { promise, resolve } = @Promise.withResolvers();\n nextEventResolve = resolve, await promise;\n }\n return { value: @undefined, done: !0 };\n },\n return() {\n if (!closed) {\n if (watcher.close(), closed = !0, nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n }\n return { value: @undefined, done: !0 };\n }\n };\n }\n };\n}, cp = function(src, dest, options) {\n if (!options)\n return fs.cp(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cp)\n lazy_cp = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cp(src, dest, options);\n }\n return fs.cp(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n};\nasync function opendir(dir) {\n const entries = await fs.readdir(dir, { withFileTypes: !0 });\n return new Dir(entries);\n}\nvar $, constants = @processBindingConstants.fs, fs = Bun.fs();\nvar lazy_cp = null;\n\nclass Dir {\n #entries;\n constructor(e) {\n this.#entries = e;\n }\n readSync() {\n return this.#entries.shift() \?\? null;\n }\n read(c) {\n if (c)\n process.nextTick(c, null, this.readSync());\n return @Promise.resolve(this.readSync());\n }\n closeSync() {\n }\n close(c) {\n if (c)\n process.nextTick(c);\n return @Promise.resolve();\n }\n *[Symbol.asyncIterator]() {\n var next;\n while (next = this.readSync())\n yield next;\n }\n}\n$ = {\n access: fs.access.bind(fs),\n appendFile: fs.appendFile.bind(fs),\n close: fs.close.bind(fs),\n copyFile: fs.copyFile.bind(fs),\n cp,\n exists: fs.exists.bind(fs),\n chown: fs.chown.bind(fs),\n chmod: fs.chmod.bind(fs),\n fchmod: fs.fchmod.bind(fs),\n fchown: fs.fchown.bind(fs),\n fstat: fs.fstat.bind(fs),\n fsync: fs.fsync.bind(fs),\n ftruncate: fs.ftruncate.bind(fs),\n futimes: fs.futimes.bind(fs),\n lchmod: fs.lchmod.bind(fs),\n lchown: fs.lchown.bind(fs),\n link: fs.link.bind(fs),\n lstat: fs.lstat.bind(fs),\n mkdir: fs.mkdir.bind(fs),\n mkdtemp: fs.mkdtemp.bind(fs),\n open: fs.open.bind(fs),\n read: fs.read.bind(fs),\n write: fs.write.bind(fs),\n readdir: fs.readdir.bind(fs),\n readFile: fs.readFile.bind(fs),\n writeFile: fs.writeFile.bind(fs),\n readlink: fs.readlink.bind(fs),\n realpath: fs.realpath.bind(fs),\n rename: fs.rename.bind(fs),\n stat: fs.stat.bind(fs),\n symlink: fs.symlink.bind(fs),\n truncate: fs.truncate.bind(fs),\n unlink: fs.unlink.bind(fs),\n utimes: fs.utimes.bind(fs),\n lutimes: fs.lutimes.bind(fs),\n rm: fs.rm.bind(fs),\n rmdir: fs.rmdir.bind(fs),\n writev: async (fd, buffers, position) => {\n var bytesWritten = await fs.writev(fd, buffers, position);\n return {\n bytesWritten,\n buffers\n };\n },\n readv: async (fd, buffers, position) => {\n var bytesRead = await fs.readv(fd, buffers, position);\n return {\n bytesRead,\n buffers\n };\n },\n constants,\n watch,\n opendir\n};\nreturn $})\n"_s; // // @@ -323,11 +323,11 @@ static constexpr ASCIILiteral NodeEventsCode = "(function (){\"use strict\";// s // // -static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar getValidatedPath = function(p) {\n if (p instanceof URL)\n return Bun.fileURLToPath(p);\n if (typeof p !== \"string\")\n @throwTypeError(\"Path must be a string or URL.\");\n return (_pathModule \?\?= @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28)).resolve(p);\n}, watchFile = function(filename, options, listener) {\n if (filename = getValidatedPath(filename), typeof options === \"function\")\n listener = options, options = {};\n if (typeof listener !== \"function\")\n @throwTypeError(\"listener must be a function\");\n var stat = statWatchers.get(filename);\n if (!stat)\n stat = new StatWatcher(filename, options), statWatchers.set(filename, stat);\n return stat.addListener(\"change\", listener), stat;\n}, unwatchFile = function(filename, listener) {\n filename = getValidatedPath(filename);\n var stat = statWatchers.get(filename);\n if (!stat)\n return;\n if (listener) {\n if (stat.removeListener(\"change\", listener), stat.listenerCount(\"change\") !== 0)\n return;\n } else\n stat.removeAllListeners(\"change\");\n stat.stop(), statWatchers.delete(filename);\n}, callbackify = function(fsFunction, args) {\n try {\n const result = fsFunction.apply(fs, args.slice(0, args.length - 1)), callback = args[args.length - 1];\n if (typeof callback === \"function\")\n queueMicrotask(() => callback(null, result));\n } catch (e) {\n const callback = args[args.length - 1];\n if (typeof callback === \"function\")\n queueMicrotask(() => callback(e));\n }\n}, createReadStream = function(path, options) {\n return new ReadStream(path, options);\n}, WriteStream_handleWrite = function(er, bytes) {\n if (er)\n return WriteStream_errorOrDestroy.call(this, er);\n this.bytesWritten += bytes;\n}, WriteStream_internalClose = function(err, cb) {\n this[_writeStreamPathFastPathSymbol] = !1;\n var fd = this.fd;\n this[_fs].close(fd, (er) => {\n this.fd = null, cb(err || er);\n });\n}, WriteStream_errorOrDestroy = function(err) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n}, createWriteStream = function(path, options) {\n return new WriteStream(path, options);\n}, cpSync = function(src, dest, options) {\n if (!options)\n return fs.cpSync(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cpSync)\n lazy_cpSync = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cpSync(src, dest, options);\n }\n return fs.cpSync(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n}, cp = function(src, dest, options, callback) {\n if (typeof options === \"function\")\n callback = options, options = @undefined;\n promises.cp(src, dest, options).then(() => callback(), callback);\n}, _toUnixTimestamp = function(time, name = \"time\") {\n if (typeof time === \"string\" && +time == time)\n return +time;\n if (NumberIsFinite(time)) {\n if (time < 0)\n return DateNow() / 1000;\n return time;\n }\n if (isDate(time))\n return DatePrototypeGetTime(time) / 1000;\n @throwTypeError(`Expected ${name} to be a number or Date`);\n}, $, ReadStream, WriteStream, EventEmitter = @getInternalField(@internalModuleRegistry, 18) || @createInternalModuleById(18), promises = @getInternalField(@internalModuleRegistry, 20) || @createInternalModuleById(20), Stream = @getInternalField(@internalModuleRegistry, 37) || @createInternalModuleById(37), { isArrayBufferView } = @requireNativeModule(\"util/types\"), _writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), _fs = Symbol.for(\"#fs\"), constants = @processBindingConstants.fs, fs = Bun.fs();\n\nclass FSWatcher extends EventEmitter {\n #watcher;\n #listener;\n constructor(path, options, listener) {\n super();\n if (typeof options === \"function\")\n listener = options, options = {};\n else if (typeof options === \"string\")\n options = { encoding: options };\n if (typeof listener !== \"function\")\n listener = () => {\n };\n this.#listener = listener;\n try {\n this.#watcher = fs.watch(path, options || {}, this.#onEvent.bind(this));\n } catch (e) {\n if (!e.message\?.startsWith(\"FileNotFound\"))\n throw e;\n const notFound = new Error(`ENOENT: no such file or directory, watch '${path}'`);\n throw notFound.code = \"ENOENT\", notFound.errno = -2, notFound.path = path, notFound.syscall = \"watch\", notFound.filename = path, notFound;\n }\n }\n #onEvent(eventType, filenameOrError) {\n if (eventType === \"error\" || eventType === \"close\")\n this.emit(eventType, filenameOrError);\n else\n this.emit(\"change\", eventType, filenameOrError), this.#listener(eventType, filenameOrError);\n }\n close() {\n this.#watcher\?.close(), this.#watcher = null;\n }\n ref() {\n this.#watcher\?.ref();\n }\n unref() {\n this.#watcher\?.unref();\n }\n start() {\n }\n}\n\nclass StatWatcher extends EventEmitter {\n constructor(path, options) {\n super();\n this._handle = fs.watchFile(path, options, this.#onChange.bind(this));\n }\n #onChange(curr, prev) {\n this.emit(\"change\", curr, prev);\n }\n start() {\n }\n stop() {\n this._handle\?.close(), this._handle = null;\n }\n ref() {\n this._handle\?.ref();\n }\n unref() {\n this._handle\?.unref();\n }\n}\nvar access = function access2(...args) {\n callbackify(fs.accessSync, args);\n}, appendFile = function appendFile2(...args) {\n callbackify(fs.appendFileSync, args);\n}, close = function close2(...args) {\n callbackify(fs.closeSync, args);\n}, rm = function rm2(...args) {\n callbackify(fs.rmSync, args);\n}, rmdir = function rmdir2(...args) {\n callbackify(fs.rmdirSync, args);\n}, copyFile = function copyFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.copyFile(...args).then((result) => callback(null, result), callback);\n}, exists = function exists2(...args) {\n callbackify(fs.existsSync, args);\n}, chown = function chown2(...args) {\n callbackify(fs.chownSync, args);\n}, chmod = function chmod2(...args) {\n callbackify(fs.chmodSync, args);\n}, fchmod = function fchmod2(...args) {\n callbackify(fs.fchmodSync, args);\n}, fchown = function fchown2(...args) {\n callbackify(fs.fchownSync, args);\n}, fstat = function fstat2(...args) {\n callbackify(fs.fstatSync, args);\n}, fsync = function fsync2(...args) {\n callbackify(fs.fsyncSync, args);\n}, ftruncate = function ftruncate2(...args) {\n callbackify(fs.ftruncateSync, args);\n}, futimes = function futimes2(...args) {\n callbackify(fs.futimesSync, args);\n}, lchmod = function lchmod2(...args) {\n callbackify(fs.lchmodSync, args);\n}, lchown = function lchown2(...args) {\n callbackify(fs.lchownSync, args);\n}, link = function link2(...args) {\n callbackify(fs.linkSync, args);\n}, mkdir = function mkdir2(...args) {\n callbackify(fs.mkdirSync, args);\n}, mkdtemp = function mkdtemp2(...args) {\n callbackify(fs.mkdtempSync, args);\n}, open = function open2(...args) {\n callbackify(fs.openSync, args);\n}, read = function read2(fd, buffer, offsetOrOptions, length, position, callback) {\n let offset = offsetOrOptions, params = null;\n if (arguments.length <= 4) {\n if (arguments.length === 4)\n callback = length, params = offsetOrOptions;\n else if (arguments.length === 3) {\n if (!isArrayBufferView(buffer))\n params = buffer, { buffer = @Buffer.alloc(16384) } = params \?\? {};\n callback = offsetOrOptions;\n } else\n callback = buffer, buffer = @Buffer.alloc(16384);\n ({ offset = 0, length = buffer\?.byteLength - offset, position = null } = params \?\? {});\n }\n queueMicrotask(() => {\n try {\n var bytesRead = fs.readSync(fd, buffer, offset, length, position);\n } catch (e) {\n callback(e);\n }\n callback(null, bytesRead, buffer);\n });\n}, write = function write2(...args) {\n callbackify(fs.writeSync, args);\n}, readdir = function readdir2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readdir(...args).then((result) => callback(null, result), callback);\n}, readFile = function readFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readFile(...args).then((result) => callback(null, result), callback);\n}, writeFile = function writeFile2(...args) {\n callbackify(fs.writeFileSync, args);\n}, readlink = function readlink2(...args) {\n callbackify(fs.readlinkSync, args);\n}, realpath = function realpath2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.realpath(...args).then((result) => callback(null, result), callback);\n}, rename = function rename2(...args) {\n callbackify(fs.renameSync, args);\n}, lstat = function lstat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.lstat(...args).then((result) => callback(null, result), callback);\n}, stat = function stat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.stat(...args).then((result) => callback(null, result), callback);\n}, symlink = function symlink2(...args) {\n callbackify(fs.symlinkSync, args);\n}, truncate = function truncate2(...args) {\n callbackify(fs.truncateSync, args);\n}, unlink = function unlink2(...args) {\n callbackify(fs.unlinkSync, args);\n}, utimes = function utimes2(...args) {\n callbackify(fs.utimesSync, args);\n}, lutimes = function lutimes2(...args) {\n callbackify(fs.lutimesSync, args);\n}, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), closeSync = fs.closeSync.bind(fs), copyFileSync = fs.copyFileSync.bind(fs), existsSync = fs.existsSync.bind(fs), chownSync = fs.chownSync.bind(fs), chmodSync = fs.chmodSync.bind(fs), fchmodSync = fs.fchmodSync.bind(fs), fchownSync = fs.fchownSync.bind(fs), fstatSync = fs.fstatSync.bind(fs), fsyncSync = fs.fsyncSync.bind(fs), ftruncateSync = fs.ftruncateSync.bind(fs), futimesSync = fs.futimesSync.bind(fs), lchmodSync = fs.lchmodSync.bind(fs), lchownSync = fs.lchownSync.bind(fs), linkSync = fs.linkSync.bind(fs), lstatSync = fs.lstatSync.bind(fs), mkdirSync = fs.mkdirSync.bind(fs), mkdtempSync = fs.mkdtempSync.bind(fs), openSync = fs.openSync.bind(fs), readSync = fs.readSync.bind(fs), writeSync = fs.writeSync.bind(fs), readdirSync = fs.readdirSync.bind(fs), readFileSync = fs.readFileSync.bind(fs), writeFileSync = fs.writeFileSync.bind(fs), readlinkSync = fs.readlinkSync.bind(fs), realpathSync = fs.realpathSync.bind(fs), renameSync = fs.renameSync.bind(fs), statSync = fs.statSync.bind(fs), symlinkSync = fs.symlinkSync.bind(fs), truncateSync = fs.truncateSync.bind(fs), unlinkSync = fs.unlinkSync.bind(fs), utimesSync = fs.utimesSync.bind(fs), lutimesSync = fs.lutimesSync.bind(fs), rmSync = fs.rmSync.bind(fs), rmdirSync = fs.rmdirSync.bind(fs), writev = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.writevSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, writevSync = fs.writevSync.bind(fs), readv = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.readvSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {\n return new FSWatcher(path, options, listener);\n}, statWatchers = new Map, _pathModule, readStreamPathFastPathSymbol = Symbol.for(\"Bun.Node.readStreamPathFastPath\"), readStreamSymbol = Symbol.for(\"Bun.NodeReadStream\"), readStreamPathOrFdSymbol = Symbol.for(\"Bun.NodeReadStreamPathOrFd\"), writeStreamSymbol = Symbol.for(\"Bun.NodeWriteStream\"), writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), writeStreamPathFastPathCallSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPathCall\"), kIoDone = Symbol.for(\"kIoDone\"), defaultReadStreamOptions = {\n file: @undefined,\n fd: null,\n flags: \"r\",\n encoding: @undefined,\n mode: 438,\n autoClose: !0,\n emitClose: !0,\n start: 0,\n end: @Infinity,\n highWaterMark: 65536,\n fs: {\n read,\n open: (path, flags, mode, cb) => {\n var fd;\n try {\n fd = openSync(path, flags, mode);\n } catch (e) {\n cb(e);\n return;\n }\n cb(null, fd);\n },\n openSync,\n close\n },\n autoDestroy: !0\n}, ReadStreamClass;\nReadStream = function(InternalReadStream) {\n ReadStreamClass = InternalReadStream, Object.defineProperty(ReadStreamClass.prototype, Symbol.toStringTag, {\n value: \"ReadStream\",\n enumerable: !1\n });\n function ReadStream3(path, options) {\n return new InternalReadStream(path, options);\n }\n return ReadStream3.prototype = InternalReadStream.prototype, Object.defineProperty(ReadStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalReadStream;\n }\n });\n}(class ReadStream2 extends Stream._getNativeReadableStreamPrototype(2, Stream.Readable) {\n constructor(pathOrFd, options = defaultReadStreamOptions) {\n if (typeof options !== \"object\" || !options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n flags = defaultReadStreamOptions.flags,\n encoding = defaultReadStreamOptions.encoding,\n mode = defaultReadStreamOptions.mode,\n autoClose = defaultReadStreamOptions.autoClose,\n emitClose = defaultReadStreamOptions.emitClose,\n start = defaultReadStreamOptions.start,\n end = defaultReadStreamOptions.end,\n autoDestroy = defaultReadStreamOptions.autoClose,\n fs: fs2 = defaultReadStreamOptions.fs,\n highWaterMark = defaultReadStreamOptions.highWaterMark,\n fd = defaultReadStreamOptions.fd\n } = options;\n if (pathOrFd\?.constructor\?.name === \"URL\")\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n var tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n @throwTypeError(\"Expected options.fd to be a number\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = fd, tempThis.autoClose = !1;\n } else if (typeof pathOrFd === \"string\") {\n if (pathOrFd.startsWith(\"file://\"))\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n if (pathOrFd.length === 0)\n @throwTypeError(\"Expected path to be a non-empty string\");\n tempThis.path = tempThis.file = tempThis[readStreamPathOrFdSymbol] = pathOrFd;\n } else if (typeof pathOrFd === \"number\") {\n if (pathOrFd |= 0, pathOrFd < 0)\n @throwTypeError(\"Expected fd to be a positive integer\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = pathOrFd, tempThis.autoClose = !1;\n } else\n @throwTypeError(\"Expected a path or file descriptor\");\n if (tempThis.fd === @undefined)\n tempThis.fd = fs2.openSync(pathOrFd, flags, mode);\n var fileRef = Bun.file(tempThis.fd), stream = fileRef.stream(), native = @direct(stream);\n if (!native)\n throw new Error(\"no native readable stream\");\n var { stream: ptr } = native;\n super(ptr, {\n ...options,\n encoding,\n autoDestroy,\n autoClose,\n emitClose,\n highWaterMark\n });\n if (Object.assign(this, tempThis), this.#fileRef = fileRef, this.end = end, this._read = this.#internalRead, this.start = start, this.flags = flags, this.mode = mode, this.emitClose = emitClose, this[readStreamPathFastPathSymbol] = start === 0 && end === @Infinity && autoClose && fs2 === defaultReadStreamOptions.fs && (encoding === \"buffer\" || encoding === \"binary\" || encoding == null || encoding === \"utf-8\" || encoding === \"utf8\"), this._readableState.autoClose = autoDestroy = autoClose, this._readableState.highWaterMark = highWaterMark, start !== @undefined)\n this.pos = start;\n }\n #fileRef;\n #fs;\n file;\n path;\n fd = null;\n flags;\n mode;\n start;\n end;\n pos;\n bytesRead = 0;\n #fileSize = -1;\n _read;\n [readStreamSymbol] = !0;\n [readStreamPathOrFdSymbol];\n [readStreamPathFastPathSymbol];\n _construct(callback) {\n if (super._construct)\n super._construct(callback);\n else\n callback();\n this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n super._destroy(err, cb);\n try {\n var fd = this.fd;\n if (this[readStreamPathFastPathSymbol] = !1, !fd)\n cb(err);\n else\n this.#fs.close(fd, (er) => {\n cb(er || err);\n }), this.fd = null;\n } catch (e) {\n throw e;\n }\n }\n close(cb) {\n if (typeof cb === \"function\")\n Stream.eos(this, cb);\n this.destroy();\n }\n push(chunk) {\n var bytesRead = chunk\?.length \?\? 0;\n if (bytesRead > 0) {\n this.bytesRead += bytesRead;\n var currPos = this.pos;\n if (currPos !== @undefined) {\n if (this.bytesRead < currPos)\n return !0;\n if (currPos === this.start) {\n var n = this.bytesRead - currPos;\n chunk = chunk.slice(-n);\n var [_, ...rest] = arguments;\n if (this.pos = this.bytesRead, this.end !== @undefined && this.bytesRead > this.end)\n chunk = chunk.slice(0, this.end - this.start + 1);\n return super.push(chunk, ...rest);\n }\n var end = this.end;\n if (end !== @undefined && this.bytesRead > end) {\n chunk = chunk.slice(0, end - currPos + 1);\n var [_, ...rest] = arguments;\n return this.pos = this.bytesRead, super.push(chunk, ...rest);\n }\n this.pos = this.bytesRead;\n }\n }\n return super.push(...arguments);\n }\n #internalRead(n) {\n var { pos, end, bytesRead, fd, encoding } = this;\n if (n = pos !== @undefined \? Math.min(end - pos + 1, n) : Math.min(end - bytesRead + 1, n), n <= 0) {\n this.push(null);\n return;\n }\n if (this.#fileSize === -1 && bytesRead === 0 && pos === @undefined) {\n var stat3 = fstatSync(fd);\n if (this.#fileSize = stat3.size, this.#fileSize > 0 && n > this.#fileSize)\n n = this.#fileSize + 1;\n }\n this[kIoDone] = !1;\n var res = super._read(n);\n if (@isPromise(res)) {\n var then = res\?.then;\n if (then && @isCallable(then))\n res.then(() => {\n if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone);\n }, (er) => {\n this[kIoDone] = !0, this.#errorOrDestroy(er);\n });\n } else if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone), this.#errorOrDestroy(new Error(\"ERR_STREAM_PREMATURE_CLOSE\"));\n }\n #errorOrDestroy(err, sync = null) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n }\n pause() {\n return this[readStreamPathFastPathSymbol] = !1, super.pause();\n }\n resume() {\n return this[readStreamPathFastPathSymbol] = !1, super.resume();\n }\n unshift(...args) {\n return this[readStreamPathFastPathSymbol] = !1, super.unshift(...args);\n }\n pipe(dest, pipeOpts) {\n if (this[readStreamPathFastPathSymbol] && (pipeOpts\?.end \?\? !0) && this._readableState\?.pipes\?.length === 0) {\n if ((writeStreamPathFastPathSymbol in dest) && dest[writeStreamPathFastPathSymbol]) {\n if (dest[writeStreamPathFastPathCallSymbol](this, pipeOpts))\n return this;\n }\n }\n return this[readStreamPathFastPathSymbol] = !1, super.pipe(dest, pipeOpts);\n }\n});\nvar defaultWriteStreamOptions = {\n fd: null,\n start: @undefined,\n pos: @undefined,\n encoding: @undefined,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass = WriteStream = function WriteStream2(path, options = defaultWriteStreamOptions) {\n if (!(this instanceof WriteStream2))\n return new WriteStream2(path, options);\n if (!options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n fs: fs2 = defaultWriteStreamOptions.fs,\n start = defaultWriteStreamOptions.start,\n flags = defaultWriteStreamOptions.flags,\n mode = defaultWriteStreamOptions.mode,\n autoClose = !0,\n emitClose = !1,\n autoDestroy = autoClose,\n encoding = defaultWriteStreamOptions.encoding,\n fd = defaultWriteStreamOptions.fd,\n pos = defaultWriteStreamOptions.pos\n } = options, tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n throw new Error(\"Expected options.fd to be a number\");\n tempThis.fd = fd, tempThis[_writeStreamPathFastPathSymbol] = !1;\n } else if (typeof path === \"string\") {\n if (path.length === 0)\n @throwTypeError(\"Expected a non-empty path\");\n if (path.startsWith(\"file:\"))\n path = Bun.fileURLToPath(path);\n tempThis.path = path, tempThis.fd = null, tempThis[_writeStreamPathFastPathSymbol] = autoClose && (start === @undefined || start === 0) && fs2.write === defaultWriteStreamOptions.fs.write && fs2.close === defaultWriteStreamOptions.fs.close;\n }\n if (tempThis.fd == null)\n tempThis.fd = fs2.openSync(path, flags, mode);\n if (NativeWritable.call(this, tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n }), Object.assign(this, tempThis), typeof fs2\?.write !== \"function\")\n @throwTypeError(\"Expected fs.write to be a function\");\n if (typeof fs2\?.close !== \"function\")\n @throwTypeError(\"Expected fs.close to be a function\");\n if (typeof fs2\?.open !== \"function\")\n @throwTypeError(\"Expected fs.open to be a function\");\n if (typeof path === \"object\" && path) {\n if (path instanceof URL)\n path = Bun.fileURLToPath(path);\n }\n if (typeof path !== \"string\" && typeof fd !== \"number\")\n @throwTypeError(\"Expected a path or file descriptor\");\n if (this.start = start, this[_fs] = fs2, this.flags = flags, this.mode = mode, this.bytesWritten = 0, this[writeStreamSymbol] = !0, this[kIoDone] = !1, this.start !== @undefined)\n this.pos = this.start;\n if (encoding !== defaultWriteStreamOptions.encoding) {\n if (this.setDefaultEncoding(encoding), encoding !== \"buffer\" && encoding !== \"utf8\" && encoding !== \"utf-8\" && encoding !== \"binary\")\n this[_writeStreamPathFastPathSymbol] = !1;\n }\n return this;\n}, NativeWritable = Stream.NativeWritable, WriteStreamPrototype = WriteStream.prototype = Object.create(NativeWritable.prototype);\nObject.defineProperties(WriteStreamPrototype, {\n autoClose: {\n get() {\n return this._writableState.autoDestroy;\n },\n set(val) {\n this._writableState.autoDestroy = val;\n }\n },\n pending: {\n get() {\n return this.fd === null;\n }\n }\n});\nWriteStreamPrototype.destroySoon = WriteStreamPrototype.end;\nWriteStreamPrototype.open = function open3() {\n};\nWriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(readStream, pipeOpts) {\n if (!this[_writeStreamPathFastPathSymbol])\n return !1;\n if (this.fd !== null)\n return this[_writeStreamPathFastPathSymbol] = !1, !1;\n return this[kIoDone] = !1, readStream[kIoDone] = !1, Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then((bytesWritten) => {\n readStream[kIoDone] = this[kIoDone] = !0, this.bytesWritten += bytesWritten, readStream.bytesRead += bytesWritten, this.end(), readStream.close();\n }, (err) => {\n readStream[kIoDone] = this[kIoDone] = !0, WriteStream_errorOrDestroy.call(this, err), readStream.emit(\"error\", err);\n });\n};\nWriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {\n return this[_writeStreamPathFastPathSymbol];\n};\nWriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {\n this[_writeStreamPathFastPathSymbol] = !1;\n};\nWriteStreamPrototype._construct = function _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n};\nWriteStreamPrototype._destroy = function _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));\n return;\n }\n WriteStream_internalClose.call(this, err, cb);\n};\nWriteStreamPrototype.close = function close3(cb) {\n if (cb) {\n if (this.closed) {\n process.nextTick(cb);\n return;\n }\n this.on(\"close\", cb);\n }\n if (!this.autoClose)\n this.on(\"finish\", this.destroy);\n this.end();\n};\nWriteStreamPrototype.write = function write3(chunk, encoding, cb) {\n if (encoding \?\?= this._writableState\?.defaultEncoding, this[_writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = @Buffer.from(chunk, encoding);\n var native = this.pos === @undefined;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, WriteStream_handleWrite.call(this, err, bytes), this.emit(kIoDone), cb)\n !err \? cb() : cb(err);\n } : () => {\n };\n if (this[kIoDone] = !0, this._write)\n return this._write(chunk, encoding, callback);\n else\n return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);\n};\nWriteStreamPrototype._write = @undefined;\nWriteStreamPrototype._writev = @undefined;\nWriteStreamPrototype.end = function end(chunk, encoding, cb) {\n var native = this.pos === @undefined;\n return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);\n};\nWriteStreamPrototype._destroy = function _destroy2(err, cb) {\n this.close(err, cb);\n};\nObject.defineProperties(fs, {\n createReadStream: {\n value: createReadStream\n },\n createWriteStream: {\n value: createWriteStream\n },\n ReadStream: {\n value: ReadStream\n },\n WriteStream: {\n value: WriteStream\n }\n});\nrealpath.native = realpath;\nrealpathSync.native = realpathSync;\nvar lazy_cpSync = null;\n$ = {\n Dirent,\n FSWatcher,\n ReadStream,\n Stats,\n WriteStream,\n _toUnixTimestamp,\n access,\n accessSync,\n appendFile,\n appendFileSync,\n chmod,\n chmodSync,\n chown,\n chownSync,\n close,\n closeSync,\n constants,\n copyFile,\n copyFileSync,\n cp,\n cpSync,\n createReadStream,\n createWriteStream,\n exists,\n existsSync,\n fchmod,\n fchmodSync,\n fchown,\n fchownSync,\n fstat,\n fstatSync,\n fsync,\n fsyncSync,\n ftruncate,\n ftruncateSync,\n futimes,\n futimesSync,\n lchmod,\n lchmodSync,\n lchown,\n lchownSync,\n link,\n linkSync,\n lstat,\n lstatSync,\n lutimes,\n lutimesSync,\n mkdir,\n mkdirSync,\n mkdtemp,\n mkdtempSync,\n open,\n openSync,\n promises,\n read,\n readFile,\n readFileSync,\n readSync,\n readdir,\n readdirSync,\n readlink,\n readlinkSync,\n readv,\n readvSync,\n realpath,\n realpathSync,\n rename,\n renameSync,\n rm,\n rmSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n symlink,\n symlinkSync,\n truncate,\n truncateSync,\n unlink,\n unlinkSync,\n unwatchFile,\n utimes,\n utimesSync,\n watch,\n watchFile,\n write,\n writeFile,\n writeFileSync,\n writeSync,\n writev,\n writevSync,\n [Symbol.for(\"::bunternal::\")]: {\n ReadStreamClass,\n WriteStreamClass\n }\n};\nreturn $})\n"_s; +static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar getValidatedPath = function(p) {\n if (p instanceof URL)\n return Bun.fileURLToPath(p);\n if (typeof p !== \"string\")\n @throwTypeError(\"Path must be a string or URL.\");\n return (_pathModule \?\?= @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28)).resolve(p);\n}, watchFile = function(filename, options, listener) {\n if (filename = getValidatedPath(filename), typeof options === \"function\")\n listener = options, options = {};\n if (typeof listener !== \"function\")\n @throwTypeError(\"listener must be a function\");\n var stat = statWatchers.get(filename);\n if (!stat)\n stat = new StatWatcher(filename, options), statWatchers.set(filename, stat);\n return stat.addListener(\"change\", listener), stat;\n}, unwatchFile = function(filename, listener) {\n filename = getValidatedPath(filename);\n var stat = statWatchers.get(filename);\n if (!stat)\n return;\n if (listener) {\n if (stat.removeListener(\"change\", listener), stat.listenerCount(\"change\") !== 0)\n return;\n } else\n stat.removeAllListeners(\"change\");\n stat.stop(), statWatchers.delete(filename);\n}, callbackify = function(fsFunction, args) {\n const callback = args[args.length - 1];\n try {\n var result = fsFunction.apply(fs, args.slice(0, args.length - 1));\n result.then((...args2) => callback(null, ...args2), (err) => callback(err));\n } catch (e) {\n if (typeof callback === \"function\")\n callback(e);\n else\n throw e;\n }\n}, createReadStream = function(path, options) {\n return new ReadStream(path, options);\n}, WriteStream_handleWrite = function(er, bytes) {\n if (er)\n return WriteStream_errorOrDestroy.call(this, er);\n this.bytesWritten += bytes;\n}, WriteStream_internalClose = function(err, cb) {\n this[_writeStreamPathFastPathSymbol] = !1;\n var fd = this.fd;\n this[_fs].close(fd, (er) => {\n this.fd = null, cb(err || er);\n });\n}, WriteStream_errorOrDestroy = function(err) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n}, createWriteStream = function(path, options) {\n return new WriteStream(path, options);\n}, cpSync = function(src, dest, options) {\n if (!options)\n return fs.cpSync(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cpSync)\n lazy_cpSync = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cpSync(src, dest, options);\n }\n return fs.cpSync(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n}, cp = function(src, dest, options, callback) {\n if (typeof options === \"function\")\n callback = options, options = @undefined;\n promises.cp(src, dest, options).then(() => callback(), callback);\n}, _toUnixTimestamp = function(time, name = \"time\") {\n if (typeof time === \"string\" && +time == time)\n return +time;\n if (NumberIsFinite(time)) {\n if (time < 0)\n return DateNow() / 1000;\n return time;\n }\n if (isDate(time))\n return DatePrototypeGetTime(time) / 1000;\n @throwTypeError(`Expected ${name} to be a number or Date`);\n}, $, ReadStream, WriteStream, EventEmitter = @getInternalField(@internalModuleRegistry, 18) || @createInternalModuleById(18), promises = @getInternalField(@internalModuleRegistry, 20) || @createInternalModuleById(20), Stream = @getInternalField(@internalModuleRegistry, 37) || @createInternalModuleById(37), { isArrayBufferView } = @requireNativeModule(\"util/types\"), _writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), _fs = Symbol.for(\"#fs\"), constants = @processBindingConstants.fs, fs = Bun.fs();\n\nclass FSWatcher extends EventEmitter {\n #watcher;\n #listener;\n constructor(path, options, listener) {\n super();\n if (typeof options === \"function\")\n listener = options, options = {};\n else if (typeof options === \"string\")\n options = { encoding: options };\n if (typeof listener !== \"function\")\n listener = () => {\n };\n this.#listener = listener;\n try {\n this.#watcher = fs.watch(path, options || {}, this.#onEvent.bind(this));\n } catch (e) {\n if (!e.message\?.startsWith(\"FileNotFound\"))\n throw e;\n const notFound = new Error(`ENOENT: no such file or directory, watch '${path}'`);\n throw notFound.code = \"ENOENT\", notFound.errno = -2, notFound.path = path, notFound.syscall = \"watch\", notFound.filename = path, notFound;\n }\n }\n #onEvent(eventType, filenameOrError) {\n if (eventType === \"error\" || eventType === \"close\")\n this.emit(eventType, filenameOrError);\n else\n this.emit(\"change\", eventType, filenameOrError), this.#listener(eventType, filenameOrError);\n }\n close() {\n this.#watcher\?.close(), this.#watcher = null;\n }\n ref() {\n this.#watcher\?.ref();\n }\n unref() {\n this.#watcher\?.unref();\n }\n start() {\n }\n}\n\nclass StatWatcher extends EventEmitter {\n constructor(path, options) {\n super();\n this._handle = fs.watchFile(path, options, this.#onChange.bind(this));\n }\n #onChange(curr, prev) {\n this.emit(\"change\", curr, prev);\n }\n start() {\n }\n stop() {\n this._handle\?.close(), this._handle = null;\n }\n ref() {\n this._handle\?.ref();\n }\n unref() {\n this._handle\?.unref();\n }\n}\nvar access = function access2(...args) {\n callbackify(fs.access, args);\n}, appendFile = function appendFile2(...args) {\n callbackify(fs.appendFile, args);\n}, close = function close2(...args) {\n callbackify(fs.close, args);\n}, rm = function rm2(...args) {\n callbackify(fs.rm, args);\n}, rmdir = function rmdir2(...args) {\n callbackify(fs.rmdir, args);\n}, copyFile = function copyFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.copyFile(...args).then((result) => callback(null, result), callback);\n}, exists = function exists2(...args) {\n callbackify(fs.exists, args);\n}, chown = function chown2(...args) {\n callbackify(fs.chown, args);\n}, chmod = function chmod2(...args) {\n callbackify(fs.chmod, args);\n}, fchmod = function fchmod2(...args) {\n callbackify(fs.fchmod, args);\n}, fchown = function fchown2(...args) {\n callbackify(fs.fchown, args);\n}, fstat = function fstat2(...args) {\n callbackify(fs.fstat, args);\n}, fsync = function fsync2(...args) {\n callbackify(fs.fsync, args);\n}, ftruncate = function ftruncate2(...args) {\n callbackify(fs.ftruncate, args);\n}, futimes = function futimes2(...args) {\n callbackify(fs.futimes, args);\n}, lchmod = function lchmod2(...args) {\n callbackify(fs.lchmod, args);\n}, lchown = function lchown2(...args) {\n callbackify(fs.lchown, args);\n}, link = function link2(...args) {\n callbackify(fs.link, args);\n}, mkdir = function mkdir2(...args) {\n callbackify(fs.mkdir, args);\n}, mkdtemp = function mkdtemp2(...args) {\n callbackify(fs.mkdtemp, args);\n}, open = function open2(...args) {\n callbackify(fs.open, args);\n}, read = function read2(fd, buffer, offsetOrOptions, length, position, callback) {\n let offset = offsetOrOptions, params = null;\n if (arguments.length <= 4) {\n if (arguments.length === 4)\n callback = length, params = offsetOrOptions;\n else if (arguments.length === 3) {\n if (!isArrayBufferView(buffer))\n params = buffer, { buffer = @Buffer.alloc(16384) } = params \?\? {};\n callback = offsetOrOptions;\n } else\n callback = buffer, buffer = @Buffer.alloc(16384);\n ({ offset = 0, length = buffer\?.byteLength - offset, position = null } = params \?\? {});\n }\n queueMicrotask(() => {\n try {\n var bytesRead = fs.readSync(fd, buffer, offset, length, position);\n } catch (e) {\n callback(e);\n }\n callback(null, bytesRead, buffer);\n });\n}, write = function write2(...args) {\n callbackify(fs.write, args);\n}, readdir = function readdir2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readdir(...args).then((result) => callback(null, result), callback);\n}, readFile = function readFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readFile(...args).then((result) => callback(null, result), callback);\n}, writeFile = function writeFile2(...args) {\n callbackify(fs.writeFile, args);\n}, readlink = function readlink2(...args) {\n callbackify(fs.readlink, args);\n}, realpath = function realpath2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.realpath(...args).then((result) => callback(null, result), callback);\n}, rename = function rename2(...args) {\n callbackify(fs.rename, args);\n}, lstat = function lstat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.lstat(...args).then((result) => callback(null, result), callback);\n}, stat = function stat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.stat(...args).then((result) => callback(null, result), callback);\n}, symlink = function symlink2(...args) {\n callbackify(fs.symlink, args);\n}, truncate = function truncate2(...args) {\n callbackify(fs.truncate, args);\n}, unlink = function unlink2(...args) {\n callbackify(fs.unlink, args);\n}, utimes = function utimes2(...args) {\n callbackify(fs.utimes, args);\n}, lutimes = function lutimes2(...args) {\n callbackify(fs.lutimes, args);\n}, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), closeSync = fs.closeSync.bind(fs), copyFileSync = fs.copyFileSync.bind(fs), existsSync = fs.existsSync.bind(fs), chownSync = fs.chownSync.bind(fs), chmodSync = fs.chmodSync.bind(fs), fchmodSync = fs.fchmodSync.bind(fs), fchownSync = fs.fchownSync.bind(fs), fstatSync = fs.fstatSync.bind(fs), fsyncSync = fs.fsyncSync.bind(fs), ftruncateSync = fs.ftruncateSync.bind(fs), futimesSync = fs.futimesSync.bind(fs), lchmodSync = fs.lchmodSync.bind(fs), lchownSync = fs.lchownSync.bind(fs), linkSync = fs.linkSync.bind(fs), lstatSync = fs.lstatSync.bind(fs), mkdirSync = fs.mkdirSync.bind(fs), mkdtempSync = fs.mkdtempSync.bind(fs), openSync = fs.openSync.bind(fs), readSync = fs.readSync.bind(fs), writeSync = fs.writeSync.bind(fs), readdirSync = fs.readdirSync.bind(fs), readFileSync = fs.readFileSync.bind(fs), writeFileSync = fs.writeFileSync.bind(fs), readlinkSync = fs.readlinkSync.bind(fs), realpathSync = fs.realpathSync.bind(fs), renameSync = fs.renameSync.bind(fs), statSync = fs.statSync.bind(fs), symlinkSync = fs.symlinkSync.bind(fs), truncateSync = fs.truncateSync.bind(fs), unlinkSync = fs.unlinkSync.bind(fs), utimesSync = fs.utimesSync.bind(fs), lutimesSync = fs.lutimesSync.bind(fs), rmSync = fs.rmSync.bind(fs), rmdirSync = fs.rmdirSync.bind(fs), writev = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.writevSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, writevSync = fs.writevSync.bind(fs), readv = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.readvSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {\n return new FSWatcher(path, options, listener);\n}, statWatchers = new Map, _pathModule, readStreamPathFastPathSymbol = Symbol.for(\"Bun.Node.readStreamPathFastPath\"), readStreamSymbol = Symbol.for(\"Bun.NodeReadStream\"), readStreamPathOrFdSymbol = Symbol.for(\"Bun.NodeReadStreamPathOrFd\"), writeStreamSymbol = Symbol.for(\"Bun.NodeWriteStream\"), writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), writeStreamPathFastPathCallSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPathCall\"), kIoDone = Symbol.for(\"kIoDone\"), defaultReadStreamOptions = {\n file: @undefined,\n fd: null,\n flags: \"r\",\n encoding: @undefined,\n mode: 438,\n autoClose: !0,\n emitClose: !0,\n start: 0,\n end: @Infinity,\n highWaterMark: 65536,\n fs: {\n read,\n open: (path, flags, mode, cb) => {\n var fd;\n try {\n fd = openSync(path, flags, mode);\n } catch (e) {\n cb(e);\n return;\n }\n cb(null, fd);\n },\n openSync,\n close\n },\n autoDestroy: !0\n}, ReadStreamClass;\nReadStream = function(InternalReadStream) {\n ReadStreamClass = InternalReadStream, Object.defineProperty(ReadStreamClass.prototype, Symbol.toStringTag, {\n value: \"ReadStream\",\n enumerable: !1\n });\n function ReadStream3(path, options) {\n return new InternalReadStream(path, options);\n }\n return ReadStream3.prototype = InternalReadStream.prototype, Object.defineProperty(ReadStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalReadStream;\n }\n });\n}(class ReadStream2 extends Stream._getNativeReadableStreamPrototype(2, Stream.Readable) {\n constructor(pathOrFd, options = defaultReadStreamOptions) {\n if (typeof options !== \"object\" || !options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n flags = defaultReadStreamOptions.flags,\n encoding = defaultReadStreamOptions.encoding,\n mode = defaultReadStreamOptions.mode,\n autoClose = defaultReadStreamOptions.autoClose,\n emitClose = defaultReadStreamOptions.emitClose,\n start = defaultReadStreamOptions.start,\n end = defaultReadStreamOptions.end,\n autoDestroy = defaultReadStreamOptions.autoClose,\n fs: fs2 = defaultReadStreamOptions.fs,\n highWaterMark = defaultReadStreamOptions.highWaterMark,\n fd = defaultReadStreamOptions.fd\n } = options;\n if (pathOrFd\?.constructor\?.name === \"URL\")\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n var tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n @throwTypeError(\"Expected options.fd to be a number\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = fd, tempThis.autoClose = !1;\n } else if (typeof pathOrFd === \"string\") {\n if (pathOrFd.startsWith(\"file://\"))\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n if (pathOrFd.length === 0)\n @throwTypeError(\"Expected path to be a non-empty string\");\n tempThis.path = tempThis.file = tempThis[readStreamPathOrFdSymbol] = pathOrFd;\n } else if (typeof pathOrFd === \"number\") {\n if (pathOrFd |= 0, pathOrFd < 0)\n @throwTypeError(\"Expected fd to be a positive integer\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = pathOrFd, tempThis.autoClose = !1;\n } else\n @throwTypeError(\"Expected a path or file descriptor\");\n if (tempThis.fd === @undefined)\n tempThis.fd = fs2.openSync(pathOrFd, flags, mode);\n var fileRef = Bun.file(tempThis.fd), stream = fileRef.stream(), native = @direct(stream);\n if (!native)\n throw new Error(\"no native readable stream\");\n var { stream: ptr } = native;\n super(ptr, {\n ...options,\n encoding,\n autoDestroy,\n autoClose,\n emitClose,\n highWaterMark\n });\n if (Object.assign(this, tempThis), this.#fileRef = fileRef, this.end = end, this._read = this.#internalRead, this.start = start, this.flags = flags, this.mode = mode, this.emitClose = emitClose, this[readStreamPathFastPathSymbol] = start === 0 && end === @Infinity && autoClose && fs2 === defaultReadStreamOptions.fs && (encoding === \"buffer\" || encoding === \"binary\" || encoding == null || encoding === \"utf-8\" || encoding === \"utf8\"), this._readableState.autoClose = autoDestroy = autoClose, this._readableState.highWaterMark = highWaterMark, start !== @undefined)\n this.pos = start;\n }\n #fileRef;\n #fs;\n file;\n path;\n fd = null;\n flags;\n mode;\n start;\n end;\n pos;\n bytesRead = 0;\n #fileSize = -1;\n _read;\n [readStreamSymbol] = !0;\n [readStreamPathOrFdSymbol];\n [readStreamPathFastPathSymbol];\n _construct(callback) {\n if (super._construct)\n super._construct(callback);\n else\n callback();\n this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n super._destroy(err, cb);\n try {\n var fd = this.fd;\n if (this[readStreamPathFastPathSymbol] = !1, !fd)\n cb(err);\n else\n this.#fs.close(fd, (er) => {\n cb(er || err);\n }), this.fd = null;\n } catch (e) {\n throw e;\n }\n }\n close(cb) {\n if (typeof cb === \"function\")\n Stream.eos(this, cb);\n this.destroy();\n }\n push(chunk) {\n var bytesRead = chunk\?.length \?\? 0;\n if (bytesRead > 0) {\n this.bytesRead += bytesRead;\n var currPos = this.pos;\n if (currPos !== @undefined) {\n if (this.bytesRead < currPos)\n return !0;\n if (currPos === this.start) {\n var n = this.bytesRead - currPos;\n chunk = chunk.slice(-n);\n var [_, ...rest] = arguments;\n if (this.pos = this.bytesRead, this.end !== @undefined && this.bytesRead > this.end)\n chunk = chunk.slice(0, this.end - this.start + 1);\n return super.push(chunk, ...rest);\n }\n var end = this.end;\n if (end !== @undefined && this.bytesRead > end) {\n chunk = chunk.slice(0, end - currPos + 1);\n var [_, ...rest] = arguments;\n return this.pos = this.bytesRead, super.push(chunk, ...rest);\n }\n this.pos = this.bytesRead;\n }\n }\n return super.push(...arguments);\n }\n #internalRead(n) {\n var { pos, end, bytesRead, fd, encoding } = this;\n if (n = pos !== @undefined \? Math.min(end - pos + 1, n) : Math.min(end - bytesRead + 1, n), n <= 0) {\n this.push(null);\n return;\n }\n if (this.#fileSize === -1 && bytesRead === 0 && pos === @undefined) {\n var stat3 = fstatSync(fd);\n if (this.#fileSize = stat3.size, this.#fileSize > 0 && n > this.#fileSize)\n n = this.#fileSize + 1;\n }\n this[kIoDone] = !1;\n var res = super._read(n);\n if (@isPromise(res)) {\n var then = res\?.then;\n if (then && @isCallable(then))\n res.then(() => {\n if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone);\n }, (er) => {\n this[kIoDone] = !0, this.#errorOrDestroy(er);\n });\n } else if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone), this.#errorOrDestroy(new Error(\"ERR_STREAM_PREMATURE_CLOSE\"));\n }\n #errorOrDestroy(err, sync = null) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n }\n pause() {\n return this[readStreamPathFastPathSymbol] = !1, super.pause();\n }\n resume() {\n return this[readStreamPathFastPathSymbol] = !1, super.resume();\n }\n unshift(...args) {\n return this[readStreamPathFastPathSymbol] = !1, super.unshift(...args);\n }\n pipe(dest, pipeOpts) {\n if (this[readStreamPathFastPathSymbol] && (pipeOpts\?.end \?\? !0) && this._readableState\?.pipes\?.length === 0) {\n if ((writeStreamPathFastPathSymbol in dest) && dest[writeStreamPathFastPathSymbol]) {\n if (dest[writeStreamPathFastPathCallSymbol](this, pipeOpts))\n return this;\n }\n }\n return this[readStreamPathFastPathSymbol] = !1, super.pipe(dest, pipeOpts);\n }\n});\nvar defaultWriteStreamOptions = {\n fd: null,\n start: @undefined,\n pos: @undefined,\n encoding: @undefined,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass = WriteStream = function WriteStream2(path, options = defaultWriteStreamOptions) {\n if (!(this instanceof WriteStream2))\n return new WriteStream2(path, options);\n if (!options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n fs: fs2 = defaultWriteStreamOptions.fs,\n start = defaultWriteStreamOptions.start,\n flags = defaultWriteStreamOptions.flags,\n mode = defaultWriteStreamOptions.mode,\n autoClose = !0,\n emitClose = !1,\n autoDestroy = autoClose,\n encoding = defaultWriteStreamOptions.encoding,\n fd = defaultWriteStreamOptions.fd,\n pos = defaultWriteStreamOptions.pos\n } = options, tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n throw new Error(\"Expected options.fd to be a number\");\n tempThis.fd = fd, tempThis[_writeStreamPathFastPathSymbol] = !1;\n } else if (typeof path === \"string\") {\n if (path.length === 0)\n @throwTypeError(\"Expected a non-empty path\");\n if (path.startsWith(\"file:\"))\n path = Bun.fileURLToPath(path);\n tempThis.path = path, tempThis.fd = null, tempThis[_writeStreamPathFastPathSymbol] = autoClose && (start === @undefined || start === 0) && fs2.write === defaultWriteStreamOptions.fs.write && fs2.close === defaultWriteStreamOptions.fs.close;\n }\n if (tempThis.fd == null)\n tempThis.fd = fs2.openSync(path, flags, mode);\n if (NativeWritable.call(this, tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n }), Object.assign(this, tempThis), typeof fs2\?.write !== \"function\")\n @throwTypeError(\"Expected fs.write to be a function\");\n if (typeof fs2\?.close !== \"function\")\n @throwTypeError(\"Expected fs.close to be a function\");\n if (typeof fs2\?.open !== \"function\")\n @throwTypeError(\"Expected fs.open to be a function\");\n if (typeof path === \"object\" && path) {\n if (path instanceof URL)\n path = Bun.fileURLToPath(path);\n }\n if (typeof path !== \"string\" && typeof fd !== \"number\")\n @throwTypeError(\"Expected a path or file descriptor\");\n if (this.start = start, this[_fs] = fs2, this.flags = flags, this.mode = mode, this.bytesWritten = 0, this[writeStreamSymbol] = !0, this[kIoDone] = !1, this.start !== @undefined)\n this.pos = this.start;\n if (encoding !== defaultWriteStreamOptions.encoding) {\n if (this.setDefaultEncoding(encoding), encoding !== \"buffer\" && encoding !== \"utf8\" && encoding !== \"utf-8\" && encoding !== \"binary\")\n this[_writeStreamPathFastPathSymbol] = !1;\n }\n return this;\n}, NativeWritable = Stream.NativeWritable, WriteStreamPrototype = WriteStream.prototype = Object.create(NativeWritable.prototype);\nObject.defineProperties(WriteStreamPrototype, {\n autoClose: {\n get() {\n return this._writableState.autoDestroy;\n },\n set(val) {\n this._writableState.autoDestroy = val;\n }\n },\n pending: {\n get() {\n return this.fd === null;\n }\n }\n});\nWriteStreamPrototype.destroySoon = WriteStreamPrototype.end;\nWriteStreamPrototype.open = function open3() {\n};\nWriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(readStream, pipeOpts) {\n if (!this[_writeStreamPathFastPathSymbol])\n return !1;\n if (this.fd !== null)\n return this[_writeStreamPathFastPathSymbol] = !1, !1;\n return this[kIoDone] = !1, readStream[kIoDone] = !1, Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then((bytesWritten) => {\n readStream[kIoDone] = this[kIoDone] = !0, this.bytesWritten += bytesWritten, readStream.bytesRead += bytesWritten, this.end(), readStream.close();\n }, (err) => {\n readStream[kIoDone] = this[kIoDone] = !0, WriteStream_errorOrDestroy.call(this, err), readStream.emit(\"error\", err);\n });\n};\nWriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {\n return this[_writeStreamPathFastPathSymbol];\n};\nWriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {\n this[_writeStreamPathFastPathSymbol] = !1;\n};\nWriteStreamPrototype._construct = function _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n};\nWriteStreamPrototype._destroy = function _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));\n return;\n }\n WriteStream_internalClose.call(this, err, cb);\n};\nWriteStreamPrototype.close = function close3(cb) {\n if (cb) {\n if (this.closed) {\n process.nextTick(cb);\n return;\n }\n this.on(\"close\", cb);\n }\n if (!this.autoClose)\n this.on(\"finish\", this.destroy);\n this.end();\n};\nWriteStreamPrototype.write = function write3(chunk, encoding, cb) {\n if (encoding \?\?= this._writableState\?.defaultEncoding, this[_writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = @Buffer.from(chunk, encoding);\n var native = this.pos === @undefined;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, WriteStream_handleWrite.call(this, err, bytes), this.emit(kIoDone), cb)\n !err \? cb() : cb(err);\n } : () => {\n };\n if (this[kIoDone] = !0, this._write)\n return this._write(chunk, encoding, callback);\n else\n return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);\n};\nWriteStreamPrototype._write = @undefined;\nWriteStreamPrototype._writev = @undefined;\nWriteStreamPrototype.end = function end(chunk, encoding, cb) {\n var native = this.pos === @undefined;\n return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);\n};\nWriteStreamPrototype._destroy = function _destroy2(err, cb) {\n this.close(err, cb);\n};\nObject.defineProperties(fs, {\n createReadStream: {\n value: createReadStream\n },\n createWriteStream: {\n value: createWriteStream\n },\n ReadStream: {\n value: ReadStream\n },\n WriteStream: {\n value: WriteStream\n }\n});\nrealpath.native = realpath;\nrealpathSync.native = realpathSync;\nvar lazy_cpSync = null;\n$ = {\n Dirent,\n FSWatcher,\n ReadStream,\n Stats,\n WriteStream,\n _toUnixTimestamp,\n access,\n accessSync,\n appendFile,\n appendFileSync,\n chmod,\n chmodSync,\n chown,\n chownSync,\n close,\n closeSync,\n constants,\n copyFile,\n copyFileSync,\n cp,\n cpSync,\n createReadStream,\n createWriteStream,\n exists,\n existsSync,\n fchmod,\n fchmodSync,\n fchown,\n fchownSync,\n fstat,\n fstatSync,\n fsync,\n fsyncSync,\n ftruncate,\n ftruncateSync,\n futimes,\n futimesSync,\n lchmod,\n lchmodSync,\n lchown,\n lchownSync,\n link,\n linkSync,\n lstat,\n lstatSync,\n lutimes,\n lutimesSync,\n mkdir,\n mkdirSync,\n mkdtemp,\n mkdtempSync,\n open,\n openSync,\n promises,\n read,\n readFile,\n readFileSync,\n readSync,\n readdir,\n readdirSync,\n readlink,\n readlinkSync,\n readv,\n readvSync,\n realpath,\n realpathSync,\n rename,\n renameSync,\n rm,\n rmSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n symlink,\n symlinkSync,\n truncate,\n truncateSync,\n unlink,\n unlinkSync,\n unwatchFile,\n utimes,\n utimesSync,\n watch,\n watchFile,\n write,\n writeFile,\n writeFileSync,\n writeSync,\n writev,\n writevSync,\n [Symbol.for(\"::bunternal::\")]: {\n ReadStreamClass,\n WriteStreamClass\n }\n};\nreturn $})\n"_s; // // -static constexpr ASCIILiteral NodeFSPromisesCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.promises.ts\nvar watch = function(filename, options = {}) {\n if (filename instanceof URL)\n @throwTypeError(\"Watch URLs are not supported yet\");\n else if (@Buffer.isBuffer(filename))\n filename = filename.toString();\n else if (typeof filename !== \"string\")\n @throwTypeError(\"Expected path to be a string or Buffer\");\n let nextEventResolve = null;\n if (typeof options === \"string\")\n options = { encoding: options };\n const queue = @createFIFO(), watcher = fs.watch(filename, options || {}, (eventType, filename2) => {\n if (queue.push({ eventType, filename: filename2 }), nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n });\n return {\n [Symbol.asyncIterator]() {\n let closed = !1;\n return {\n async next() {\n while (!closed) {\n let event;\n while (event = queue.shift()) {\n if (event.eventType === \"close\")\n return closed = !0, { value: @undefined, done: !0 };\n if (event.eventType === \"error\")\n throw closed = !0, event.filename;\n return { value: event, done: !1 };\n }\n const { promise, resolve } = @Promise.withResolvers();\n nextEventResolve = resolve, await promise;\n }\n return { value: @undefined, done: !0 };\n },\n return() {\n if (!closed) {\n if (watcher.close(), closed = !0, nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n }\n return { value: @undefined, done: !0 };\n }\n };\n }\n };\n}, cp = function(src, dest, options) {\n if (!options)\n return fs.cp(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cp)\n lazy_cp = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cp(src, dest, options);\n }\n return fs.cp(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n};\nasync function opendir(dir) {\n const entries = await fs.readdir(dir, { withFileTypes: !0 });\n return new Dir(entries);\n}\nvar $, constants = @processBindingConstants.fs, fs = Bun.fs(), notrace = \"::bunternal::\", promisify = {\n [notrace]: (fsFunction) => {\n return async function(...args) {\n return await 1, fsFunction.apply(fs, args);\n };\n }\n}[notrace], lazy_cp = null;\n\nclass Dir {\n #entries;\n constructor(e) {\n this.#entries = e;\n }\n readSync() {\n return this.#entries.shift() \?\? null;\n }\n read(c) {\n if (c)\n process.nextTick(c, null, this.readSync());\n return @Promise.resolve(this.readSync());\n }\n closeSync() {\n }\n close(c) {\n if (c)\n process.nextTick(c);\n return @Promise.resolve();\n }\n *[Symbol.asyncIterator]() {\n var next;\n while (next = this.readSync())\n yield next;\n }\n}\n$ = {\n access: promisify(fs.accessSync),\n appendFile: promisify(fs.appendFileSync),\n close: promisify(fs.closeSync),\n copyFile: fs.copyFile.bind(fs),\n cp,\n exists: promisify(fs.existsSync),\n chown: promisify(fs.chownSync),\n chmod: promisify(fs.chmodSync),\n fchmod: promisify(fs.fchmodSync),\n fchown: promisify(fs.fchownSync),\n fstat: promisify(fs.fstatSync),\n fsync: promisify(fs.fsyncSync),\n ftruncate: promisify(fs.ftruncateSync),\n futimes: promisify(fs.futimesSync),\n lchmod: promisify(fs.lchmodSync),\n lchown: promisify(fs.lchownSync),\n link: promisify(fs.linkSync),\n lstat: fs.lstat.bind(fs),\n mkdir: promisify(fs.mkdirSync),\n mkdtemp: promisify(fs.mkdtempSync),\n open: promisify(fs.openSync),\n read: promisify(fs.readSync),\n write: promisify(fs.writeSync),\n readdir: fs.readdir.bind(fs),\n readFile: fs.readFile.bind(fs),\n writeFile: promisify(fs.writeFileSync),\n readlink: promisify(fs.readlinkSync),\n realpath: fs.realpath.bind(fs),\n rename: promisify(fs.renameSync),\n stat: fs.stat.bind(fs),\n symlink: promisify(fs.symlinkSync),\n truncate: promisify(fs.truncateSync),\n unlink: promisify(fs.unlinkSync),\n utimes: promisify(fs.utimesSync),\n lutimes: promisify(fs.lutimesSync),\n rm: promisify(fs.rmSync),\n rmdir: promisify(fs.rmdirSync),\n writev: (fd, buffers, position) => {\n return new @Promise((resolve, reject) => {\n try {\n var bytesWritten = fs.writevSync(fd, buffers, position);\n } catch (err) {\n reject(err);\n return;\n }\n resolve({\n bytesWritten,\n buffers\n });\n });\n },\n readv: (fd, buffers, position) => {\n return new @Promise((resolve, reject) => {\n try {\n var bytesRead = fs.readvSync(fd, buffers, position);\n } catch (err) {\n reject(err);\n return;\n }\n resolve({\n bytesRead,\n buffers\n });\n });\n },\n constants,\n watch,\n opendir\n};\nreturn $})\n"_s; +static constexpr ASCIILiteral NodeFSPromisesCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.promises.ts\nvar watch = function(filename, options = {}) {\n if (filename instanceof URL)\n @throwTypeError(\"Watch URLs are not supported yet\");\n else if (@Buffer.isBuffer(filename))\n filename = filename.toString();\n else if (typeof filename !== \"string\")\n @throwTypeError(\"Expected path to be a string or Buffer\");\n let nextEventResolve = null;\n if (typeof options === \"string\")\n options = { encoding: options };\n const queue = @createFIFO(), watcher = fs.watch(filename, options || {}, (eventType, filename2) => {\n if (queue.push({ eventType, filename: filename2 }), nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n });\n return {\n [Symbol.asyncIterator]() {\n let closed = !1;\n return {\n async next() {\n while (!closed) {\n let event;\n while (event = queue.shift()) {\n if (event.eventType === \"close\")\n return closed = !0, { value: @undefined, done: !0 };\n if (event.eventType === \"error\")\n throw closed = !0, event.filename;\n return { value: event, done: !1 };\n }\n const { promise, resolve } = @Promise.withResolvers();\n nextEventResolve = resolve, await promise;\n }\n return { value: @undefined, done: !0 };\n },\n return() {\n if (!closed) {\n if (watcher.close(), closed = !0, nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n }\n return { value: @undefined, done: !0 };\n }\n };\n }\n };\n}, cp = function(src, dest, options) {\n if (!options)\n return fs.cp(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cp)\n lazy_cp = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cp(src, dest, options);\n }\n return fs.cp(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n};\nasync function opendir(dir) {\n const entries = await fs.readdir(dir, { withFileTypes: !0 });\n return new Dir(entries);\n}\nvar $, constants = @processBindingConstants.fs, fs = Bun.fs();\nvar lazy_cp = null;\n\nclass Dir {\n #entries;\n constructor(e) {\n this.#entries = e;\n }\n readSync() {\n return this.#entries.shift() \?\? null;\n }\n read(c) {\n if (c)\n process.nextTick(c, null, this.readSync());\n return @Promise.resolve(this.readSync());\n }\n closeSync() {\n }\n close(c) {\n if (c)\n process.nextTick(c);\n return @Promise.resolve();\n }\n *[Symbol.asyncIterator]() {\n var next;\n while (next = this.readSync())\n yield next;\n }\n}\n$ = {\n access: fs.access.bind(fs),\n appendFile: fs.appendFile.bind(fs),\n close: fs.close.bind(fs),\n copyFile: fs.copyFile.bind(fs),\n cp,\n exists: fs.exists.bind(fs),\n chown: fs.chown.bind(fs),\n chmod: fs.chmod.bind(fs),\n fchmod: fs.fchmod.bind(fs),\n fchown: fs.fchown.bind(fs),\n fstat: fs.fstat.bind(fs),\n fsync: fs.fsync.bind(fs),\n ftruncate: fs.ftruncate.bind(fs),\n futimes: fs.futimes.bind(fs),\n lchmod: fs.lchmod.bind(fs),\n lchown: fs.lchown.bind(fs),\n link: fs.link.bind(fs),\n lstat: fs.lstat.bind(fs),\n mkdir: fs.mkdir.bind(fs),\n mkdtemp: fs.mkdtemp.bind(fs),\n open: fs.open.bind(fs),\n read: fs.read.bind(fs),\n write: fs.write.bind(fs),\n readdir: fs.readdir.bind(fs),\n readFile: fs.readFile.bind(fs),\n writeFile: fs.writeFile.bind(fs),\n readlink: fs.readlink.bind(fs),\n realpath: fs.realpath.bind(fs),\n rename: fs.rename.bind(fs),\n stat: fs.stat.bind(fs),\n symlink: fs.symlink.bind(fs),\n truncate: fs.truncate.bind(fs),\n unlink: fs.unlink.bind(fs),\n utimes: fs.utimes.bind(fs),\n lutimes: fs.lutimes.bind(fs),\n rm: fs.rm.bind(fs),\n rmdir: fs.rmdir.bind(fs),\n writev: async (fd, buffers, position) => {\n var bytesWritten = await fs.writev(fd, buffers, position);\n return {\n bytesWritten,\n buffers\n };\n },\n readv: async (fd, buffers, position) => {\n var bytesRead = await fs.readv(fd, buffers, position);\n return {\n bytesRead,\n buffers\n };\n },\n constants,\n watch,\n opendir\n};\nreturn $})\n"_s; // // @@ -565,11 +565,11 @@ static constexpr ASCIILiteral NodeEventsCode = "(function (){\"use strict\";// s // // -static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar getValidatedPath = function(p) {\n if (p instanceof URL)\n return Bun.fileURLToPath(p);\n if (typeof p !== \"string\")\n @throwTypeError(\"Path must be a string or URL.\");\n return (_pathModule \?\?= @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28)).resolve(p);\n}, watchFile = function(filename, options, listener) {\n if (filename = getValidatedPath(filename), typeof options === \"function\")\n listener = options, options = {};\n if (typeof listener !== \"function\")\n @throwTypeError(\"listener must be a function\");\n var stat = statWatchers.get(filename);\n if (!stat)\n stat = new StatWatcher(filename, options), statWatchers.set(filename, stat);\n return stat.addListener(\"change\", listener), stat;\n}, unwatchFile = function(filename, listener) {\n filename = getValidatedPath(filename);\n var stat = statWatchers.get(filename);\n if (!stat)\n return;\n if (listener) {\n if (stat.removeListener(\"change\", listener), stat.listenerCount(\"change\") !== 0)\n return;\n } else\n stat.removeAllListeners(\"change\");\n stat.stop(), statWatchers.delete(filename);\n}, callbackify = function(fsFunction, args) {\n try {\n const result = fsFunction.apply(fs, args.slice(0, args.length - 1)), callback = args[args.length - 1];\n if (typeof callback === \"function\")\n queueMicrotask(() => callback(null, result));\n } catch (e) {\n const callback = args[args.length - 1];\n if (typeof callback === \"function\")\n queueMicrotask(() => callback(e));\n }\n}, createReadStream = function(path, options) {\n return new ReadStream(path, options);\n}, WriteStream_handleWrite = function(er, bytes) {\n if (er)\n return WriteStream_errorOrDestroy.call(this, er);\n this.bytesWritten += bytes;\n}, WriteStream_internalClose = function(err, cb) {\n this[_writeStreamPathFastPathSymbol] = !1;\n var fd = this.fd;\n this[_fs].close(fd, (er) => {\n this.fd = null, cb(err || er);\n });\n}, WriteStream_errorOrDestroy = function(err) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n}, createWriteStream = function(path, options) {\n return new WriteStream(path, options);\n}, cpSync = function(src, dest, options) {\n if (!options)\n return fs.cpSync(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cpSync)\n lazy_cpSync = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cpSync(src, dest, options);\n }\n return fs.cpSync(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n}, cp = function(src, dest, options, callback) {\n if (typeof options === \"function\")\n callback = options, options = @undefined;\n promises.cp(src, dest, options).then(() => callback(), callback);\n}, _toUnixTimestamp = function(time, name = \"time\") {\n if (typeof time === \"string\" && +time == time)\n return +time;\n if (NumberIsFinite(time)) {\n if (time < 0)\n return DateNow() / 1000;\n return time;\n }\n if (isDate(time))\n return DatePrototypeGetTime(time) / 1000;\n @throwTypeError(`Expected ${name} to be a number or Date`);\n}, $, ReadStream, WriteStream, EventEmitter = @getInternalField(@internalModuleRegistry, 18) || @createInternalModuleById(18), promises = @getInternalField(@internalModuleRegistry, 20) || @createInternalModuleById(20), Stream = @getInternalField(@internalModuleRegistry, 37) || @createInternalModuleById(37), { isArrayBufferView } = @requireNativeModule(\"util/types\"), _writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), _fs = Symbol.for(\"#fs\"), constants = @processBindingConstants.fs, fs = Bun.fs();\n\nclass FSWatcher extends EventEmitter {\n #watcher;\n #listener;\n constructor(path, options, listener) {\n super();\n if (typeof options === \"function\")\n listener = options, options = {};\n else if (typeof options === \"string\")\n options = { encoding: options };\n if (typeof listener !== \"function\")\n listener = () => {\n };\n this.#listener = listener;\n try {\n this.#watcher = fs.watch(path, options || {}, this.#onEvent.bind(this));\n } catch (e) {\n if (!e.message\?.startsWith(\"FileNotFound\"))\n throw e;\n const notFound = new Error(`ENOENT: no such file or directory, watch '${path}'`);\n throw notFound.code = \"ENOENT\", notFound.errno = -2, notFound.path = path, notFound.syscall = \"watch\", notFound.filename = path, notFound;\n }\n }\n #onEvent(eventType, filenameOrError) {\n if (eventType === \"error\" || eventType === \"close\")\n this.emit(eventType, filenameOrError);\n else\n this.emit(\"change\", eventType, filenameOrError), this.#listener(eventType, filenameOrError);\n }\n close() {\n this.#watcher\?.close(), this.#watcher = null;\n }\n ref() {\n this.#watcher\?.ref();\n }\n unref() {\n this.#watcher\?.unref();\n }\n start() {\n }\n}\n\nclass StatWatcher extends EventEmitter {\n constructor(path, options) {\n super();\n this._handle = fs.watchFile(path, options, this.#onChange.bind(this));\n }\n #onChange(curr, prev) {\n this.emit(\"change\", curr, prev);\n }\n start() {\n }\n stop() {\n this._handle\?.close(), this._handle = null;\n }\n ref() {\n this._handle\?.ref();\n }\n unref() {\n this._handle\?.unref();\n }\n}\nvar access = function access2(...args) {\n callbackify(fs.accessSync, args);\n}, appendFile = function appendFile2(...args) {\n callbackify(fs.appendFileSync, args);\n}, close = function close2(...args) {\n callbackify(fs.closeSync, args);\n}, rm = function rm2(...args) {\n callbackify(fs.rmSync, args);\n}, rmdir = function rmdir2(...args) {\n callbackify(fs.rmdirSync, args);\n}, copyFile = function copyFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.copyFile(...args).then((result) => callback(null, result), callback);\n}, exists = function exists2(...args) {\n callbackify(fs.existsSync, args);\n}, chown = function chown2(...args) {\n callbackify(fs.chownSync, args);\n}, chmod = function chmod2(...args) {\n callbackify(fs.chmodSync, args);\n}, fchmod = function fchmod2(...args) {\n callbackify(fs.fchmodSync, args);\n}, fchown = function fchown2(...args) {\n callbackify(fs.fchownSync, args);\n}, fstat = function fstat2(...args) {\n callbackify(fs.fstatSync, args);\n}, fsync = function fsync2(...args) {\n callbackify(fs.fsyncSync, args);\n}, ftruncate = function ftruncate2(...args) {\n callbackify(fs.ftruncateSync, args);\n}, futimes = function futimes2(...args) {\n callbackify(fs.futimesSync, args);\n}, lchmod = function lchmod2(...args) {\n callbackify(fs.lchmodSync, args);\n}, lchown = function lchown2(...args) {\n callbackify(fs.lchownSync, args);\n}, link = function link2(...args) {\n callbackify(fs.linkSync, args);\n}, mkdir = function mkdir2(...args) {\n callbackify(fs.mkdirSync, args);\n}, mkdtemp = function mkdtemp2(...args) {\n callbackify(fs.mkdtempSync, args);\n}, open = function open2(...args) {\n callbackify(fs.openSync, args);\n}, read = function read2(fd, buffer, offsetOrOptions, length, position, callback) {\n let offset = offsetOrOptions, params = null;\n if (arguments.length <= 4) {\n if (arguments.length === 4)\n callback = length, params = offsetOrOptions;\n else if (arguments.length === 3) {\n if (!isArrayBufferView(buffer))\n params = buffer, { buffer = @Buffer.alloc(16384) } = params \?\? {};\n callback = offsetOrOptions;\n } else\n callback = buffer, buffer = @Buffer.alloc(16384);\n ({ offset = 0, length = buffer\?.byteLength - offset, position = null } = params \?\? {});\n }\n queueMicrotask(() => {\n try {\n var bytesRead = fs.readSync(fd, buffer, offset, length, position);\n } catch (e) {\n callback(e);\n }\n callback(null, bytesRead, buffer);\n });\n}, write = function write2(...args) {\n callbackify(fs.writeSync, args);\n}, readdir = function readdir2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readdir(...args).then((result) => callback(null, result), callback);\n}, readFile = function readFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readFile(...args).then((result) => callback(null, result), callback);\n}, writeFile = function writeFile2(...args) {\n callbackify(fs.writeFileSync, args);\n}, readlink = function readlink2(...args) {\n callbackify(fs.readlinkSync, args);\n}, realpath = function realpath2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.realpath(...args).then((result) => callback(null, result), callback);\n}, rename = function rename2(...args) {\n callbackify(fs.renameSync, args);\n}, lstat = function lstat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.lstat(...args).then((result) => callback(null, result), callback);\n}, stat = function stat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.stat(...args).then((result) => callback(null, result), callback);\n}, symlink = function symlink2(...args) {\n callbackify(fs.symlinkSync, args);\n}, truncate = function truncate2(...args) {\n callbackify(fs.truncateSync, args);\n}, unlink = function unlink2(...args) {\n callbackify(fs.unlinkSync, args);\n}, utimes = function utimes2(...args) {\n callbackify(fs.utimesSync, args);\n}, lutimes = function lutimes2(...args) {\n callbackify(fs.lutimesSync, args);\n}, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), closeSync = fs.closeSync.bind(fs), copyFileSync = fs.copyFileSync.bind(fs), existsSync = fs.existsSync.bind(fs), chownSync = fs.chownSync.bind(fs), chmodSync = fs.chmodSync.bind(fs), fchmodSync = fs.fchmodSync.bind(fs), fchownSync = fs.fchownSync.bind(fs), fstatSync = fs.fstatSync.bind(fs), fsyncSync = fs.fsyncSync.bind(fs), ftruncateSync = fs.ftruncateSync.bind(fs), futimesSync = fs.futimesSync.bind(fs), lchmodSync = fs.lchmodSync.bind(fs), lchownSync = fs.lchownSync.bind(fs), linkSync = fs.linkSync.bind(fs), lstatSync = fs.lstatSync.bind(fs), mkdirSync = fs.mkdirSync.bind(fs), mkdtempSync = fs.mkdtempSync.bind(fs), openSync = fs.openSync.bind(fs), readSync = fs.readSync.bind(fs), writeSync = fs.writeSync.bind(fs), readdirSync = fs.readdirSync.bind(fs), readFileSync = fs.readFileSync.bind(fs), writeFileSync = fs.writeFileSync.bind(fs), readlinkSync = fs.readlinkSync.bind(fs), realpathSync = fs.realpathSync.bind(fs), renameSync = fs.renameSync.bind(fs), statSync = fs.statSync.bind(fs), symlinkSync = fs.symlinkSync.bind(fs), truncateSync = fs.truncateSync.bind(fs), unlinkSync = fs.unlinkSync.bind(fs), utimesSync = fs.utimesSync.bind(fs), lutimesSync = fs.lutimesSync.bind(fs), rmSync = fs.rmSync.bind(fs), rmdirSync = fs.rmdirSync.bind(fs), writev = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.writevSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, writevSync = fs.writevSync.bind(fs), readv = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.readvSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {\n return new FSWatcher(path, options, listener);\n}, statWatchers = new Map, _pathModule, readStreamPathFastPathSymbol = Symbol.for(\"Bun.Node.readStreamPathFastPath\"), readStreamSymbol = Symbol.for(\"Bun.NodeReadStream\"), readStreamPathOrFdSymbol = Symbol.for(\"Bun.NodeReadStreamPathOrFd\"), writeStreamSymbol = Symbol.for(\"Bun.NodeWriteStream\"), writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), writeStreamPathFastPathCallSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPathCall\"), kIoDone = Symbol.for(\"kIoDone\"), defaultReadStreamOptions = {\n file: @undefined,\n fd: null,\n flags: \"r\",\n encoding: @undefined,\n mode: 438,\n autoClose: !0,\n emitClose: !0,\n start: 0,\n end: @Infinity,\n highWaterMark: 65536,\n fs: {\n read,\n open: (path, flags, mode, cb) => {\n var fd;\n try {\n fd = openSync(path, flags, mode);\n } catch (e) {\n cb(e);\n return;\n }\n cb(null, fd);\n },\n openSync,\n close\n },\n autoDestroy: !0\n}, ReadStreamClass;\nReadStream = function(InternalReadStream) {\n ReadStreamClass = InternalReadStream, Object.defineProperty(ReadStreamClass.prototype, Symbol.toStringTag, {\n value: \"ReadStream\",\n enumerable: !1\n });\n function ReadStream3(path, options) {\n return new InternalReadStream(path, options);\n }\n return ReadStream3.prototype = InternalReadStream.prototype, Object.defineProperty(ReadStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalReadStream;\n }\n });\n}(class ReadStream2 extends Stream._getNativeReadableStreamPrototype(2, Stream.Readable) {\n constructor(pathOrFd, options = defaultReadStreamOptions) {\n if (typeof options !== \"object\" || !options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n flags = defaultReadStreamOptions.flags,\n encoding = defaultReadStreamOptions.encoding,\n mode = defaultReadStreamOptions.mode,\n autoClose = defaultReadStreamOptions.autoClose,\n emitClose = defaultReadStreamOptions.emitClose,\n start = defaultReadStreamOptions.start,\n end = defaultReadStreamOptions.end,\n autoDestroy = defaultReadStreamOptions.autoClose,\n fs: fs2 = defaultReadStreamOptions.fs,\n highWaterMark = defaultReadStreamOptions.highWaterMark,\n fd = defaultReadStreamOptions.fd\n } = options;\n if (pathOrFd\?.constructor\?.name === \"URL\")\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n var tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n @throwTypeError(\"Expected options.fd to be a number\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = fd, tempThis.autoClose = !1;\n } else if (typeof pathOrFd === \"string\") {\n if (pathOrFd.startsWith(\"file://\"))\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n if (pathOrFd.length === 0)\n @throwTypeError(\"Expected path to be a non-empty string\");\n tempThis.path = tempThis.file = tempThis[readStreamPathOrFdSymbol] = pathOrFd;\n } else if (typeof pathOrFd === \"number\") {\n if (pathOrFd |= 0, pathOrFd < 0)\n @throwTypeError(\"Expected fd to be a positive integer\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = pathOrFd, tempThis.autoClose = !1;\n } else\n @throwTypeError(\"Expected a path or file descriptor\");\n if (tempThis.fd === @undefined)\n tempThis.fd = fs2.openSync(pathOrFd, flags, mode);\n var fileRef = Bun.file(tempThis.fd), stream = fileRef.stream(), native = @direct(stream);\n if (!native)\n throw new Error(\"no native readable stream\");\n var { stream: ptr } = native;\n super(ptr, {\n ...options,\n encoding,\n autoDestroy,\n autoClose,\n emitClose,\n highWaterMark\n });\n if (Object.assign(this, tempThis), this.#fileRef = fileRef, this.end = end, this._read = this.#internalRead, this.start = start, this.flags = flags, this.mode = mode, this.emitClose = emitClose, this[readStreamPathFastPathSymbol] = start === 0 && end === @Infinity && autoClose && fs2 === defaultReadStreamOptions.fs && (encoding === \"buffer\" || encoding === \"binary\" || encoding == null || encoding === \"utf-8\" || encoding === \"utf8\"), this._readableState.autoClose = autoDestroy = autoClose, this._readableState.highWaterMark = highWaterMark, start !== @undefined)\n this.pos = start;\n }\n #fileRef;\n #fs;\n file;\n path;\n fd = null;\n flags;\n mode;\n start;\n end;\n pos;\n bytesRead = 0;\n #fileSize = -1;\n _read;\n [readStreamSymbol] = !0;\n [readStreamPathOrFdSymbol];\n [readStreamPathFastPathSymbol];\n _construct(callback) {\n if (super._construct)\n super._construct(callback);\n else\n callback();\n this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n super._destroy(err, cb);\n try {\n var fd = this.fd;\n if (this[readStreamPathFastPathSymbol] = !1, !fd)\n cb(err);\n else\n this.#fs.close(fd, (er) => {\n cb(er || err);\n }), this.fd = null;\n } catch (e) {\n throw e;\n }\n }\n close(cb) {\n if (typeof cb === \"function\")\n Stream.eos(this, cb);\n this.destroy();\n }\n push(chunk) {\n var bytesRead = chunk\?.length \?\? 0;\n if (bytesRead > 0) {\n this.bytesRead += bytesRead;\n var currPos = this.pos;\n if (currPos !== @undefined) {\n if (this.bytesRead < currPos)\n return !0;\n if (currPos === this.start) {\n var n = this.bytesRead - currPos;\n chunk = chunk.slice(-n);\n var [_, ...rest] = arguments;\n if (this.pos = this.bytesRead, this.end !== @undefined && this.bytesRead > this.end)\n chunk = chunk.slice(0, this.end - this.start + 1);\n return super.push(chunk, ...rest);\n }\n var end = this.end;\n if (end !== @undefined && this.bytesRead > end) {\n chunk = chunk.slice(0, end - currPos + 1);\n var [_, ...rest] = arguments;\n return this.pos = this.bytesRead, super.push(chunk, ...rest);\n }\n this.pos = this.bytesRead;\n }\n }\n return super.push(...arguments);\n }\n #internalRead(n) {\n var { pos, end, bytesRead, fd, encoding } = this;\n if (n = pos !== @undefined \? Math.min(end - pos + 1, n) : Math.min(end - bytesRead + 1, n), n <= 0) {\n this.push(null);\n return;\n }\n if (this.#fileSize === -1 && bytesRead === 0 && pos === @undefined) {\n var stat3 = fstatSync(fd);\n if (this.#fileSize = stat3.size, this.#fileSize > 0 && n > this.#fileSize)\n n = this.#fileSize + 1;\n }\n this[kIoDone] = !1;\n var res = super._read(n);\n if (@isPromise(res)) {\n var then = res\?.then;\n if (then && @isCallable(then))\n res.then(() => {\n if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone);\n }, (er) => {\n this[kIoDone] = !0, this.#errorOrDestroy(er);\n });\n } else if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone), this.#errorOrDestroy(new Error(\"ERR_STREAM_PREMATURE_CLOSE\"));\n }\n #errorOrDestroy(err, sync = null) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n }\n pause() {\n return this[readStreamPathFastPathSymbol] = !1, super.pause();\n }\n resume() {\n return this[readStreamPathFastPathSymbol] = !1, super.resume();\n }\n unshift(...args) {\n return this[readStreamPathFastPathSymbol] = !1, super.unshift(...args);\n }\n pipe(dest, pipeOpts) {\n if (this[readStreamPathFastPathSymbol] && (pipeOpts\?.end \?\? !0) && this._readableState\?.pipes\?.length === 0) {\n if ((writeStreamPathFastPathSymbol in dest) && dest[writeStreamPathFastPathSymbol]) {\n if (dest[writeStreamPathFastPathCallSymbol](this, pipeOpts))\n return this;\n }\n }\n return this[readStreamPathFastPathSymbol] = !1, super.pipe(dest, pipeOpts);\n }\n});\nvar defaultWriteStreamOptions = {\n fd: null,\n start: @undefined,\n pos: @undefined,\n encoding: @undefined,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass = WriteStream = function WriteStream2(path, options = defaultWriteStreamOptions) {\n if (!(this instanceof WriteStream2))\n return new WriteStream2(path, options);\n if (!options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n fs: fs2 = defaultWriteStreamOptions.fs,\n start = defaultWriteStreamOptions.start,\n flags = defaultWriteStreamOptions.flags,\n mode = defaultWriteStreamOptions.mode,\n autoClose = !0,\n emitClose = !1,\n autoDestroy = autoClose,\n encoding = defaultWriteStreamOptions.encoding,\n fd = defaultWriteStreamOptions.fd,\n pos = defaultWriteStreamOptions.pos\n } = options, tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n throw new Error(\"Expected options.fd to be a number\");\n tempThis.fd = fd, tempThis[_writeStreamPathFastPathSymbol] = !1;\n } else if (typeof path === \"string\") {\n if (path.length === 0)\n @throwTypeError(\"Expected a non-empty path\");\n if (path.startsWith(\"file:\"))\n path = Bun.fileURLToPath(path);\n tempThis.path = path, tempThis.fd = null, tempThis[_writeStreamPathFastPathSymbol] = autoClose && (start === @undefined || start === 0) && fs2.write === defaultWriteStreamOptions.fs.write && fs2.close === defaultWriteStreamOptions.fs.close;\n }\n if (tempThis.fd == null)\n tempThis.fd = fs2.openSync(path, flags, mode);\n if (NativeWritable.call(this, tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n }), Object.assign(this, tempThis), typeof fs2\?.write !== \"function\")\n @throwTypeError(\"Expected fs.write to be a function\");\n if (typeof fs2\?.close !== \"function\")\n @throwTypeError(\"Expected fs.close to be a function\");\n if (typeof fs2\?.open !== \"function\")\n @throwTypeError(\"Expected fs.open to be a function\");\n if (typeof path === \"object\" && path) {\n if (path instanceof URL)\n path = Bun.fileURLToPath(path);\n }\n if (typeof path !== \"string\" && typeof fd !== \"number\")\n @throwTypeError(\"Expected a path or file descriptor\");\n if (this.start = start, this[_fs] = fs2, this.flags = flags, this.mode = mode, this.bytesWritten = 0, this[writeStreamSymbol] = !0, this[kIoDone] = !1, this.start !== @undefined)\n this.pos = this.start;\n if (encoding !== defaultWriteStreamOptions.encoding) {\n if (this.setDefaultEncoding(encoding), encoding !== \"buffer\" && encoding !== \"utf8\" && encoding !== \"utf-8\" && encoding !== \"binary\")\n this[_writeStreamPathFastPathSymbol] = !1;\n }\n return this;\n}, NativeWritable = Stream.NativeWritable, WriteStreamPrototype = WriteStream.prototype = Object.create(NativeWritable.prototype);\nObject.defineProperties(WriteStreamPrototype, {\n autoClose: {\n get() {\n return this._writableState.autoDestroy;\n },\n set(val) {\n this._writableState.autoDestroy = val;\n }\n },\n pending: {\n get() {\n return this.fd === null;\n }\n }\n});\nWriteStreamPrototype.destroySoon = WriteStreamPrototype.end;\nWriteStreamPrototype.open = function open3() {\n};\nWriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(readStream, pipeOpts) {\n if (!this[_writeStreamPathFastPathSymbol])\n return !1;\n if (this.fd !== null)\n return this[_writeStreamPathFastPathSymbol] = !1, !1;\n return this[kIoDone] = !1, readStream[kIoDone] = !1, Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then((bytesWritten) => {\n readStream[kIoDone] = this[kIoDone] = !0, this.bytesWritten += bytesWritten, readStream.bytesRead += bytesWritten, this.end(), readStream.close();\n }, (err) => {\n readStream[kIoDone] = this[kIoDone] = !0, WriteStream_errorOrDestroy.call(this, err), readStream.emit(\"error\", err);\n });\n};\nWriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {\n return this[_writeStreamPathFastPathSymbol];\n};\nWriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {\n this[_writeStreamPathFastPathSymbol] = !1;\n};\nWriteStreamPrototype._construct = function _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n};\nWriteStreamPrototype._destroy = function _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));\n return;\n }\n WriteStream_internalClose.call(this, err, cb);\n};\nWriteStreamPrototype.close = function close3(cb) {\n if (cb) {\n if (this.closed) {\n process.nextTick(cb);\n return;\n }\n this.on(\"close\", cb);\n }\n if (!this.autoClose)\n this.on(\"finish\", this.destroy);\n this.end();\n};\nWriteStreamPrototype.write = function write3(chunk, encoding, cb) {\n if (encoding \?\?= this._writableState\?.defaultEncoding, this[_writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = @Buffer.from(chunk, encoding);\n var native = this.pos === @undefined;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, WriteStream_handleWrite.call(this, err, bytes), this.emit(kIoDone), cb)\n !err \? cb() : cb(err);\n } : () => {\n };\n if (this[kIoDone] = !0, this._write)\n return this._write(chunk, encoding, callback);\n else\n return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);\n};\nWriteStreamPrototype._write = @undefined;\nWriteStreamPrototype._writev = @undefined;\nWriteStreamPrototype.end = function end(chunk, encoding, cb) {\n var native = this.pos === @undefined;\n return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);\n};\nWriteStreamPrototype._destroy = function _destroy2(err, cb) {\n this.close(err, cb);\n};\nObject.defineProperties(fs, {\n createReadStream: {\n value: createReadStream\n },\n createWriteStream: {\n value: createWriteStream\n },\n ReadStream: {\n value: ReadStream\n },\n WriteStream: {\n value: WriteStream\n }\n});\nrealpath.native = realpath;\nrealpathSync.native = realpathSync;\nvar lazy_cpSync = null;\n$ = {\n Dirent,\n FSWatcher,\n ReadStream,\n Stats,\n WriteStream,\n _toUnixTimestamp,\n access,\n accessSync,\n appendFile,\n appendFileSync,\n chmod,\n chmodSync,\n chown,\n chownSync,\n close,\n closeSync,\n constants,\n copyFile,\n copyFileSync,\n cp,\n cpSync,\n createReadStream,\n createWriteStream,\n exists,\n existsSync,\n fchmod,\n fchmodSync,\n fchown,\n fchownSync,\n fstat,\n fstatSync,\n fsync,\n fsyncSync,\n ftruncate,\n ftruncateSync,\n futimes,\n futimesSync,\n lchmod,\n lchmodSync,\n lchown,\n lchownSync,\n link,\n linkSync,\n lstat,\n lstatSync,\n lutimes,\n lutimesSync,\n mkdir,\n mkdirSync,\n mkdtemp,\n mkdtempSync,\n open,\n openSync,\n promises,\n read,\n readFile,\n readFileSync,\n readSync,\n readdir,\n readdirSync,\n readlink,\n readlinkSync,\n readv,\n readvSync,\n realpath,\n realpathSync,\n rename,\n renameSync,\n rm,\n rmSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n symlink,\n symlinkSync,\n truncate,\n truncateSync,\n unlink,\n unlinkSync,\n unwatchFile,\n utimes,\n utimesSync,\n watch,\n watchFile,\n write,\n writeFile,\n writeFileSync,\n writeSync,\n writev,\n writevSync,\n [Symbol.for(\"::bunternal::\")]: {\n ReadStreamClass,\n WriteStreamClass\n }\n};\nreturn $})\n"_s; +static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar getValidatedPath = function(p) {\n if (p instanceof URL)\n return Bun.fileURLToPath(p);\n if (typeof p !== \"string\")\n @throwTypeError(\"Path must be a string or URL.\");\n return (_pathModule \?\?= @getInternalField(@internalModuleRegistry, 28) || @createInternalModuleById(28)).resolve(p);\n}, watchFile = function(filename, options, listener) {\n if (filename = getValidatedPath(filename), typeof options === \"function\")\n listener = options, options = {};\n if (typeof listener !== \"function\")\n @throwTypeError(\"listener must be a function\");\n var stat = statWatchers.get(filename);\n if (!stat)\n stat = new StatWatcher(filename, options), statWatchers.set(filename, stat);\n return stat.addListener(\"change\", listener), stat;\n}, unwatchFile = function(filename, listener) {\n filename = getValidatedPath(filename);\n var stat = statWatchers.get(filename);\n if (!stat)\n return;\n if (listener) {\n if (stat.removeListener(\"change\", listener), stat.listenerCount(\"change\") !== 0)\n return;\n } else\n stat.removeAllListeners(\"change\");\n stat.stop(), statWatchers.delete(filename);\n}, callbackify = function(fsFunction, args) {\n const callback = args[args.length - 1];\n try {\n var result = fsFunction.apply(fs, args.slice(0, args.length - 1));\n result.then((...args2) => callback(null, ...args2), (err) => callback(err));\n } catch (e) {\n if (typeof callback === \"function\")\n callback(e);\n else\n throw e;\n }\n}, createReadStream = function(path, options) {\n return new ReadStream(path, options);\n}, WriteStream_handleWrite = function(er, bytes) {\n if (er)\n return WriteStream_errorOrDestroy.call(this, er);\n this.bytesWritten += bytes;\n}, WriteStream_internalClose = function(err, cb) {\n this[_writeStreamPathFastPathSymbol] = !1;\n var fd = this.fd;\n this[_fs].close(fd, (er) => {\n this.fd = null, cb(err || er);\n });\n}, WriteStream_errorOrDestroy = function(err) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n}, createWriteStream = function(path, options) {\n return new WriteStream(path, options);\n}, cpSync = function(src, dest, options) {\n if (!options)\n return fs.cpSync(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cpSync)\n lazy_cpSync = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cpSync(src, dest, options);\n }\n return fs.cpSync(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n}, cp = function(src, dest, options, callback) {\n if (typeof options === \"function\")\n callback = options, options = @undefined;\n promises.cp(src, dest, options).then(() => callback(), callback);\n}, _toUnixTimestamp = function(time, name = \"time\") {\n if (typeof time === \"string\" && +time == time)\n return +time;\n if (NumberIsFinite(time)) {\n if (time < 0)\n return DateNow() / 1000;\n return time;\n }\n if (isDate(time))\n return DatePrototypeGetTime(time) / 1000;\n @throwTypeError(`Expected ${name} to be a number or Date`);\n}, $, ReadStream, WriteStream, EventEmitter = @getInternalField(@internalModuleRegistry, 18) || @createInternalModuleById(18), promises = @getInternalField(@internalModuleRegistry, 20) || @createInternalModuleById(20), Stream = @getInternalField(@internalModuleRegistry, 37) || @createInternalModuleById(37), { isArrayBufferView } = @requireNativeModule(\"util/types\"), _writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), _fs = Symbol.for(\"#fs\"), constants = @processBindingConstants.fs, fs = Bun.fs();\n\nclass FSWatcher extends EventEmitter {\n #watcher;\n #listener;\n constructor(path, options, listener) {\n super();\n if (typeof options === \"function\")\n listener = options, options = {};\n else if (typeof options === \"string\")\n options = { encoding: options };\n if (typeof listener !== \"function\")\n listener = () => {\n };\n this.#listener = listener;\n try {\n this.#watcher = fs.watch(path, options || {}, this.#onEvent.bind(this));\n } catch (e) {\n if (!e.message\?.startsWith(\"FileNotFound\"))\n throw e;\n const notFound = new Error(`ENOENT: no such file or directory, watch '${path}'`);\n throw notFound.code = \"ENOENT\", notFound.errno = -2, notFound.path = path, notFound.syscall = \"watch\", notFound.filename = path, notFound;\n }\n }\n #onEvent(eventType, filenameOrError) {\n if (eventType === \"error\" || eventType === \"close\")\n this.emit(eventType, filenameOrError);\n else\n this.emit(\"change\", eventType, filenameOrError), this.#listener(eventType, filenameOrError);\n }\n close() {\n this.#watcher\?.close(), this.#watcher = null;\n }\n ref() {\n this.#watcher\?.ref();\n }\n unref() {\n this.#watcher\?.unref();\n }\n start() {\n }\n}\n\nclass StatWatcher extends EventEmitter {\n constructor(path, options) {\n super();\n this._handle = fs.watchFile(path, options, this.#onChange.bind(this));\n }\n #onChange(curr, prev) {\n this.emit(\"change\", curr, prev);\n }\n start() {\n }\n stop() {\n this._handle\?.close(), this._handle = null;\n }\n ref() {\n this._handle\?.ref();\n }\n unref() {\n this._handle\?.unref();\n }\n}\nvar access = function access2(...args) {\n callbackify(fs.access, args);\n}, appendFile = function appendFile2(...args) {\n callbackify(fs.appendFile, args);\n}, close = function close2(...args) {\n callbackify(fs.close, args);\n}, rm = function rm2(...args) {\n callbackify(fs.rm, args);\n}, rmdir = function rmdir2(...args) {\n callbackify(fs.rmdir, args);\n}, copyFile = function copyFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.copyFile(...args).then((result) => callback(null, result), callback);\n}, exists = function exists2(...args) {\n callbackify(fs.exists, args);\n}, chown = function chown2(...args) {\n callbackify(fs.chown, args);\n}, chmod = function chmod2(...args) {\n callbackify(fs.chmod, args);\n}, fchmod = function fchmod2(...args) {\n callbackify(fs.fchmod, args);\n}, fchown = function fchown2(...args) {\n callbackify(fs.fchown, args);\n}, fstat = function fstat2(...args) {\n callbackify(fs.fstat, args);\n}, fsync = function fsync2(...args) {\n callbackify(fs.fsync, args);\n}, ftruncate = function ftruncate2(...args) {\n callbackify(fs.ftruncate, args);\n}, futimes = function futimes2(...args) {\n callbackify(fs.futimes, args);\n}, lchmod = function lchmod2(...args) {\n callbackify(fs.lchmod, args);\n}, lchown = function lchown2(...args) {\n callbackify(fs.lchown, args);\n}, link = function link2(...args) {\n callbackify(fs.link, args);\n}, mkdir = function mkdir2(...args) {\n callbackify(fs.mkdir, args);\n}, mkdtemp = function mkdtemp2(...args) {\n callbackify(fs.mkdtemp, args);\n}, open = function open2(...args) {\n callbackify(fs.open, args);\n}, read = function read2(fd, buffer, offsetOrOptions, length, position, callback) {\n let offset = offsetOrOptions, params = null;\n if (arguments.length <= 4) {\n if (arguments.length === 4)\n callback = length, params = offsetOrOptions;\n else if (arguments.length === 3) {\n if (!isArrayBufferView(buffer))\n params = buffer, { buffer = @Buffer.alloc(16384) } = params \?\? {};\n callback = offsetOrOptions;\n } else\n callback = buffer, buffer = @Buffer.alloc(16384);\n ({ offset = 0, length = buffer\?.byteLength - offset, position = null } = params \?\? {});\n }\n queueMicrotask(() => {\n try {\n var bytesRead = fs.readSync(fd, buffer, offset, length, position);\n } catch (e) {\n callback(e);\n }\n callback(null, bytesRead, buffer);\n });\n}, write = function write2(...args) {\n callbackify(fs.write, args);\n}, readdir = function readdir2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readdir(...args).then((result) => callback(null, result), callback);\n}, readFile = function readFile2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.readFile(...args).then((result) => callback(null, result), callback);\n}, writeFile = function writeFile2(...args) {\n callbackify(fs.writeFile, args);\n}, readlink = function readlink2(...args) {\n callbackify(fs.readlink, args);\n}, realpath = function realpath2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.realpath(...args).then((result) => callback(null, result), callback);\n}, rename = function rename2(...args) {\n callbackify(fs.rename, args);\n}, lstat = function lstat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.lstat(...args).then((result) => callback(null, result), callback);\n}, stat = function stat2(...args) {\n const callback = args[args.length - 1];\n if (typeof callback !== \"function\")\n @throwTypeError(\"Callback must be a function\");\n fs.stat(...args).then((result) => callback(null, result), callback);\n}, symlink = function symlink2(...args) {\n callbackify(fs.symlink, args);\n}, truncate = function truncate2(...args) {\n callbackify(fs.truncate, args);\n}, unlink = function unlink2(...args) {\n callbackify(fs.unlink, args);\n}, utimes = function utimes2(...args) {\n callbackify(fs.utimes, args);\n}, lutimes = function lutimes2(...args) {\n callbackify(fs.lutimes, args);\n}, accessSync = fs.accessSync.bind(fs), appendFileSync = fs.appendFileSync.bind(fs), closeSync = fs.closeSync.bind(fs), copyFileSync = fs.copyFileSync.bind(fs), existsSync = fs.existsSync.bind(fs), chownSync = fs.chownSync.bind(fs), chmodSync = fs.chmodSync.bind(fs), fchmodSync = fs.fchmodSync.bind(fs), fchownSync = fs.fchownSync.bind(fs), fstatSync = fs.fstatSync.bind(fs), fsyncSync = fs.fsyncSync.bind(fs), ftruncateSync = fs.ftruncateSync.bind(fs), futimesSync = fs.futimesSync.bind(fs), lchmodSync = fs.lchmodSync.bind(fs), lchownSync = fs.lchownSync.bind(fs), linkSync = fs.linkSync.bind(fs), lstatSync = fs.lstatSync.bind(fs), mkdirSync = fs.mkdirSync.bind(fs), mkdtempSync = fs.mkdtempSync.bind(fs), openSync = fs.openSync.bind(fs), readSync = fs.readSync.bind(fs), writeSync = fs.writeSync.bind(fs), readdirSync = fs.readdirSync.bind(fs), readFileSync = fs.readFileSync.bind(fs), writeFileSync = fs.writeFileSync.bind(fs), readlinkSync = fs.readlinkSync.bind(fs), realpathSync = fs.realpathSync.bind(fs), renameSync = fs.renameSync.bind(fs), statSync = fs.statSync.bind(fs), symlinkSync = fs.symlinkSync.bind(fs), truncateSync = fs.truncateSync.bind(fs), unlinkSync = fs.unlinkSync.bind(fs), utimesSync = fs.utimesSync.bind(fs), lutimesSync = fs.lutimesSync.bind(fs), rmSync = fs.rmSync.bind(fs), rmdirSync = fs.rmdirSync.bind(fs), writev = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.writevSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, writevSync = fs.writevSync.bind(fs), readv = (fd, buffers, position, callback) => {\n if (typeof position === \"function\")\n callback = position, position = null;\n queueMicrotask(() => {\n try {\n var written = fs.readvSync(fd, buffers, position);\n } catch (e) {\n callback(e);\n }\n callback(null, written, buffers);\n });\n}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {\n return new FSWatcher(path, options, listener);\n}, statWatchers = new Map, _pathModule, readStreamPathFastPathSymbol = Symbol.for(\"Bun.Node.readStreamPathFastPath\"), readStreamSymbol = Symbol.for(\"Bun.NodeReadStream\"), readStreamPathOrFdSymbol = Symbol.for(\"Bun.NodeReadStreamPathOrFd\"), writeStreamSymbol = Symbol.for(\"Bun.NodeWriteStream\"), writeStreamPathFastPathSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPath\"), writeStreamPathFastPathCallSymbol = Symbol.for(\"Bun.NodeWriteStreamFastPathCall\"), kIoDone = Symbol.for(\"kIoDone\"), defaultReadStreamOptions = {\n file: @undefined,\n fd: null,\n flags: \"r\",\n encoding: @undefined,\n mode: 438,\n autoClose: !0,\n emitClose: !0,\n start: 0,\n end: @Infinity,\n highWaterMark: 65536,\n fs: {\n read,\n open: (path, flags, mode, cb) => {\n var fd;\n try {\n fd = openSync(path, flags, mode);\n } catch (e) {\n cb(e);\n return;\n }\n cb(null, fd);\n },\n openSync,\n close\n },\n autoDestroy: !0\n}, ReadStreamClass;\nReadStream = function(InternalReadStream) {\n ReadStreamClass = InternalReadStream, Object.defineProperty(ReadStreamClass.prototype, Symbol.toStringTag, {\n value: \"ReadStream\",\n enumerable: !1\n });\n function ReadStream3(path, options) {\n return new InternalReadStream(path, options);\n }\n return ReadStream3.prototype = InternalReadStream.prototype, Object.defineProperty(ReadStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalReadStream;\n }\n });\n}(class ReadStream2 extends Stream._getNativeReadableStreamPrototype(2, Stream.Readable) {\n constructor(pathOrFd, options = defaultReadStreamOptions) {\n if (typeof options !== \"object\" || !options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n flags = defaultReadStreamOptions.flags,\n encoding = defaultReadStreamOptions.encoding,\n mode = defaultReadStreamOptions.mode,\n autoClose = defaultReadStreamOptions.autoClose,\n emitClose = defaultReadStreamOptions.emitClose,\n start = defaultReadStreamOptions.start,\n end = defaultReadStreamOptions.end,\n autoDestroy = defaultReadStreamOptions.autoClose,\n fs: fs2 = defaultReadStreamOptions.fs,\n highWaterMark = defaultReadStreamOptions.highWaterMark,\n fd = defaultReadStreamOptions.fd\n } = options;\n if (pathOrFd\?.constructor\?.name === \"URL\")\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n var tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n @throwTypeError(\"Expected options.fd to be a number\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = fd, tempThis.autoClose = !1;\n } else if (typeof pathOrFd === \"string\") {\n if (pathOrFd.startsWith(\"file://\"))\n pathOrFd = Bun.fileURLToPath(pathOrFd);\n if (pathOrFd.length === 0)\n @throwTypeError(\"Expected path to be a non-empty string\");\n tempThis.path = tempThis.file = tempThis[readStreamPathOrFdSymbol] = pathOrFd;\n } else if (typeof pathOrFd === \"number\") {\n if (pathOrFd |= 0, pathOrFd < 0)\n @throwTypeError(\"Expected fd to be a positive integer\");\n tempThis.fd = tempThis[readStreamPathOrFdSymbol] = pathOrFd, tempThis.autoClose = !1;\n } else\n @throwTypeError(\"Expected a path or file descriptor\");\n if (tempThis.fd === @undefined)\n tempThis.fd = fs2.openSync(pathOrFd, flags, mode);\n var fileRef = Bun.file(tempThis.fd), stream = fileRef.stream(), native = @direct(stream);\n if (!native)\n throw new Error(\"no native readable stream\");\n var { stream: ptr } = native;\n super(ptr, {\n ...options,\n encoding,\n autoDestroy,\n autoClose,\n emitClose,\n highWaterMark\n });\n if (Object.assign(this, tempThis), this.#fileRef = fileRef, this.end = end, this._read = this.#internalRead, this.start = start, this.flags = flags, this.mode = mode, this.emitClose = emitClose, this[readStreamPathFastPathSymbol] = start === 0 && end === @Infinity && autoClose && fs2 === defaultReadStreamOptions.fs && (encoding === \"buffer\" || encoding === \"binary\" || encoding == null || encoding === \"utf-8\" || encoding === \"utf8\"), this._readableState.autoClose = autoDestroy = autoClose, this._readableState.highWaterMark = highWaterMark, start !== @undefined)\n this.pos = start;\n }\n #fileRef;\n #fs;\n file;\n path;\n fd = null;\n flags;\n mode;\n start;\n end;\n pos;\n bytesRead = 0;\n #fileSize = -1;\n _read;\n [readStreamSymbol] = !0;\n [readStreamPathOrFdSymbol];\n [readStreamPathFastPathSymbol];\n _construct(callback) {\n if (super._construct)\n super._construct(callback);\n else\n callback();\n this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n super._destroy(err, cb);\n try {\n var fd = this.fd;\n if (this[readStreamPathFastPathSymbol] = !1, !fd)\n cb(err);\n else\n this.#fs.close(fd, (er) => {\n cb(er || err);\n }), this.fd = null;\n } catch (e) {\n throw e;\n }\n }\n close(cb) {\n if (typeof cb === \"function\")\n Stream.eos(this, cb);\n this.destroy();\n }\n push(chunk) {\n var bytesRead = chunk\?.length \?\? 0;\n if (bytesRead > 0) {\n this.bytesRead += bytesRead;\n var currPos = this.pos;\n if (currPos !== @undefined) {\n if (this.bytesRead < currPos)\n return !0;\n if (currPos === this.start) {\n var n = this.bytesRead - currPos;\n chunk = chunk.slice(-n);\n var [_, ...rest] = arguments;\n if (this.pos = this.bytesRead, this.end !== @undefined && this.bytesRead > this.end)\n chunk = chunk.slice(0, this.end - this.start + 1);\n return super.push(chunk, ...rest);\n }\n var end = this.end;\n if (end !== @undefined && this.bytesRead > end) {\n chunk = chunk.slice(0, end - currPos + 1);\n var [_, ...rest] = arguments;\n return this.pos = this.bytesRead, super.push(chunk, ...rest);\n }\n this.pos = this.bytesRead;\n }\n }\n return super.push(...arguments);\n }\n #internalRead(n) {\n var { pos, end, bytesRead, fd, encoding } = this;\n if (n = pos !== @undefined \? Math.min(end - pos + 1, n) : Math.min(end - bytesRead + 1, n), n <= 0) {\n this.push(null);\n return;\n }\n if (this.#fileSize === -1 && bytesRead === 0 && pos === @undefined) {\n var stat3 = fstatSync(fd);\n if (this.#fileSize = stat3.size, this.#fileSize > 0 && n > this.#fileSize)\n n = this.#fileSize + 1;\n }\n this[kIoDone] = !1;\n var res = super._read(n);\n if (@isPromise(res)) {\n var then = res\?.then;\n if (then && @isCallable(then))\n res.then(() => {\n if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone);\n }, (er) => {\n this[kIoDone] = !0, this.#errorOrDestroy(er);\n });\n } else if (this[kIoDone] = !0, this.destroyed)\n this.emit(kIoDone), this.#errorOrDestroy(new Error(\"ERR_STREAM_PREMATURE_CLOSE\"));\n }\n #errorOrDestroy(err, sync = null) {\n var {\n _readableState: r = { destroyed: !1, autoDestroy: !1 },\n _writableState: w = { destroyed: !1, autoDestroy: !1 }\n } = this;\n if (w\?.destroyed || r\?.destroyed)\n return this;\n if (r\?.autoDestroy || w\?.autoDestroy)\n this.destroy(err);\n else if (err)\n this.emit(\"error\", err);\n }\n pause() {\n return this[readStreamPathFastPathSymbol] = !1, super.pause();\n }\n resume() {\n return this[readStreamPathFastPathSymbol] = !1, super.resume();\n }\n unshift(...args) {\n return this[readStreamPathFastPathSymbol] = !1, super.unshift(...args);\n }\n pipe(dest, pipeOpts) {\n if (this[readStreamPathFastPathSymbol] && (pipeOpts\?.end \?\? !0) && this._readableState\?.pipes\?.length === 0) {\n if ((writeStreamPathFastPathSymbol in dest) && dest[writeStreamPathFastPathSymbol]) {\n if (dest[writeStreamPathFastPathCallSymbol](this, pipeOpts))\n return this;\n }\n }\n return this[readStreamPathFastPathSymbol] = !1, super.pipe(dest, pipeOpts);\n }\n});\nvar defaultWriteStreamOptions = {\n fd: null,\n start: @undefined,\n pos: @undefined,\n encoding: @undefined,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass = WriteStream = function WriteStream2(path, options = defaultWriteStreamOptions) {\n if (!(this instanceof WriteStream2))\n return new WriteStream2(path, options);\n if (!options)\n @throwTypeError(\"Expected options to be an object\");\n var {\n fs: fs2 = defaultWriteStreamOptions.fs,\n start = defaultWriteStreamOptions.start,\n flags = defaultWriteStreamOptions.flags,\n mode = defaultWriteStreamOptions.mode,\n autoClose = !0,\n emitClose = !1,\n autoDestroy = autoClose,\n encoding = defaultWriteStreamOptions.encoding,\n fd = defaultWriteStreamOptions.fd,\n pos = defaultWriteStreamOptions.pos\n } = options, tempThis = {};\n if (fd != null) {\n if (typeof fd !== \"number\")\n throw new Error(\"Expected options.fd to be a number\");\n tempThis.fd = fd, tempThis[_writeStreamPathFastPathSymbol] = !1;\n } else if (typeof path === \"string\") {\n if (path.length === 0)\n @throwTypeError(\"Expected a non-empty path\");\n if (path.startsWith(\"file:\"))\n path = Bun.fileURLToPath(path);\n tempThis.path = path, tempThis.fd = null, tempThis[_writeStreamPathFastPathSymbol] = autoClose && (start === @undefined || start === 0) && fs2.write === defaultWriteStreamOptions.fs.write && fs2.close === defaultWriteStreamOptions.fs.close;\n }\n if (tempThis.fd == null)\n tempThis.fd = fs2.openSync(path, flags, mode);\n if (NativeWritable.call(this, tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n }), Object.assign(this, tempThis), typeof fs2\?.write !== \"function\")\n @throwTypeError(\"Expected fs.write to be a function\");\n if (typeof fs2\?.close !== \"function\")\n @throwTypeError(\"Expected fs.close to be a function\");\n if (typeof fs2\?.open !== \"function\")\n @throwTypeError(\"Expected fs.open to be a function\");\n if (typeof path === \"object\" && path) {\n if (path instanceof URL)\n path = Bun.fileURLToPath(path);\n }\n if (typeof path !== \"string\" && typeof fd !== \"number\")\n @throwTypeError(\"Expected a path or file descriptor\");\n if (this.start = start, this[_fs] = fs2, this.flags = flags, this.mode = mode, this.bytesWritten = 0, this[writeStreamSymbol] = !0, this[kIoDone] = !1, this.start !== @undefined)\n this.pos = this.start;\n if (encoding !== defaultWriteStreamOptions.encoding) {\n if (this.setDefaultEncoding(encoding), encoding !== \"buffer\" && encoding !== \"utf8\" && encoding !== \"utf-8\" && encoding !== \"binary\")\n this[_writeStreamPathFastPathSymbol] = !1;\n }\n return this;\n}, NativeWritable = Stream.NativeWritable, WriteStreamPrototype = WriteStream.prototype = Object.create(NativeWritable.prototype);\nObject.defineProperties(WriteStreamPrototype, {\n autoClose: {\n get() {\n return this._writableState.autoDestroy;\n },\n set(val) {\n this._writableState.autoDestroy = val;\n }\n },\n pending: {\n get() {\n return this.fd === null;\n }\n }\n});\nWriteStreamPrototype.destroySoon = WriteStreamPrototype.end;\nWriteStreamPrototype.open = function open3() {\n};\nWriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(readStream, pipeOpts) {\n if (!this[_writeStreamPathFastPathSymbol])\n return !1;\n if (this.fd !== null)\n return this[_writeStreamPathFastPathSymbol] = !1, !1;\n return this[kIoDone] = !1, readStream[kIoDone] = !1, Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then((bytesWritten) => {\n readStream[kIoDone] = this[kIoDone] = !0, this.bytesWritten += bytesWritten, readStream.bytesRead += bytesWritten, this.end(), readStream.close();\n }, (err) => {\n readStream[kIoDone] = this[kIoDone] = !0, WriteStream_errorOrDestroy.call(this, err), readStream.emit(\"error\", err);\n });\n};\nWriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {\n return this[_writeStreamPathFastPathSymbol];\n};\nWriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {\n this[_writeStreamPathFastPathSymbol] = !1;\n};\nWriteStreamPrototype._construct = function _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n};\nWriteStreamPrototype._destroy = function _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));\n return;\n }\n WriteStream_internalClose.call(this, err, cb);\n};\nWriteStreamPrototype.close = function close3(cb) {\n if (cb) {\n if (this.closed) {\n process.nextTick(cb);\n return;\n }\n this.on(\"close\", cb);\n }\n if (!this.autoClose)\n this.on(\"finish\", this.destroy);\n this.end();\n};\nWriteStreamPrototype.write = function write3(chunk, encoding, cb) {\n if (encoding \?\?= this._writableState\?.defaultEncoding, this[_writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = @Buffer.from(chunk, encoding);\n var native = this.pos === @undefined;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, WriteStream_handleWrite.call(this, err, bytes), this.emit(kIoDone), cb)\n !err \? cb() : cb(err);\n } : () => {\n };\n if (this[kIoDone] = !0, this._write)\n return this._write(chunk, encoding, callback);\n else\n return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);\n};\nWriteStreamPrototype._write = @undefined;\nWriteStreamPrototype._writev = @undefined;\nWriteStreamPrototype.end = function end(chunk, encoding, cb) {\n var native = this.pos === @undefined;\n return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);\n};\nWriteStreamPrototype._destroy = function _destroy2(err, cb) {\n this.close(err, cb);\n};\nObject.defineProperties(fs, {\n createReadStream: {\n value: createReadStream\n },\n createWriteStream: {\n value: createWriteStream\n },\n ReadStream: {\n value: ReadStream\n },\n WriteStream: {\n value: WriteStream\n }\n});\nrealpath.native = realpath;\nrealpathSync.native = realpathSync;\nvar lazy_cpSync = null;\n$ = {\n Dirent,\n FSWatcher,\n ReadStream,\n Stats,\n WriteStream,\n _toUnixTimestamp,\n access,\n accessSync,\n appendFile,\n appendFileSync,\n chmod,\n chmodSync,\n chown,\n chownSync,\n close,\n closeSync,\n constants,\n copyFile,\n copyFileSync,\n cp,\n cpSync,\n createReadStream,\n createWriteStream,\n exists,\n existsSync,\n fchmod,\n fchmodSync,\n fchown,\n fchownSync,\n fstat,\n fstatSync,\n fsync,\n fsyncSync,\n ftruncate,\n ftruncateSync,\n futimes,\n futimesSync,\n lchmod,\n lchmodSync,\n lchown,\n lchownSync,\n link,\n linkSync,\n lstat,\n lstatSync,\n lutimes,\n lutimesSync,\n mkdir,\n mkdirSync,\n mkdtemp,\n mkdtempSync,\n open,\n openSync,\n promises,\n read,\n readFile,\n readFileSync,\n readSync,\n readdir,\n readdirSync,\n readlink,\n readlinkSync,\n readv,\n readvSync,\n realpath,\n realpathSync,\n rename,\n renameSync,\n rm,\n rmSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n symlink,\n symlinkSync,\n truncate,\n truncateSync,\n unlink,\n unlinkSync,\n unwatchFile,\n utimes,\n utimesSync,\n watch,\n watchFile,\n write,\n writeFile,\n writeFileSync,\n writeSync,\n writev,\n writevSync,\n [Symbol.for(\"::bunternal::\")]: {\n ReadStreamClass,\n WriteStreamClass\n }\n};\nreturn $})\n"_s; // // -static constexpr ASCIILiteral NodeFSPromisesCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.promises.ts\nvar watch = function(filename, options = {}) {\n if (filename instanceof URL)\n @throwTypeError(\"Watch URLs are not supported yet\");\n else if (@Buffer.isBuffer(filename))\n filename = filename.toString();\n else if (typeof filename !== \"string\")\n @throwTypeError(\"Expected path to be a string or Buffer\");\n let nextEventResolve = null;\n if (typeof options === \"string\")\n options = { encoding: options };\n const queue = @createFIFO(), watcher = fs.watch(filename, options || {}, (eventType, filename2) => {\n if (queue.push({ eventType, filename: filename2 }), nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n });\n return {\n [Symbol.asyncIterator]() {\n let closed = !1;\n return {\n async next() {\n while (!closed) {\n let event;\n while (event = queue.shift()) {\n if (event.eventType === \"close\")\n return closed = !0, { value: @undefined, done: !0 };\n if (event.eventType === \"error\")\n throw closed = !0, event.filename;\n return { value: event, done: !1 };\n }\n const { promise, resolve } = @Promise.withResolvers();\n nextEventResolve = resolve, await promise;\n }\n return { value: @undefined, done: !0 };\n },\n return() {\n if (!closed) {\n if (watcher.close(), closed = !0, nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n }\n return { value: @undefined, done: !0 };\n }\n };\n }\n };\n}, cp = function(src, dest, options) {\n if (!options)\n return fs.cp(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cp)\n lazy_cp = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cp(src, dest, options);\n }\n return fs.cp(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n};\nasync function opendir(dir) {\n const entries = await fs.readdir(dir, { withFileTypes: !0 });\n return new Dir(entries);\n}\nvar $, constants = @processBindingConstants.fs, fs = Bun.fs(), notrace = \"::bunternal::\", promisify = {\n [notrace]: (fsFunction) => {\n return async function(...args) {\n return await 1, fsFunction.apply(fs, args);\n };\n }\n}[notrace], lazy_cp = null;\n\nclass Dir {\n #entries;\n constructor(e) {\n this.#entries = e;\n }\n readSync() {\n return this.#entries.shift() \?\? null;\n }\n read(c) {\n if (c)\n process.nextTick(c, null, this.readSync());\n return @Promise.resolve(this.readSync());\n }\n closeSync() {\n }\n close(c) {\n if (c)\n process.nextTick(c);\n return @Promise.resolve();\n }\n *[Symbol.asyncIterator]() {\n var next;\n while (next = this.readSync())\n yield next;\n }\n}\n$ = {\n access: promisify(fs.accessSync),\n appendFile: promisify(fs.appendFileSync),\n close: promisify(fs.closeSync),\n copyFile: fs.copyFile.bind(fs),\n cp,\n exists: promisify(fs.existsSync),\n chown: promisify(fs.chownSync),\n chmod: promisify(fs.chmodSync),\n fchmod: promisify(fs.fchmodSync),\n fchown: promisify(fs.fchownSync),\n fstat: promisify(fs.fstatSync),\n fsync: promisify(fs.fsyncSync),\n ftruncate: promisify(fs.ftruncateSync),\n futimes: promisify(fs.futimesSync),\n lchmod: promisify(fs.lchmodSync),\n lchown: promisify(fs.lchownSync),\n link: promisify(fs.linkSync),\n lstat: fs.lstat.bind(fs),\n mkdir: promisify(fs.mkdirSync),\n mkdtemp: promisify(fs.mkdtempSync),\n open: promisify(fs.openSync),\n read: promisify(fs.readSync),\n write: promisify(fs.writeSync),\n readdir: fs.readdir.bind(fs),\n readFile: fs.readFile.bind(fs),\n writeFile: promisify(fs.writeFileSync),\n readlink: promisify(fs.readlinkSync),\n realpath: fs.realpath.bind(fs),\n rename: promisify(fs.renameSync),\n stat: fs.stat.bind(fs),\n symlink: promisify(fs.symlinkSync),\n truncate: promisify(fs.truncateSync),\n unlink: promisify(fs.unlinkSync),\n utimes: promisify(fs.utimesSync),\n lutimes: promisify(fs.lutimesSync),\n rm: promisify(fs.rmSync),\n rmdir: promisify(fs.rmdirSync),\n writev: (fd, buffers, position) => {\n return new @Promise((resolve, reject) => {\n try {\n var bytesWritten = fs.writevSync(fd, buffers, position);\n } catch (err) {\n reject(err);\n return;\n }\n resolve({\n bytesWritten,\n buffers\n });\n });\n },\n readv: (fd, buffers, position) => {\n return new @Promise((resolve, reject) => {\n try {\n var bytesRead = fs.readvSync(fd, buffers, position);\n } catch (err) {\n reject(err);\n return;\n }\n resolve({\n bytesRead,\n buffers\n });\n });\n },\n constants,\n watch,\n opendir\n};\nreturn $})\n"_s; +static constexpr ASCIILiteral NodeFSPromisesCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.promises.ts\nvar watch = function(filename, options = {}) {\n if (filename instanceof URL)\n @throwTypeError(\"Watch URLs are not supported yet\");\n else if (@Buffer.isBuffer(filename))\n filename = filename.toString();\n else if (typeof filename !== \"string\")\n @throwTypeError(\"Expected path to be a string or Buffer\");\n let nextEventResolve = null;\n if (typeof options === \"string\")\n options = { encoding: options };\n const queue = @createFIFO(), watcher = fs.watch(filename, options || {}, (eventType, filename2) => {\n if (queue.push({ eventType, filename: filename2 }), nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n });\n return {\n [Symbol.asyncIterator]() {\n let closed = !1;\n return {\n async next() {\n while (!closed) {\n let event;\n while (event = queue.shift()) {\n if (event.eventType === \"close\")\n return closed = !0, { value: @undefined, done: !0 };\n if (event.eventType === \"error\")\n throw closed = !0, event.filename;\n return { value: event, done: !1 };\n }\n const { promise, resolve } = @Promise.withResolvers();\n nextEventResolve = resolve, await promise;\n }\n return { value: @undefined, done: !0 };\n },\n return() {\n if (!closed) {\n if (watcher.close(), closed = !0, nextEventResolve) {\n const resolve = nextEventResolve;\n nextEventResolve = null, resolve();\n }\n }\n return { value: @undefined, done: !0 };\n }\n };\n }\n };\n}, cp = function(src, dest, options) {\n if (!options)\n return fs.cp(src, dest);\n if (typeof options !== \"object\")\n @throwTypeError(\"options must be an object\");\n if (options.dereference || options.filter || options.preserveTimestamps || options.verbatimSymlinks) {\n if (!lazy_cp)\n lazy_cp = @getInternalField(@internalModuleRegistry, 3) || @createInternalModuleById(3);\n return lazy_cp(src, dest, options);\n }\n return fs.cp(src, dest, options.recursive, options.errorOnExist, options.force \?\? !0, options.mode);\n};\nasync function opendir(dir) {\n const entries = await fs.readdir(dir, { withFileTypes: !0 });\n return new Dir(entries);\n}\nvar $, constants = @processBindingConstants.fs, fs = Bun.fs();\nvar lazy_cp = null;\n\nclass Dir {\n #entries;\n constructor(e) {\n this.#entries = e;\n }\n readSync() {\n return this.#entries.shift() \?\? null;\n }\n read(c) {\n if (c)\n process.nextTick(c, null, this.readSync());\n return @Promise.resolve(this.readSync());\n }\n closeSync() {\n }\n close(c) {\n if (c)\n process.nextTick(c);\n return @Promise.resolve();\n }\n *[Symbol.asyncIterator]() {\n var next;\n while (next = this.readSync())\n yield next;\n }\n}\n$ = {\n access: fs.access.bind(fs),\n appendFile: fs.appendFile.bind(fs),\n close: fs.close.bind(fs),\n copyFile: fs.copyFile.bind(fs),\n cp,\n exists: fs.exists.bind(fs),\n chown: fs.chown.bind(fs),\n chmod: fs.chmod.bind(fs),\n fchmod: fs.fchmod.bind(fs),\n fchown: fs.fchown.bind(fs),\n fstat: fs.fstat.bind(fs),\n fsync: fs.fsync.bind(fs),\n ftruncate: fs.ftruncate.bind(fs),\n futimes: fs.futimes.bind(fs),\n lchmod: fs.lchmod.bind(fs),\n lchown: fs.lchown.bind(fs),\n link: fs.link.bind(fs),\n lstat: fs.lstat.bind(fs),\n mkdir: fs.mkdir.bind(fs),\n mkdtemp: fs.mkdtemp.bind(fs),\n open: fs.open.bind(fs),\n read: fs.read.bind(fs),\n write: fs.write.bind(fs),\n readdir: fs.readdir.bind(fs),\n readFile: fs.readFile.bind(fs),\n writeFile: fs.writeFile.bind(fs),\n readlink: fs.readlink.bind(fs),\n realpath: fs.realpath.bind(fs),\n rename: fs.rename.bind(fs),\n stat: fs.stat.bind(fs),\n symlink: fs.symlink.bind(fs),\n truncate: fs.truncate.bind(fs),\n unlink: fs.unlink.bind(fs),\n utimes: fs.utimes.bind(fs),\n lutimes: fs.lutimes.bind(fs),\n rm: fs.rm.bind(fs),\n rmdir: fs.rmdir.bind(fs),\n writev: async (fd, buffers, position) => {\n var bytesWritten = await fs.writev(fd, buffers, position);\n return {\n bytesWritten,\n buffers\n };\n },\n readv: async (fd, buffers, position) => {\n var bytesRead = await fs.readv(fd, buffers, position);\n return {\n bytesRead,\n buffers\n };\n },\n constants,\n watch,\n opendir\n};\nreturn $})\n"_s; // // diff --git a/test/js/node/fs/fs.test.ts b/test/js/node/fs/fs.test.ts index 8ea9522e1..41275edd5 100644 --- a/test/js/node/fs/fs.test.ts +++ b/test/js/node/fs/fs.test.ts @@ -1016,19 +1016,22 @@ describe("rmdir", () => { done(); }); }); - it("does not remove a dir with a file in it", done => { + it("does not remove a dir with a file in it", async () => { const path = `${tmpdir()}/${Date.now()}.rm.dir`; try { mkdirSync(path); writeFileSync(`${path}/file.txt`, "File written successfully", "utf8"); } catch (e) {} expect(existsSync(path + "/file.txt")).toBe(true); - rmdir(path, err => { + try { + await promises.rmdir(path); + } catch (err) { expect("ENOTEMPTY EPERM").toContain(err!.code); - done(); - }); + } + expect(existsSync(path + "/file.txt")).toBe(true); - rmdir(path, { recursive: true }, () => {}); + + await promises.rmdir(path, { recursive: true }); expect(existsSync(path + "/file.txt")).toBe(false); }); it("removes a dir recursively", done => { |