From 27c90786ca7b824d8b033f3bcf846fab767c96c2 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Thu, 20 Feb 2025 22:15:01 -0800 Subject: [PATCH] node: implement `process.binding('fs')` (#17480) --- cmake/targets/BuildBun.cmake | 2 + src/bun.js/api/BunObject.zig | 10 +- src/bun.js/bindings/BunPlugin.cpp | 2 +- src/bun.js/bindings/BunProcess.cpp | 2 +- src/bun.js/bindings/BunString.cpp | 1 + src/bun.js/bindings/JSBuffer.cpp | 2 +- src/bun.js/bindings/ProcessBindingBuffer.cpp | 2 +- src/bun.js/bindings/ProcessBindingFs.cpp | 204 +++++++++++++++++++ src/bun.js/bindings/ProcessBindingFs.h | 37 ++++ src/bun.js/bindings/ZigGlobalObject.cpp | 29 +++ src/bun.js/bindings/ZigGlobalObject.h | 7 + src/bun.js/node/node_fs.zig | 2 +- src/bun.js/node/types.zig | 2 +- src/bun.js/webcore/blob.zig | 4 +- src/bun.js/webcore/body.zig | 2 +- src/css/css_internals.zig | 10 +- src/resolver/resolver.zig | 2 +- src/shell/shell.zig | 8 +- src/sql/postgres.zig | 12 +- test/cli/create/create-jsx.test.ts | 10 +- test/js/node/process/process.test.js | 2 +- 21 files changed, 316 insertions(+), 36 deletions(-) create mode 100644 src/bun.js/bindings/ProcessBindingFs.cpp create mode 100644 src/bun.js/bindings/ProcessBindingFs.h diff --git a/cmake/targets/BuildBun.cmake b/cmake/targets/BuildBun.cmake index 4b3a02b169..a221068103 100644 --- a/cmake/targets/BuildBun.cmake +++ b/cmake/targets/BuildBun.cmake @@ -432,6 +432,7 @@ set(BUN_OBJECT_LUT_SOURCES ${CWD}/src/bun.js/bindings/BunProcess.cpp ${CWD}/src/bun.js/bindings/ProcessBindingBuffer.cpp ${CWD}/src/bun.js/bindings/ProcessBindingConstants.cpp + ${CWD}/src/bun.js/bindings/ProcessBindingFs.cpp ${CWD}/src/bun.js/bindings/ProcessBindingNatives.cpp ${CWD}/src/bun.js/modules/NodeModuleModule.cpp ${CODEGEN_PATH}/ZigGeneratedClasses.lut.txt @@ -444,6 +445,7 @@ set(BUN_OBJECT_LUT_OUTPUTS ${CODEGEN_PATH}/BunProcess.lut.h ${CODEGEN_PATH}/ProcessBindingBuffer.lut.h ${CODEGEN_PATH}/ProcessBindingConstants.lut.h + ${CODEGEN_PATH}/ProcessBindingFs.lut.h ${CODEGEN_PATH}/ProcessBindingNatives.lut.h ${CODEGEN_PATH}/NodeModuleModule.lut.h ${CODEGEN_PATH}/ZigGeneratedClasses.lut.h diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index e84f1b1d81..2abec63b9c 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -960,10 +960,10 @@ pub fn resolve(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun } export fn Bun__resolve(global: *JSGlobalObject, specifier: JSValue, source: JSValue, is_esm: bool) JSC.JSValue { - const specifier_str = specifier.toBunString(global); + const specifier_str = specifier.toBunString2(global) catch return .zero; defer specifier_str.deref(); - const source_str = source.toBunString(global); + const source_str = source.toBunString2(global) catch return .zero; defer source_str.deref(); const value = doResolveWithArgs(global, specifier_str, source_str, is_esm, true) catch { @@ -975,10 +975,10 @@ export fn Bun__resolve(global: *JSGlobalObject, specifier: JSValue, source: JSVa } export fn Bun__resolveSync(global: *JSGlobalObject, specifier: JSValue, source: JSValue, is_esm: bool) JSC.JSValue { - const specifier_str = specifier.toBunString(global); + const specifier_str = specifier.toBunString2(global) catch return .zero; defer specifier_str.deref(); - const source_str = source.toBunString(global); + const source_str = source.toBunString2(global) catch return .zero; defer source_str.deref(); return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source_str, is_esm, true)); @@ -990,7 +990,7 @@ export fn Bun__resolveSyncWithStrings(global: *JSGlobalObject, specifier: *bun.S } export fn Bun__resolveSyncWithSource(global: *JSGlobalObject, specifier: JSValue, source: *bun.String, is_esm: bool) JSC.JSValue { - const specifier_str = specifier.toBunString(global); + const specifier_str = specifier.toBunString2(global) catch return .zero; defer specifier_str.deref(); return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source.*, is_esm, true)); } diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index 0b3d9ad2b2..0591cda623 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -916,7 +916,7 @@ JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specif if (!result.isObject()) { JSC::throwTypeError(globalObject, throwScope, "virtual module expects an object returned"_s); - return JSC::jsUndefined(); + return {}; } return result; diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index f0bd08565e..685299efee 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -2566,7 +2566,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObje if (moduleName == "contextify"_s) PROCESS_BINDING_NOT_IMPLEMENTED("contextify"); if (moduleName == "crypto"_s) PROCESS_BINDING_NOT_IMPLEMENTED("crypto"); if (moduleName == "crypto/x509"_s) return JSValue::encode(createCryptoX509Object(globalObject)); - if (moduleName == "fs"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("fs", "3546"); + if (moduleName == "fs"_s) return JSValue::encode(globalObject->processBindingFs()); if (moduleName == "fs_event_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("fs_event_wrap"); if (moduleName == "http_parser"_s) PROCESS_BINDING_NOT_IMPLEMENTED("http_parser"); if (moduleName == "icu"_s) PROCESS_BINDING_NOT_IMPLEMENTED("icu"); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index bbac2a3962..b796010360 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -151,6 +151,7 @@ extern "C" int64_t BunString__toInt32(BunString* bunString) } namespace Bun { + JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, BunString bunString) { if (bunString.tag == BunStringTag::Empty || bunString.tag == BunStringTag::Dead) { diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 67b1c92f12..971172393c 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -310,7 +310,7 @@ public: auto thisValue = callFrame.thisValue().toThis(&lexicalGlobalObject, JSC::ECMAMode::strict()); if (thisValue.isUndefinedOrNull()) { throwTypeError(&lexicalGlobalObject, throwScope, "Cannot convert undefined or null to object"_s); - return JSC::JSValue::encode(JSC::jsUndefined()); + return {}; } auto thisObject = JSC::jsDynamicCast(thisValue); diff --git a/src/bun.js/bindings/ProcessBindingBuffer.cpp b/src/bun.js/bindings/ProcessBindingBuffer.cpp index c0bb0f079c..6c3ac6b1f4 100644 --- a/src/bun.js/bindings/ProcessBindingBuffer.cpp +++ b/src/bun.js/bindings/ProcessBindingBuffer.cpp @@ -13,7 +13,7 @@ using namespace JSC; auto& vm = JSC::getVM(lexicalGlobalObject); \ auto throwScope = DECLARE_THROW_SCOPE(vm); \ auto prelude = "process.binding('buffer')."_s; \ - auto name = WTF::ASCIILiteral::fromLiteralUnsafe(#str); \ + auto name = #str##_s; \ auto finale = " is not implemented in Bun. If that breaks something, please file an issue and include a reproducible code sample."_s; \ auto message = makeString(prelude, name, finale); \ throwScope.throwException(lexicalGlobalObject, createError(lexicalGlobalObject, message)); \ diff --git a/src/bun.js/bindings/ProcessBindingFs.cpp b/src/bun.js/bindings/ProcessBindingFs.cpp new file mode 100644 index 0000000000..be0e396ff5 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingFs.cpp @@ -0,0 +1,204 @@ + +#include "ProcessBindingFs.h" +#include +#include "ZigGlobalObject.h" + +namespace Bun { +using namespace JSC; + +#define PROCESS_BINDING_NOT_IMPLEMENTED(str) \ + JSC_DEFINE_HOST_FUNCTION(ProcessBinding_Fs_##str, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame * callFrame)) \ + { \ + { \ + auto& vm = JSC::getVM(lexicalGlobalObject); \ + auto throwScope = DECLARE_THROW_SCOPE(vm); \ + auto prelude = "process.binding('fs')."_s; \ + auto name = #str##_s; \ + auto finale = " is not implemented in Bun. If that breaks something, please file an issue and include a reproducible code sample."_s; \ + auto message = makeString(prelude, name, finale); \ + throwScope.throwException(lexicalGlobalObject, createError(lexicalGlobalObject, message)); \ + return {}; \ + } \ + } + +PROCESS_BINDING_NOT_IMPLEMENTED(access) + +PROCESS_BINDING_NOT_IMPLEMENTED(chmod) + +PROCESS_BINDING_NOT_IMPLEMENTED(chown) + +PROCESS_BINDING_NOT_IMPLEMENTED(close) + +PROCESS_BINDING_NOT_IMPLEMENTED(copyFile) + +PROCESS_BINDING_NOT_IMPLEMENTED(cpSyncCheckPaths) + +PROCESS_BINDING_NOT_IMPLEMENTED(existsSync) + +PROCESS_BINDING_NOT_IMPLEMENTED(fchmod) + +PROCESS_BINDING_NOT_IMPLEMENTED(fchown) + +PROCESS_BINDING_NOT_IMPLEMENTED(fdatasync) + +PROCESS_BINDING_NOT_IMPLEMENTED(fstat) + +PROCESS_BINDING_NOT_IMPLEMENTED(fsync) + +PROCESS_BINDING_NOT_IMPLEMENTED(ftruncate) + +PROCESS_BINDING_NOT_IMPLEMENTED(futimes) + +PROCESS_BINDING_NOT_IMPLEMENTED(getFormatOfExtensionlessFile) + +PROCESS_BINDING_NOT_IMPLEMENTED(internalModuleStat) + +PROCESS_BINDING_NOT_IMPLEMENTED(lchown) + +PROCESS_BINDING_NOT_IMPLEMENTED(legacyMainResolve) + +PROCESS_BINDING_NOT_IMPLEMENTED(link) + +PROCESS_BINDING_NOT_IMPLEMENTED(lstat) + +PROCESS_BINDING_NOT_IMPLEMENTED(lutimes) + +PROCESS_BINDING_NOT_IMPLEMENTED(mkdir) + +PROCESS_BINDING_NOT_IMPLEMENTED(mkdtemp) + +PROCESS_BINDING_NOT_IMPLEMENTED(open) + +PROCESS_BINDING_NOT_IMPLEMENTED(openFileHandle) + +PROCESS_BINDING_NOT_IMPLEMENTED(read) + +PROCESS_BINDING_NOT_IMPLEMENTED(readBuffers) + +PROCESS_BINDING_NOT_IMPLEMENTED(readdir) + +PROCESS_BINDING_NOT_IMPLEMENTED(readFileUtf8) + +PROCESS_BINDING_NOT_IMPLEMENTED(readlink) + +PROCESS_BINDING_NOT_IMPLEMENTED(realpath) + +PROCESS_BINDING_NOT_IMPLEMENTED(rename) + +PROCESS_BINDING_NOT_IMPLEMENTED(rmdir) + +PROCESS_BINDING_NOT_IMPLEMENTED(rmSync) + +PROCESS_BINDING_NOT_IMPLEMENTED(stat) + +PROCESS_BINDING_NOT_IMPLEMENTED(statfs) + +PROCESS_BINDING_NOT_IMPLEMENTED(StatWatcher) + +PROCESS_BINDING_NOT_IMPLEMENTED(symlink) + +PROCESS_BINDING_NOT_IMPLEMENTED(unlink) + +PROCESS_BINDING_NOT_IMPLEMENTED(utimes) + +PROCESS_BINDING_NOT_IMPLEMENTED(writeBuffer) + +PROCESS_BINDING_NOT_IMPLEMENTED(writeBuffers) + +PROCESS_BINDING_NOT_IMPLEMENTED(writeFileUtf8) + +PROCESS_BINDING_NOT_IMPLEMENTED(writeString) + +// FileHandle: [Function: FileHandle], +// FSReqCallback: [Function: FSReqCallback], + +/* Source for ProcessBindingFs.lut.h +@begin processBindingFsTable + access ProcessBinding_Fs_access Function 1 + chmod ProcessBinding_Fs_chmod Function 1 + chown ProcessBinding_Fs_chown Function 1 + close ProcessBinding_Fs_close Function 1 + copyFile ProcessBinding_Fs_copyFile Function 1 + cpSyncCheckPaths ProcessBinding_Fs_cpSyncCheckPaths Function 1 + existsSync ProcessBinding_Fs_existsSync Function 1 + fchmod ProcessBinding_Fs_fchmod Function 1 + fchown ProcessBinding_Fs_fchown Function 1 + fdatasync ProcessBinding_Fs_fdatasync Function 1 + fstat ProcessBinding_Fs_fstat Function 1 + fsync ProcessBinding_Fs_fsync Function 1 + ftruncate ProcessBinding_Fs_ftruncate Function 1 + futimes ProcessBinding_Fs_futimes Function 1 + getFormatOfExtensionlessFile ProcessBinding_Fs_getFormatOfExtensionlessFile Function 1 + internalModuleStat ProcessBinding_Fs_internalModuleStat Function 1 + lchown ProcessBinding_Fs_lchown Function 1 + legacyMainResolve ProcessBinding_Fs_legacyMainResolve Function 1 + link ProcessBinding_Fs_link Function 1 + lstat ProcessBinding_Fs_lstat Function 1 + lutimes ProcessBinding_Fs_lutimes Function 1 + mkdir ProcessBinding_Fs_mkdir Function 1 + mkdtemp ProcessBinding_Fs_mkdtemp Function 1 + open ProcessBinding_Fs_open Function 1 + openFileHandle ProcessBinding_Fs_openFileHandle Function 1 + read ProcessBinding_Fs_read Function 1 + readBuffers ProcessBinding_Fs_readBuffers Function 1 + readdir ProcessBinding_Fs_readdir Function 1 + readFileUtf8 ProcessBinding_Fs_readFileUtf8 Function 1 + readlink ProcessBinding_Fs_readlink Function 1 + realpath ProcessBinding_Fs_realpath Function 1 + rename ProcessBinding_Fs_rename Function 1 + rmdir ProcessBinding_Fs_rmdir Function 1 + rmSync ProcessBinding_Fs_rmSync Function 1 + stat ProcessBinding_Fs_stat Function 1 + statfs ProcessBinding_Fs_statfs Function 1 + StatWatcher ProcessBinding_Fs_StatWatcher Function 1 + symlink ProcessBinding_Fs_symlink Function 1 + unlink ProcessBinding_Fs_unlink Function 1 + utimes ProcessBinding_Fs_utimes Function 1 + writeBuffer ProcessBinding_Fs_writeBuffer Function 1 + writeBuffers ProcessBinding_Fs_writeBuffers Function 1 + writeFileUtf8 ProcessBinding_Fs_writeFileUtf8 Function 1 + writeString ProcessBinding_Fs_writeString Function 1 +@end +*/ +#include "ProcessBindingFs.lut.h" + +const ClassInfo ProcessBindingFs::s_info = { "ProcessBindingFs"_s, &Base::s_info, &processBindingFsTable, nullptr, CREATE_METHOD_TABLE(ProcessBindingFs) }; + +ProcessBindingFs* ProcessBindingFs::create(VM& vm, Structure* structure) +{ + ProcessBindingFs* obj = new (NotNull, allocateCell(vm)) ProcessBindingFs(vm, structure); + obj->finishCreation(vm); + return obj; +} + +Structure* ProcessBindingFs::createStructure(VM& vm, JSGlobalObject* globalObject) +{ + return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), ProcessBindingFs::info()); +} + +void ProcessBindingFs::finishCreation(JSC::VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + + auto* globalObject = this->globalObject(); + auto* zigGlobal = defaultGlobalObject(globalObject); + + putDirect(vm, Identifier::fromString(vm, "kFsStatsFieldsNumber"_s), jsNumber(18), 0); + putDirect(vm, Identifier::fromString(vm, "statValues"_s), zigGlobal->m_statValues.get(zigGlobal), 0); + putDirect(vm, Identifier::fromString(vm, "bigintStatValues"_s), zigGlobal->m_bigintStatValues.get(zigGlobal), 0); + putDirect(vm, Identifier::fromString(vm, "statFsValues"_s), zigGlobal->m_statFsValues.get(zigGlobal), 0); + putDirect(vm, Identifier::fromString(vm, "bigintStatFsValues"_s), zigGlobal->m_bigintStatFsValues.get(zigGlobal), 0); +} + +template +void ProcessBindingFs::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + ProcessBindingFs* thisObject = jsCast(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); +} + +DEFINE_VISIT_CHILDREN(ProcessBindingFs); + +} // namespace Bun diff --git a/src/bun.js/bindings/ProcessBindingFs.h b/src/bun.js/bindings/ProcessBindingFs.h new file mode 100644 index 0000000000..fe7601ce0e --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingFs.h @@ -0,0 +1,37 @@ +#pragma once +#include "root.h" + +namespace Bun { + +using namespace JSC; + +// The object returned from process.binding('fs') +class ProcessBindingFs final : public JSC::JSNonFinalObject { +public: + DECLARE_INFO; + DECLARE_VISIT_CHILDREN; + + using Base = JSC::JSNonFinalObject; + + static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable; + + static ProcessBindingFs* create(JSC::VM& vm, JSC::Structure* structure); + static Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject); + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ProcessBindingFs, Base); + return &vm.plainObjectSpace(); + } + +private: + void finishCreation(JSC::VM& vm); + + ProcessBindingFs(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } +}; + +} // namespace Bun diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 06e66895ea..6a6b5feea3 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -164,6 +164,7 @@ #include "S3Error.h" #include "ProcessBindingBuffer.h" #include "NodeValidator.h" +#include "ProcessBindingFs.h" #include "JSBunRequest.h" #include "ServerRouteList.h" @@ -3255,6 +3256,14 @@ void GlobalObject::finishCreation(VM& vm) ProcessBindingConstants::createStructure(init.vm, init.owner))); }); + m_processBindingFs.initLater( + [](const JSC::LazyProperty::Initializer& init) { + init.set( + ProcessBindingFs::create( + init.vm, + ProcessBindingFs::createStructure(init.vm, init.owner))); + }); + m_importMetaObjectStructure.initLater( [](const JSC::LazyProperty::Initializer& init) { init.set(Zig::ImportMetaObject::createStructure(init.vm, init.owner)); @@ -3380,6 +3389,19 @@ void GlobalObject::finishCreation(VM& vm) init.setStructure(Zig::JSFFIFunction::createStructure(init.vm, init.global, init.global->functionPrototype())); }); + m_statValues.initLater([](const LazyProperty::Initializer& init) { + init.set(JSC::JSFloat64Array::create(init.owner, JSC::JSFloat64Array::createStructure(init.vm, init.owner, init.owner->objectPrototype()), 36)); + }); + m_bigintStatValues.initLater([](const LazyProperty::Initializer& init) { + init.set(JSC::JSBigInt64Array::create(init.owner, JSC::JSBigInt64Array::createStructure(init.vm, init.owner, init.owner->objectPrototype()), 36)); + }); + m_statFsValues.initLater([](const LazyProperty::Initializer& init) { + init.set(JSC::JSFloat64Array::create(init.owner, JSC::JSFloat64Array::createStructure(init.vm, init.owner, init.owner->objectPrototype()), 7)); + }); + m_bigintStatFsValues.initLater([](const LazyProperty::Initializer& init) { + init.set(JSC::JSBigInt64Array::create(init.owner, JSC::JSBigInt64Array::createStructure(init.vm, init.owner, init.owner->objectPrototype()), 7)); + }); + configureNodeVM(vm, this); #if ENABLE(REMOTE_INSPECTOR) @@ -3891,6 +3913,9 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_esmRegistryMap.visit(visitor); thisObject->m_importMetaObjectStructure.visit(visitor); thisObject->m_internalModuleRegistry.visit(visitor); + thisObject->m_processBindingBuffer.visit(visitor); + thisObject->m_processBindingConstants.visit(visitor); + thisObject->m_processBindingFs.visit(visitor); thisObject->m_JSArrayBufferControllerPrototype.visit(visitor); thisObject->m_JSArrayBufferSinkClassStructure.visit(visitor); thisObject->m_JSBufferClassStructure.visit(visitor); @@ -3961,6 +3986,10 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_JSBunRequestStructure.visit(visitor); thisObject->m_JSBunRequestParamsPrototype.visit(visitor); thisObject->m_JSX509CertificateClassStructure.visit(visitor); + thisObject->m_statValues.visit(visitor); + thisObject->m_bigintStatValues.visit(visitor); + thisObject->m_statFsValues.visit(visitor); + thisObject->m_bigintStatFsValues.visit(visitor); thisObject->m_nodeErrorCache.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 45980c1a3b..ce784d6724 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -251,6 +251,7 @@ public: JSObject* processBindingBuffer() const { return m_processBindingBuffer.getInitializedOnMainThread(this); } JSObject* processBindingConstants() const { return m_processBindingConstants.getInitializedOnMainThread(this); } + JSObject* processBindingFs() const { return m_processBindingFs.getInitializedOnMainThread(this); } JSObject* lazyRequireCacheObject() const { return m_lazyRequireCacheObject.getInitializedOnMainThread(this); } @@ -584,6 +585,7 @@ public: LazyProperty m_internalModuleRegistry; LazyProperty m_processBindingBuffer; LazyProperty m_processBindingConstants; + LazyProperty m_processBindingFs; LazyProperty m_importMetaObjectStructure; LazyProperty m_asyncBoundFunctionStructure; LazyProperty m_JSDOMFileConstructor; @@ -608,6 +610,11 @@ public: LazyProperty m_JSBunRequestStructure; LazyProperty m_JSBunRequestParamsPrototype; + LazyProperty m_statValues; + LazyProperty m_bigintStatValues; + LazyProperty m_statFsValues; + LazyProperty m_bigintStatFsValues; + bool hasOverridenModuleResolveFilenameFunction = false; // Almost all NAPI functions should set error_code to the status they're returning right before diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 1bc741454c..528846d359 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -1916,7 +1916,7 @@ pub const Arguments = struct { } if (next_val.isString()) { arguments.eat(); - var str = next_val.toBunString(ctx); + var str = try next_val.toBunString2(ctx); defer str.deref(); if (str.eqlComptime("dir")) break :link_type .dir; if (str.eqlComptime("file")) break :link_type .file; diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 3a8c307c6a..726ce347fd 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -995,7 +995,7 @@ pub const PathLike = union(enum) { .StringObject, .DerivedStringObject, => { - var str = arg.toBunString(ctx); + var str = try arg.toBunString2(ctx); defer str.deref(); arguments.eat(); diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index e935b6d9cb..bf5b4ce18d 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -1205,7 +1205,7 @@ pub const Blob = struct { const len = data.getLength(globalThis); if (len < 256 * 1024) { - const str = data.toBunString(globalThis); + const str = try data.toBunString2(globalThis); defer str.deref(); const pathlike: JSC.Node.PathOrFileDescriptor = if (path_or_blob == .path) @@ -5528,7 +5528,7 @@ pub const Blob = struct { JSC.JSValue.JSType.DerivedStringObject, => { if (!fail_if_top_value_is_not_typed_array_like) { - var str = top_value.toBunString(global); + var str = try top_value.toBunString2(global); defer str.deref(); const bytes, const ascii = try str.toOwnedSliceReturningAllASCII(bun.default_allocator); return Blob.initWithAllASCII(bytes, bun.default_allocator, global, ascii); diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig index 3452ec5e66..15e57c367b 100644 --- a/src/bun.js/webcore/body.zig +++ b/src/bun.js/webcore/body.zig @@ -564,7 +564,7 @@ pub const Body = struct { const js_type = value.jsType(); if (js_type.isStringLike()) { - var str = value.toBunString(globalThis); + var str = try value.toBunString2(globalThis); if (str.length() == 0) { return Body.Value{ .Empty = {}, diff --git a/src/css/css_internals.zig b/src/css/css_internals.zig index d5d9786c18..ad19fdbcd4 100644 --- a/src/css/css_internals.zig +++ b/src/css/css_internals.zig @@ -67,7 +67,7 @@ pub fn testingImpl(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, c if (!source_arg.isString()) { return globalThis.throw("minifyTestWithOptions: expected source to be a string", .{}); } - const source_bunstr = source_arg.toBunString(globalThis); + const source_bunstr = try source_arg.toBunString2(globalThis); defer source_bunstr.deref(); const source = source_bunstr.toUTF8(bun.default_allocator); defer source.deinit(); @@ -78,7 +78,7 @@ pub fn testingImpl(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, c if (!expected_arg.isString()) { return globalThis.throw("minifyTestWithOptions: expected `expected` arg to be a string", .{}); } - const expected_bunstr = expected_arg.toBunString(globalThis); + const expected_bunstr = try expected_arg.toBunString2(globalThis); defer expected_bunstr.deref(); const expected = expected_bunstr.toUTF8(bun.default_allocator); defer expected.deinit(); @@ -159,7 +159,7 @@ fn parserOptionsFromJS(globalThis: *JSC.JSGlobalObject, allocator: Allocator, op if (val.isArray()) { var iter = val.arrayIterator(globalThis); while (iter.next()) |item| { - const bunstr = item.toBunString(globalThis); + const bunstr = try item.toBunString2(globalThis); defer bunstr.deref(); const str = bunstr.toUTF8(bun.default_allocator); defer str.deinit(); @@ -273,7 +273,7 @@ pub fn attrTest(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun. if (!source_arg.isString()) { return globalThis.throw("attrTest: expected source to be a string", .{}); } - const source_bunstr = source_arg.toBunString(globalThis); + const source_bunstr = try source_arg.toBunString2(globalThis); defer source_bunstr.deref(); const source = source_bunstr.toUTF8(bun.default_allocator); defer source.deinit(); @@ -284,7 +284,7 @@ pub fn attrTest(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun. if (!expected_arg.isString()) { return globalThis.throw("attrTest: expected `expected` arg to be a string", .{}); } - const expected_bunstr = expected_arg.toBunString(globalThis); + const expected_bunstr = try expected_arg.toBunString2(globalThis); defer expected_bunstr.deref(); const expected = expected_bunstr.toUTF8(bun.default_allocator); defer expected.deinit(); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index b8ce712bac..81d3921a87 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -3379,7 +3379,7 @@ pub const Resolver = struct { return globalThis.throwInvalidArgumentType("nodeModulePaths", "path", "string"); } - const in_str = argument.toBunString(globalThis); + const in_str = try argument.toBunString2(globalThis); defer in_str.deref(); const r = &globalThis.bunVM().transpiler.resolver; return nodeModulePathsJSValue(r, in_str, globalThis); diff --git a/src/shell/shell.zig b/src/shell/shell.zig index 20ebf2f86a..757b57be98 100644 --- a/src/shell/shell.zig +++ b/src/shell/shell.zig @@ -3859,7 +3859,7 @@ pub fn handleTemplateValue( if (template_value.isObject()) { if (template_value.getOwnTruthy(globalThis, "raw")) |maybe_str| { - const bunstr = maybe_str.toBunString(globalThis); + const bunstr = try maybe_str.toBunString2(globalThis); defer bunstr.deref(); if (!try builder.appendBunStr(bunstr, false)) { return globalThis.throw("Shell script string contains invalid UTF-16", .{}); @@ -3906,8 +3906,8 @@ pub const ShellSrcBuilder = struct { }; } - pub fn appendJSValueStr(this: *ShellSrcBuilder, jsval: JSValue, comptime allow_escape: bool) bun.OOM!bool { - const bunstr = jsval.toBunString(this.globalThis); + pub fn appendJSValueStr(this: *ShellSrcBuilder, jsval: JSValue, comptime allow_escape: bool) bun.JSError!bool { + const bunstr = try jsval.toBunString2(this.globalThis); defer bunstr.deref(); return try this.appendBunStr(bunstr, allow_escape); @@ -4316,7 +4316,7 @@ pub const TestingAPIs = struct { return globalThis.throw("shellInternals.disabledOnPosix: expected 1 arguments, got 0", .{}); }; - const bunstr = string.toBunString(globalThis); + const bunstr = try string.toBunString2(globalThis); defer bunstr.deref(); const utf8str = bunstr.toUTF8(bun.default_allocator); defer utf8str.deinit(); diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index f2c7e920c0..59792c26d2 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -652,7 +652,7 @@ pub const PostgresSQLQuery = struct { this_value.ensureStillAlive(); ptr.* = .{ - .query = query.toBunString(globalThis), + .query = try query.toBunString2(globalThis), .thisValue = JSRef.initWeak(this_value), .flags = .{ .bigint = bigint, @@ -1829,15 +1829,15 @@ pub const PostgresSQLConnection = struct { pub fn call(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var vm = globalObject.bunVM(); const arguments = callframe.arguments_old(14).slice(); - const hostname_str = arguments[0].toBunString(globalObject); + const hostname_str = try arguments[0].toBunString2(globalObject); defer hostname_str.deref(); const port = arguments[1].coerce(i32, globalObject); - const username_str = arguments[2].toBunString(globalObject); + const username_str = try arguments[2].toBunString2(globalObject); defer username_str.deref(); - const password_str = arguments[3].toBunString(globalObject); + const password_str = try arguments[3].toBunString2(globalObject); defer password_str.deref(); - const database_str = arguments[4].toBunString(globalObject); + const database_str = try arguments[4].toBunString2(globalObject); defer database_str.deref(); const ssl_mode: SSLMode = switch (arguments[5].toInt32()) { 0 => .disable, @@ -1898,7 +1898,7 @@ pub const PostgresSQLConnection = struct { var database: []const u8 = ""; var options: []const u8 = ""; - const options_str = arguments[7].toBunString(globalObject); + const options_str = try arguments[7].toBunString2(globalObject); defer options_str.deref(); const options_buf: []u8 = brk: { diff --git a/test/cli/create/create-jsx.test.ts b/test/cli/create/create-jsx.test.ts index c3bf198608..137c23f103 100644 --- a/test/cli/create/create-jsx.test.ts +++ b/test/cli/create/create-jsx.test.ts @@ -116,7 +116,7 @@ describe.each(["true", "false"])("development: %s", developmentString => { }); }); - test("dev server", async () => { + test.todoIf(isCI)("dev server", async () => { await using process = Bun.spawn([bunExe(), "create", "./index.jsx"], { cwd: dir, env: env, @@ -149,7 +149,7 @@ describe.each(["true", "false"])("development: %s", developmentString => { } }); - test.todoIf(isWindows)("build", async () => { + test.todoIf(isCI || isWindows)("build", async () => { { const process = Bun.spawn([bunExe(), "create", "./index.jsx"], { cwd: dir, @@ -214,7 +214,7 @@ describe.each(["true", "false"])("development: %s", developmentString => { } }); - test.todoIf(isWindows)("build", async () => { + test.todoIf(isCI || isWindows)("build", async () => { { const process = Bun.spawn([bunExe(), "create", "./index.tsx"], { cwd: dir, @@ -246,7 +246,7 @@ describe.each(["true", "false"])("development: %s", developmentString => { }); }); - test("dev server", async () => { + test.todoIf(isCI)("dev server", async () => { const process = Bun.spawn([bunExe(), "create", "./index.tsx"], { cwd: dir, env: env, @@ -285,7 +285,7 @@ describe.each(["true", "false"])("development: %s", developmentString => { } }); - test.todoIf(isWindows)("build", async () => { + test.todoIf(isCI || isWindows)("build", async () => { { const process = Bun.spawn([bunExe(), "create", "./index.tsx"], { cwd: dir, diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index c2b5d8e7ac..340dcdd82b 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -327,7 +327,7 @@ it("process.binding", () => { expect(() => process.binding("contextify")).toThrow(); expect(() => process.binding("crypto")).toThrow(); expect(() => process.binding("crypto/x509")).not.toThrow(); - expect(() => process.binding("fs")).toThrow(); + expect(() => process.binding("fs")).not.toThrow(); expect(() => process.binding("fs_event_wrap")).toThrow(); expect(() => process.binding("http_parser")).toThrow(); expect(() => process.binding("icu")).toThrow();