mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 13:22:07 +00:00
425 lines
11 KiB
C++
425 lines
11 KiB
C++
#include "ProcessBindingUV.h"
|
|
#include "JavaScriptCore/ArrayAllocationProfile.h"
|
|
#include "JavaScriptCore/JSCJSValue.h"
|
|
#include "JavaScriptCore/ThrowScope.h"
|
|
#include "ZigGlobalObject.h"
|
|
#include "JavaScriptCore/ObjectConstructor.h"
|
|
#include "JavaScriptCore/JSMap.h"
|
|
#include "JavaScriptCore/JSMapInlines.h"
|
|
|
|
// clang-format off
|
|
|
|
#if !defined(E2BIG)
|
|
#define E2BIG 7
|
|
#endif
|
|
#if !defined(EACCES)
|
|
#define EACCES 13
|
|
#endif
|
|
#if !defined(EADDRINUSE)
|
|
#define EADDRINUSE 48
|
|
#endif
|
|
#if !defined(EADDRNOTAVAIL)
|
|
#define EADDRNOTAVAIL 49
|
|
#endif
|
|
#if !defined(EAFNOSUPPORT)
|
|
#define EAFNOSUPPORT 47
|
|
#endif
|
|
#if !defined(EAGAIN)
|
|
#define EAGAIN 35
|
|
#endif
|
|
#if !defined(EAI_ADDRFAMILY)
|
|
#define EAI_ADDRFAMILY 3000
|
|
#endif
|
|
#if !defined(EAI_AGAIN)
|
|
#define EAI_AGAIN 3001
|
|
#endif
|
|
#if !defined(EAI_BADFLAGS)
|
|
#define EAI_BADFLAGS 3002
|
|
#endif
|
|
#if !defined(EAI_BADHINTS)
|
|
#define EAI_BADHINTS 3013
|
|
#endif
|
|
#if !defined(EAI_CANCELED)
|
|
#define EAI_CANCELED 3003
|
|
#endif
|
|
#if !defined(EAI_FAIL)
|
|
#define EAI_FAIL 3004
|
|
#endif
|
|
#if !defined(EAI_FAMILY)
|
|
#define EAI_FAMILY 3005
|
|
#endif
|
|
#if !defined(EAI_MEMORY)
|
|
#define EAI_MEMORY 3006
|
|
#endif
|
|
#if !defined(EAI_NODATA)
|
|
#define EAI_NODATA 3007
|
|
#endif
|
|
#if !defined(EAI_NONAME)
|
|
#define EAI_NONAME 3008
|
|
#endif
|
|
#if !defined(EAI_OVERFLOW)
|
|
#define EAI_OVERFLOW 3009
|
|
#endif
|
|
#if !defined(EAI_PROTOCOL)
|
|
#define EAI_PROTOCOL 3014
|
|
#endif
|
|
#if !defined(EAI_SERVICE)
|
|
#define EAI_SERVICE 3010
|
|
#endif
|
|
#if !defined(EAI_SOCKTYPE)
|
|
#define EAI_SOCKTYPE 3011
|
|
#endif
|
|
#if !defined(EALREADY)
|
|
#define EALREADY 37
|
|
#endif
|
|
#if !defined(EBADF)
|
|
#define EBADF 9
|
|
#endif
|
|
#if !defined(EBUSY)
|
|
#define EBUSY 16
|
|
#endif
|
|
#if !defined(ECANCELED)
|
|
#define ECANCELED 89
|
|
#endif
|
|
#if !defined(ECHARSET)
|
|
#define ECHARSET 4080
|
|
#endif
|
|
#if !defined(ECONNABORTED)
|
|
#define ECONNABORTED 53
|
|
#endif
|
|
#if !defined(ECONNREFUSED)
|
|
#define ECONNREFUSED 61
|
|
#endif
|
|
#if !defined(ECONNRESET)
|
|
#define ECONNRESET 54
|
|
#endif
|
|
#if !defined(EDESTADDRREQ)
|
|
#define EDESTADDRREQ 39
|
|
#endif
|
|
#if !defined(EEXIST)
|
|
#define EEXIST 17
|
|
#endif
|
|
#if !defined(EFAULT)
|
|
#define EFAULT 14
|
|
#endif
|
|
#if !defined(EFBIG)
|
|
#define EFBIG 27
|
|
#endif
|
|
#if !defined(EHOSTUNREACH)
|
|
#define EHOSTUNREACH 65
|
|
#endif
|
|
#if !defined(EINTR)
|
|
#define EINTR 4
|
|
#endif
|
|
#if !defined(EINVAL)
|
|
#define EINVAL 22
|
|
#endif
|
|
#if !defined(EIO)
|
|
#define EIO 5
|
|
#endif
|
|
#if !defined(EISCONN)
|
|
#define EISCONN 56
|
|
#endif
|
|
#if !defined(EISDIR)
|
|
#define EISDIR 21
|
|
#endif
|
|
#if !defined(ELOOP)
|
|
#define ELOOP 62
|
|
#endif
|
|
#if !defined(EMFILE)
|
|
#define EMFILE 24
|
|
#endif
|
|
#if !defined(EMSGSIZE)
|
|
#define EMSGSIZE 40
|
|
#endif
|
|
#if !defined(ENAMETOOLONG)
|
|
#define ENAMETOOLONG 63
|
|
#endif
|
|
#if !defined(ENETDOWN)
|
|
#define ENETDOWN 50
|
|
#endif
|
|
#if !defined(ENETUNREACH)
|
|
#define ENETUNREACH 51
|
|
#endif
|
|
#if !defined(ENFILE)
|
|
#define ENFILE 23
|
|
#endif
|
|
#if !defined(ENOBUFS)
|
|
#define ENOBUFS 55
|
|
#endif
|
|
#if !defined(ENODEV)
|
|
#define ENODEV 19
|
|
#endif
|
|
#if !defined(ENOENT)
|
|
#define ENOENT 2
|
|
#endif
|
|
#if !defined(ENOMEM)
|
|
#define ENOMEM 12
|
|
#endif
|
|
#if !defined(ENONET)
|
|
#define ENONET 4056
|
|
#endif
|
|
#if !defined(ENOPROTOOPT)
|
|
#define ENOPROTOOPT 42
|
|
#endif
|
|
#if !defined(ENOSPC)
|
|
#define ENOSPC 28
|
|
#endif
|
|
#if !defined(ENOSYS)
|
|
#define ENOSYS 78
|
|
#endif
|
|
#if !defined(ENOTCONN)
|
|
#define ENOTCONN 57
|
|
#endif
|
|
#if !defined(ENOTDIR)
|
|
#define ENOTDIR 20
|
|
#endif
|
|
#if !defined(ENOTEMPTY)
|
|
#define ENOTEMPTY 66
|
|
#endif
|
|
#if !defined(ENOTSOCK)
|
|
#define ENOTSOCK 38
|
|
#endif
|
|
#if !defined(ENOTSUP)
|
|
#define ENOTSUP 45
|
|
#endif
|
|
#if !defined(EOVERFLOW)
|
|
#define EOVERFLOW 84
|
|
#endif
|
|
#if !defined(EPERM)
|
|
#define EPERM 1
|
|
#endif
|
|
#if !defined(EPIPE)
|
|
#define EPIPE 32
|
|
#endif
|
|
#if !defined(EPROTO)
|
|
#define EPROTO 100
|
|
#endif
|
|
#if !defined(EPROTONOSUPPORT)
|
|
#define EPROTONOSUPPORT 43
|
|
#endif
|
|
#if !defined(EPROTOTYPE)
|
|
#define EPROTOTYPE 41
|
|
#endif
|
|
#if !defined(ERANGE)
|
|
#define ERANGE 34
|
|
#endif
|
|
#if !defined(EROFS)
|
|
#define EROFS 30
|
|
#endif
|
|
#if !defined(ESHUTDOWN)
|
|
#define ESHUTDOWN 58
|
|
#endif
|
|
#if !defined(ESPIPE)
|
|
#define ESPIPE 29
|
|
#endif
|
|
#if !defined(ESRCH)
|
|
#define ESRCH 3
|
|
#endif
|
|
#if !defined(ETIMEDOUT)
|
|
#define ETIMEDOUT 60
|
|
#endif
|
|
#if !defined(ETXTBSY)
|
|
#define ETXTBSY 26
|
|
#endif
|
|
#if !defined(EXDEV)
|
|
#define EXDEV 18
|
|
#endif
|
|
#if !defined(UNKNOWN)
|
|
#define UNKNOWN 4094
|
|
#endif
|
|
// this is intentionally always overridden
|
|
#if defined(EOF)
|
|
#undef EOF
|
|
#endif
|
|
#define EOF 4095
|
|
#if !defined(ENXIO)
|
|
#define ENXIO 6
|
|
#endif
|
|
#if !defined(EMLINK)
|
|
#define EMLINK 31
|
|
#endif
|
|
#if !defined(EHOSTDOWN)
|
|
#define EHOSTDOWN 64
|
|
#endif
|
|
#if !defined(EREMOTEIO)
|
|
#define EREMOTEIO 4030
|
|
#endif
|
|
#if !defined(ENOTTY)
|
|
#define ENOTTY 25
|
|
#endif
|
|
#if !defined(EFTYPE)
|
|
#define EFTYPE 79
|
|
#endif
|
|
#if !defined(EILSEQ)
|
|
#define EILSEQ 92
|
|
#endif
|
|
#if !defined(ESOCKTNOSUPPORT)
|
|
#define ESOCKTNOSUPPORT 44
|
|
#endif
|
|
#if !defined(ENODATA)
|
|
#define ENODATA 96
|
|
#endif
|
|
#if !defined(EUNATCH)
|
|
#define EUNATCH 4023
|
|
#endif
|
|
|
|
#define BUN_UV_ERRNO_MAP(macro) \
|
|
macro(E2BIG, "argument list too long") \
|
|
macro(EACCES, "permission denied") \
|
|
macro(EADDRINUSE, "address already in use") \
|
|
macro(EADDRNOTAVAIL, "address not available") \
|
|
macro(EAFNOSUPPORT, "address family not supported") \
|
|
macro(EAGAIN, "resource temporarily unavailable") \
|
|
macro(EAI_ADDRFAMILY, "address family not supported") \
|
|
macro(EAI_AGAIN, "temporary failure") \
|
|
macro(EAI_BADFLAGS, "bad ai_flags value") \
|
|
macro(EAI_BADHINTS, "invalid value for hints") \
|
|
macro(EAI_CANCELED, "request canceled") \
|
|
macro(EAI_FAIL, "permanent failure") \
|
|
macro(EAI_FAMILY, "ai_family not supported") \
|
|
macro(EAI_MEMORY, "out of memory") \
|
|
macro(EAI_NODATA, "no address") \
|
|
macro(EAI_NONAME, "unknown node or service") \
|
|
macro(EAI_OVERFLOW, "argument buffer overflow") \
|
|
macro(EAI_PROTOCOL, "resolved protocol is unknown") \
|
|
macro(EAI_SERVICE, "service not available for socket type") \
|
|
macro(EAI_SOCKTYPE, "socket type not supported") \
|
|
macro(EALREADY, "connection already in progress") \
|
|
macro(EBADF, "bad file descriptor") \
|
|
macro(EBUSY, "resource busy or locked") \
|
|
macro(ECANCELED, "operation canceled") \
|
|
macro(ECHARSET, "invalid Unicode character") \
|
|
macro(ECONNABORTED, "software caused connection abort") \
|
|
macro(ECONNREFUSED, "connection refused") \
|
|
macro(ECONNRESET, "connection reset by peer") \
|
|
macro(EDESTADDRREQ, "destination address required") \
|
|
macro(EEXIST, "file already exists") \
|
|
macro(EFAULT, "bad address in system call argument") \
|
|
macro(EFBIG, "file too large") \
|
|
macro(EHOSTUNREACH, "host is unreachable") \
|
|
macro(EINTR, "interrupted system call") \
|
|
macro(EINVAL, "invalid argument") \
|
|
macro(EIO, "i/o error") \
|
|
macro(EISCONN, "socket is already connected") \
|
|
macro(EISDIR, "illegal operation on a directory") \
|
|
macro(ELOOP, "too many symbolic links encountered") \
|
|
macro(EMFILE, "too many open files") \
|
|
macro(EMSGSIZE, "message too long") \
|
|
macro(ENAMETOOLONG, "name too long") \
|
|
macro(ENETDOWN, "network is down") \
|
|
macro(ENETUNREACH, "network is unreachable") \
|
|
macro(ENFILE, "file table overflow") \
|
|
macro(ENOBUFS, "no buffer space available") \
|
|
macro(ENODEV, "no such device") \
|
|
macro(ENOENT, "no such file or directory") \
|
|
macro(ENOMEM, "not enough memory") \
|
|
macro(ENONET, "machine is not on the network") \
|
|
macro(ENOPROTOOPT, "protocol not available") \
|
|
macro(ENOSPC, "no space left on device") \
|
|
macro(ENOSYS, "function not implemented") \
|
|
macro(ENOTCONN, "socket is not connected") \
|
|
macro(ENOTDIR, "not a directory") \
|
|
macro(ENOTEMPTY, "directory not empty") \
|
|
macro(ENOTSOCK, "socket operation on non-socket") \
|
|
macro(ENOTSUP, "operation not supported on socket") \
|
|
macro(EOVERFLOW, "value too large for defined data type") \
|
|
macro(EPERM, "operation not permitted") \
|
|
macro(EPIPE, "broken pipe") \
|
|
macro(EPROTO, "protocol error") \
|
|
macro(EPROTONOSUPPORT, "protocol not supported") \
|
|
macro(EPROTOTYPE, "protocol wrong type for socket") \
|
|
macro(ERANGE, "result too large") \
|
|
macro(EROFS, "read-only file system") \
|
|
macro(ESHUTDOWN, "cannot send after transport endpoint shutdown") \
|
|
macro(ESPIPE, "invalid seek") \
|
|
macro(ESRCH, "no such process") \
|
|
macro(ETIMEDOUT, "connection timed out") \
|
|
macro(ETXTBSY, "text file is busy") \
|
|
macro(EXDEV, "cross-device link not permitted") \
|
|
macro(UNKNOWN, "unknown error") \
|
|
macro(EOF, "end of file") \
|
|
macro(ENXIO, "no such device or address") \
|
|
macro(EMLINK, "too many links") \
|
|
macro(EHOSTDOWN, "host is down") \
|
|
macro(EREMOTEIO, "remote I/O error") \
|
|
macro(ENOTTY, "inappropriate ioctl for device") \
|
|
macro(EFTYPE, "inappropriate file type or format") \
|
|
macro(EILSEQ, "illegal byte sequence") \
|
|
macro(ESOCKTNOSUPPORT, "socket type not supported") \
|
|
macro(ENODATA, "no data available") \
|
|
macro(EUNATCH, "protocol driver not attached")
|
|
|
|
// clang-format on
|
|
namespace Bun {
|
|
namespace ProcessBindingUV {
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(jsErrname, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
|
{
|
|
auto& vm = JSC::getVM(globalObject);
|
|
auto arg0 = callFrame->argument(0);
|
|
|
|
// Node.js crashes here:
|
|
// However, we should ensure this function never throws
|
|
// That's why we do not call toPrimitive here or throw on invalid input.
|
|
if (!arg0.isInt32AsAnyInt()) [[unlikely]] {
|
|
return JSValue::encode(jsString(vm, String("Unknown system error"_s)));
|
|
}
|
|
|
|
auto err = arg0.toInt32(globalObject);
|
|
#define CASE(name, desc) \
|
|
if (err == -name) return JSValue::encode(JSC::jsString(vm, String(#name##_s)));
|
|
|
|
BUN_UV_ERRNO_MAP(CASE)
|
|
#undef CASE
|
|
|
|
return JSValue::encode(jsString(vm, makeString("Unknown system error: "_s, err)));
|
|
}
|
|
|
|
JSC_DEFINE_HOST_FUNCTION(jsGetErrorMap, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
|
{
|
|
auto& vm = JSC::getVM(globalObject);
|
|
auto map = JSC::JSMap::create(vm, globalObject->mapStructure());
|
|
|
|
// Inlining each of these via macros costs like 300 KB.
|
|
const auto putProperty = [](JSC::VM& vm, JSC::JSMap* map, JSC::JSGlobalObject* globalObject, ASCIILiteral name, int value, ASCIILiteral desc) -> void {
|
|
auto arr = JSC::constructEmptyArray(globalObject, static_cast<JSC::ArrayAllocationProfile*>(nullptr), 2);
|
|
// RETURN_IF_EXCEPTION
|
|
arr->putDirectIndex(globalObject, 0, JSC::jsString(vm, String(name)));
|
|
arr->putDirectIndex(globalObject, 1, JSC::jsString(vm, String(desc)));
|
|
map->set(globalObject, JSC::jsNumber(value), arr);
|
|
};
|
|
|
|
#define PUT_PROPERTY(name, desc) putProperty(vm, map, globalObject, #name##_s, -name, desc##_s);
|
|
BUN_UV_ERRNO_MAP(PUT_PROPERTY)
|
|
#undef PUT_PROPERTY
|
|
|
|
return JSValue::encode(map);
|
|
}
|
|
|
|
JSObject* create(VM& vm, JSGlobalObject* globalObject)
|
|
{
|
|
auto bindingObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 0);
|
|
EnsureStillAliveScope ensureStillAlive(bindingObject);
|
|
bindingObject->putDirect(vm, JSC::Identifier::fromString(vm, "errname"_s), JSC::JSFunction::create(vm, globalObject, 1, "errname"_s, jsErrname, ImplementationVisibility::Public));
|
|
|
|
// Inlining each of these via macros costs like 300 KB.
|
|
// Before: 96305608
|
|
// After: 95973832
|
|
const auto putNamedProperty = [](JSC::VM& vm, JSObject* bindingObject, const ASCIILiteral name, int value) -> void {
|
|
bindingObject->putDirect(vm, JSC::Identifier::fromString(vm, name), JSC::jsNumber(value));
|
|
};
|
|
|
|
#define PUT_PROPERTY(name, desc) \
|
|
putNamedProperty(vm, bindingObject, "UV_" #name##_s, -name);
|
|
BUN_UV_ERRNO_MAP(PUT_PROPERTY)
|
|
#undef PUT_PROPERTY
|
|
|
|
bindingObject->putDirect(vm, JSC::Identifier::fromString(vm, "getErrorMap"_s), JSC::JSFunction::create(vm, globalObject, 0, "getErrorMap"_s, jsGetErrorMap, ImplementationVisibility::Public));
|
|
|
|
return bindingObject;
|
|
}
|
|
|
|
} // namespace ProcessBindingUV
|
|
} // namespace Bun
|