diff options
author | 2023-09-05 17:41:39 -0700 | |
---|---|---|
committer | 2023-09-05 17:41:39 -0700 | |
commit | acfd028e8f859a0e8139b7adab5d319e326c2373 (patch) | |
tree | f6bf98b2e40fcbcc036348bf7e0556e9edfa3b4e | |
parent | 6f8a3934923198cbadae64cda24201e2de2655c1 (diff) | |
download | bun-acfd028e8f859a0e8139b7adab5d319e326c2373.tar.gz bun-acfd028e8f859a0e8139b7adab5d319e326c2373.tar.zst bun-acfd028e8f859a0e8139b7adab5d319e326c2373.zip |
feat(runtime): Implement `fs.watchFile` (#4467)
* really lame prototype
* uses threads but badly
* it works i guess
* unwatchFile but lame
* it works
* test
* a
* aomitcs
* fix unwatching race condition
* use hasPendingActivity and GC stuff better
* test
* revert this
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h | 3 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h | 3 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h | 6 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h | 7 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 336 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.h | 83 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 95 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes_list.zig | 1 | ||||
-rw-r--r-- | src/bun.js/node/node.classes.ts | 31 | ||||
-rw-r--r-- | src/bun.js/node/node_fs.zig | 23 | ||||
-rw-r--r-- | src/bun.js/node/node_fs_binding.zig | 2 | ||||
-rw-r--r-- | src/bun.js/node/node_fs_stat_watcher.zig | 503 | ||||
-rw-r--r-- | src/bun.js/rare_data.zig | 10 | ||||
-rw-r--r-- | src/js/node/fs.js | 90 | ||||
-rw-r--r-- | src/js/out/InternalModuleRegistryConstants.h | 6 | ||||
-rw-r--r-- | src/jsc.zig | 1 | ||||
-rw-r--r-- | test/js/node/watch/fs.watchFile.test.ts | 121 |
17 files changed, 1309 insertions, 12 deletions
diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h index 3c3aa5669..a364c0a48 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h @@ -39,7 +39,8 @@ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA256Constructor;std: std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA384Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocket; -std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForStats; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForStatWatcher; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForStats; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForStatsConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSubprocess; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTCPSocket; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTLSSocket; diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h index a521090c0..e98ea16c3 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h @@ -39,7 +39,8 @@ std::unique_ptr<IsoSubspace> m_subspaceForSHA256Constructor;std::unique_ptr<IsoS std::unique_ptr<IsoSubspace> m_subspaceForSHA384Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA512; std::unique_ptr<IsoSubspace> m_subspaceForSHA512Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256; std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256Constructor;std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocket; -std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForStats; +std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForStatWatcher; +std::unique_ptr<IsoSubspace> m_subspaceForStats; std::unique_ptr<IsoSubspace> m_subspaceForStatsConstructor;std::unique_ptr<IsoSubspace> m_subspaceForSubprocess; std::unique_ptr<IsoSubspace> m_subspaceForTCPSocket; std::unique_ptr<IsoSubspace> m_subspaceForTLSSocket; diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h index 0596372b4..2c075a508 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h @@ -244,6 +244,12 @@ JSC::Structure* JSServerWebSocketStructure() { return m_JSServerWebSocket.getIni JSC::LazyClassStructure m_JSServerWebSocket; bool hasJSServerWebSocketSetterValue { false }; mutable JSC::WriteBarrier<JSC::Unknown> m_JSServerWebSocketSetterValue; +JSC::Structure* JSStatWatcherStructure() { return m_JSStatWatcher.getInitializedOnMainThread(this); } + JSC::JSObject* JSStatWatcherConstructor() { return m_JSStatWatcher.constructorInitializedOnMainThread(this); } + JSC::JSValue JSStatWatcherPrototype() { return m_JSStatWatcher.prototypeInitializedOnMainThread(this); } + JSC::LazyClassStructure m_JSStatWatcher; + bool hasJSStatWatcherSetterValue { false }; + mutable JSC::WriteBarrier<JSC::Unknown> m_JSStatWatcherSetterValue; JSC::Structure* JSStatsStructure() { return m_JSStats.getInitializedOnMainThread(this); } JSC::JSObject* JSStatsConstructor() { return m_JSStats.constructorInitializedOnMainThread(this); } JSC::JSValue JSStatsPrototype() { return m_JSStats.prototypeInitializedOnMainThread(this); } diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h index 40a473727..cb4c47ccb 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h @@ -245,6 +245,12 @@ void GlobalObject::initGeneratedLazyClasses() { init.setStructure(WebCore::JSServerWebSocket::createStructure(init.vm, init.global, init.prototype)); init.setConstructor(WebCore::JSServerWebSocket::createConstructor(init.vm, init.global, init.prototype)); }); + m_JSStatWatcher.initLater( + [](LazyClassStructure::Initializer& init) { + init.setPrototype(WebCore::JSStatWatcher::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); + init.setStructure(WebCore::JSStatWatcher::createStructure(init.vm, init.global, init.prototype)); + + }); m_JSStats.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSStats::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); @@ -338,6 +344,7 @@ void GlobalObject::visitGeneratedLazyClasses(GlobalObject *thisObject, Visitor& thisObject->m_JSSHA512.visit(visitor); visitor.append(thisObject->m_JSSHA512SetterValue); thisObject->m_JSSHA512_256.visit(visitor); visitor.append(thisObject->m_JSSHA512_256SetterValue); thisObject->m_JSServerWebSocket.visit(visitor); visitor.append(thisObject->m_JSServerWebSocketSetterValue); + thisObject->m_JSStatWatcher.visit(visitor); visitor.append(thisObject->m_JSStatWatcherSetterValue); thisObject->m_JSStats.visit(visitor); visitor.append(thisObject->m_JSStatsSetterValue); thisObject->m_JSSubprocess.visit(visitor); visitor.append(thisObject->m_JSSubprocessSetterValue); thisObject->m_JSTCPSocket.visit(visitor); visitor.append(thisObject->m_JSTCPSocketSetterValue); diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 523735c7b..5a10a05d3 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -14184,6 +14184,9 @@ JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__unlinkCallback); extern "C" EncodedJSValue NodeJSFSPrototype__unlinkSync(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__unlinkSyncCallback); +extern "C" EncodedJSValue NodeJSFSPrototype__unwatchFile(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__unwatchFileCallback); + extern "C" EncodedJSValue NodeJSFSPrototype__utimes(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__utimesCallback); @@ -14193,6 +14196,9 @@ JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__utimesSyncCallback); extern "C" EncodedJSValue NodeJSFSPrototype__watch(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__watchCallback); +extern "C" EncodedJSValue NodeJSFSPrototype__watchFile(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__watchFileCallback); + extern "C" EncodedJSValue NodeJSFSPrototype__write(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(NodeJSFSPrototype__writeCallback); @@ -14290,9 +14296,11 @@ static const HashTableValue JSNodeJSFSPrototypeTableValues[] = { { "truncateSync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__truncateSyncCallback, 2 } }, { "unlink"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__unlinkCallback, 2 } }, { "unlinkSync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__unlinkSyncCallback, 1 } }, + { "unwatchFile"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__unwatchFileCallback, 2 } }, { "utimes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__utimesCallback, 4 } }, { "utimesSync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__utimesSyncCallback, 3 } }, { "watch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__watchCallback, 3 } }, + { "watchFile"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__watchFileCallback, 3 } }, { "write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__writeCallback, 6 } }, { "writeFile"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__writeFileCallback, 4 } }, { "writeFileSync"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, NodeJSFSPrototype__writeFileSyncCallback, 3 } }, @@ -16411,6 +16419,34 @@ JSC_DEFINE_HOST_FUNCTION(NodeJSFSPrototype__unlinkSyncCallback, (JSGlobalObject return NodeJSFSPrototype__unlinkSync(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(NodeJSFSPrototype__unwatchFileCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSNodeJSFS* thisObject = jsDynamicCast<JSNodeJSFS*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof NodeJSFS"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return NodeJSFSPrototype__unwatchFile(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(NodeJSFSPrototype__utimesCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -16495,6 +16531,34 @@ JSC_DEFINE_HOST_FUNCTION(NodeJSFSPrototype__watchCallback, (JSGlobalObject * lex return NodeJSFSPrototype__watch(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(NodeJSFSPrototype__watchFileCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSNodeJSFS* thisObject = jsDynamicCast<JSNodeJSFS*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof NodeJSFS"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return NodeJSFSPrototype__watchFile(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(NodeJSFSPrototype__writeCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -21850,6 +21914,278 @@ void JSServerWebSocket::visitOutputConstraintsImpl(JSCell* cell, Visitor& visito } DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSServerWebSocket); +class JSStatWatcherPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + + static JSStatWatcherPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSStatWatcherPrototype* ptr = new (NotNull, JSC::allocateCell<JSStatWatcherPrototype>(vm)) JSStatWatcherPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSStatWatcherPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +extern "C" void StatWatcherClass__finalize(void*); + +extern "C" EncodedJSValue StatWatcherPrototype__doClose(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(StatWatcherPrototype__closeCallback); + +extern "C" EncodedJSValue StatWatcherPrototype__doRef(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(StatWatcherPrototype__refCallback); + +extern "C" EncodedJSValue StatWatcherPrototype__doUnref(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(StatWatcherPrototype__unrefCallback); + +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStatWatcherPrototype, JSStatWatcherPrototype::Base); + +static const HashTableValue JSStatWatcherPrototypeTableValues[] = { + { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, StatWatcherPrototype__closeCallback, 0 } }, + { "ref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, StatWatcherPrototype__refCallback, 0 } }, + { "unref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, StatWatcherPrototype__unrefCallback, 0 } } +}; + +const ClassInfo JSStatWatcherPrototype::s_info = { "StatWatcher"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStatWatcherPrototype) }; + +JSC_DEFINE_HOST_FUNCTION(StatWatcherPrototype__closeCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSStatWatcher* thisObject = jsDynamicCast<JSStatWatcher*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof StatWatcher"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return StatWatcherPrototype__doClose(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(StatWatcherPrototype__refCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSStatWatcher* thisObject = jsDynamicCast<JSStatWatcher*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof StatWatcher"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return StatWatcherPrototype__doRef(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(StatWatcherPrototype__unrefCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSStatWatcher* thisObject = jsDynamicCast<JSStatWatcher*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof StatWatcher"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return StatWatcherPrototype__doUnref(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +extern "C" void StatWatcherPrototype__listenerSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSStatWatcher*>(JSValue::decode(thisValue)); + thisObject->m_listener.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue StatWatcherPrototype__listenerGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSStatWatcher*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_listener.get()); +} + +void JSStatWatcherPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSStatWatcher::info(), JSStatWatcherPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +extern "C" bool StatWatcher__hasPendingActivity(void* ptr); +bool JSStatWatcher::hasPendingActivity(void* ctx) +{ + return StatWatcher__hasPendingActivity(ctx); +} + +JSStatWatcher::~JSStatWatcher() +{ + if (m_ctx) { + StatWatcherClass__finalize(m_ctx); + } +} +void JSStatWatcher::destroy(JSCell* cell) +{ + static_cast<JSStatWatcher*>(cell)->JSStatWatcher::~JSStatWatcher(); +} + +const ClassInfo JSStatWatcher::s_info = { "StatWatcher"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStatWatcher) }; + +void JSStatWatcher::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +JSStatWatcher* JSStatWatcher::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx) +{ + JSStatWatcher* ptr = new (NotNull, JSC::allocateCell<JSStatWatcher>(vm)) JSStatWatcher(vm, structure, ctx); + ptr->finishCreation(vm); + return ptr; +} + +extern "C" void* StatWatcher__fromJS(JSC::EncodedJSValue value) +{ + JSC::JSValue decodedValue = JSC::JSValue::decode(value); + if (decodedValue.isEmpty() || !decodedValue.isCell()) + return nullptr; + + JSC::JSCell* cell = decodedValue.asCell(); + JSStatWatcher* object = JSC::jsDynamicCast<JSStatWatcher*>(cell); + + if (!object) + return nullptr; + + return object->wrapped(); +} + +extern "C" bool StatWatcher__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) +{ + JSStatWatcher* object = JSC::jsDynamicCast<JSStatWatcher*>(JSValue::decode(value)); + if (!object) + return false; + + object->m_ctx = ptr; + return true; +} + +extern "C" const size_t StatWatcher__ptrOffset = JSStatWatcher::offsetOfWrapped(); + +void JSStatWatcher::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSStatWatcher*>(cell); + if (void* wrapped = thisObject->wrapped()) { + // if (thisObject->scriptExecutionContext()) + // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + } + Base::analyzeHeap(cell, analyzer); +} + +JSObject* JSStatWatcher::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +{ + return JSStatWatcherPrototype::create(vm, globalObject, JSStatWatcherPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); +} + +extern "C" EncodedJSValue StatWatcher__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSStatWatcherStructure(); + JSStatWatcher* instance = JSStatWatcher::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + +template<typename Visitor> +void JSStatWatcher::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSStatWatcher* thisObject = jsCast<JSStatWatcher*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_CHILDREN(JSStatWatcher); + +template<typename Visitor> +void JSStatWatcher::visitAdditionalChildren(Visitor& visitor) +{ + JSStatWatcher* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_listener); + + visitor.addOpaqueRoot(this->wrapped()); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSStatWatcher); + +template<typename Visitor> +void JSStatWatcher::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSStatWatcher* thisObject = jsCast<JSStatWatcher*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSStatWatcher); class JSStatsPrototype final : public JSC::JSNonFinalObject { public: using Base = JSC::JSNonFinalObject; diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h index e0b10ff55..142a96746 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.h +++ b/src/bun.js/bindings/ZigGeneratedClasses.h @@ -2283,6 +2283,89 @@ public: mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; }; +class JSStatWatcher final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSStatWatcher* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSStatWatcher, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForStatWatcher.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForStatWatcher = std::forward<decltype(space)>(space); }, + [](auto& spaces) { return spaces.m_subspaceForStatWatcher.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForStatWatcher = std::forward<decltype(space)>(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; + + ~JSStatWatcher(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSStatWatcher, m_ctx); } + + void* m_ctx { nullptr }; + + JSStatWatcher(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSStatWatcher>(this, getOwner()); + } + + void finishCreation(JSC::VM&); + + JSC::Weak<JSStatWatcher> m_weakThis; + + static bool hasPendingActivity(void* ctx); + + class Owner final : public JSC::WeakHandleOwner { + public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final + { + auto* controller = JSC::jsCast<JSStatWatcher*>(handle.slot()->asCell()); + if (JSStatWatcher::hasPendingActivity(controller->wrapped())) { + if (UNLIKELY(reason)) + *reason = "has pending activity"; + return true; + } + + return visitor.containsOpaqueRoot(context); + } + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; + + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_listener; +}; + class JSStats final : public JSC::JSDestructibleObject { public: using Base = JSC::JSDestructibleObject; diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 392a5ae4d..e7e16e889 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -4114,12 +4114,16 @@ pub const JSNodeJSFS = struct { @compileLog("Expected NodeJSFS.unlink to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.unlink))); if (@TypeOf(NodeJSFS.unlinkSync) != CallbackType) @compileLog("Expected NodeJSFS.unlinkSync to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.unlinkSync))); + if (@TypeOf(NodeJSFS.unwatchFile) != CallbackType) + @compileLog("Expected NodeJSFS.unwatchFile to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.unwatchFile))); if (@TypeOf(NodeJSFS.utimes) != CallbackType) @compileLog("Expected NodeJSFS.utimes to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.utimes))); if (@TypeOf(NodeJSFS.utimesSync) != CallbackType) @compileLog("Expected NodeJSFS.utimesSync to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.utimesSync))); if (@TypeOf(NodeJSFS.watch) != CallbackType) @compileLog("Expected NodeJSFS.watch to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.watch))); + if (@TypeOf(NodeJSFS.watchFile) != CallbackType) + @compileLog("Expected NodeJSFS.watchFile to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.watchFile))); if (@TypeOf(NodeJSFS.write) != CallbackType) @compileLog("Expected NodeJSFS.write to be a callback but received " ++ @typeName(@TypeOf(NodeJSFS.write))); if (@TypeOf(NodeJSFS.writeFile) != CallbackType) @@ -4210,9 +4214,11 @@ pub const JSNodeJSFS = struct { @export(NodeJSFS.truncateSync, .{ .name = "NodeJSFSPrototype__truncateSync" }); @export(NodeJSFS.unlink, .{ .name = "NodeJSFSPrototype__unlink" }); @export(NodeJSFS.unlinkSync, .{ .name = "NodeJSFSPrototype__unlinkSync" }); + @export(NodeJSFS.unwatchFile, .{ .name = "NodeJSFSPrototype__unwatchFile" }); @export(NodeJSFS.utimes, .{ .name = "NodeJSFSPrototype__utimes" }); @export(NodeJSFS.utimesSync, .{ .name = "NodeJSFSPrototype__utimesSync" }); @export(NodeJSFS.watch, .{ .name = "NodeJSFSPrototype__watch" }); + @export(NodeJSFS.watchFile, .{ .name = "NodeJSFSPrototype__watchFile" }); @export(NodeJSFS.write, .{ .name = "NodeJSFSPrototype__write" }); @export(NodeJSFS.writeFile, .{ .name = "NodeJSFSPrototype__writeFile" }); @export(NodeJSFS.writeFileSync, .{ .name = "NodeJSFSPrototype__writeFileSync" }); @@ -5641,6 +5647,94 @@ pub const JSServerWebSocket = struct { } } }; +pub const JSStatWatcher = struct { + const StatWatcher = Classes.StatWatcher; + const GetterType = fn (*StatWatcher, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const GetterTypeWithThisValue = fn (*StatWatcher, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const SetterType = fn (*StatWatcher, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const SetterTypeWithThisValue = fn (*StatWatcher, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const CallbackType = fn (*StatWatcher, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; + + /// Return the pointer to the wrapped object. + /// If the object does not match the type, return null. + pub fn fromJS(value: JSC.JSValue) ?*StatWatcher { + JSC.markBinding(@src()); + return StatWatcher__fromJS(value); + } + + extern fn StatWatcherPrototype__listenerSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn StatWatcherPrototype__listenerGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `StatWatcher.listener` setter + /// This value will be visited by the garbage collector. + pub fn listenerSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + StatWatcherPrototype__listenerSetCachedValue(thisValue, globalObject, value); + } + + /// `StatWatcher.listener` getter + /// This value will be visited by the garbage collector. + pub fn listenerGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = StatWatcherPrototype__listenerGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + /// Create a new instance of StatWatcher + pub fn toJS(this: *StatWatcher, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + JSC.markBinding(@src()); + if (comptime Environment.allow_assert) { + const value__ = StatWatcher__create(globalObject, this); + std.debug.assert(value__.as(StatWatcher).? == this); // If this fails, likely a C ABI issue. + return value__; + } else { + return StatWatcher__create(globalObject, this); + } + } + + /// Modify the internal ptr to point to a new instance of StatWatcher. + pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*StatWatcher) bool { + JSC.markBinding(@src()); + return StatWatcher__dangerouslySetPtr(value, ptr); + } + + /// Detach the ptr from the thisValue + pub fn detachPtr(_: *StatWatcher, value: JSC.JSValue) void { + JSC.markBinding(@src()); + std.debug.assert(StatWatcher__dangerouslySetPtr(value, null)); + } + + extern fn StatWatcher__fromJS(JSC.JSValue) ?*StatWatcher; + extern fn StatWatcher__getConstructor(*JSC.JSGlobalObject) JSC.JSValue; + + extern fn StatWatcher__create(globalObject: *JSC.JSGlobalObject, ptr: ?*StatWatcher) JSC.JSValue; + + extern fn StatWatcher__dangerouslySetPtr(JSC.JSValue, ?*StatWatcher) bool; + + comptime { + if (@TypeOf(StatWatcher.finalize) != (fn (*StatWatcher) callconv(.C) void)) { + @compileLog("StatWatcher.finalize is not a finalizer"); + } + + if (@TypeOf(StatWatcher.doClose) != CallbackType) + @compileLog("Expected StatWatcher.doClose to be a callback but received " ++ @typeName(@TypeOf(StatWatcher.doClose))); + if (@TypeOf(StatWatcher.doRef) != CallbackType) + @compileLog("Expected StatWatcher.doRef to be a callback but received " ++ @typeName(@TypeOf(StatWatcher.doRef))); + if (@TypeOf(StatWatcher.doUnref) != CallbackType) + @compileLog("Expected StatWatcher.doUnref to be a callback but received " ++ @typeName(@TypeOf(StatWatcher.doUnref))); + if (!JSC.is_bindgen) { + @export(StatWatcher.doClose, .{ .name = "StatWatcherPrototype__doClose" }); + @export(StatWatcher.doRef, .{ .name = "StatWatcherPrototype__doRef" }); + @export(StatWatcher.doUnref, .{ .name = "StatWatcherPrototype__doUnref" }); + @export(StatWatcher.finalize, .{ .name = "StatWatcherClass__finalize" }); + @export(StatWatcher.hasPendingActivity, .{ .name = "StatWatcher__hasPendingActivity" }); + } + } +}; pub const JSStats = struct { const Stats = Classes.Stats; const GetterType = fn (*Stats, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; @@ -6932,6 +7026,7 @@ comptime { _ = JSSHA512; _ = JSSHA512_256; _ = JSServerWebSocket; + _ = JSStatWatcher; _ = JSStats; _ = JSSubprocess; _ = JSTCPSocket; diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig index 20f36a458..a86f74dd3 100644 --- a/src/bun.js/bindings/generated_classes_list.zig +++ b/src/bun.js/bindings/generated_classes_list.zig @@ -47,6 +47,7 @@ pub const Classes = struct { pub const BuildMessage = JSC.BuildMessage; pub const ResolveMessage = JSC.ResolveMessage; pub const FSWatcher = JSC.Node.FSWatcher; + pub const StatWatcher = JSC.Node.StatWatcher; pub const HTTPServer = JSC.API.HTTPServer; pub const HTTPSServer = JSC.API.HTTPSServer; pub const DebugHTTPServer = JSC.API.DebugHTTPServer; diff --git a/src/bun.js/node/node.classes.ts b/src/bun.js/node/node.classes.ts index 695a58d5e..46c25ad06 100644 --- a/src/bun.js/node/node.classes.ts +++ b/src/bun.js/node/node.classes.ts @@ -31,6 +31,31 @@ export default [ values: ["listener"], }), define({ + name: "StatWatcher", + construct: false, + noConstructor: true, + finalize: true, + configurable: false, + hasPendingActivity: true, + klass: {}, + JSType: "0b11101110", + proto: { + ref: { + fn: "doRef", + length: 0, + }, + unref: { + fn: "doUnref", + length: 0, + }, + close: { + fn: "doClose", + length: 0, + }, + }, + values: ["listener"], + }), + define({ name: "Timeout", construct: false, noConstructor: true, @@ -471,15 +496,13 @@ export default [ symlinkSync: { fn: "symlinkSync", length: 3 }, truncate: { fn: "truncate", length: 3 }, truncateSync: { fn: "truncateSync", length: 2 }, - // TODO: - // unwatchFile: { fn: "unwatchFile", length: 2 }, + unwatchFile: { fn: "unwatchFile", length: 2 }, unlink: { fn: "unlink", length: 2 }, unlinkSync: { fn: "unlinkSync", length: 1 }, utimes: { fn: "utimes", length: 4 }, utimesSync: { fn: "utimesSync", length: 3 }, watch: { fn: "watch", length: 3 }, - // TODO: - // watchFile: { fn: "watchFile", length: 3 }, + watchFile: { fn: "watchFile", length: 3 }, writeFile: { fn: "writeFile", length: 4 }, writeFileSync: { fn: "writeFileSync", length: 3 }, write: { fn: "write", length: 6 }, diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 5407c2d5c..4f9e2bf68 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -3177,7 +3177,7 @@ pub const Arguments = struct { pub const UnwatchFile = void; pub const Watch = JSC.Node.FSWatcher.Arguments; - pub const WatchFile = void; + pub const WatchFile = JSC.Node.StatWatcher.Arguments; pub const Fsync = struct { fd: FileDescriptor, @@ -3362,7 +3362,7 @@ const Return = struct { pub const Unlink = void; pub const UnwatchFile = void; pub const Watch = JSC.JSValue; - pub const WatchFile = void; + pub const WatchFile = JSC.JSValue; pub const Utimes = void; pub const Chown = void; @@ -5245,6 +5245,25 @@ pub const NodeFS = struct { return Maybe(Return.Unlink).todo; } + pub fn watchFile(_: *NodeFS, args: Arguments.WatchFile, comptime flavor: Flavor) Maybe(Return.WatchFile) { + std.debug.assert(flavor == .sync); + + if (comptime Environment.isWindows) { + args.global_this.throwTODO("watch is not supported on Windows yet"); + return Maybe(Return.Watch){ .result = JSC.JSValue.undefined }; + } + + const watcher = args.createStatWatcher() catch |err| { + var buf = std.fmt.allocPrint(bun.default_allocator, "{s} watching {}", .{ @errorName(err), strings.QuotedFormatter{ .text = args.path.slice() } }) catch unreachable; + defer bun.default_allocator.free(buf); + args.global_this.throwValue((JSC.SystemError{ + .message = bun.String.init(buf), + .path = bun.String.init(args.path.slice()), + }).toErrorInstance(args.global_this)); + return Maybe(Return.Watch){ .result = JSC.JSValue.undefined }; + }; + return Maybe(Return.Watch){ .result = watcher }; + } pub fn unwatchFile(_: *NodeFS, _: Arguments.UnwatchFile, comptime _: Flavor) Maybe(Return.UnwatchFile) { return Maybe(Return.UnwatchFile).todo; } diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 16128be44..b3866b557 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -299,6 +299,8 @@ pub const NodeJSFS = struct { } pub const watch = callSync(.watch); + pub const watchFile = callSync(.watchFile); + pub const unwatchFile = callSync(.unwatchFile); // Not implemented yet: const notimpl = fdatasync; diff --git a/src/bun.js/node/node_fs_stat_watcher.zig b/src/bun.js/node/node_fs_stat_watcher.zig new file mode 100644 index 000000000..c2690c200 --- /dev/null +++ b/src/bun.js/node/node_fs_stat_watcher.zig @@ -0,0 +1,503 @@ +const std = @import("std"); +const JSC = @import("root").bun.JSC; +const bun = @import("root").bun; +const Fs = @import("../../fs.zig"); +const Path = @import("../../resolver/resolve_path.zig"); +const Encoder = JSC.WebCore.Encoder; +const Mutex = @import("../../lock.zig").Lock; +const uws = @import("../../deps/uws.zig"); + +const PathWatcher = @import("./path_watcher.zig"); + +const VirtualMachine = JSC.VirtualMachine; +const EventLoop = JSC.EventLoop; +const PathLike = JSC.Node.PathLike; +const ArgumentsSlice = JSC.Node.ArgumentsSlice; +const Output = bun.Output; +const string = bun.string; +const StoredFileDescriptorType = bun.StoredFileDescriptorType; +const Environment = bun.Environment; + +const StatsSmall = bun.JSC.Node.StatsSmall; +const StatsBig = bun.JSC.Node.StatsBig; + +const log = bun.Output.scoped(.StatWatcher, false); + +fn statToJSStats(globalThis: *JSC.JSGlobalObject, stats: bun.Stat, bigint: bool) JSC.JSValue { + if (bigint) { + return StatsBig.initWithAllocator(globalThis.allocator(), stats).toJS(globalThis); + } else { + return StatsSmall.initWithAllocator(globalThis.allocator(), stats).toJS(globalThis); + } +} + +/// This is a singleton struct that contains the timer used to schedule restat calls. +pub const StatWatcherScheduler = struct { + timer: ?*uws.Timer = null, + + head: std.atomic.Atomic(?*StatWatcher) = .{ .value = null }, + is_running: std.atomic.Atomic(bool) = .{ .value = false }, + + task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, + + pub fn init(allocator: std.mem.Allocator, _: *bun.JSC.VirtualMachine) *StatWatcherScheduler { + var this = allocator.create(StatWatcherScheduler) catch @panic("out of memory"); + this.* = .{}; + return this; + } + + pub fn append(this: *StatWatcherScheduler, watcher: *StatWatcher) void { + log("append new watcher {s}", .{watcher.path}); + std.debug.assert(watcher.closed == false); + std.debug.assert(watcher.next == null); + + if (this.head.swap(watcher, .Monotonic)) |head| { + watcher.next = head; + if (!this.is_running.load(.Monotonic)) { + this.timer.?.set(this, timerCallback, 1, 0); + } + } else { + if (!this.is_running.load(.Monotonic)) { + watcher.last_check = std.time.Instant.now() catch unreachable; + + const vm = watcher.globalThis.bunVM(); + this.timer = uws.Timer.create( + vm.event_loop_handle orelse @panic("UWS Loop was not initialized yet."), + this, + ); + + this.timer.?.set(this, timerCallback, watcher.interval, 0); + log("I will wait {d} milli initially", .{watcher.interval}); + } + } + } + + pub fn timerCallback(timer: *uws.Timer) callconv(.C) void { + var this = timer.ext(StatWatcherScheduler).?; + this.is_running.store(true, .Monotonic); + JSC.WorkPool.schedule(&this.task); + } + + pub fn workPoolCallback(task: *JSC.WorkPoolTask) void { + var this: *StatWatcherScheduler = @fieldParentPtr(StatWatcherScheduler, "task", task); + // Instant.now will not fail on our target platforms. + const now = std.time.Instant.now() catch unreachable; + + var head: *StatWatcher = this.head.swap(null, .Monotonic).?; + + var prev = head; + while (prev.closed) { + var c = prev; + defer { + c.used_by_scheduler_thread = false; + } + + log("[1] removing closed watcher for '{s}'", .{prev.path}); + if (prev.next) |next| { + prev = next; + } else { + if (this.head.load(.Monotonic) == null) { + this.timer.?.deinit(); + this.timer = null; + // The scheduler is not deinit here, but it will get reused. + } + return; + } + } + + if (now.since(prev.last_check) > (@as(u64, @intCast(prev.interval)) * 1_000_000 -| 500)) { + prev.last_check = now; + prev.restat(); + } + var min_interval = prev.interval; + + var curr: ?*StatWatcher = prev.next; + while (curr) |c| : (curr = c.next) { + if (c.closed) { + log("[2] removing closed watcher for '{s}'", .{c.path}); + prev.next = c.next; + curr = c.next; + c.used_by_scheduler_thread = false; + continue; + } + if (now.since(c.last_check) > (@as(u64, @intCast(c.interval)) * 1_000_000 -| 500)) { + c.last_check = now; + c.restat(); + } + min_interval = @min(min_interval, c.interval); + prev = c; + curr = c.next; + } + + prev.next = this.head.swap(head, .Monotonic); + + log("I will wait {d} milli", .{min_interval}); + + this.timer.?.set(this, timerCallback, min_interval, 0); + } +}; + +pub const StatWatcher = struct { + next: ?*StatWatcher = null, + + ctx: *VirtualMachine, + + /// Closed is set to true to tell the scheduler to remove from list and mark `used_by_scheduler_thread` as false. + closed: bool, + /// When this is marked `false` this StatWatcher can get freed + used_by_scheduler_thread: bool, + + path: [:0]u8, + persistent: bool, + bigint: bool, + interval: i32, + last_check: std.time.Instant, + + globalThis: *JSC.JSGlobalObject, + js_this: JSC.JSValue, + + poll_ref: JSC.PollRef = .{}, + + last_stat: bun.Stat, + last_jsvalue: JSC.Strong, + + pub usingnamespace JSC.Codegen.JSStatWatcher; + + pub fn eventLoop(this: StatWatcher) *EventLoop { + return this.ctx.eventLoop(); + } + + pub fn enqueueTaskConcurrent(this: StatWatcher, task: *JSC.ConcurrentTask) void { + this.eventLoop().enqueueTaskConcurrent(task); + } + + pub fn deinit(this: *StatWatcher) void { + log("deinit\n", .{}); + std.debug.assert(!this.hasPendingActivity()); + + if (this.persistent) { + this.persistent = false; + this.poll_ref.unref(this.ctx); + } + this.closed = true; + this.last_jsvalue.clear(); + + bun.default_allocator.free(this.path); + bun.default_allocator.destroy(this); + } + + pub const Arguments = struct { + path: PathLike, + listener: JSC.JSValue, + + persistent: bool, + bigint: bool, + interval: i32, + + global_this: JSC.C.JSContextRef, + + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Arguments { + const vm = ctx.vm(); + const path = PathLike.fromJS(ctx, arguments, exception) orelse { + if (exception.* == null) { + JSC.throwInvalidArguments( + "filename must be a string or TypedArray", + .{}, + ctx, + exception, + ); + } + return null; + }; + + if (exception.* != null) return null; + + var listener: JSC.JSValue = .zero; + var persistent: bool = true; + var bigint: bool = false; + var interval: i32 = 5007; + + if (arguments.nextEat()) |options_or_callable| { + // options + if (options_or_callable.isObject()) { + if (options_or_callable.get(ctx, "persistent")) |persistent_| { + if (!persistent_.isBoolean()) { + JSC.throwInvalidArguments( + "persistent must be a boolean.", + .{}, + ctx, + exception, + ); + return null; + } + persistent = persistent_.toBoolean(); + } + + if (options_or_callable.get(ctx, "bigint")) |bigint_| { + if (!bigint_.isBoolean()) { + JSC.throwInvalidArguments( + "bigint must be a boolean.", + .{}, + ctx, + exception, + ); + return null; + } + bigint = bigint_.toBoolean(); + } + + if (options_or_callable.get(ctx, "interval")) |interval_| { + if (!interval_.isNumber()) { + JSC.throwInvalidArguments( + "bigint must be a boolean.", + .{}, + ctx, + exception, + ); + return null; + } + interval = interval_.toInt32(); //* + } + } + } + + if (arguments.nextEat()) |listener_| { + if (listener_.isCallable(vm)) { + listener = listener_.withAsyncContextIfNeeded(ctx); + } + } + + if (listener == .zero) { + exception.* = JSC.toInvalidArguments("Expected \"listener\" callback", .{}, ctx).asObjectRef(); + return null; + } + + return Arguments{ + .path = path, + .listener = listener, + .persistent = persistent, + .bigint = bigint, + .interval = interval, + .global_this = ctx, + }; + } + + pub fn createStatWatcher(this: Arguments) !JSC.JSValue { + const obj = try StatWatcher.init(this); + if (obj.js_this != .zero) { + return obj.js_this; + } + return JSC.JSValue.jsUndefined(); + } + }; + + pub fn doRef(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + if (!this.closed and !this.persistent) { + this.persistent = true; + this.poll_ref.ref(this.ctx); + } + return JSC.JSValue.jsUndefined(); + } + + pub fn doUnref(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + if (this.persistent) { + this.persistent = false; + this.poll_ref.unref(this.ctx); + } + return JSC.JSValue.jsUndefined(); + } + + pub fn hasPendingActivity(this: *StatWatcher) callconv(.C) bool { + return this.used_by_scheduler_thread; + } + + /// Stops file watching but does not free the instance. + pub fn close( + this: *StatWatcher, + ) void { + if (this.persistent) { + this.persistent = false; + this.poll_ref.unref(this.ctx); + } + this.closed = true; + this.last_jsvalue.clear(); + } + + pub fn doClose(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + this.close(); + return JSC.JSValue.jsUndefined(); + } + + /// If the scheduler is not using this, free instantly, otherwise mark for being freed. + pub fn finalize(this: *StatWatcher) callconv(.C) void { + log("Finalize\n", .{}); + this.deinit(); + } + + pub const InitialStatTask = struct { + watcher: *StatWatcher, + task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, + + pub fn createAndSchedule( + watcher: *StatWatcher, + ) void { + var task = bun.default_allocator.create(InitialStatTask) catch @panic("out of memory"); + task.* = .{ .watcher = watcher }; + JSC.WorkPool.schedule(&task.task); + } + + fn workPoolCallback(task: *JSC.WorkPoolTask) void { + var initial_stat_task: *InitialStatTask = @fieldParentPtr(InitialStatTask, "task", task); + defer bun.default_allocator.destroy(initial_stat_task); + const this = initial_stat_task.watcher; + + if (this.closed) { + this.used_by_scheduler_thread = false; + return; + } + + const stat = bun.sys.stat(this.path); + switch (stat) { + .result => |res| { + // we store the stat, but do not call the callback + this.last_stat = res; + this.enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, initialStatSuccessOnMainThread)); + }, + .err => { + // on enoent, eperm, we call cb with two zeroed stat objects + // and store previous stat as a zeroed stat object, and then call the callback. + this.last_stat = std.mem.zeroes(bun.Stat); + this.enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, initialStatErrorOnMainThread)); + }, + } + } + }; + + pub fn initialStatSuccessOnMainThread(this: *StatWatcher) void { + if (this.closed) { + this.used_by_scheduler_thread = false; + return; + } + + const jsvalue = statToJSStats(this.globalThis, this.last_stat, this.bigint); + this.last_jsvalue = JSC.Strong.create(jsvalue, this.globalThis); + + const vm = this.globalThis.bunVM(); + vm.rareData().nodeFSStatWatcherScheduler(vm).append(this); + } + + pub fn initialStatErrorOnMainThread(this: *StatWatcher) void { + if (this.closed) { + this.used_by_scheduler_thread = false; + return; + } + + const jsvalue = statToJSStats(this.globalThis, this.last_stat, this.bigint); + this.last_jsvalue = JSC.Strong.create(jsvalue, this.globalThis); + + const result = StatWatcher.listenerGetCached(this.js_this).?.call( + this.globalThis, + &[2]JSC.JSValue{ + jsvalue, + jsvalue, + }, + ); + + const vm = this.globalThis.bunVM(); + if (result.isAnyError()) { + vm.onUnhandledError(this.globalThis, result); + } + + vm.rareData().nodeFSStatWatcherScheduler(vm).append(this); + } + + /// Called from any thread + pub fn restat(this: *StatWatcher) void { + log("recalling stat", .{}); + const stat = bun.sys.stat(this.path); + const res = switch (stat) { + .result => |res| res, + .err => std.mem.zeroes(bun.Stat), + }; + + if (std.mem.eql(u8, std.mem.asBytes(&res), std.mem.asBytes(&this.last_stat))) return; + + this.last_stat = res; + this.enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, swapAndCallListenerOnMainThread)); + } + + /// After a restat found the file changed, this calls the listener function. + pub fn swapAndCallListenerOnMainThread(this: *StatWatcher) void { + const prev_jsvalue = this.last_jsvalue.swap(); + const current_jsvalue = statToJSStats(this.globalThis, this.last_stat, this.bigint); + this.last_jsvalue.set(this.globalThis, current_jsvalue); + + const result = StatWatcher.listenerGetCached(this.js_this).?.call( + this.globalThis, + &[2]JSC.JSValue{ + current_jsvalue, + prev_jsvalue, + }, + ); + if (result.isAnyError()) { + const vm = this.globalThis.bunVM(); + vm.onUnhandledError(this.globalThis, result); + } + } + + pub fn onTimerInterval(timer: *uws.Timer) callconv(.C) void { + timer.ext(StatWatcher).?.restat(); + } + + pub fn init(args: Arguments) !*StatWatcher { + log("init", .{}); + + var buf: [bun.MAX_PATH_BYTES + 1]u8 = undefined; + var slice = args.path.slice(); + if (bun.strings.startsWith(slice, "file://")) { + slice = slice[6..]; + } + var parts = [_]string{slice}; + var file_path = Path.joinAbsStringBuf( + Fs.FileSystem.instance.top_level_dir, + &buf, + &parts, + .auto, + ); + + var alloc_file_path = try bun.default_allocator.allocSentinel(u8, file_path.len, 0); + errdefer bun.default_allocator.free(alloc_file_path); + @memcpy(alloc_file_path, file_path); + + var this = try bun.default_allocator.create(StatWatcher); + const vm = args.global_this.bunVM(); + this.* = .{ + .ctx = vm, + .persistent = args.persistent, + .bigint = args.bigint, + .interval = @max(5, args.interval), + .globalThis = args.global_this, + .js_this = .zero, + .closed = false, + .path = alloc_file_path, + .used_by_scheduler_thread = true, + // Instant.now will not fail on our target platforms. + .last_check = std.time.Instant.now() catch unreachable, + // InitStatTask is responsible for setting this + .last_stat = undefined, + .last_jsvalue = JSC.Strong.init(), + }; + errdefer this.deinit(); + + if (this.persistent) { + this.poll_ref.ref(this.ctx); + } + + const js_this = StatWatcher.toJS(this, this.globalThis); + this.js_this = js_this; + StatWatcher.listenerSetCached(js_this, this.globalThis, args.listener); + InitialStatTask.createAndSchedule(this); + + return this; + } +}; diff --git a/src/bun.js/rare_data.zig b/src/bun.js/rare_data.zig index 78354676f..706826033 100644 --- a/src/bun.js/rare_data.zig +++ b/src/bun.js/rare_data.zig @@ -10,6 +10,7 @@ const BoringSSL = @import("root").bun.BoringSSL; const bun = @import("root").bun; const WebSocketClientMask = @import("../http/websocket_http_client.zig").Mask; const UUID = @import("./uuid.zig"); +const StatWatcherScheduler = @import("./node/node_fs_stat_watcher.zig").StatWatcherScheduler; boring_ssl_engine: ?*BoringSSL.ENGINE = null, editor_context: EditorContext = EditorContext{}, @@ -32,6 +33,8 @@ global_dns_data: ?*JSC.DNS.GlobalData = null, mime_types: ?bun.HTTP.MimeType.Map = null, +node_fs_stat_watcher_scheduler: ?*StatWatcherScheduler = null, + pub fn hotMap(this: *RareData, allocator: std.mem.Allocator) *HotMap { if (this.hot_map == null) { this.hot_map = HotMap.init(allocator); @@ -314,3 +317,10 @@ pub fn globalDNSResolver(rare: *RareData, vm: *JSC.VirtualMachine) *JSC.DNS.DNSR return &rare.global_dns_data.?.resolver; } + +pub fn nodeFSStatWatcherScheduler(rare: *RareData, vm: *JSC.VirtualMachine) *StatWatcherScheduler { + return rare.node_fs_stat_watcher_scheduler orelse { + rare.node_fs_stat_watcher_scheduler = StatWatcherScheduler.init(vm.allocator, vm); + return rare.node_fs_stat_watcher_scheduler.?; + }; +} diff --git a/src/js/node/fs.js b/src/js/node/fs.js index ab6816904..2c6b8cfbe 100644 --- a/src/js/node/fs.js +++ b/src/js/node/fs.js @@ -7,7 +7,6 @@ const Stream = require("node:stream"); const { isArrayBufferView } = require("node:util/types"); const constants = $processBindingConstants.fs; -const { COPYFILE_EXCL } = constants; var fs = Bun.fs(); class FSWatcher extends EventEmitter { @@ -65,6 +64,45 @@ class FSWatcher extends EventEmitter { unref() { this.#watcher?.unref(); } + + // https://github.com/nodejs/node/blob/9f51c55a47702dc6a0ca3569853dd7ba022bf7bb/lib/internal/fs/watchers.js#L259-L263 + start() {} +} + +/** Implemented in `node_fs_stat_watcher.zig` */ +// interface StatWatcherHandle { +// ref(); +// unref(); +// close(); +// } + +class StatWatcher extends EventEmitter { + // _handle: StatWatcherHandle; + + constructor(path, options) { + super(); + this._handle = fs.watchFile(path, options, this.#onChange.bind(this)); + } + + #onChange(curr, prev) { + this.emit("change", curr, prev); + } + + // https://github.com/nodejs/node/blob/9f51c55a47702dc6a0ca3569853dd7ba022bf7bb/lib/internal/fs/watchers.js#L259-L263 + start() {} + + stop() { + this._handle?.close(); + this._handle = null; + } + + ref() { + this._handle?.ref(); + } + + unref() { + this._handle?.unref(); + } } var access = function access(...args) { @@ -316,6 +354,54 @@ var access = function access(...args) { return new FSWatcher(path, options, listener); }; +// TODO: move this entire thing into native code. +// the reason it's not done right now is because there isnt a great way to have multiple +// listeners per StatWatcher with the current implementation in native code. the downside +// of this means we need to do path validation in the js side of things +const statWatchers = new Map(); +let _pathModule; +function getValidatedPath(p) { + if (p instanceof URL) return Bun.fileURLToPath(p); + if (typeof p !== "string") throw new TypeError("Path must be a string or URL."); + return (_pathModule ??= require("node:path")).resolve(p); +} +function watchFile(filename, options, listener) { + filename = getValidatedPath(filename); + + if (typeof options === "function") { + listener = options; + options = {}; + } + + if (typeof listener !== "function") { + throw new TypeError("listener must be a function"); + } + + var stat = statWatchers.get(filename); + if (!stat) { + stat = new StatWatcher(filename, options); + statWatchers.set(filename, stat); + } + stat.addListener("change", listener); + return stat; +} +function unwatchFile(filename, listener) { + filename = getValidatedPath(filename); + + var stat = statWatchers.get(filename); + if (!stat) return; + if (listener) { + stat.removeListener("change", listener); + if (stat.listenerCount("change") !== 0) { + return; + } + } else { + stat.removeAllListeners("change"); + } + stat.stop(); + statWatchers.delete(filename); +} + function callbackify(fsFunction, args) { try { const result = fsFunction.apply(fs, args.slice(0, args.length - 1)); @@ -1200,9 +1286,11 @@ export default { truncateSync, unlink, unlinkSync, + unwatchFile, utimes, utimesSync, watch, + watchFile, write, writeFile, writeFileSync, diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h index edcbd8baf..65da73e66 100644 --- a/src/js/out/InternalModuleRegistryConstants.h +++ b/src/js/out/InternalModuleRegistryConstants.h @@ -82,7 +82,7 @@ static constexpr ASCIILiteral NodeEventsCode = "(function (){\"use strict\";// s // // -static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar 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}, 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 = void 0;\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(\"node:util/types\"), constants = @processBindingConstants.fs;\nvar 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}\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}, 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: void 0,\n fd: null,\n flags: \"r\",\n encoding: void 0,\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 === void 0)\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 !== void 0)\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 !== void 0) {\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 !== void 0 && 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 !== void 0 && 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 !== void 0 \? 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 === void 0) {\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: void 0,\n pos: void 0,\n encoding: void 0,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass;\nWriteStream = function(InternalWriteStream) {\n WriteStreamClass = InternalWriteStream, Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {\n value: \"WritesStream\",\n enumerable: !1\n });\n function WriteStream3(path, options) {\n return new InternalWriteStream(path, options);\n }\n return WriteStream3.prototype = InternalWriteStream.prototype, Object.defineProperty(WriteStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalWriteStream;\n }\n });\n}(class WriteStream2 extends Stream.NativeWritable {\n constructor(path, options = defaultWriteStreamOptions) {\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 === void 0 || 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 super(tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n });\n if (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.start !== void 0)\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 }\n get autoClose() {\n return this._writableState.autoDestroy;\n }\n set autoClose(val) {\n this._writableState.autoDestroy = val;\n }\n destroySoon = this.end;\n open() {\n }\n path;\n fd;\n flags;\n mode;\n #fs;\n bytesWritten = 0;\n pos;\n [writeStreamPathFastPathSymbol];\n [writeStreamSymbol] = !0;\n start;\n [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, this.#errorOrDestroy(err), readStream.emit(\"error\", err);\n });\n }\n isBunFastPathEnabled() {\n return this[writeStreamPathFastPathSymbol];\n }\n disableBunFastPath() {\n this[writeStreamPathFastPathSymbol] = !1;\n }\n #handleWrite(er, bytes) {\n if (er)\n return this.#errorOrDestroy(er);\n this.bytesWritten += bytes;\n }\n #internalClose(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 }\n _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => this.#internalClose(err, cb));\n return;\n }\n this.#internalClose(err, cb);\n }\n [kIoDone] = !1;\n close(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 }\n write(chunk, encoding = this._writableState.defaultEncoding, cb) {\n if (this[writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = Buffer.from(chunk, encoding);\n var native = this.pos === void 0;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, this.#handleWrite(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 super.write(chunk, encoding, callback, native);\n }\n end(chunk, encoding, cb) {\n var native = this.pos === void 0;\n return super.end(chunk, encoding, cb, native);\n }\n _write = void 0;\n _writev = void 0;\n get pending() {\n return this.fd === null;\n }\n _destroy(err, cb) {\n this.close(err, cb);\n }\n #errorOrDestroy(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 }\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 utimes,\n utimesSync,\n watch,\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 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}, 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 = void 0;\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(\"node:util/types\"), 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: void 0,\n fd: null,\n flags: \"r\",\n encoding: void 0,\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 === void 0)\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 !== void 0)\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 !== void 0) {\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 !== void 0 && 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 !== void 0 && 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 !== void 0 \? 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 === void 0) {\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: void 0,\n pos: void 0,\n encoding: void 0,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass;\nWriteStream = function(InternalWriteStream) {\n WriteStreamClass = InternalWriteStream, Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {\n value: \"WritesStream\",\n enumerable: !1\n });\n function WriteStream3(path, options) {\n return new InternalWriteStream(path, options);\n }\n return WriteStream3.prototype = InternalWriteStream.prototype, Object.defineProperty(WriteStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalWriteStream;\n }\n });\n}(class WriteStream2 extends Stream.NativeWritable {\n constructor(path, options = defaultWriteStreamOptions) {\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 === void 0 || 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 super(tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n });\n if (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.start !== void 0)\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 }\n get autoClose() {\n return this._writableState.autoDestroy;\n }\n set autoClose(val) {\n this._writableState.autoDestroy = val;\n }\n destroySoon = this.end;\n open() {\n }\n path;\n fd;\n flags;\n mode;\n #fs;\n bytesWritten = 0;\n pos;\n [writeStreamPathFastPathSymbol];\n [writeStreamSymbol] = !0;\n start;\n [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, this.#errorOrDestroy(err), readStream.emit(\"error\", err);\n });\n }\n isBunFastPathEnabled() {\n return this[writeStreamPathFastPathSymbol];\n }\n disableBunFastPath() {\n this[writeStreamPathFastPathSymbol] = !1;\n }\n #handleWrite(er, bytes) {\n if (er)\n return this.#errorOrDestroy(er);\n this.bytesWritten += bytes;\n }\n #internalClose(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 }\n _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => this.#internalClose(err, cb));\n return;\n }\n this.#internalClose(err, cb);\n }\n [kIoDone] = !1;\n close(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 }\n write(chunk, encoding = this._writableState.defaultEncoding, cb) {\n if (this[writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = Buffer.from(chunk, encoding);\n var native = this.pos === void 0;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, this.#handleWrite(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 super.write(chunk, encoding, callback, native);\n }\n end(chunk, encoding, cb) {\n var native = this.pos === void 0;\n return super.end(chunk, encoding, cb, native);\n }\n _write = void 0;\n _writev = void 0;\n get pending() {\n return this.fd === null;\n }\n _destroy(err, cb) {\n this.close(err, cb);\n }\n #errorOrDestroy(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 }\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; // // @@ -323,7 +323,7 @@ static constexpr ASCIILiteral NodeEventsCode = "(function (){\"use strict\";// s // // -static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar 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}, 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 = void 0;\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(\"node:util/types\"), constants = @processBindingConstants.fs;\nvar 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}\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}, 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: void 0,\n fd: null,\n flags: \"r\",\n encoding: void 0,\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 === void 0)\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 !== void 0)\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 !== void 0) {\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 !== void 0 && 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 !== void 0 && 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 !== void 0 \? 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 === void 0) {\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: void 0,\n pos: void 0,\n encoding: void 0,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass;\nWriteStream = function(InternalWriteStream) {\n WriteStreamClass = InternalWriteStream, Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {\n value: \"WritesStream\",\n enumerable: !1\n });\n function WriteStream3(path, options) {\n return new InternalWriteStream(path, options);\n }\n return WriteStream3.prototype = InternalWriteStream.prototype, Object.defineProperty(WriteStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalWriteStream;\n }\n });\n}(class WriteStream2 extends Stream.NativeWritable {\n constructor(path, options = defaultWriteStreamOptions) {\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 === void 0 || 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 super(tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n });\n if (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.start !== void 0)\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 }\n get autoClose() {\n return this._writableState.autoDestroy;\n }\n set autoClose(val) {\n this._writableState.autoDestroy = val;\n }\n destroySoon = this.end;\n open() {\n }\n path;\n fd;\n flags;\n mode;\n #fs;\n bytesWritten = 0;\n pos;\n [writeStreamPathFastPathSymbol];\n [writeStreamSymbol] = !0;\n start;\n [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, this.#errorOrDestroy(err), readStream.emit(\"error\", err);\n });\n }\n isBunFastPathEnabled() {\n return this[writeStreamPathFastPathSymbol];\n }\n disableBunFastPath() {\n this[writeStreamPathFastPathSymbol] = !1;\n }\n #handleWrite(er, bytes) {\n if (er)\n return this.#errorOrDestroy(er);\n this.bytesWritten += bytes;\n }\n #internalClose(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 }\n _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => this.#internalClose(err, cb));\n return;\n }\n this.#internalClose(err, cb);\n }\n [kIoDone] = !1;\n close(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 }\n write(chunk, encoding = this._writableState.defaultEncoding, cb) {\n if (this[writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = Buffer.from(chunk, encoding);\n var native = this.pos === void 0;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, this.#handleWrite(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 super.write(chunk, encoding, callback, native);\n }\n end(chunk, encoding, cb) {\n var native = this.pos === void 0;\n return super.end(chunk, encoding, cb, native);\n }\n _write = void 0;\n _writev = void 0;\n get pending() {\n return this.fd === null;\n }\n _destroy(err, cb) {\n this.close(err, cb);\n }\n #errorOrDestroy(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 }\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 utimes,\n utimesSync,\n watch,\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 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}, 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 = void 0;\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(\"node:util/types\"), 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: void 0,\n fd: null,\n flags: \"r\",\n encoding: void 0,\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 === void 0)\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 !== void 0)\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 !== void 0) {\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 !== void 0 && 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 !== void 0 && 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 !== void 0 \? 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 === void 0) {\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: void 0,\n pos: void 0,\n encoding: void 0,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass;\nWriteStream = function(InternalWriteStream) {\n WriteStreamClass = InternalWriteStream, Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {\n value: \"WritesStream\",\n enumerable: !1\n });\n function WriteStream3(path, options) {\n return new InternalWriteStream(path, options);\n }\n return WriteStream3.prototype = InternalWriteStream.prototype, Object.defineProperty(WriteStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalWriteStream;\n }\n });\n}(class WriteStream2 extends Stream.NativeWritable {\n constructor(path, options = defaultWriteStreamOptions) {\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 === void 0 || 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 super(tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n });\n if (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.start !== void 0)\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 }\n get autoClose() {\n return this._writableState.autoDestroy;\n }\n set autoClose(val) {\n this._writableState.autoDestroy = val;\n }\n destroySoon = this.end;\n open() {\n }\n path;\n fd;\n flags;\n mode;\n #fs;\n bytesWritten = 0;\n pos;\n [writeStreamPathFastPathSymbol];\n [writeStreamSymbol] = !0;\n start;\n [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, this.#errorOrDestroy(err), readStream.emit(\"error\", err);\n });\n }\n isBunFastPathEnabled() {\n return this[writeStreamPathFastPathSymbol];\n }\n disableBunFastPath() {\n this[writeStreamPathFastPathSymbol] = !1;\n }\n #handleWrite(er, bytes) {\n if (er)\n return this.#errorOrDestroy(er);\n this.bytesWritten += bytes;\n }\n #internalClose(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 }\n _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => this.#internalClose(err, cb));\n return;\n }\n this.#internalClose(err, cb);\n }\n [kIoDone] = !1;\n close(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 }\n write(chunk, encoding = this._writableState.defaultEncoding, cb) {\n if (this[writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = Buffer.from(chunk, encoding);\n var native = this.pos === void 0;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, this.#handleWrite(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 super.write(chunk, encoding, callback, native);\n }\n end(chunk, encoding, cb) {\n var native = this.pos === void 0;\n return super.end(chunk, encoding, cb, native);\n }\n _write = void 0;\n _writev = void 0;\n get pending() {\n return this.fd === null;\n }\n _destroy(err, cb) {\n this.close(err, cb);\n }\n #errorOrDestroy(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 }\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; // // @@ -565,7 +565,7 @@ static constexpr ASCIILiteral NodeEventsCode = "(function (){\"use strict\";// s // // -static constexpr ASCIILiteral NodeFSCode = "(function (){\"use strict\";// src/js/out/tmp/node/fs.ts\nvar 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}, 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 = void 0;\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(\"node:util/types\"), constants = @processBindingConstants.fs;\nvar 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}\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}, 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: void 0,\n fd: null,\n flags: \"r\",\n encoding: void 0,\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 === void 0)\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 !== void 0)\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 !== void 0) {\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 !== void 0 && 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 !== void 0 && 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 !== void 0 \? 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 === void 0) {\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: void 0,\n pos: void 0,\n encoding: void 0,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass;\nWriteStream = function(InternalWriteStream) {\n WriteStreamClass = InternalWriteStream, Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {\n value: \"WritesStream\",\n enumerable: !1\n });\n function WriteStream3(path, options) {\n return new InternalWriteStream(path, options);\n }\n return WriteStream3.prototype = InternalWriteStream.prototype, Object.defineProperty(WriteStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalWriteStream;\n }\n });\n}(class WriteStream2 extends Stream.NativeWritable {\n constructor(path, options = defaultWriteStreamOptions) {\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 === void 0 || 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 super(tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n });\n if (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.start !== void 0)\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 }\n get autoClose() {\n return this._writableState.autoDestroy;\n }\n set autoClose(val) {\n this._writableState.autoDestroy = val;\n }\n destroySoon = this.end;\n open() {\n }\n path;\n fd;\n flags;\n mode;\n #fs;\n bytesWritten = 0;\n pos;\n [writeStreamPathFastPathSymbol];\n [writeStreamSymbol] = !0;\n start;\n [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, this.#errorOrDestroy(err), readStream.emit(\"error\", err);\n });\n }\n isBunFastPathEnabled() {\n return this[writeStreamPathFastPathSymbol];\n }\n disableBunFastPath() {\n this[writeStreamPathFastPathSymbol] = !1;\n }\n #handleWrite(er, bytes) {\n if (er)\n return this.#errorOrDestroy(er);\n this.bytesWritten += bytes;\n }\n #internalClose(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 }\n _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => this.#internalClose(err, cb));\n return;\n }\n this.#internalClose(err, cb);\n }\n [kIoDone] = !1;\n close(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 }\n write(chunk, encoding = this._writableState.defaultEncoding, cb) {\n if (this[writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = Buffer.from(chunk, encoding);\n var native = this.pos === void 0;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, this.#handleWrite(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 super.write(chunk, encoding, callback, native);\n }\n end(chunk, encoding, cb) {\n var native = this.pos === void 0;\n return super.end(chunk, encoding, cb, native);\n }\n _write = void 0;\n _writev = void 0;\n get pending() {\n return this.fd === null;\n }\n _destroy(err, cb) {\n this.close(err, cb);\n }\n #errorOrDestroy(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 }\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 utimes,\n utimesSync,\n watch,\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 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}, 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 = void 0;\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(\"node:util/types\"), 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: void 0,\n fd: null,\n flags: \"r\",\n encoding: void 0,\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 === void 0)\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 !== void 0)\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 !== void 0) {\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 !== void 0 && 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 !== void 0 && 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 !== void 0 \? 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 === void 0) {\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: void 0,\n pos: void 0,\n encoding: void 0,\n flags: \"w\",\n mode: 438,\n fs: {\n write,\n close,\n open,\n openSync\n }\n}, WriteStreamClass;\nWriteStream = function(InternalWriteStream) {\n WriteStreamClass = InternalWriteStream, Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {\n value: \"WritesStream\",\n enumerable: !1\n });\n function WriteStream3(path, options) {\n return new InternalWriteStream(path, options);\n }\n return WriteStream3.prototype = InternalWriteStream.prototype, Object.defineProperty(WriteStream3, Symbol.hasInstance, {\n value(instance) {\n return instance instanceof InternalWriteStream;\n }\n });\n}(class WriteStream2 extends Stream.NativeWritable {\n constructor(path, options = defaultWriteStreamOptions) {\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 === void 0 || 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 super(tempThis.fd, {\n ...options,\n decodeStrings: !1,\n autoDestroy,\n emitClose,\n fd: tempThis\n });\n if (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.start !== void 0)\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 }\n get autoClose() {\n return this._writableState.autoDestroy;\n }\n set autoClose(val) {\n this._writableState.autoDestroy = val;\n }\n destroySoon = this.end;\n open() {\n }\n path;\n fd;\n flags;\n mode;\n #fs;\n bytesWritten = 0;\n pos;\n [writeStreamPathFastPathSymbol];\n [writeStreamSymbol] = !0;\n start;\n [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, this.#errorOrDestroy(err), readStream.emit(\"error\", err);\n });\n }\n isBunFastPathEnabled() {\n return this[writeStreamPathFastPathSymbol];\n }\n disableBunFastPath() {\n this[writeStreamPathFastPathSymbol] = !1;\n }\n #handleWrite(er, bytes) {\n if (er)\n return this.#errorOrDestroy(er);\n this.bytesWritten += bytes;\n }\n #internalClose(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 }\n _construct(callback) {\n if (typeof this.fd === \"number\") {\n callback();\n return;\n }\n callback(), this.emit(\"open\", this.fd), this.emit(\"ready\");\n }\n _destroy(err, cb) {\n if (this.fd === null)\n return cb(err);\n if (this[kIoDone]) {\n this.once(kIoDone, () => this.#internalClose(err, cb));\n return;\n }\n this.#internalClose(err, cb);\n }\n [kIoDone] = !1;\n close(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 }\n write(chunk, encoding = this._writableState.defaultEncoding, cb) {\n if (this[writeStreamPathFastPathSymbol] = !1, typeof chunk === \"string\")\n chunk = Buffer.from(chunk, encoding);\n var native = this.pos === void 0;\n const callback = native \? (err, bytes) => {\n if (this[kIoDone] = !1, this.#handleWrite(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 super.write(chunk, encoding, callback, native);\n }\n end(chunk, encoding, cb) {\n var native = this.pos === void 0;\n return super.end(chunk, encoding, cb, native);\n }\n _write = void 0;\n _writev = void 0;\n get pending() {\n return this.fd === null;\n }\n _destroy(err, cb) {\n this.close(err, cb);\n }\n #errorOrDestroy(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 }\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; // // diff --git a/src/jsc.zig b/src/jsc.zig index c33192f32..e5be26321 100644 --- a/src/jsc.zig +++ b/src/jsc.zig @@ -51,6 +51,7 @@ pub const Node = struct { pub usingnamespace @import("./bun.js/node/types.zig"); pub usingnamespace @import("./bun.js/node/node_fs.zig"); pub usingnamespace @import("./bun.js/node/node_fs_watcher.zig"); + pub usingnamespace @import("./bun.js/node/node_fs_stat_watcher.zig"); pub usingnamespace @import("./bun.js/node/node_fs_binding.zig"); pub usingnamespace @import("./bun.js/node/node_os.zig"); pub const fs = @import("./bun.js/node/node_fs_constant.zig"); diff --git a/test/js/node/watch/fs.watchFile.test.ts b/test/js/node/watch/fs.watchFile.test.ts new file mode 100644 index 000000000..25cd0c8c5 --- /dev/null +++ b/test/js/node/watch/fs.watchFile.test.ts @@ -0,0 +1,121 @@ +import fs, { FSWatcher } from "node:fs"; +import path from "path"; +import { tempDirWithFiles, bunRun, bunRunAsScript } from "harness"; +import { pathToFileURL } from "bun"; + +import { describe, expect, test } from "bun:test"; +// Because macOS (and possibly other operating systems) can return a watcher +// before it is actually watching, we need to repeat the operation to avoid +// a race condition. +function repeat(fn: any) { + const interval = setInterval(fn, 20); + return interval; +} +const encodingFileName = `新建文夹件.txt`; +const testDir = tempDirWithFiles("watch", { + "watch.txt": "hello", + [encodingFileName]: "hello", +}); + +describe("fs.watchFile", () => { + test("zeroed stats if does not exist", async () => { + let entries: any = []; + fs.watchFile(path.join(testDir, "does-not-exist"), (curr, prev) => { + entries.push([curr, prev]); + }); + + await Bun.sleep(35); + + fs.unwatchFile(path.join(testDir, "does-not-exist")); + + expect(entries.length).toBe(1); + expect(entries[0][0].size).toBe(0); + expect(entries[0][0].mtimeMs).toBe(0); + expect(entries[0][1].size).toBe(0); + expect(entries[0][1].mtimeMs).toBe(0); + }); + test("it watches a file", async () => { + let entries: any = []; + fs.watchFile(path.join(testDir, "watch.txt"), { interval: 50 }, (curr, prev) => { + entries.push([curr, prev]); + }); + await Bun.sleep(100); + fs.writeFileSync(path.join(testDir, "watch.txt"), "hello2"); + await Bun.sleep(100); + + fs.unwatchFile(path.join(testDir, "watch.txt")); + + expect(entries.length).toBeGreaterThan(0); + + expect(entries[0][0].size).toBe(6); + expect(entries[0][1].size).toBe(5); + expect(entries[0][0].mtimeMs).toBeGreaterThan(entries[0][1].mtimeMs); + }); + test("unicode file name", async () => { + let entries: any = []; + fs.watchFile(path.join(testDir, encodingFileName), { interval: 50 }, (curr, prev) => { + entries.push([curr, prev]); + }); + await Bun.sleep(100); + fs.writeFileSync(path.join(testDir, encodingFileName), "hello2"); + await Bun.sleep(100); + + fs.unwatchFile(path.join(testDir, encodingFileName)); + + expect(entries.length).toBeGreaterThan(0); + + expect(entries[0][0].size).toBe(6); + expect(entries[0][1].size).toBe(5); + expect(entries[0][0].mtimeMs).toBeGreaterThan(entries[0][1].mtimeMs); + }); + test("bigint stats", async () => { + let entries: any = []; + fs.watchFile(path.join(testDir, encodingFileName), { interval: 50, bigint: true }, (curr, prev) => { + entries.push([curr, prev]); + }); + await Bun.sleep(100); + fs.writeFileSync(path.join(testDir, encodingFileName), "hello2"); + await Bun.sleep(100); + + fs.unwatchFile(path.join(testDir, encodingFileName)); + + expect(entries.length).toBeGreaterThan(0); + + expect(typeof entries[0][0].mtimeMs === "bigint").toBe(true); + }); + + test("StatWatcherScheduler stress test (1000 watchers with random times)", async () => { + const EventEmitter = require("events"); + let defaultMaxListeners = EventEmitter.defaultMaxListeners; + try { + EventEmitter.defaultMaxListeners = 1000; + // This tests StatWatcher's scheduler for add/remove race conditions, + // as the actual stat()ing is done on another thread using a specialized linked list implementation + // so we're testing that here, less so that stats will properly notify js, since that code is already known to be very threadsafe. + const set = new Set<string>(); + const { promise, resolve } = Promise.withResolvers(); + for (let i = 0; i < 1000; i++) { + const file = path.join(testDir, i + ".txt"); + setTimeout(() => { + let first = true; + fs.watchFile(file, { interval: 500 }, (curr, prev) => { + set.add(file); + if (first) { + first = false; + setTimeout(() => { + fs.unwatchFile(file); + + if (set.size === 1000) resolve(); + }, Math.random() * 2000); + } + }); + }, Math.random() * 2000); + } + await promise; + + expect(set.size).toBe(1000); + } finally { + EventEmitter.defaultMaxListeners = defaultMaxListeners; + } + }, 20000); +}); |