diff --git a/docs/runtime/nodejs-apis.md b/docs/runtime/nodejs-apis.md index 36407cdf6ec56..91a8b61a203d9 100644 --- a/docs/runtime/nodejs-apis.md +++ b/docs/runtime/nodejs-apis.md @@ -153,7 +153,7 @@ Some methods are not optimized yet. ### [`node:util`](https://nodejs.org/api/util.html) -🟡 Missing `MIMEParams` `MIMEType` `aborted` `debug` `getSystemErrorMap` `getSystemErrorName` `transferableAbortController` `transferableAbortSignal` `stripVTControlCharacters` +🟡 Missing `MIMEParams` `MIMEType` `aborted` `debug` `getSystemErrorMap` `transferableAbortController` `transferableAbortSignal` `stripVTControlCharacters` ### [`node:v8`](https://nodejs.org/api/v8.html) diff --git a/src/bun.js/bindings/NodeError.cpp b/src/bun.js/bindings/NodeError.cpp new file mode 100644 index 0000000000000..c29dd34338473 --- /dev/null +++ b/src/bun.js/bindings/NodeError.cpp @@ -0,0 +1,95 @@ +#include "root.h" +#include "headers-handwritten.h" +#include "BunClientData.h" +#include "helpers.h" +#include "JavaScriptCore/JSCJSValue.h" +#include "JavaScriptCore/ErrorInstance.h" +#include "JavaScriptCore/ExceptionScope.h" +#include "wtf/text/ASCIILiteral.h" +#include "wtf/text/MakeString.h" +#include + +JSC::EncodedJSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigString* arg1, JSC::JSGlobalObject* globalObject); +JSC::EncodedJSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigString* arg1, JSC::JSGlobalObject* globalObject); + +namespace Bun { + +using namespace JSC; + +JSC::JSValue createTypeErrorWithCode(JSC::JSGlobalObject* globalObject, String message, ASCIILiteral code) +{ + JSC::VM& vm = globalObject->vm(); + + JSC::JSObject* result = JSC::createTypeError(globalObject, message); + JSC::EnsureStillAliveScope ensureAlive(result); + auto typeError = JSC::JSValue(result).asCell()->getObject(); + + auto clientData = WebCore::clientData(vm); + typeError->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, String(code)), 0); + + return typeError; +} + +JSC::JSValue createRangeErrorWithCode(JSC::JSGlobalObject* globalObject, String message, ASCIILiteral code) +{ + JSC::VM& vm = globalObject->vm(); + + JSC::JSObject* result = JSC::createRangeError(globalObject, message); + JSC::EnsureStillAliveScope ensureAlive(result); + auto typeError = JSC::JSValue(result).asCell()->getObject(); + + auto clientData = WebCore::clientData(vm); + typeError->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, String(code)), 0); + + return typeError; +} + +JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_INVALID_ARG_TYPE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + JSC::VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto argCount = callFrame->argumentCount(); + if (argCount < 3) { + JSC::throwTypeError(globalObject, scope, "requires 3 arguments"_s); + return {}; + } + + auto arg_name = callFrame->argument(0).toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + auto expected_type = callFrame->argument(1).toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + auto actual_value = callFrame->argument(2).toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + auto message = makeString("The \""_s, arg_name, "\" argument must be of type "_s, expected_type, ". Recieved "_s, actual_value); + return JSC::JSValue::encode(createTypeErrorWithCode(globalObject, message, "ERR_INVALID_ARG_TYPE"_s)); +} + +JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + JSC::VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto argCount = callFrame->argumentCount(); + if (argCount < 3) { + JSC::throwTypeError(globalObject, scope, "requires 3 arguments"_s); + return {}; + } + + auto arg_name = callFrame->argument(0).toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + auto range = callFrame->argument(1).toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + auto input = callFrame->argument(2).toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + auto message = makeString("The value of \""_s, arg_name, "\" is out of range. It must be "_s, range, ". Received "_s, input); + return JSC::JSValue::encode(createRangeErrorWithCode(globalObject, message, "ERR_OUT_OF_RANGE"_s)); +} + +} diff --git a/src/bun.js/bindings/NodeError.h b/src/bun.js/bindings/NodeError.h new file mode 100644 index 0000000000000..dc959feff0287 --- /dev/null +++ b/src/bun.js/bindings/NodeError.h @@ -0,0 +1,8 @@ +#include "root.h" + +namespace Bun { + +JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_INVALID_ARG_TYPE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)); +JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)); + +} diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 61f7f700e8634..d1c58ac9a0d93 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1570,6 +1570,7 @@ JSC__JSValue WebCore__FetchHeaders__toJS(WebCore__FetchHeaders* headers, JSC__JS return JSC::JSValue::encode(value); } + JSC__JSValue WebCore__FetchHeaders__clone(WebCore__FetchHeaders* headers, JSC__JSGlobalObject* arg1) { auto throwScope = DECLARE_THROW_SCOPE(arg1->vm()); @@ -2132,6 +2133,7 @@ JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0) JSC::JSValue value = JSC::JSValue::decode(JSValue0); return JSC::jsDynamicCast(value); } + JSC__JSValue JSC__JSValue__createInternalPromise(JSC__JSGlobalObject* globalObject) { JSC::VM& vm = globalObject->vm(); @@ -2192,6 +2194,7 @@ JSC__JSValue JSC__JSPromise__asValue(JSC__JSPromise* arg0, JSC__JSGlobalObject* ASSERT_WITH_MESSAGE(value.inherits(), "JSPromise::asValue() called on a non-promise object"); return JSC::JSValue::encode(value); } + JSC__JSPromise* JSC__JSPromise__create(JSC__JSGlobalObject* arg0) { return JSC::JSPromise::create(arg0->vm(), arg0->promiseStructure()); @@ -2232,6 +2235,7 @@ JSC__JSValue JSC__JSGlobalObject__getCachedObject(JSC__JSGlobalObject* globalObj JSC::JSValue result = globalObject->getIfPropertyExists(globalObject, ident); return JSC::JSValue::encode(result); } + JSC__JSValue JSC__JSGlobalObject__putCachedObject(JSC__JSGlobalObject* globalObject, const ZigString* arg1, JSC__JSValue JSValue2) { JSC::VM& vm = globalObject->vm(); @@ -2473,6 +2477,7 @@ JSC__Exception* JSC__Exception__create(JSC__JSGlobalObject* arg0, JSC__JSObject* ? JSC::Exception::StackCaptureAction::CaptureStack : JSC::Exception::StackCaptureAction::DoNotCaptureStack); } + JSC__JSValue JSC__Exception__value(JSC__Exception* arg0) { return JSC::JSValue::encode(arg0->value()); @@ -2485,17 +2490,20 @@ JSC__JSValue JSC__Exception__value(JSC__Exception* arg0) // JSC__PropertyNameArray__next(JSC__PropertyNameArray* arg0, size_t arg1); // CPP_DECL void JSC__PropertyNameArray__release(JSC__PropertyNameArray* arg0); size_t JSC__JSObject__getArrayLength(JSC__JSObject* arg0) { return arg0->getArrayLength(); } + JSC__JSValue JSC__JSObject__getIndex(JSC__JSValue jsValue, JSC__JSGlobalObject* arg1, uint32_t arg3) { return JSC::JSValue::encode(JSC::JSValue::decode(jsValue).toObject(arg1)->getIndex(arg1, arg3)); } + JSC__JSValue JSC__JSValue__getDirectIndex(JSC__JSValue jsValue, JSC__JSGlobalObject* arg1, uint32_t arg3) { JSC::JSObject* object = JSC::JSValue::decode(jsValue).getObject(); return JSC::JSValue::encode(object->getDirectIndex(arg1, arg3)); } + JSC__JSValue JSC__JSObject__getDirect(JSC__JSObject* arg0, JSC__JSGlobalObject* arg1, const ZigString* arg2) { @@ -2530,6 +2538,7 @@ bool JSC__JSString__eql(const JSC__JSString* arg0, JSC__JSGlobalObject* obj, JSC } bool JSC__JSString__is8Bit(const JSC__JSString* arg0) { return arg0->is8Bit(); }; size_t JSC__JSString__length(const JSC__JSString* arg0) { return arg0->length(); } + JSC__JSObject* JSC__JSString__toObject(JSC__JSString* arg0, JSC__JSGlobalObject* arg1) { return arg0->toObject(arg1); @@ -2551,6 +2560,7 @@ extern "C" JSC::JSInternalPromise* JSModuleLoader__import(JSC::JSGlobalObject* g RETURN_IF_EXCEPTION(scope, nullptr); return promise; } + JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* globalObject, const unsigned char* arg1, size_t arg2, const unsigned char* originUrlPtr, size_t originURLLen, const unsigned char* referrerUrlPtr, size_t referrerUrlLen, JSC__JSValue JSValue5, JSC__JSValue* arg6) @@ -2625,6 +2635,7 @@ JSC__JSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigS return JSC::JSValue::encode(rangeError); } + JSC__JSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigString* arg1, JSC__JSGlobalObject* globalObject) { @@ -3083,6 +3094,7 @@ void JSC__JSPromise__rejectAsHandledException(JSC__JSPromise* arg0, JSC__JSGloba { arg0->rejectAsHandled(arg1, arg2); } + JSC__JSPromise* JSC__JSPromise__rejectedPromise(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1) { return JSC::JSPromise::rejectedPromise(arg0, JSC::JSValue::decode(JSValue1)); @@ -3148,6 +3160,7 @@ void JSC__JSPromise__rejectOnNextTickWithHandled(JSC__JSPromise* promise, JSC__J RETURN_IF_EXCEPTION(scope, void()); } } + JSC__JSPromise* JSC__JSPromise__resolvedPromise(JSC__JSGlobalObject* globalObject, JSC__JSValue JSValue1) { JSC::VM& vm = globalObject->vm(); @@ -3236,6 +3249,7 @@ void JSC__JSInternalPromise__rejectAsHandledException(JSC__JSInternalPromise* ar { arg0->rejectAsHandled(arg1, arg2); } + JSC__JSInternalPromise* JSC__JSInternalPromise__rejectedPromise(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1) { @@ -3248,6 +3262,7 @@ void JSC__JSInternalPromise__resolve(JSC__JSInternalPromise* arg0, JSC__JSGlobal { arg0->resolve(arg1, JSC::JSValue::decode(JSValue2)); } + JSC__JSInternalPromise* JSC__JSInternalPromise__resolvedPromise(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1) { @@ -3493,6 +3508,7 @@ bool JSC__JSValue__isUndefinedOrNull(JSC__JSValue JSValue0) { return JSC::JSValue::decode(JSValue0).isUndefinedOrNull(); } + JSC__JSValue JSC__JSValue__jsBoolean(bool arg0) { return JSC::JSValue::encode(JSC::jsBoolean(arg0)); @@ -3501,6 +3517,7 @@ JSC__JSValue JSC__JSValue__jsDoubleNumber(double arg0) { return JSC::JSValue::encode(JSC::jsNumber(arg0)); } + JSC__JSValue JSC__JSValue__jsEmptyString(JSC__JSGlobalObject* arg0) { return JSC::JSValue::encode(JSC::jsEmptyString(arg0->vm())); @@ -4918,6 +4935,7 @@ JSC__JSValue JSC__JSPromise__rejectedPromiseValue(JSC__JSGlobalObject* globalObj JSC::ensureStillAliveHere(JSC::JSValue::decode(JSValue1)); return JSC::JSValue::encode(promise); } + JSC__JSValue JSC__JSPromise__resolvedPromiseValue(JSC__JSGlobalObject* globalObject, JSC__JSValue JSValue1) { diff --git a/src/bun.js/node/node_util_binding.zig b/src/bun.js/node/node_util_binding.zig new file mode 100644 index 0000000000000..d58bac22db85b --- /dev/null +++ b/src/bun.js/node/node_util_binding.zig @@ -0,0 +1,108 @@ +const std = @import("std"); +const bun = @import("root").bun; +const Environment = bun.Environment; +const JSC = bun.JSC; +const string = bun.string; +const Output = bun.Output; +const ZigString = JSC.ZigString; +const uv = bun.windows.libuv; + +pub fn internalErrorName(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { + const arguments = callframe.arguments(1).slice(); + if (arguments.len < 1) { + globalThis.throwNotEnoughArguments("internalErrorName", 1, arguments.len); + return .zero; + } + + const err_value = arguments[0]; + const err_int = err_value.toInt32(); + + if (err_int == -4095) return ZigString.static("EOF").toJS(globalThis); + if (err_int == -4094) return ZigString.static("UNKNOWN").toJS(globalThis); + if (err_int == -3000) return ZigString.static("EAI_ADDRFAMILY").toJS(globalThis); + if (err_int == -3001) return ZigString.static("EAI_AGAIN").toJS(globalThis); + if (err_int == -3002) return ZigString.static("EAI_BADFLAGS").toJS(globalThis); + if (err_int == -3003) return ZigString.static("EAI_CANCELED").toJS(globalThis); + if (err_int == -3004) return ZigString.static("EAI_FAIL").toJS(globalThis); + if (err_int == -3005) return ZigString.static("EAI_FAMILY").toJS(globalThis); + if (err_int == -3006) return ZigString.static("EAI_MEMORY").toJS(globalThis); + if (err_int == -3007) return ZigString.static("EAI_NODATA").toJS(globalThis); + if (err_int == -3008) return ZigString.static("EAI_NONAME").toJS(globalThis); + if (err_int == -3009) return ZigString.static("EAI_OVERFLOW").toJS(globalThis); + if (err_int == -3010) return ZigString.static("EAI_SERVICE").toJS(globalThis); + if (err_int == -3011) return ZigString.static("EAI_SOCKTYPE").toJS(globalThis); + if (err_int == -3013) return ZigString.static("EAI_BADHINTS").toJS(globalThis); + if (err_int == -3014) return ZigString.static("EAI_PROTOCOL").toJS(globalThis); + + if (err_int == -bun.C.UV_E2BIG) return ZigString.static("E2BIG").toJS(globalThis); + if (err_int == -bun.C.UV_EACCES) return ZigString.static("EACCES").toJS(globalThis); + if (err_int == -bun.C.UV_EADDRINUSE) return ZigString.static("EADDRINUSE").toJS(globalThis); + if (err_int == -bun.C.UV_EADDRNOTAVAIL) return ZigString.static("EADDRNOTAVAIL").toJS(globalThis); + if (err_int == -bun.C.UV_EAFNOSUPPORT) return ZigString.static("EAFNOSUPPORT").toJS(globalThis); + if (err_int == -bun.C.UV_EAGAIN) return ZigString.static("EAGAIN").toJS(globalThis); + if (err_int == -bun.C.UV_EALREADY) return ZigString.static("EALREADY").toJS(globalThis); + if (err_int == -bun.C.UV_EBADF) return ZigString.static("EBADF").toJS(globalThis); + if (err_int == -bun.C.UV_EBUSY) return ZigString.static("EBUSY").toJS(globalThis); + if (err_int == -bun.C.UV_ECANCELED) return ZigString.static("ECANCELED").toJS(globalThis); + if (err_int == -bun.C.UV_ECHARSET) return ZigString.static("ECHARSET").toJS(globalThis); + if (err_int == -bun.C.UV_ECONNABORTED) return ZigString.static("ECONNABORTED").toJS(globalThis); + if (err_int == -bun.C.UV_ECONNREFUSED) return ZigString.static("ECONNREFUSED").toJS(globalThis); + if (err_int == -bun.C.UV_ECONNRESET) return ZigString.static("ECONNRESET").toJS(globalThis); + if (err_int == -bun.C.UV_EDESTADDRREQ) return ZigString.static("EDESTADDRREQ").toJS(globalThis); + if (err_int == -bun.C.UV_EEXIST) return ZigString.static("EEXIST").toJS(globalThis); + if (err_int == -bun.C.UV_EFAULT) return ZigString.static("EFAULT").toJS(globalThis); + if (err_int == -bun.C.UV_EHOSTUNREACH) return ZigString.static("EHOSTUNREACH").toJS(globalThis); + if (err_int == -bun.C.UV_EINTR) return ZigString.static("EINTR").toJS(globalThis); + if (err_int == -bun.C.UV_EINVAL) return ZigString.static("EINVAL").toJS(globalThis); + if (err_int == -bun.C.UV_EIO) return ZigString.static("EIO").toJS(globalThis); + if (err_int == -bun.C.UV_EISCONN) return ZigString.static("EISCONN").toJS(globalThis); + if (err_int == -bun.C.UV_EISDIR) return ZigString.static("EISDIR").toJS(globalThis); + if (err_int == -bun.C.UV_ELOOP) return ZigString.static("ELOOP").toJS(globalThis); + if (err_int == -bun.C.UV_EMFILE) return ZigString.static("EMFILE").toJS(globalThis); + if (err_int == -bun.C.UV_EMSGSIZE) return ZigString.static("EMSGSIZE").toJS(globalThis); + if (err_int == -bun.C.UV_ENAMETOOLONG) return ZigString.static("ENAMETOOLONG").toJS(globalThis); + if (err_int == -bun.C.UV_ENETDOWN) return ZigString.static("ENETDOWN").toJS(globalThis); + if (err_int == -bun.C.UV_ENETUNREACH) return ZigString.static("ENETUNREACH").toJS(globalThis); + if (err_int == -bun.C.UV_ENFILE) return ZigString.static("ENFILE").toJS(globalThis); + if (err_int == -bun.C.UV_ENOBUFS) return ZigString.static("ENOBUFS").toJS(globalThis); + if (err_int == -bun.C.UV_ENODEV) return ZigString.static("ENODEV").toJS(globalThis); + if (err_int == -bun.C.UV_ENOENT) return ZigString.static("ENOENT").toJS(globalThis); + if (err_int == -bun.C.UV_ENOMEM) return ZigString.static("ENOMEM").toJS(globalThis); + if (err_int == -bun.C.UV_ENONET) return ZigString.static("ENONET").toJS(globalThis); + if (err_int == -bun.C.UV_ENOSPC) return ZigString.static("ENOSPC").toJS(globalThis); + if (err_int == -bun.C.UV_ENOSYS) return ZigString.static("ENOSYS").toJS(globalThis); + if (err_int == -bun.C.UV_ENOTCONN) return ZigString.static("ENOTCONN").toJS(globalThis); + if (err_int == -bun.C.UV_ENOTDIR) return ZigString.static("ENOTDIR").toJS(globalThis); + if (err_int == -bun.C.UV_ENOTEMPTY) return ZigString.static("ENOTEMPTY").toJS(globalThis); + if (err_int == -bun.C.UV_ENOTSOCK) return ZigString.static("ENOTSOCK").toJS(globalThis); + if (err_int == -bun.C.UV_ENOTSUP) return ZigString.static("ENOTSUP").toJS(globalThis); + if (err_int == -bun.C.UV_EPERM) return ZigString.static("EPERM").toJS(globalThis); + if (err_int == -bun.C.UV_EPIPE) return ZigString.static("EPIPE").toJS(globalThis); + if (err_int == -bun.C.UV_EPROTO) return ZigString.static("EPROTO").toJS(globalThis); + if (err_int == -bun.C.UV_EPROTONOSUPPORT) return ZigString.static("EPROTONOSUPPORT").toJS(globalThis); + if (err_int == -bun.C.UV_EPROTOTYPE) return ZigString.static("EPROTOTYPE").toJS(globalThis); + if (err_int == -bun.C.UV_EROFS) return ZigString.static("EROFS").toJS(globalThis); + if (err_int == -bun.C.UV_ESHUTDOWN) return ZigString.static("ESHUTDOWN").toJS(globalThis); + if (err_int == -bun.C.UV_ESPIPE) return ZigString.static("ESPIPE").toJS(globalThis); + if (err_int == -bun.C.UV_ESRCH) return ZigString.static("ESRCH").toJS(globalThis); + if (err_int == -bun.C.UV_ETIMEDOUT) return ZigString.static("ETIMEDOUT").toJS(globalThis); + if (err_int == -bun.C.UV_ETXTBSY) return ZigString.static("ETXTBSY").toJS(globalThis); + if (err_int == -bun.C.UV_EXDEV) return ZigString.static("EXDEV").toJS(globalThis); + if (err_int == -bun.C.UV_EFBIG) return ZigString.static("EFBIG").toJS(globalThis); + if (err_int == -bun.C.UV_ENOPROTOOPT) return ZigString.static("ENOPROTOOPT").toJS(globalThis); + if (err_int == -bun.C.UV_ERANGE) return ZigString.static("ERANGE").toJS(globalThis); + if (err_int == -bun.C.UV_ENXIO) return ZigString.static("ENXIO").toJS(globalThis); + if (err_int == -bun.C.UV_EMLINK) return ZigString.static("EMLINK").toJS(globalThis); + if (err_int == -bun.C.UV_EHOSTDOWN) return ZigString.static("EHOSTDOWN").toJS(globalThis); + if (err_int == -bun.C.UV_EREMOTEIO) return ZigString.static("EREMOTEIO").toJS(globalThis); + if (err_int == -bun.C.UV_ENOTTY) return ZigString.static("ENOTTY").toJS(globalThis); + if (err_int == -bun.C.UV_EFTYPE) return ZigString.static("EFTYPE").toJS(globalThis); + if (err_int == -bun.C.UV_EILSEQ) return ZigString.static("EILSEQ").toJS(globalThis); + if (err_int == -bun.C.UV_EOVERFLOW) return ZigString.static("EOVERFLOW").toJS(globalThis); + if (err_int == -bun.C.UV_ESOCKTNOSUPPORT) return ZigString.static("ESOCKTNOSUPPORT").toJS(globalThis); + if (err_int == -bun.C.UV_ENODATA) return ZigString.static("ENODATA").toJS(globalThis); + if (err_int == -bun.C.UV_EUNATCH) return ZigString.static("EUNATCH").toJS(globalThis); + + const fmtstring = bun.String.createFormat("Unknown system error {d}", .{err_int}) catch bun.outOfMemory(); + return fmtstring.toJS(globalThis); +} diff --git a/src/darwin_c.zig b/src/darwin_c.zig index 075b6c1852bf6..a5b3a8721ab63 100644 --- a/src/darwin_c.zig +++ b/src/darwin_c.zig @@ -415,6 +415,75 @@ pub const SystemErrno = enum(u8) { }; }; +pub const UV_E2BIG: i32 = @intFromEnum(SystemErrno.E2BIG); +pub const UV_EACCES: i32 = @intFromEnum(SystemErrno.EACCES); +pub const UV_EADDRINUSE: i32 = @intFromEnum(SystemErrno.EADDRINUSE); +pub const UV_EADDRNOTAVAIL: i32 = @intFromEnum(SystemErrno.EADDRNOTAVAIL); +pub const UV_EAFNOSUPPORT: i32 = @intFromEnum(SystemErrno.EAFNOSUPPORT); +pub const UV_EAGAIN: i32 = @intFromEnum(SystemErrno.EAGAIN); +pub const UV_EALREADY: i32 = @intFromEnum(SystemErrno.EALREADY); +pub const UV_EBADF: i32 = @intFromEnum(SystemErrno.EBADF); +pub const UV_EBUSY: i32 = @intFromEnum(SystemErrno.EBUSY); +pub const UV_ECANCELED: i32 = @intFromEnum(SystemErrno.ECANCELED); +pub const UV_ECHARSET: i32 = -bun.windows.libuv.UV__ECHARSET; +pub const UV_ECONNABORTED: i32 = @intFromEnum(SystemErrno.ECONNABORTED); +pub const UV_ECONNREFUSED: i32 = @intFromEnum(SystemErrno.ECONNREFUSED); +pub const UV_ECONNRESET: i32 = @intFromEnum(SystemErrno.ECONNRESET); +pub const UV_EDESTADDRREQ: i32 = @intFromEnum(SystemErrno.EDESTADDRREQ); +pub const UV_EEXIST: i32 = @intFromEnum(SystemErrno.EEXIST); +pub const UV_EFAULT: i32 = @intFromEnum(SystemErrno.EFAULT); +pub const UV_EHOSTUNREACH: i32 = @intFromEnum(SystemErrno.EHOSTUNREACH); +pub const UV_EINTR: i32 = @intFromEnum(SystemErrno.EINTR); +pub const UV_EINVAL: i32 = @intFromEnum(SystemErrno.EINVAL); +pub const UV_EIO: i32 = @intFromEnum(SystemErrno.EIO); +pub const UV_EISCONN: i32 = @intFromEnum(SystemErrno.EISCONN); +pub const UV_EISDIR: i32 = @intFromEnum(SystemErrno.EISDIR); +pub const UV_ELOOP: i32 = @intFromEnum(SystemErrno.ELOOP); +pub const UV_EMFILE: i32 = @intFromEnum(SystemErrno.EMFILE); +pub const UV_EMSGSIZE: i32 = @intFromEnum(SystemErrno.EMSGSIZE); +pub const UV_ENAMETOOLONG: i32 = @intFromEnum(SystemErrno.ENAMETOOLONG); +pub const UV_ENETDOWN: i32 = @intFromEnum(SystemErrno.ENETDOWN); +pub const UV_ENETUNREACH: i32 = @intFromEnum(SystemErrno.ENETUNREACH); +pub const UV_ENFILE: i32 = @intFromEnum(SystemErrno.ENFILE); +pub const UV_ENOBUFS: i32 = @intFromEnum(SystemErrno.ENOBUFS); +pub const UV_ENODEV: i32 = @intFromEnum(SystemErrno.ENODEV); +pub const UV_ENOENT: i32 = @intFromEnum(SystemErrno.ENOENT); +pub const UV_ENOMEM: i32 = @intFromEnum(SystemErrno.ENOMEM); +pub const UV_ENONET: i32 = -bun.windows.libuv.UV_ENONET; +pub const UV_ENOSPC: i32 = @intFromEnum(SystemErrno.ENOSPC); +pub const UV_ENOSYS: i32 = @intFromEnum(SystemErrno.ENOSYS); +pub const UV_ENOTCONN: i32 = @intFromEnum(SystemErrno.ENOTCONN); +pub const UV_ENOTDIR: i32 = @intFromEnum(SystemErrno.ENOTDIR); +pub const UV_ENOTEMPTY: i32 = @intFromEnum(SystemErrno.ENOTEMPTY); +pub const UV_ENOTSOCK: i32 = @intFromEnum(SystemErrno.ENOTSOCK); +pub const UV_ENOTSUP: i32 = @intFromEnum(SystemErrno.ENOTSUP); +pub const UV_EPERM: i32 = @intFromEnum(SystemErrno.EPERM); +pub const UV_EPIPE: i32 = @intFromEnum(SystemErrno.EPIPE); +pub const UV_EPROTO: i32 = @intFromEnum(SystemErrno.EPROTO); +pub const UV_EPROTONOSUPPORT: i32 = @intFromEnum(SystemErrno.EPROTONOSUPPORT); +pub const UV_EPROTOTYPE: i32 = @intFromEnum(SystemErrno.EPROTOTYPE); +pub const UV_EROFS: i32 = @intFromEnum(SystemErrno.EROFS); +pub const UV_ESHUTDOWN: i32 = @intFromEnum(SystemErrno.ESHUTDOWN); +pub const UV_ESPIPE: i32 = @intFromEnum(SystemErrno.ESPIPE); +pub const UV_ESRCH: i32 = @intFromEnum(SystemErrno.ESRCH); +pub const UV_ETIMEDOUT: i32 = @intFromEnum(SystemErrno.ETIMEDOUT); +pub const UV_ETXTBSY: i32 = @intFromEnum(SystemErrno.ETXTBSY); +pub const UV_EXDEV: i32 = @intFromEnum(SystemErrno.EXDEV); +pub const UV_EFBIG: i32 = @intFromEnum(SystemErrno.EFBIG); +pub const UV_ENOPROTOOPT: i32 = @intFromEnum(SystemErrno.ENOPROTOOPT); +pub const UV_ERANGE: i32 = @intFromEnum(SystemErrno.ERANGE); +pub const UV_ENXIO: i32 = @intFromEnum(SystemErrno.ENXIO); +pub const UV_EMLINK: i32 = @intFromEnum(SystemErrno.EMLINK); +pub const UV_EHOSTDOWN: i32 = @intFromEnum(SystemErrno.EHOSTDOWN); +pub const UV_EREMOTEIO: i32 = -bun.windows.libuv.UV_EREMOTEIO; +pub const UV_ENOTTY: i32 = @intFromEnum(SystemErrno.ENOTTY); +pub const UV_EFTYPE: i32 = @intFromEnum(SystemErrno.EFTYPE); +pub const UV_EILSEQ: i32 = @intFromEnum(SystemErrno.EILSEQ); +pub const UV_EOVERFLOW: i32 = @intFromEnum(SystemErrno.EOVERFLOW); +pub const UV_ESOCKTNOSUPPORT: i32 = @intFromEnum(SystemErrno.ESOCKTNOSUPPORT); +pub const UV_ENODATA: i32 = @intFromEnum(SystemErrno.ENODATA); +pub const UV_EUNATCH: i32 = -bun.windows.libuv.UV_EUNATCH; + // Courtesy of https://github.com/nodejs/node/blob/master/deps/uv/src/unix/darwin-stub.h pub const struct_CFArrayCallBacks = opaque {}; pub const CFIndex = c_long; diff --git a/src/js/internal/errors.ts b/src/js/internal/errors.ts new file mode 100644 index 0000000000000..034f33b4575e3 --- /dev/null +++ b/src/js/internal/errors.ts @@ -0,0 +1,4 @@ +export default { + ERR_INVALID_ARG_TYPE: $newCppFunction("NodeError.cpp", "jsFunction_ERR_INVALID_ARG_TYPE", 3), + ERR_OUT_OF_RANGE: $newCppFunction("NodeError.cpp", "jsFunction_ERR_OUT_OF_RANGE", 3), +}; diff --git a/src/js/node/util.ts b/src/js/node/util.ts index c237a1915fd97..eb7db1298542b 100644 --- a/src/js/node/util.ts +++ b/src/js/node/util.ts @@ -2,6 +2,11 @@ const types = require("node:util/types"); /** @type {import('node-inspect-extracted')} */ const utl = require("internal/util/inspect"); +const { ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE } = require("internal/errors"); + +const internalErrorName = $newZigFunction("node_util_binding.zig", "internalErrorName", 1); + +const NumberIsSafeInteger = Number.isSafeInteger; var cjs_exports = {}; @@ -280,6 +285,12 @@ function styleText(format, text) { return `\u001b[${formatCodes[0]}m${text}\u001b[${formatCodes[1]}m`; } +function getSystemErrorName(err: any) { + if (typeof err !== "number") throw ERR_INVALID_ARG_TYPE("err", "number", err); + if (err >= 0 || !NumberIsSafeInteger(err)) throw ERR_OUT_OF_RANGE("err", "a negative integer", err); + return internalErrorName(err); +} + export default Object.assign(cjs_exports, { format, formatWithOptions, @@ -315,4 +326,5 @@ export default Object.assign(cjs_exports, { TextEncoder, parseArgs, styleText, + getSystemErrorName, }); diff --git a/src/linux_c.zig b/src/linux_c.zig index 5ba1b39b75bf8..46e1b080a04b1 100644 --- a/src/linux_c.zig +++ b/src/linux_c.zig @@ -293,6 +293,75 @@ pub const SystemErrno = enum(u8) { }; }; +pub const UV_E2BIG: i32 = @intFromEnum(SystemErrno.E2BIG); +pub const UV_EACCES: i32 = @intFromEnum(SystemErrno.EACCES); +pub const UV_EADDRINUSE: i32 = @intFromEnum(SystemErrno.EADDRINUSE); +pub const UV_EADDRNOTAVAIL: i32 = @intFromEnum(SystemErrno.EADDRNOTAVAIL); +pub const UV_EAFNOSUPPORT: i32 = @intFromEnum(SystemErrno.EAFNOSUPPORT); +pub const UV_EAGAIN: i32 = @intFromEnum(SystemErrno.EAGAIN); +pub const UV_EALREADY: i32 = @intFromEnum(SystemErrno.EALREADY); +pub const UV_EBADF: i32 = @intFromEnum(SystemErrno.EBADF); +pub const UV_EBUSY: i32 = @intFromEnum(SystemErrno.EBUSY); +pub const UV_ECANCELED: i32 = @intFromEnum(SystemErrno.ECANCELED); +pub const UV_ECHARSET: i32 = -bun.windows.libuv.UV_ECHARSET; +pub const UV_ECONNABORTED: i32 = @intFromEnum(SystemErrno.ECONNABORTED); +pub const UV_ECONNREFUSED: i32 = @intFromEnum(SystemErrno.ECONNREFUSED); +pub const UV_ECONNRESET: i32 = @intFromEnum(SystemErrno.ECONNRESET); +pub const UV_EDESTADDRREQ: i32 = @intFromEnum(SystemErrno.EDESTADDRREQ); +pub const UV_EEXIST: i32 = @intFromEnum(SystemErrno.EEXIST); +pub const UV_EFAULT: i32 = @intFromEnum(SystemErrno.EFAULT); +pub const UV_EHOSTUNREACH: i32 = @intFromEnum(SystemErrno.EHOSTUNREACH); +pub const UV_EINTR: i32 = @intFromEnum(SystemErrno.EINTR); +pub const UV_EINVAL: i32 = @intFromEnum(SystemErrno.EINVAL); +pub const UV_EIO: i32 = @intFromEnum(SystemErrno.EIO); +pub const UV_EISCONN: i32 = @intFromEnum(SystemErrno.EISCONN); +pub const UV_EISDIR: i32 = @intFromEnum(SystemErrno.EISDIR); +pub const UV_ELOOP: i32 = @intFromEnum(SystemErrno.ELOOP); +pub const UV_EMFILE: i32 = @intFromEnum(SystemErrno.EMFILE); +pub const UV_EMSGSIZE: i32 = @intFromEnum(SystemErrno.EMSGSIZE); +pub const UV_ENAMETOOLONG: i32 = @intFromEnum(SystemErrno.ENAMETOOLONG); +pub const UV_ENETDOWN: i32 = @intFromEnum(SystemErrno.ENETDOWN); +pub const UV_ENETUNREACH: i32 = @intFromEnum(SystemErrno.ENETUNREACH); +pub const UV_ENFILE: i32 = @intFromEnum(SystemErrno.ENFILE); +pub const UV_ENOBUFS: i32 = @intFromEnum(SystemErrno.ENOBUFS); +pub const UV_ENODEV: i32 = @intFromEnum(SystemErrno.ENODEV); +pub const UV_ENOENT: i32 = @intFromEnum(SystemErrno.ENOENT); +pub const UV_ENOMEM: i32 = @intFromEnum(SystemErrno.ENOMEM); +pub const UV_ENONET: i32 = @intFromEnum(SystemErrno.ENONET); +pub const UV_ENOSPC: i32 = @intFromEnum(SystemErrno.ENOSPC); +pub const UV_ENOSYS: i32 = @intFromEnum(SystemErrno.ENOSYS); +pub const UV_ENOTCONN: i32 = @intFromEnum(SystemErrno.ENOTCONN); +pub const UV_ENOTDIR: i32 = @intFromEnum(SystemErrno.ENOTDIR); +pub const UV_ENOTEMPTY: i32 = @intFromEnum(SystemErrno.ENOTEMPTY); +pub const UV_ENOTSOCK: i32 = @intFromEnum(SystemErrno.ENOTSOCK); +pub const UV_ENOTSUP: i32 = @intFromEnum(SystemErrno.ENOTSUP); +pub const UV_EPERM: i32 = @intFromEnum(SystemErrno.EPERM); +pub const UV_EPIPE: i32 = @intFromEnum(SystemErrno.EPIPE); +pub const UV_EPROTO: i32 = @intFromEnum(SystemErrno.EPROTO); +pub const UV_EPROTONOSUPPORT: i32 = @intFromEnum(SystemErrno.EPROTONOSUPPORT); +pub const UV_EPROTOTYPE: i32 = @intFromEnum(SystemErrno.EPROTOTYPE); +pub const UV_EROFS: i32 = @intFromEnum(SystemErrno.EROFS); +pub const UV_ESHUTDOWN: i32 = @intFromEnum(SystemErrno.ESHUTDOWN); +pub const UV_ESPIPE: i32 = @intFromEnum(SystemErrno.ESPIPE); +pub const UV_ESRCH: i32 = @intFromEnum(SystemErrno.ESRCH); +pub const UV_ETIMEDOUT: i32 = @intFromEnum(SystemErrno.ETIMEDOUT); +pub const UV_ETXTBSY: i32 = @intFromEnum(SystemErrno.ETXTBSY); +pub const UV_EXDEV: i32 = @intFromEnum(SystemErrno.EXDEV); +pub const UV_EFBIG: i32 = @intFromEnum(SystemErrno.EFBIG); +pub const UV_ENOPROTOOPT: i32 = @intFromEnum(SystemErrno.ENOPROTOOPT); +pub const UV_ERANGE: i32 = @intFromEnum(SystemErrno.ERANGE); +pub const UV_ENXIO: i32 = @intFromEnum(SystemErrno.ENXIO); +pub const UV_EMLINK: i32 = @intFromEnum(SystemErrno.EMLINK); +pub const UV_EHOSTDOWN: i32 = @intFromEnum(SystemErrno.EHOSTDOWN); +pub const UV_EREMOTEIO: i32 = @intFromEnum(SystemErrno.EREMOTEIO); +pub const UV_ENOTTY: i32 = @intFromEnum(SystemErrno.ENOTTY); +pub const UV_EFTYPE: i32 = -bun.windows.libuv.UV_EFTYPE; +pub const UV_EILSEQ: i32 = @intFromEnum(SystemErrno.EILSEQ); +pub const UV_EOVERFLOW: i32 = @intFromEnum(SystemErrno.EOVERFLOW); +pub const UV_ESOCKTNOSUPPORT: i32 = @intFromEnum(SystemErrno.ESOCKTNOSUPPORT); +pub const UV_ENODATA: i32 = @intFromEnum(SystemErrno.ENODATA); +pub const UV_EUNATCH: i32 = @intFromEnum(SystemErrno.EUNATCH); + pub const preallocate_length = 2048 * 1024; pub fn preallocate_file(fd: std.posix.fd_t, offset: std.posix.off_t, len: std.posix.off_t) anyerror!void { // https://gist.github.com/Jarred-Sumner/b37b93399b63cbfd86e908c59a0a37df diff --git a/src/windows_c.zig b/src/windows_c.zig index d465ac0ecf155..db6a06b8a3efa 100644 --- a/src/windows_c.zig +++ b/src/windows_c.zig @@ -958,6 +958,75 @@ pub const SystemErrno = enum(u16) { }; }; +pub const UV_E2BIG = -uv.UV_E2BIG; +pub const UV_EACCES = -uv.UV_EACCES; +pub const UV_EADDRINUSE = -uv.UV_EADDRINUSE; +pub const UV_EADDRNOTAVAIL = -uv.UV_EADDRNOTAVAIL; +pub const UV_EAFNOSUPPORT = -uv.UV_EAFNOSUPPORT; +pub const UV_EAGAIN = -uv.UV_EAGAIN; +pub const UV_EALREADY = -uv.UV_EALREADY; +pub const UV_EBADF = -uv.UV_EBADF; +pub const UV_EBUSY = -uv.UV_EBUSY; +pub const UV_ECANCELED = -uv.UV_ECANCELED; +pub const UV_ECHARSET = -uv.UV_ECHARSET; +pub const UV_ECONNABORTED = -uv.UV_ECONNABORTED; +pub const UV_ECONNREFUSED = -uv.UV_ECONNREFUSED; +pub const UV_ECONNRESET = -uv.UV_ECONNRESET; +pub const UV_EDESTADDRREQ = -uv.UV_EDESTADDRREQ; +pub const UV_EEXIST = -uv.UV_EEXIST; +pub const UV_EFAULT = -uv.UV_EFAULT; +pub const UV_EHOSTUNREACH = -uv.UV_EHOSTUNREACH; +pub const UV_EINTR = -uv.UV_EINTR; +pub const UV_EINVAL = -uv.UV_EINVAL; +pub const UV_EIO = -uv.UV_EIO; +pub const UV_EISCONN = -uv.UV_EISCONN; +pub const UV_EISDIR = -uv.UV_EISDIR; +pub const UV_ELOOP = -uv.UV_ELOOP; +pub const UV_EMFILE = -uv.UV_EMFILE; +pub const UV_EMSGSIZE = -uv.UV_EMSGSIZE; +pub const UV_ENAMETOOLONG = -uv.UV_ENAMETOOLONG; +pub const UV_ENETDOWN = -uv.UV_ENETDOWN; +pub const UV_ENETUNREACH = -uv.UV_ENETUNREACH; +pub const UV_ENFILE = -uv.UV_ENFILE; +pub const UV_ENOBUFS = -uv.UV_ENOBUFS; +pub const UV_ENODEV = -uv.UV_ENODEV; +pub const UV_ENOENT = -uv.UV_ENOENT; +pub const UV_ENOMEM = -uv.UV_ENOMEM; +pub const UV_ENONET = -uv.UV_ENONET; +pub const UV_ENOSPC = -uv.UV_ENOSPC; +pub const UV_ENOSYS = -uv.UV_ENOSYS; +pub const UV_ENOTCONN = -uv.UV_ENOTCONN; +pub const UV_ENOTDIR = -uv.UV_ENOTDIR; +pub const UV_ENOTEMPTY = -uv.UV_ENOTEMPTY; +pub const UV_ENOTSOCK = -uv.UV_ENOTSOCK; +pub const UV_ENOTSUP = -uv.UV_ENOTSUP; +pub const UV_EPERM = -uv.UV_EPERM; +pub const UV_EPIPE = -uv.UV_EPIPE; +pub const UV_EPROTO = -uv.UV_EPROTO; +pub const UV_EPROTONOSUPPORT = -uv.UV_EPROTONOSUPPORT; +pub const UV_EPROTOTYPE = -uv.UV_EPROTOTYPE; +pub const UV_EROFS = -uv.UV_EROFS; +pub const UV_ESHUTDOWN = -uv.UV_ESHUTDOWN; +pub const UV_ESPIPE = -uv.UV_ESPIPE; +pub const UV_ESRCH = -uv.UV_ESRCH; +pub const UV_ETIMEDOUT = -uv.UV_ETIMEDOUT; +pub const UV_ETXTBSY = -uv.UV_ETXTBSY; +pub const UV_EXDEV = -uv.UV_EXDEV; +pub const UV_EFBIG = -uv.UV_EFBIG; +pub const UV_ENOPROTOOPT = -uv.UV_ENOPROTOOPT; +pub const UV_ERANGE = -uv.UV_ERANGE; +pub const UV_ENXIO = -uv.UV_ENXIO; +pub const UV_EMLINK = -uv.UV_EMLINK; +pub const UV_EHOSTDOWN = -uv.UV_EHOSTDOWN; +pub const UV_EREMOTEIO = -uv.UV_EREMOTEIO; +pub const UV_ENOTTY = -uv.UV_ENOTTY; +pub const UV_EFTYPE = -uv.UV_EFTYPE; +pub const UV_EILSEQ = -uv.UV_EILSEQ; +pub const UV_EOVERFLOW = -uv.UV_EOVERFLOW; +pub const UV_ESOCKTNOSUPPORT = -uv.UV_ESOCKTNOSUPPORT; +pub const UV_ENODATA = -uv.UV_ENODATA; +pub const UV_EUNATCH = -uv.UV_EUNATCH; + pub const off_t = i64; pub fn preallocate_file(_: posix.fd_t, _: off_t, _: off_t) !void {} diff --git a/test/harness.ts b/test/harness.ts index 704d41f1f9e92..6710381e756ea 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -386,6 +386,43 @@ expect.extend({ message: () => `Expected ${cmds.join(" ")} to fail`, }; }, + toThrowWithCode(fn: CallableFunction, cls: CallableFunction, code: string) { + try { + fn(); + return { + pass: false, + message: () => `Received function did not throw`, + }; + } catch (e) { + // expect(e).toBeInstanceOf(cls); + if (!(e instanceof cls)) { + return { + pass: false, + message: () => `Expected error to be instanceof ${cls.name}; got ${e.__proto__.constructor.name}`, + }; + } + + // expect(e).toHaveProperty("code"); + if (!("code" in e)) { + return { + pass: false, + message: () => `Expected error to have property 'code'; got ${e}`, + }; + } + + // expect(e.code).toEqual(code); + if (e.code !== code) { + return { + pass: false, + message: () => `Expected error to have code '${code}'; got ${e.code}`, + }; + } + + return { + pass: true, + }; + } + }, }); export function ospath(path: string) { @@ -1033,6 +1070,7 @@ interface BunHarnessTestMatchers { toHaveTestTimedOutAfter(expected: number): void; toBeBinaryType(expected: keyof typeof binaryTypes): void; toRun(optionalStdout?: string, expectedCode?: number): void; + toThrowWithCode(cls: CallableFunction, code: string): void; } declare module "bun:test" { diff --git a/test/js/node/util/util.test.js b/test/js/node/util/util.test.js index 4c1c51511e08c..a1f63ca801012 100644 --- a/test/js/node/util/util.test.js +++ b/test/js/node/util/util.test.js @@ -24,6 +24,7 @@ import { expect, describe, it } from "bun:test"; import util from "util"; import assert from "assert"; +import "harness"; // const context = require('vm').runInNewContext; // TODO: Use a vm polyfill const strictEqual = (...args) => { @@ -357,4 +358,46 @@ describe("util", () => { assert.strictEqual(util.styleText("red", "test"), "\u001b[31mtest\u001b[39m"); }); + + describe("getSystemErrorName", () => { + for (const item of ["test", {}, []]) { + it(`throws when passing: ${item}`, () => { + expect(() => util.getSystemErrorName(item)).toThrowWithCode(TypeError, "ERR_INVALID_ARG_TYPE"); + }); + } + + for (const item of [0, 1, Infinity, -Infinity, NaN]) { + it(`throws when passing: ${item}`, () => { + expect(() => util.getSystemErrorName(item)).toThrowWithCode(RangeError, "ERR_OUT_OF_RANGE"); + }); + } + + const proc = Bun.spawnSync({ + cmd: [ + "node", + "-e", + "console.log(JSON.stringify([...require('node:util').getSystemErrorMap().entries()].map((v) => [v[0], v[1][0]])));", + ], + stdio: ["ignore", "pipe", "pipe"], + }); + for (const [code, name] of JSON.parse(proc.stdout.toString())) { + it(`getSystemErrorName(${code}) should be ${name}`, () => { + expect(util.getSystemErrorName(code)).toBe(name); + }); + } + + it("getSystemErrorName(-4096) should be unknown", () => { + expect(util.getSystemErrorName(-4096)).toBe("Unknown system error -4096"); + }); + + // these are the windows/fallback codes and they should match node in either returning the correct name or 'Unknown system error'. + // eg on linux getSystemErrorName(-4034) should return unkown and not 'ERANGE' since errno defines it as -34 for that platform. + for (let i = -4095; i <= -4023; i++) { + it(`negative space: getSystemErrorName(${i}) is correct`, () => { + const cmd = ["node", "-e", `console.log(JSON.stringify(util.getSystemErrorName(${i})));`]; + const stdio = ["ignore", "pipe", "pipe"]; + expect(util.getSystemErrorName(i)).toEqual(JSON.parse(Bun.spawnSync({ cmd, stdio }).stdout.toString())); + }); + } + }); });