mirror of
https://github.com/oven-sh/bun
synced 2026-02-04 16:08:53 +00:00
Compare commits
29 Commits
dylan/byte
...
nektro-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44069ef29f | ||
|
|
eed13c7823 | ||
|
|
f7652e6a3d | ||
|
|
5ea9de6214 | ||
|
|
234ba97830 | ||
|
|
63780d5411 | ||
|
|
fdcf59d5fb | ||
|
|
0c59cb4566 | ||
|
|
bc4a0e4d04 | ||
|
|
de82b4a34c | ||
|
|
c588751082 | ||
|
|
b4b82b8555 | ||
|
|
c69815ca66 | ||
|
|
77e8a35cad | ||
|
|
a985b076c5 | ||
|
|
d4828a1743 | ||
|
|
eb293d5a5a | ||
|
|
54e674404f | ||
|
|
842c713f81 | ||
|
|
76147dad5a | ||
|
|
2d49f62034 | ||
|
|
15ddb36f50 | ||
|
|
fbe9b9136b | ||
|
|
358eb10f1d | ||
|
|
aa4244b4d2 | ||
|
|
3271b2bb47 | ||
|
|
b6cd955f7e | ||
|
|
c154559f24 | ||
|
|
f34bf7be42 |
@@ -31,6 +31,8 @@
|
||||
#include <JavaScriptCore/LazyPropertyInlines.h>
|
||||
#include <JavaScriptCore/VMTrapsInlines.h>
|
||||
#include "wtf-bindings.h"
|
||||
#include "NodeValidator.h"
|
||||
|
||||
#include <webcore/SerializedScriptValue.h>
|
||||
#include "ProcessBindingTTYWrap.h"
|
||||
#include "wtf/text/ASCIILiteral.h"
|
||||
@@ -49,6 +51,9 @@
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#else
|
||||
#include <uv.h>
|
||||
#include <io.h>
|
||||
@@ -226,13 +231,10 @@ static JSValue constructProcessReleaseObject(VM& vm, JSObject* processObject)
|
||||
auto* globalObject = processObject->globalObject();
|
||||
auto* release = JSC::constructEmptyObject(globalObject);
|
||||
|
||||
// SvelteKit compatibility hack
|
||||
release->putDirect(vm, vm.propertyNames->name, jsString(vm, WTF::String("node"_s)), 0);
|
||||
release->putDirect(vm, vm.propertyNames->name, jsString(vm, String("node"_s)), 0); // maybe this should be 'bun' eventually
|
||||
|
||||
release->putDirect(vm, Identifier::fromString(vm, "lts"_s), jsBoolean(false), 0);
|
||||
release->putDirect(vm, Identifier::fromString(vm, "sourceUrl"_s), jsString(vm, WTF::String(std::span { Bun__githubURL, strlen(Bun__githubURL) })), 0);
|
||||
release->putDirect(vm, Identifier::fromString(vm, "headersUrl"_s), jsEmptyString(vm), 0);
|
||||
release->putDirect(vm, Identifier::fromString(vm, "libUrl"_s), jsEmptyString(vm), 0);
|
||||
release->putDirect(vm, Identifier::fromString(vm, "headersUrl"_s), jsString(vm, String("https://nodejs.org/download/release/v" REPORTED_NODEJS_VERSION "/node-v" REPORTED_NODEJS_VERSION "-headers.tar.gz"_s)), 0);
|
||||
|
||||
return release;
|
||||
}
|
||||
@@ -463,7 +465,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUmask,
|
||||
|
||||
double number = numberValue.toNumber(globalObject);
|
||||
int64_t newUmask = isInt52(number) ? tryConvertToInt52(number) : numberValue.toInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::JSValue {}));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
if (newUmask < 0 || newUmask > 4294967295) {
|
||||
return Bun::ERR::OUT_OF_RANGE(throwScope, globalObject, "mask"_s, 0, 4294967295, numberValue);
|
||||
}
|
||||
@@ -507,21 +509,21 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUptime,
|
||||
return JSC::JSValue::encode(JSC::jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionExit,
|
||||
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionExit, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm());
|
||||
auto& vm = globalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
uint8_t exitCode = 0;
|
||||
JSValue arg0 = callFrame->argument(0);
|
||||
if (arg0.isAnyInt()) {
|
||||
int extiCode32 = arg0.toInt32(globalObject) % 256;
|
||||
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::JSValue {}));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
exitCode = static_cast<uint8_t>(extiCode32);
|
||||
Bun__setExitCode(bunVM(globalObject), exitCode);
|
||||
} else if (!arg0.isUndefinedOrNull()) {
|
||||
throwTypeError(globalObject, throwScope, "The \"code\" argument must be an integer"_s);
|
||||
return {};
|
||||
return Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "code"_s, "number"_s, arg0);
|
||||
} else {
|
||||
exitCode = Bun__getExitCode(bunVM(globalObject));
|
||||
}
|
||||
@@ -531,7 +533,15 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionExit,
|
||||
process->m_isExitCodeObservable = true;
|
||||
|
||||
Process__dispatchOnExit(zigGlobal, exitCode);
|
||||
Bun__Process__exit(zigGlobal, exitCode);
|
||||
|
||||
// process.reallyExit(exitCode);
|
||||
auto reallyExitVal = process->get(globalObject, Identifier::fromString(vm, "reallyExit"_s));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
MarkedArgumentBuffer args;
|
||||
args.append(jsNumber(exitCode));
|
||||
JSC::call(globalObject, reallyExitVal, args, ""_s);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
return JSC::JSValue::encode(jsUndefined());
|
||||
}
|
||||
|
||||
@@ -563,12 +573,9 @@ JSC_DEFINE_HOST_FUNCTION(Process_hasUncaughtExceptionCaptureCallback,
|
||||
|
||||
extern "C" uint64_t Bun__readOriginTimer(void*);
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionHRTime,
|
||||
(JSC::JSGlobalObject * globalObject_, JSC::CallFrame* callFrame))
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionHRTime, (JSC::JSGlobalObject * globalObject_, JSC::CallFrame* callFrame))
|
||||
{
|
||||
|
||||
Zig::GlobalObject* globalObject
|
||||
= reinterpret_cast<Zig::GlobalObject*>(globalObject_);
|
||||
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject_);
|
||||
auto& vm = globalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
@@ -576,29 +583,25 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionHRTime,
|
||||
int64_t seconds = static_cast<int64_t>(time / 1000000000);
|
||||
int64_t nanoseconds = time % 1000000000;
|
||||
|
||||
if (callFrame->argumentCount() > 0) {
|
||||
JSC::JSValue arg0 = callFrame->uncheckedArgument(0);
|
||||
if (!arg0.isUndefinedOrNull()) {
|
||||
JSArray* relativeArray = JSC::jsDynamicCast<JSC::JSArray*>(arg0);
|
||||
if ((!relativeArray && !arg0.isUndefinedOrNull()) || relativeArray->length() < 2) {
|
||||
JSC::throwTypeError(globalObject, throwScope, "hrtime() argument must be an array or undefined"_s);
|
||||
return {};
|
||||
}
|
||||
JSValue relativeSecondsValue = relativeArray->getIndexQuickly(0);
|
||||
JSValue relativeNanosecondsValue = relativeArray->getIndexQuickly(1);
|
||||
if (!relativeSecondsValue.isNumber() || !relativeNanosecondsValue.isNumber()) {
|
||||
JSC::throwTypeError(globalObject, throwScope, "hrtime() argument must be an array of 2 integers"_s);
|
||||
return {};
|
||||
}
|
||||
auto arg0 = callFrame->argument(0);
|
||||
if (callFrame->argumentCount() > 0 && !arg0.isUndefined()) {
|
||||
JSArray* relativeArray = JSC::jsDynamicCast<JSC::JSArray*>(arg0);
|
||||
if (!relativeArray) {
|
||||
return Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "time"_s, "Array"_s, arg0);
|
||||
}
|
||||
Bun::V::validateInteger(throwScope, globalObject, jsNumber(relativeArray->length()), jsString(vm, String("time"_s)), jsNumber(2), jsNumber(2));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
int64_t relativeSeconds = JSC__JSValue__toInt64(JSC::JSValue::encode(relativeSecondsValue));
|
||||
int64_t relativeNanoseconds = JSC__JSValue__toInt64(JSC::JSValue::encode(relativeNanosecondsValue));
|
||||
seconds -= relativeSeconds;
|
||||
nanoseconds -= relativeNanoseconds;
|
||||
if (nanoseconds < 0) {
|
||||
seconds--;
|
||||
nanoseconds += 1000000000;
|
||||
}
|
||||
JSValue relativeSecondsValue = relativeArray->getIndexQuickly(0);
|
||||
JSValue relativeNanosecondsValue = relativeArray->getIndexQuickly(1);
|
||||
|
||||
int64_t relativeSeconds = JSC__JSValue__toInt64(JSC::JSValue::encode(relativeSecondsValue));
|
||||
int64_t relativeNanoseconds = JSC__JSValue__toInt64(JSC::JSValue::encode(relativeNanosecondsValue));
|
||||
seconds -= relativeSeconds;
|
||||
nanoseconds -= relativeNanoseconds;
|
||||
if (nanoseconds < 0) {
|
||||
seconds--;
|
||||
nanoseconds += 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,8 +626,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionHRTime,
|
||||
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(array));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionHRTimeBigInt,
|
||||
(JSC::JSGlobalObject * globalObject_, JSC::CallFrame* callFrame))
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionHRTimeBigInt, (JSC::JSGlobalObject * globalObject_, JSC::CallFrame* callFrame))
|
||||
{
|
||||
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject_);
|
||||
return JSC::JSValue::encode(JSValue(JSC::JSBigInt::createFrom(globalObject, Bun__readOriginTimer(globalObject->bunVM()))));
|
||||
@@ -636,11 +638,11 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionChdir,
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
ZigString str = ZigString { nullptr, 0 };
|
||||
if (callFrame->argumentCount() > 0) {
|
||||
str = Zig::toZigString(callFrame->uncheckedArgument(0).toWTFString(globalObject));
|
||||
}
|
||||
auto value = callFrame->argument(0);
|
||||
Bun::V::validateString(scope, globalObject, value, jsString(vm, String("directory"_s)));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
ZigString str = Zig::toZigString(value.toWTFString(globalObject));
|
||||
JSC::JSValue result = JSC::JSValue::decode(Bun__Process__setCwd(globalObject, &str));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
@@ -1834,11 +1836,9 @@ static JSValue constructProcessConfigObject(VM& vm, JSObject* processObject)
|
||||
static JSValue constructProcessHrtimeObject(VM& vm, JSObject* processObject)
|
||||
{
|
||||
auto* globalObject = processObject->globalObject();
|
||||
JSC::JSFunction* hrtime = JSC::JSFunction::create(vm, globalObject, 0,
|
||||
String("hrtime"_s), Process_functionHRTime, ImplementationVisibility::Public);
|
||||
JSC::JSFunction* hrtime = JSC::JSFunction::create(vm, globalObject, 0, String("hrtime"_s), Process_functionHRTime, ImplementationVisibility::Public);
|
||||
|
||||
JSC::JSFunction* hrtimeBigInt = JSC::JSFunction::create(vm, globalObject, 0,
|
||||
String("bigint"_s), Process_functionHRTimeBigInt, ImplementationVisibility::Public);
|
||||
JSC::JSFunction* hrtimeBigInt = JSC::JSFunction::create(vm, globalObject, 0, String("bigint"_s), Process_functionHRTimeBigInt, ImplementationVisibility::Public);
|
||||
|
||||
hrtime->putDirect(vm, JSC::Identifier::fromString(vm, "bigint"_s), hrtimeBigInt);
|
||||
|
||||
@@ -2120,6 +2120,166 @@ JSC_DEFINE_HOST_FUNCTION(Process_functiongetgroups, (JSGlobalObject * globalObje
|
||||
|
||||
return JSValue::encode(groups);
|
||||
}
|
||||
|
||||
static JSValue maybe_uid_by_name(JSC::ThrowScope& throwScope, JSGlobalObject* globalObject, JSValue value)
|
||||
{
|
||||
if (!value.isNumber() && !value.isString()) return JSValue::decode(Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "id"_s, "number or string"_s, value));
|
||||
if (!value.isString()) return value;
|
||||
|
||||
auto str = value.getString(globalObject);
|
||||
if (!str.is8Bit()) {
|
||||
auto message = makeString("User identifier does not exist: "_s, str);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
auto name = (const char*)(str.span8().data());
|
||||
struct passwd pwd;
|
||||
struct passwd* pp = nullptr;
|
||||
char buf[8192];
|
||||
|
||||
if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
|
||||
return jsNumber(pp->pw_uid);
|
||||
}
|
||||
|
||||
auto message = makeString("User identifier does not exist: "_s, str);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
static JSValue maybe_gid_by_name(JSC::ThrowScope& throwScope, JSGlobalObject* globalObject, JSValue value)
|
||||
{
|
||||
if (!value.isNumber() && !value.isString()) return JSValue::decode(Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "id"_s, "number or string"_s, value));
|
||||
if (!value.isString()) return value;
|
||||
|
||||
auto str = value.getString(globalObject);
|
||||
if (!str.is8Bit()) {
|
||||
auto message = makeString("Group identifier does not exist: "_s, str);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
auto name = (const char*)(str.span8().data());
|
||||
struct group pwd;
|
||||
struct group* pp = nullptr;
|
||||
char buf[8192];
|
||||
|
||||
if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
|
||||
return jsNumber(pp->gr_gid);
|
||||
}
|
||||
|
||||
auto message = makeString("Group identifier does not exist: "_s, str);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetuid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
auto is_number = value.isNumber();
|
||||
value = maybe_uid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (is_number) Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 31) - 1));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto result = setuid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setuid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionseteuid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
auto is_number = value.isNumber();
|
||||
value = maybe_uid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (is_number) Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 31) - 1));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto result = seteuid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "seteuid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetegid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
auto is_number = value.isNumber();
|
||||
value = maybe_gid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (is_number) Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 31) - 1));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto result = setegid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setegid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetgid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
auto is_number = value.isNumber();
|
||||
value = maybe_gid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (is_number) Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 31) - 1));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto result = setgid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setgid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetgroups, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto groups = callFrame->argument(0);
|
||||
Bun::V::validateArray(scope, globalObject, groups, jsString(vm, String("groups"_s)), jsUndefined());
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto groupsArray = JSC::jsDynamicCast<JSC::JSArray*>(groups);
|
||||
auto count = groupsArray->length();
|
||||
gid_t groupsStack[64];
|
||||
if (count > 64) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, "groups.length"_s, 0, 64, groups);
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
auto item = groupsArray->getIndexQuickly(i);
|
||||
auto name = makeString("groups["_s, i, "]"_s);
|
||||
|
||||
if (item.isNumber()) {
|
||||
Bun::V::validateUint32(scope, globalObject, item, jsString(vm, name), jsUndefined());
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
groupsStack[i] = item.toUInt32(globalObject);
|
||||
continue;
|
||||
} else if (item.isString()) {
|
||||
item = maybe_gid_by_name(scope, globalObject, item);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
groupsStack[i] = item.toUInt32(globalObject);
|
||||
continue;
|
||||
}
|
||||
return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "number or string"_s, item);
|
||||
}
|
||||
|
||||
auto result = setgroups(count, groupsStack);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setgid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
#endif
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
@@ -2143,6 +2303,12 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject,
|
||||
return {};
|
||||
}
|
||||
|
||||
extern "C" uint64_t Bun__Os__getFreeMemory(void);
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_availableMemory, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
return JSValue::encode(jsDoubleNumber(Bun__Os__getFreeMemory()));
|
||||
}
|
||||
|
||||
#define PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE(str, issue) \
|
||||
{ \
|
||||
throwScope.throwException(globalObject, createError(globalObject, String("process.binding(\"" str "\") is not implemented in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/" issue ""_s))); \
|
||||
@@ -2236,12 +2402,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionReallyExit, (JSGlobalObject * globalObj
|
||||
JSValue arg0 = callFrame->argument(0);
|
||||
if (arg0.isAnyInt()) {
|
||||
exitCode = static_cast<uint8_t>(arg0.toInt32(globalObject) % 256);
|
||||
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::JSValue {}));
|
||||
} else if (!arg0.isUndefinedOrNull()) {
|
||||
throwTypeError(globalObject, throwScope, "The \"code\" argument must be an integer"_s);
|
||||
return {};
|
||||
} else {
|
||||
exitCode = Bun__getExitCode(bunVM(globalObject));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
}
|
||||
|
||||
auto* zigGlobal = defaultGlobalObject(globalObject);
|
||||
@@ -2338,14 +2499,9 @@ static Process* getProcessObject(JSC::JSGlobalObject* lexicalGlobalObject, JSVal
|
||||
return process;
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionConstrainedMemory,
|
||||
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionConstrainedMemory, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
#if OS(LINUX) || OS(FREEBSD)
|
||||
return JSValue::encode(jsDoubleNumber(static_cast<double>(WTF::ramSize())));
|
||||
#else
|
||||
return JSValue::encode(jsUndefined());
|
||||
#endif
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage,
|
||||
@@ -2381,8 +2537,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage,
|
||||
if (!comparatorValue.isUndefined()) {
|
||||
JSC::JSObject* comparator = comparatorValue.getObject();
|
||||
if (UNLIKELY(!comparator)) {
|
||||
throwTypeError(globalObject, throwScope, "Expected an object as the first argument"_s);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
return Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "previousValue"_s, "object"_s, comparatorValue);
|
||||
}
|
||||
|
||||
JSValue userValue;
|
||||
@@ -2392,34 +2547,28 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage,
|
||||
userValue = comparator->getDirect(0);
|
||||
systemValue = comparator->getDirect(1);
|
||||
} else {
|
||||
userValue = comparator->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "user"_s));
|
||||
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined()));
|
||||
userValue = comparator->get(globalObject, JSC::Identifier::fromString(vm, "user"_s));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
systemValue = comparator->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "system"_s));
|
||||
RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined()));
|
||||
systemValue = comparator->get(globalObject, JSC::Identifier::fromString(vm, "system"_s));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
}
|
||||
|
||||
if (UNLIKELY(!userValue || !userValue.isNumber())) {
|
||||
throwTypeError(globalObject, throwScope, "Expected a number for the 'user' property"_s);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
Bun::V::validateNumber(throwScope, globalObject, userValue, jsString(vm, String("prevValue.user"_s)), jsUndefined(), jsUndefined());
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
if (UNLIKELY(!systemValue || !systemValue.isNumber())) {
|
||||
throwTypeError(globalObject, throwScope, "Expected a number for the 'system' property"_s);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
Bun::V::validateNumber(throwScope, globalObject, systemValue, jsString(vm, String("prevValue.system"_s)), jsUndefined(), jsUndefined());
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
double userComparator = userValue.toNumber(globalObject);
|
||||
double systemComparator = systemValue.toNumber(globalObject);
|
||||
|
||||
if (userComparator > JSC::maxSafeInteger() || userComparator < 0 || std::isnan(userComparator)) {
|
||||
throwRangeError(globalObject, throwScope, "The 'user' property must be a number between 0 and 2^53"_s);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
if (!(userComparator >= 0 && userComparator <= JSC::maxSafeInteger())) {
|
||||
return Bun::ERR::INVALID_ARG_VALUE(throwScope, globalObject, "prevValue.user"_s, userValue, "must be a number between 0 and 2^53"_s);
|
||||
}
|
||||
|
||||
if (systemComparator > JSC::maxSafeInteger() || systemComparator < 0 || std::isnan(systemComparator)) {
|
||||
throwRangeError(globalObject, throwScope, "The 'system' property must be a number between 0 and 2^53"_s);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
if (!(systemComparator >= 0 && systemComparator <= JSC::maxSafeInteger())) {
|
||||
return Bun::ERR::INVALID_ARG_VALUE(throwScope, globalObject, "prevValue.system"_s, systemValue, "must be a number between 0 and 2^53"_s);
|
||||
}
|
||||
|
||||
user -= userComparator;
|
||||
@@ -2536,7 +2685,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsage,
|
||||
|
||||
JSC::JSObject* result = JSC::constructEmptyObject(vm, process->memoryUsageStructure());
|
||||
if (UNLIKELY(throwScope.exception())) {
|
||||
return JSC::JSValue::encode(JSC::JSValue {});
|
||||
return {};
|
||||
}
|
||||
|
||||
// Node.js:
|
||||
@@ -3011,6 +3160,7 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
|
||||
argv constructArgv PropertyCallback
|
||||
argv0 constructArgv0 PropertyCallback
|
||||
assert Process_functionAssert Function 1
|
||||
availableMemory Process_availableMemory Function 0
|
||||
binding Process_functionBinding Function 1
|
||||
browser constructBrowser PropertyCallback
|
||||
chdir Process_functionChdir Function 1
|
||||
@@ -3070,12 +3220,19 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
|
||||
_stopProfilerIdleNotifier Process_stubEmptyFunction Function 0
|
||||
_tickCallback Process_stubEmptyFunction Function 0
|
||||
_kill Process_functionReallyKill Function 2
|
||||
|
||||
#if !OS(WINDOWS)
|
||||
getegid Process_functiongetegid Function 0
|
||||
geteuid Process_functiongeteuid Function 0
|
||||
getgid Process_functiongetgid Function 0
|
||||
getgroups Process_functiongetgroups Function 0
|
||||
getuid Process_functiongetuid Function 0
|
||||
|
||||
setegid Process_functionsetegid Function 1
|
||||
seteuid Process_functionseteuid Function 1
|
||||
setgid Process_functionsetgid Function 1
|
||||
setgroups Process_functionsetgroups Function 1
|
||||
setuid Process_functionsetuid Function 1
|
||||
#endif
|
||||
@end
|
||||
*/
|
||||
|
||||
@@ -304,7 +304,7 @@ JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalO
|
||||
auto arg_name = val_arg_name.span8();
|
||||
ASSERT(WTF::charactersAreAllASCII(arg_name));
|
||||
|
||||
auto arg_kind = String(arg_name).startsWith("options."_s) ? "property"_s : "argument"_s;
|
||||
auto arg_kind = String(arg_name).contains("."_s) ? "property"_s : "argument"_s;
|
||||
|
||||
auto expected_type = val_expected_type.span8();
|
||||
ASSERT(WTF::charactersAreAllASCII(expected_type));
|
||||
@@ -324,7 +324,7 @@ JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalO
|
||||
auto arg_name = val_arg_name.toWTFString(globalObject);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
auto arg_kind = String(arg_name).startsWith("options."_s) ? "property"_s : "argument"_s;
|
||||
auto arg_kind = String(arg_name).contains("."_s) ? "property"_s : "argument"_s;
|
||||
|
||||
auto expected_type = val_expected_type.span8();
|
||||
ASSERT(WTF::charactersAreAllASCII(expected_type));
|
||||
@@ -360,6 +360,11 @@ JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObjec
|
||||
auto actual_value = JSValueToStringSafe(globalObject, actual);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
if (lower == upper) {
|
||||
auto message = makeString("The value of \""_s, arg_name, "\" is out of range. It must be "_s, lowerStr, ". Received "_s, actual_value);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_OUT_OF_RANGE, message));
|
||||
return {};
|
||||
}
|
||||
auto message = makeString("The value of \""_s, arg_name, "\" is out of range. It must be >= "_s, lowerStr, " and <= "_s, upperStr, ". Received "_s, actual_value);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_OUT_OF_RANGE, message));
|
||||
return {};
|
||||
@@ -407,13 +412,7 @@ JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObjec
|
||||
|
||||
JSC::EncodedJSValue INVALID_ARG_VALUE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& name, JSC::JSValue value, const WTF::String& reason)
|
||||
{
|
||||
ASCIILiteral type;
|
||||
{
|
||||
auto sp = name.span8();
|
||||
auto str = std::string_view((const char*)(sp.data()), sp.size());
|
||||
auto has = str.find('.') == std::string::npos;
|
||||
type = has ? "property"_s : "argument"_s;
|
||||
}
|
||||
auto type = name.contains("."_s) ? "property"_s : "argument"_s;
|
||||
|
||||
auto value_string = JSValueToStringSafe(globalObject, value);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
@@ -614,6 +613,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_BUFFER_OUT_OF_BOUNDS, (JSC::JSGlobalObje
|
||||
return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, "Attempt to access memory outside buffer bounds"_s));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_IPC_ONE_PIPE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*))
|
||||
{
|
||||
return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_IPC_ONE_PIPE, "Child process can have only one IPC pipe"_s));
|
||||
}
|
||||
|
||||
} // namespace Bun
|
||||
|
||||
JSC::JSValue WebCore::toJS(JSC::JSGlobalObject* globalObject, CommonAbortReason abortReason)
|
||||
|
||||
@@ -67,6 +67,7 @@ JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_BROTLI_INVALID_PARAM);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_BUFFER_TOO_LARGE);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_ZLIB_INITIALIZATION_FAILED);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_BUFFER_OUT_OF_BOUNDS);
|
||||
JSC_DECLARE_HOST_FUNCTION(jsFunction_ERR_IPC_ONE_PIPE);
|
||||
|
||||
enum Bound {
|
||||
LOWER,
|
||||
|
||||
@@ -45,6 +45,8 @@ export default [
|
||||
["ERR_BUFFER_OUT_OF_BOUNDS", RangeError, "RangeError"],
|
||||
["ERR_UNKNOWN_SIGNAL", TypeError, "TypeError"],
|
||||
["ERR_SOCKET_BAD_PORT", RangeError, "RangeError"],
|
||||
["ERR_IPC_ONE_PIPE", Error, "Error"],
|
||||
["ERR_UNKNOWN_CREDENTIAL", Error, "Error"],
|
||||
["ERR_STREAM_RELEASE_LOCK", Error, "AbortError"],
|
||||
|
||||
// Bun-specific
|
||||
|
||||
@@ -297,6 +297,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateArray, (JSC::JSGlobalObject * global
|
||||
auto value = callFrame->argument(0);
|
||||
auto name = callFrame->argument(1);
|
||||
auto minLength = callFrame->argument(2);
|
||||
return V::validateArray(scope, globalObject, value, name, minLength);
|
||||
}
|
||||
JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue minLength)
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
|
||||
if (minLength.isUndefined()) minLength = jsNumber(0);
|
||||
|
||||
@@ -348,7 +353,10 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateUint32, (JSC::JSGlobalObject * globa
|
||||
auto value = callFrame->argument(0);
|
||||
auto name = callFrame->argument(1);
|
||||
auto positive = callFrame->argument(2);
|
||||
|
||||
return V::validateUint32(scope, globalObject, value, name, positive);
|
||||
}
|
||||
JSC::EncodedJSValue V::validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue positive)
|
||||
{
|
||||
if (!value.isNumber()) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "number"_s, value);
|
||||
if (positive.isUndefined()) positive = jsBoolean(false);
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ JSC::EncodedJSValue validateNumber(JSC::ThrowScope& scope, JSC::JSGlobalObject*
|
||||
JSC::EncodedJSValue validateFiniteNumber(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue number, JSC::JSValue name);
|
||||
JSC::EncodedJSValue validateString(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name);
|
||||
JSC::EncodedJSValue validateString(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name);
|
||||
JSC::EncodedJSValue validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue minLength);
|
||||
JSC::EncodedJSValue validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue positive);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,31 @@ extern "C" uint64_t Bun__Os__getFreeMemory(void)
|
||||
vm_statistics_data_t info;
|
||||
mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t);
|
||||
|
||||
if (host_statistics(mach_host_self(), HOST_VM_INFO,
|
||||
(host_info_t)&info, &count)
|
||||
!= KERN_SUCCESS) {
|
||||
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&info, &count) != KERN_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint64_t)info.free_count * sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS(LINUX)
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
extern "C" uint64_t Bun__Os__getFreeMemory(void)
|
||||
{
|
||||
struct sysinfo info;
|
||||
if (sysinfo(&info) == 0) {
|
||||
return info.freeram * info.mem_unit;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS(WINDOWS)
|
||||
extern "C" uint64_t uv_get_available_memory(void);
|
||||
|
||||
extern "C" uint64_t Bun__Os__getFreeMemory(void)
|
||||
{
|
||||
return uv_get_available_memory();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,260 @@
|
||||
#include "root.h"
|
||||
#include "helpers.h"
|
||||
#include "BunClientData.h"
|
||||
#include <string.h>
|
||||
|
||||
const char* errno_string(int errorno)
|
||||
{
|
||||
#define ERRNO_CASE(e) \
|
||||
case e: \
|
||||
return #e;
|
||||
switch (errorno) {
|
||||
#ifdef EACCES
|
||||
ERRNO_CASE(EACCES);
|
||||
#endif
|
||||
#ifdef EADDRINUSE
|
||||
ERRNO_CASE(EADDRINUSE);
|
||||
#endif
|
||||
#ifdef EADDRNOTAVAIL
|
||||
ERRNO_CASE(EADDRNOTAVAIL);
|
||||
#endif
|
||||
#ifdef EAFNOSUPPORT
|
||||
ERRNO_CASE(EAFNOSUPPORT);
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
ERRNO_CASE(EAGAIN);
|
||||
#endif
|
||||
#ifdef EWOULDBLOCK
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
ERRNO_CASE(EWOULDBLOCK);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef EALREADY
|
||||
ERRNO_CASE(EALREADY);
|
||||
#endif
|
||||
#ifdef EBADF
|
||||
ERRNO_CASE(EBADF);
|
||||
#endif
|
||||
#ifdef EBADMSG
|
||||
ERRNO_CASE(EBADMSG);
|
||||
#endif
|
||||
#ifdef EBUSY
|
||||
ERRNO_CASE(EBUSY);
|
||||
#endif
|
||||
#ifdef ECANCELED
|
||||
ERRNO_CASE(ECANCELED);
|
||||
#endif
|
||||
#ifdef ECHILD
|
||||
ERRNO_CASE(ECHILD);
|
||||
#endif
|
||||
#ifdef ECONNABORTED
|
||||
ERRNO_CASE(ECONNABORTED);
|
||||
#endif
|
||||
#ifdef ECONNREFUSED
|
||||
ERRNO_CASE(ECONNREFUSED);
|
||||
#endif
|
||||
#ifdef ECONNRESET
|
||||
ERRNO_CASE(ECONNRESET);
|
||||
#endif
|
||||
#ifdef EDEADLK
|
||||
ERRNO_CASE(EDEADLK);
|
||||
#endif
|
||||
#ifdef EDESTADDRREQ
|
||||
ERRNO_CASE(EDESTADDRREQ);
|
||||
#endif
|
||||
#ifdef EDOM
|
||||
ERRNO_CASE(EDOM);
|
||||
#endif
|
||||
#ifdef EDQUOT
|
||||
ERRNO_CASE(EDQUOT);
|
||||
#endif
|
||||
#ifdef EEXIST
|
||||
ERRNO_CASE(EEXIST);
|
||||
#endif
|
||||
#ifdef EFAULT
|
||||
ERRNO_CASE(EFAULT);
|
||||
#endif
|
||||
#ifdef EFBIG
|
||||
ERRNO_CASE(EFBIG);
|
||||
#endif
|
||||
#ifdef EHOSTUNREACH
|
||||
ERRNO_CASE(EHOSTUNREACH);
|
||||
#endif
|
||||
#ifdef EIDRM
|
||||
ERRNO_CASE(EIDRM);
|
||||
#endif
|
||||
#ifdef EILSEQ
|
||||
ERRNO_CASE(EILSEQ);
|
||||
#endif
|
||||
#ifdef EINPROGRESS
|
||||
ERRNO_CASE(EINPROGRESS);
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
ERRNO_CASE(EINTR);
|
||||
#endif
|
||||
#ifdef EINVAL
|
||||
ERRNO_CASE(EINVAL);
|
||||
#endif
|
||||
#ifdef EIO
|
||||
ERRNO_CASE(EIO);
|
||||
#endif
|
||||
#ifdef EISCONN
|
||||
ERRNO_CASE(EISCONN);
|
||||
#endif
|
||||
#ifdef EISDIR
|
||||
ERRNO_CASE(EISDIR);
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
ERRNO_CASE(ELOOP);
|
||||
#endif
|
||||
#ifdef EMFILE
|
||||
ERRNO_CASE(EMFILE);
|
||||
#endif
|
||||
#ifdef EMLINK
|
||||
ERRNO_CASE(EMLINK);
|
||||
#endif
|
||||
#ifdef EMSGSIZE
|
||||
ERRNO_CASE(EMSGSIZE);
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
ERRNO_CASE(EMULTIHOP);
|
||||
#endif
|
||||
#ifdef ENAMETOOLONG
|
||||
ERRNO_CASE(ENAMETOOLONG);
|
||||
#endif
|
||||
#ifdef ENETDOWN
|
||||
ERRNO_CASE(ENETDOWN);
|
||||
#endif
|
||||
#ifdef ENETRESET
|
||||
ERRNO_CASE(ENETRESET);
|
||||
#endif
|
||||
#ifdef ENETUNREACH
|
||||
ERRNO_CASE(ENETUNREACH);
|
||||
#endif
|
||||
#ifdef ENFILE
|
||||
ERRNO_CASE(ENFILE);
|
||||
#endif
|
||||
#ifdef ENOBUFS
|
||||
ERRNO_CASE(ENOBUFS);
|
||||
#endif
|
||||
#ifdef ENODATA
|
||||
ERRNO_CASE(ENODATA);
|
||||
#endif
|
||||
#ifdef ENODEV
|
||||
ERRNO_CASE(ENODEV);
|
||||
#endif
|
||||
#ifdef ENOENT
|
||||
ERRNO_CASE(ENOENT);
|
||||
#endif
|
||||
#ifdef ENOEXEC
|
||||
ERRNO_CASE(ENOEXEC);
|
||||
#endif
|
||||
#ifdef ENOLINK
|
||||
ERRNO_CASE(ENOLINK);
|
||||
#endif
|
||||
#ifdef ENOLCK
|
||||
#if ENOLINK != ENOLCK
|
||||
ERRNO_CASE(ENOLCK);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENOMEM
|
||||
ERRNO_CASE(ENOMEM);
|
||||
#endif
|
||||
#ifdef ENOMSG
|
||||
ERRNO_CASE(ENOMSG);
|
||||
#endif
|
||||
#ifdef ENOPROTOOPT
|
||||
ERRNO_CASE(ENOPROTOOPT);
|
||||
#endif
|
||||
#ifdef ENOSPC
|
||||
ERRNO_CASE(ENOSPC);
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
ERRNO_CASE(ENOSR);
|
||||
#endif
|
||||
#ifdef ENOSTR
|
||||
ERRNO_CASE(ENOSTR);
|
||||
#endif
|
||||
#ifdef ENOSYS
|
||||
ERRNO_CASE(ENOSYS);
|
||||
#endif
|
||||
#ifdef ENOTCONN
|
||||
ERRNO_CASE(ENOTCONN);
|
||||
#endif
|
||||
#ifdef ENOTDIR
|
||||
ERRNO_CASE(ENOTDIR);
|
||||
#endif
|
||||
#ifdef ENOTEMPTY
|
||||
#if ENOTEMPTY != EEXIST
|
||||
ERRNO_CASE(ENOTEMPTY);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENOTSOCK
|
||||
ERRNO_CASE(ENOTSOCK);
|
||||
#endif
|
||||
#ifdef ENOTSUP
|
||||
ERRNO_CASE(ENOTSUP);
|
||||
#else
|
||||
#ifdef EOPNOTSUPP
|
||||
ERRNO_CASE(EOPNOTSUPP);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENOTTY
|
||||
ERRNO_CASE(ENOTTY);
|
||||
#endif
|
||||
#ifdef ENXIO
|
||||
ERRNO_CASE(ENXIO);
|
||||
#endif
|
||||
#ifdef EOVERFLOW
|
||||
ERRNO_CASE(EOVERFLOW);
|
||||
#endif
|
||||
#ifdef EPERM
|
||||
ERRNO_CASE(EPERM);
|
||||
#endif
|
||||
#ifdef EPIPE
|
||||
ERRNO_CASE(EPIPE);
|
||||
#endif
|
||||
#ifdef EPROTO
|
||||
ERRNO_CASE(EPROTO);
|
||||
#endif
|
||||
#ifdef EPROTONOSUPPORT
|
||||
ERRNO_CASE(EPROTONOSUPPORT);
|
||||
#endif
|
||||
#ifdef EPROTOTYPE
|
||||
ERRNO_CASE(EPROTOTYPE);
|
||||
#endif
|
||||
#ifdef ERANGE
|
||||
ERRNO_CASE(ERANGE);
|
||||
#endif
|
||||
#ifdef EROFS
|
||||
ERRNO_CASE(EROFS);
|
||||
#endif
|
||||
#ifdef ESPIPE
|
||||
ERRNO_CASE(ESPIPE);
|
||||
#endif
|
||||
#ifdef ESRCH
|
||||
ERRNO_CASE(ESRCH);
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
ERRNO_CASE(ESTALE);
|
||||
#endif
|
||||
#ifdef ETIME
|
||||
ERRNO_CASE(ETIME);
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
ERRNO_CASE(ETIMEDOUT);
|
||||
#endif
|
||||
#ifdef ETXTBSY
|
||||
ERRNO_CASE(ETXTBSY);
|
||||
#endif
|
||||
#ifdef EXDEV
|
||||
ERRNO_CASE(EXDEV);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
JSC::JSValue createSystemError(JSC::JSGlobalObject* global, ASCIILiteral message, ASCIILiteral syscall, int err)
|
||||
{
|
||||
@@ -15,11 +269,13 @@ JSC::JSValue createSystemError(JSC::JSGlobalObject* global, ASCIILiteral message
|
||||
|
||||
JSC::JSValue createSystemError(JSC::JSGlobalObject* global, ASCIILiteral syscall, int err)
|
||||
{
|
||||
auto* instance = JSC::createError(global, makeString(String(syscall), "() failed"_s));
|
||||
auto errstr = String::fromLatin1(errno_string(err));
|
||||
auto* instance = JSC::createError(global, makeString(String(syscall), "() failed: "_s, errstr, ": "_s, String::fromLatin1(strerror(err))));
|
||||
auto& vm = global->vm();
|
||||
auto& builtinNames = WebCore::builtinNames(vm);
|
||||
instance->putDirect(vm, builtinNames.syscallPublicName(), jsString(vm, String(syscall)), 0);
|
||||
instance->putDirect(vm, builtinNames.errnoPublicName(), JSC::jsNumber(err), 0);
|
||||
instance->putDirect(vm, vm.propertyNames->name, jsString(vm, String("SystemError"_s)), JSC::PropertyAttribute::DontEnum | 0);
|
||||
instance->putDirect(vm, builtinNames.codePublicName(), jsString(vm, errstr));
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -10,4 +10,5 @@ export default {
|
||||
ERR_BUFFER_TOO_LARGE: $newCppFunction("ErrorCode.cpp", "jsFunction_ERR_BUFFER_TOO_LARGE", 0),
|
||||
ERR_ZLIB_INITIALIZATION_FAILED: $newCppFunction("ErrorCode.cpp", "jsFunction_ERR_ZLIB_INITIALIZATION_FAILED", 0),
|
||||
ERR_BUFFER_OUT_OF_BOUNDS: $newCppFunction("ErrorCode.cpp", "jsFunction_ERR_BUFFER_OUT_OF_BOUNDS", 0),
|
||||
ERR_IPC_ONE_PIPE: $newCppFunction("ErrorCode.cpp", "jsFunction_ERR_IPC_ONE_PIPE", 0),
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
const EventEmitter = require("node:events");
|
||||
const StreamModule = require("node:stream");
|
||||
const OsModule = require("node:os");
|
||||
const { ERR_INVALID_ARG_TYPE, ERR_IPC_DISCONNECTED } = require("internal/errors");
|
||||
const { ERR_INVALID_ARG_TYPE, ERR_IPC_DISCONNECTED, ERR_IPC_ONE_PIPE } = require("internal/errors");
|
||||
const { kHandle } = require("internal/shared");
|
||||
const {
|
||||
validateBoolean,
|
||||
@@ -74,9 +74,7 @@ var ReadableFromWeb;
|
||||
// TODO: Add these params after support added in Bun.spawn
|
||||
// uid <number> Sets the user identity of the process (see setuid(2)).
|
||||
// gid <number> Sets the group identity of the process (see setgid(2)).
|
||||
// detached <boolean> Prepare child to run independently of its parent process. Specific behavior depends on the platform, see options.detached).
|
||||
|
||||
// TODO: Add support for ipc option, verify only one IPC channel in array
|
||||
// stdio <Array> | <string> Child's stdio configuration (see options.stdio).
|
||||
// Support wrapped ipc types (e.g. net.Socket, dgram.Socket, TTY, etc.)
|
||||
// IPC FD passing support
|
||||
@@ -1391,7 +1389,7 @@ const nodeToBunLookup = {
|
||||
ipc: "ipc",
|
||||
};
|
||||
|
||||
function nodeToBun(item, index) {
|
||||
function nodeToBun(item: string, index: number): string | number | null {
|
||||
// If not defined, use the default.
|
||||
// For stdin/stdout/stderr, it's pipe. For others, it's ignore.
|
||||
if (item == null) {
|
||||
@@ -1460,6 +1458,7 @@ function fdToStdioName(fd) {
|
||||
|
||||
function getBunStdioFromOptions(stdio) {
|
||||
const normalizedStdio = normalizeStdio(stdio);
|
||||
if (normalizedStdio.filter(v => v === "ipc").length > 1) throw ERR_IPC_ONE_PIPE();
|
||||
// Node options:
|
||||
// pipe: just a pipe
|
||||
// ipc = can only be one in array
|
||||
@@ -1486,7 +1485,7 @@ function getBunStdioFromOptions(stdio) {
|
||||
return bunStdio;
|
||||
}
|
||||
|
||||
function normalizeStdio(stdio) {
|
||||
function normalizeStdio(stdio): string[] {
|
||||
if (typeof stdio === "string") {
|
||||
switch (stdio) {
|
||||
case "ignore":
|
||||
|
||||
@@ -454,13 +454,13 @@ describe("process.cpuUsage", () => {
|
||||
user: -1,
|
||||
system: 100,
|
||||
}),
|
||||
).toThrow("The 'user' property must be a number between 0 and 2^53");
|
||||
).toThrow("The property 'prevValue.user' must be a number between 0 and 2^53. Received -1");
|
||||
expect(() =>
|
||||
process.cpuUsage({
|
||||
user: 100,
|
||||
system: -1,
|
||||
}),
|
||||
).toThrow("The 'system' property must be a number between 0 and 2^53");
|
||||
).toThrow("The property 'prevValue.system' must be a number between 0 and 2^53. Received -1");
|
||||
});
|
||||
|
||||
// Skipped on Windows because it seems UV returns { user: 15000, system: 0 } constantly
|
||||
@@ -680,13 +680,7 @@ it("dlopen accepts file: URLs", () => {
|
||||
});
|
||||
|
||||
it("process.constrainedMemory()", () => {
|
||||
if (process.platform === "linux") {
|
||||
// On Linux, it returns 0 if the kernel doesn't support it
|
||||
expect(process.constrainedMemory() >= 0).toBe(true);
|
||||
} else {
|
||||
// On unsupported platforms, it returns undefined
|
||||
expect(process.constrainedMemory()).toBeUndefined();
|
||||
}
|
||||
expect(process.constrainedMemory() >= 0).toBe(true);
|
||||
});
|
||||
|
||||
it("process.report", () => {
|
||||
|
||||
35
test/js/node/test/parallel/buffer-tojson.test.js
Normal file
35
test/js/node/test/parallel/buffer-tojson.test.js
Normal file
@@ -0,0 +1,35 @@
|
||||
//#FILE: test-buffer-tojson.js
|
||||
//#SHA1: 39b31549a09e67c89316a24c895db2dfab939ec4
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
test("Buffer JSON serialization", () => {
|
||||
expect(JSON.stringify(Buffer.alloc(0))).toBe('{"type":"Buffer","data":[]}');
|
||||
expect(JSON.stringify(Buffer.from([1, 2, 3, 4]))).toBe('{"type":"Buffer","data":[1,2,3,4]}');
|
||||
});
|
||||
|
||||
// issue GH-7849
|
||||
test("Buffer deserialization", () => {
|
||||
const buf = Buffer.from("test");
|
||||
const json = JSON.stringify(buf);
|
||||
const obj = JSON.parse(json);
|
||||
const copy = Buffer.from(obj);
|
||||
|
||||
expect(copy).toEqual(buf);
|
||||
});
|
||||
|
||||
// GH-5110
|
||||
test("Buffer serialization and custom deserialization", () => {
|
||||
const buffer = Buffer.from("test");
|
||||
const string = JSON.stringify(buffer);
|
||||
|
||||
expect(string).toBe('{"type":"Buffer","data":[116,101,115,116]}');
|
||||
|
||||
function receiver(key, value) {
|
||||
return value && value.type === "Buffer" ? Buffer.from(value.data) : value;
|
||||
}
|
||||
|
||||
expect(JSON.parse(string, receiver)).toEqual(buffer);
|
||||
});
|
||||
|
||||
//<#END_FILE: test-buffer-tojson.js
|
||||
80
test/js/node/test/parallel/child-process-stdio.test.js
Normal file
80
test/js/node/test/parallel/child-process-stdio.test.js
Normal file
@@ -0,0 +1,80 @@
|
||||
//#FILE: test-child-process-stdio.js
|
||||
//#SHA1: a121f9dd100777ada90408ac3980c35230cc119f
|
||||
//-----------------
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"use strict";
|
||||
const { spawn } = require("child_process");
|
||||
|
||||
const pwdCommand = process.platform === "win32" ? ["cmd", ["/c", "cd"]] : ["pwd"];
|
||||
|
||||
test("stdio piping", () => {
|
||||
const child = spawn(...pwdCommand, { stdio: ["pipe"] });
|
||||
expect(child.stdout).not.toBeNull();
|
||||
expect(child.stderr).not.toBeNull();
|
||||
});
|
||||
|
||||
test("stdio ignoring", () => {
|
||||
const child = spawn(...pwdCommand, { stdio: "ignore" });
|
||||
expect(child.stdout).toBeNull();
|
||||
expect(child.stderr).toBeNull();
|
||||
});
|
||||
|
||||
test("Asset options invariance", () => {
|
||||
const options = { stdio: "ignore" };
|
||||
spawn(...pwdCommand, options);
|
||||
expect(options).toEqual({ stdio: "ignore" });
|
||||
});
|
||||
|
||||
test("stdout buffering", done => {
|
||||
let output = "";
|
||||
const child = spawn(...pwdCommand);
|
||||
|
||||
child.stdout.setEncoding("utf8");
|
||||
child.stdout.on("data", function (s) {
|
||||
output += s;
|
||||
});
|
||||
|
||||
child.on("exit", code => {
|
||||
expect(code).toBe(0);
|
||||
});
|
||||
|
||||
child.on("close", () => {
|
||||
expect(output.length).toBeGreaterThan(1);
|
||||
expect(output[output.length - 1]).toBe("\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test("Assert only one IPC pipe allowed", () => {
|
||||
expect(() => {
|
||||
spawn(...pwdCommand, { stdio: ["pipe", "pipe", "pipe", "ipc", "ipc"] });
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_IPC_ONE_PIPE",
|
||||
name: "Error",
|
||||
message: expect.any(String),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
//<#END_FILE: test-child-process-stdio.js
|
||||
@@ -0,0 +1,55 @@
|
||||
//#FILE: test-child-process-windows-hide.js
|
||||
//#SHA1: c3cc8bbd27694658607c3a7f42a8e7901aeab807
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
const cp = require("child_process");
|
||||
const cmd = process.execPath;
|
||||
const args = ["--print", "42"];
|
||||
const options = { windowsHide: true, env: { ...Bun.env } };
|
||||
delete options.env.FORCE_COLOR;
|
||||
|
||||
// Since windowsHide isn't really observable, we'll use Jest's mocking capabilities
|
||||
// to verify that the flag is being passed through correctly.
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(cp, "spawn");
|
||||
jest.spyOn(cp, "spawnSync");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
test("spawnSync passes windowsHide option", () => {
|
||||
const child = cp.spawnSync(cmd, args, options);
|
||||
|
||||
expect(cp.spawnSync).toHaveBeenCalledWith(cmd, args, expect.objectContaining({ windowsHide: true }));
|
||||
expect(child.status).toBe(0);
|
||||
expect(child.signal).toBeNull();
|
||||
expect(child.stdout.toString().trim()).toBe("42");
|
||||
expect(child.stderr.toString().trim()).toBe("");
|
||||
});
|
||||
|
||||
test("spawn passes windowsHide option", done => {
|
||||
const child = cp.spawn(cmd, args, options);
|
||||
|
||||
expect(cp.spawn).toHaveBeenCalledWith(cmd, args, expect.objectContaining({ windowsHide: true }));
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
expect(code).toBe(0);
|
||||
expect(signal).toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test("execFile passes windowsHide option", done => {
|
||||
cp.execFile(cmd, args, options, (error, stdout, stderr) => {
|
||||
expect(error).toBeNull();
|
||||
expect(stdout.trim()).toBe("42");
|
||||
expect(stderr.trim()).toBe("");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
//<#END_FILE: test-child-process-windows-hide.js
|
||||
21
test/js/node/test/parallel/fs-buffertype-writesync.test.js
Normal file
21
test/js/node/test/parallel/fs-buffertype-writesync.test.js
Normal file
@@ -0,0 +1,21 @@
|
||||
//#FILE: test-fs-buffertype-writesync.js
|
||||
//#SHA1: 6af4aca43ae7299ed310d17733db6dcc43d0ed2b
|
||||
//-----------------
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
|
||||
test('fs.writeSync throws for invalid data input', () => {
|
||||
const invalidInputs = [
|
||||
true, false, 0, 1, Infinity, () => {}, {}, [], undefined, null,
|
||||
];
|
||||
|
||||
invalidInputs.forEach((value) => {
|
||||
expect(() => fs.writeSync(1, value)).toThrow(expect.objectContaining({
|
||||
message: expect.stringMatching(/"buffer"/),
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
//<#END_FILE: test-fs-buffertype-writesync.js
|
||||
41
test/js/node/test/parallel/fs-read-zero-length.test.js
Normal file
41
test/js/node/test/parallel/fs-read-zero-length.test.js
Normal file
@@ -0,0 +1,41 @@
|
||||
//#FILE: test-fs-read-zero-length.js
|
||||
//#SHA1: bda4b0f0c821a8479ffbf0a9099444eed6ee5c4e
|
||||
//-----------------
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const fixturesPath = path.join(__dirname, '..', 'fixtures');
|
||||
const filepath = path.join(fixturesPath, 'x.txt');
|
||||
|
||||
let fd;
|
||||
|
||||
beforeAll(() => {
|
||||
fd = fs.openSync(filepath, 'r');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
fs.closeSync(fd);
|
||||
});
|
||||
|
||||
test('fs.read with zero length buffer (async)', (done) => {
|
||||
const bufferAsync = Buffer.alloc(0);
|
||||
|
||||
fs.read(fd, bufferAsync, 0, 0, 0, (err, bytesRead) => {
|
||||
expect(err).toBeNull();
|
||||
expect(bytesRead).toBe(0);
|
||||
expect(bufferAsync).toEqual(Buffer.alloc(0));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('fs.readSync with zero length buffer', () => {
|
||||
const bufferSync = Buffer.alloc(0);
|
||||
|
||||
const bytesRead = fs.readSync(fd, bufferSync, 0, 0, 0);
|
||||
|
||||
expect(bufferSync).toEqual(Buffer.alloc(0));
|
||||
expect(bytesRead).toBe(0);
|
||||
});
|
||||
|
||||
//<#END_FILE: test-fs-read-zero-length.js
|
||||
11
test/js/node/test/parallel/process-available-memory.test.js
Normal file
11
test/js/node/test/parallel/process-available-memory.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
//#FILE: test-process-available-memory.js
|
||||
//#SHA1: 9dd0a4755f67f4786a0b7fc076d81be2a0b2063b
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
test("process.availableMemory()", () => {
|
||||
const availableMemory = process.availableMemory();
|
||||
expect(typeof availableMemory).toBe("number");
|
||||
});
|
||||
|
||||
//<#END_FILE: test-process-available-memory.js
|
||||
70
test/js/node/test/parallel/process-chdir.test.js
Normal file
70
test/js/node/test/parallel/process-chdir.test.js
Normal file
@@ -0,0 +1,70 @@
|
||||
//#FILE: test-process-chdir.js
|
||||
//#SHA1: af98467edcecd1605cd517f45d87e02ba840420b
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// Skip test for workers
|
||||
if (typeof process.chdir !== "function") {
|
||||
test.skip("process.chdir is not available in Workers", () => {});
|
||||
} else {
|
||||
const originalCwd = process.cwd();
|
||||
|
||||
afterAll(() => {
|
||||
// Ensure we return to the original directory after all tests
|
||||
process.chdir(originalCwd);
|
||||
});
|
||||
|
||||
test("process.chdir changes current working directory", () => {
|
||||
process.chdir("..");
|
||||
expect(process.cwd()).not.toBe(__dirname);
|
||||
process.chdir(__dirname);
|
||||
expect(process.cwd()).toBe(__dirname);
|
||||
});
|
||||
|
||||
test("process.chdir works with non-ASCII characters", () => {
|
||||
let dirName;
|
||||
if (process.versions.icu) {
|
||||
// ICU is available, use characters that could possibly be decomposed
|
||||
dirName = "weird \uc3a4\uc3ab\uc3af characters \u00e1\u00e2\u00e3";
|
||||
} else {
|
||||
// ICU is unavailable, use characters that can't be decomposed
|
||||
dirName = "weird \ud83d\udc04 characters \ud83d\udc05";
|
||||
}
|
||||
const tmpdir = path.resolve(__dirname, "../tmp");
|
||||
const dir = path.resolve(tmpdir, dirName);
|
||||
|
||||
// Make sure that the tmp directory is clean
|
||||
if (fs.existsSync(tmpdir)) {
|
||||
fs.rmSync(tmpdir, { recursive: true, force: true });
|
||||
}
|
||||
fs.mkdirSync(tmpdir, { recursive: true });
|
||||
|
||||
fs.mkdirSync(dir);
|
||||
process.chdir(dir);
|
||||
expect(process.cwd().normalize()).toBe(dir.normalize());
|
||||
|
||||
process.chdir("..");
|
||||
expect(process.cwd().normalize()).toBe(path.resolve(tmpdir).normalize());
|
||||
});
|
||||
|
||||
test("process.chdir throws for invalid arguments", () => {
|
||||
expect(() => process.chdir({})).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
message: expect.stringMatching(/The "directory" argument must be of type string/),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => process.chdir()).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
message: expect.stringMatching(/The "directory" argument must be of type string/),
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
//<#END_FILE: test-process-chdir.js
|
||||
@@ -0,0 +1,11 @@
|
||||
//#FILE: test-process-constrained-memory.js
|
||||
//#SHA1: 6c09d5733a7ac49f00b4923125a023c670423adf
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
test("process.constrainedMemory()", () => {
|
||||
const constrainedMemory = process.constrainedMemory();
|
||||
expect(typeof constrainedMemory).toBe("number");
|
||||
});
|
||||
|
||||
//<#END_FILE: test-process-constrained-memory.js
|
||||
112
test/js/node/test/parallel/process-cpuusage.test.js
Normal file
112
test/js/node/test/parallel/process-cpuusage.test.js
Normal file
@@ -0,0 +1,112 @@
|
||||
//#FILE: test-process-cpuUsage.js
|
||||
//#SHA1: 68c5aeede535139b8caa17340dcad82df9677047
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
test("process.cpuUsage", () => {
|
||||
const result = process.cpuUsage();
|
||||
|
||||
// Validate the result of calling with no previous value argument.
|
||||
validateResult(result);
|
||||
|
||||
// Validate the result of calling with a previous value argument.
|
||||
validateResult(process.cpuUsage(result));
|
||||
|
||||
// Ensure the results are >= the previous.
|
||||
let thisUsage;
|
||||
let lastUsage = process.cpuUsage();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
thisUsage = process.cpuUsage();
|
||||
validateResult(thisUsage);
|
||||
expect(thisUsage.user).toBeGreaterThanOrEqual(lastUsage.user);
|
||||
expect(thisUsage.system).toBeGreaterThanOrEqual(lastUsage.system);
|
||||
lastUsage = thisUsage;
|
||||
}
|
||||
|
||||
// Ensure that the diffs are >= 0.
|
||||
let startUsage;
|
||||
let diffUsage;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
startUsage = process.cpuUsage();
|
||||
diffUsage = process.cpuUsage(startUsage);
|
||||
validateResult(startUsage);
|
||||
validateResult(diffUsage);
|
||||
expect(diffUsage.user).toBeGreaterThanOrEqual(0);
|
||||
expect(diffUsage.system).toBeGreaterThanOrEqual(0);
|
||||
}
|
||||
|
||||
// Ensure that an invalid shape for the previous value argument throws an error.
|
||||
expect(() => process.cpuUsage(1)).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining(`The "previousValue" argument must be of type object. Received`),
|
||||
}),
|
||||
);
|
||||
|
||||
// Check invalid types.
|
||||
[{}, { user: "a" }, { user: null, system: "c" }].forEach(value => {
|
||||
expect(() => process.cpuUsage(value)).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining(`The "prevValue.user" property must be of type number. Received`),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
[
|
||||
{ user: 3, system: "b" },
|
||||
{ user: 3, system: null },
|
||||
].forEach(value => {
|
||||
expect(() => process.cpuUsage(value)).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining(`The "prevValue.system" property must be of type number. Received`),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
// Check invalid values.
|
||||
[
|
||||
{ user: -1, system: 2 },
|
||||
{ user: Number.POSITIVE_INFINITY, system: 4 },
|
||||
].forEach(value => {
|
||||
expect(() => process.cpuUsage(value)).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_VALUE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining(`The property 'prevValue.user' must be a number between 0 and 2^53. Received`),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
[
|
||||
{ user: 3, system: -2 },
|
||||
{ user: 5, system: Number.NEGATIVE_INFINITY },
|
||||
].forEach(value => {
|
||||
expect(() => process.cpuUsage(value)).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_VALUE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining(
|
||||
`The property 'prevValue.system' must be a number between 0 and 2^53. Received`,
|
||||
),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Ensure that the return value is the expected shape.
|
||||
function validateResult(result) {
|
||||
expect(result).not.toBeNull();
|
||||
|
||||
expect(Number.isFinite(result.user)).toBe(true);
|
||||
expect(Number.isFinite(result.system)).toBe(true);
|
||||
|
||||
expect(result.user).toBeGreaterThanOrEqual(0);
|
||||
expect(result.system).toBeGreaterThanOrEqual(0);
|
||||
}
|
||||
|
||||
//<#END_FILE: test-process-cpuUsage.js
|
||||
@@ -28,7 +28,7 @@ test('Calling .exit() from within "exit" should not overflow the call stack', ()
|
||||
let nexits = 0;
|
||||
|
||||
const exitHandler = jest.fn(code => {
|
||||
expect(nexits++).toBe(0);
|
||||
expect(nexits++).toBeOneOf([0, 1]);
|
||||
expect(code).toBe(0);
|
||||
process.exit();
|
||||
});
|
||||
|
||||
96
test/js/node/test/parallel/process-hrtime.test.js
Normal file
96
test/js/node/test/parallel/process-hrtime.test.js
Normal file
@@ -0,0 +1,96 @@
|
||||
//#FILE: test-process-hrtime.js
|
||||
//#SHA1: 99ce31a994db014be4c3835d3a5d46ed3ec3a89e
|
||||
//-----------------
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"use strict";
|
||||
|
||||
test("process.hrtime() default behavior", () => {
|
||||
// The default behavior, return an Array "tuple" of numbers
|
||||
const tuple = process.hrtime();
|
||||
|
||||
// Validate the default behavior
|
||||
validateTuple(tuple);
|
||||
});
|
||||
|
||||
test("process.hrtime() with existing tuple", () => {
|
||||
const tuple = process.hrtime();
|
||||
// Validate that passing an existing tuple returns another valid tuple
|
||||
validateTuple(process.hrtime(tuple));
|
||||
});
|
||||
|
||||
test("process.hrtime() with invalid arguments", () => {
|
||||
// Test that only an Array may be passed to process.hrtime()
|
||||
expect(() => {
|
||||
process.hrtime(1);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.any(String),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
process.hrtime([]);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_OUT_OF_RANGE",
|
||||
name: "RangeError",
|
||||
message: expect.any(String),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
process.hrtime([1]);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_OUT_OF_RANGE",
|
||||
name: "RangeError",
|
||||
message: expect.any(String),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
process.hrtime([1, 2, 3]);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_OUT_OF_RANGE",
|
||||
name: "RangeError",
|
||||
message: expect.any(String),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
function validateTuple(tuple) {
|
||||
expect(Array.isArray(tuple)).toBe(true);
|
||||
expect(tuple).toHaveLength(2);
|
||||
expect(Number.isInteger(tuple[0])).toBe(true);
|
||||
expect(Number.isInteger(tuple[1])).toBe(true);
|
||||
}
|
||||
|
||||
test("process.hrtime() diff", () => {
|
||||
const diff = process.hrtime([0, 1e9 - 1]);
|
||||
expect(diff[1]).toBeGreaterThanOrEqual(0); // https://github.com/nodejs/node/issues/4751
|
||||
});
|
||||
|
||||
//<#END_FILE: test-process-hrtime.js
|
||||
23
test/js/node/test/parallel/process-really-exit.test.js
Normal file
23
test/js/node/test/parallel/process-really-exit.test.js
Normal file
@@ -0,0 +1,23 @@
|
||||
//#FILE: test-process-really-exit.js
|
||||
//#SHA1: ad12d9cd84340ccf30df102407fc23cdc83801f0
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
const { spawnSync } = require("child_process");
|
||||
|
||||
if (process.argv[2] === "subprocess") {
|
||||
process.reallyExit = function () {
|
||||
console.info("really exited");
|
||||
};
|
||||
process.exit();
|
||||
} else {
|
||||
test("reallyExit hook is executed", () => {
|
||||
// Ensure that the reallyExit hook is executed.
|
||||
// see: https://github.com/nodejs/node/issues/25650
|
||||
const out = spawnSync(process.execPath, [__filename, "subprocess"]);
|
||||
const observed = out.output[1].toString("utf8").trim();
|
||||
expect(observed).toBe("really exited");
|
||||
});
|
||||
}
|
||||
|
||||
//<#END_FILE: test-process-really-exit.js
|
||||
14
test/js/node/test/parallel/process-release.test.js
Normal file
14
test/js/node/test/parallel/process-release.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
//#FILE: test-process-release.js
|
||||
//#SHA1: c1e8d1247391778d25fb0d2aeec5525fbe7d05b1
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
const versionParts = process.versions.node.split(".");
|
||||
|
||||
test("process.release properties", () => {
|
||||
expect(process.release.name).toBe("node");
|
||||
|
||||
expect(process.release.lts).toBeUndefined();
|
||||
});
|
||||
|
||||
//<#END_FILE: test-process-release.js
|
||||
63
test/js/node/test/parallel/process-setgroups.test.js
Normal file
63
test/js/node/test/parallel/process-setgroups.test.js
Normal file
@@ -0,0 +1,63 @@
|
||||
//#FILE: test-process-setgroups.js
|
||||
//#SHA1: 8fe1c3ec36e208d67f92c9d1325b228cb3f46312
|
||||
//-----------------
|
||||
"use strict";
|
||||
|
||||
if (process.platform === "win32") {
|
||||
test("process.setgroups is undefined on Windows", () => {
|
||||
expect(process.setgroups).toBeUndefined();
|
||||
});
|
||||
} else if (typeof process.isMainThread !== "undefined" && !process.isMainThread) {
|
||||
// Skip tests in non-main threads
|
||||
} else {
|
||||
describe("process.setgroups", () => {
|
||||
test("throws TypeError when called without arguments", () => {
|
||||
expect(() => {
|
||||
process.setgroups();
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining('The "groups" argument must be an instance of Array'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("throws RangeError for invalid group ID", () => {
|
||||
expect(() => {
|
||||
process.setgroups([1, -1]);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_OUT_OF_RANGE",
|
||||
name: "RangeError",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
// [], https://github.com/oven-sh/bun/issues/11793
|
||||
test.each([undefined, null, true, {}, () => {}])("throws TypeError for invalid group type: %p", val => {
|
||||
expect(() => {
|
||||
process.setgroups([val]);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining('The "groups[0]" argument must be of type number or string'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("throws ERR_UNKNOWN_CREDENTIAL for non-existent group", () => {
|
||||
expect(() => {
|
||||
process.setgroups([1, "fhqwhgadshgnsdhjsdbkhsdabkfabkveyb"]);
|
||||
}).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_UNKNOWN_CREDENTIAL",
|
||||
message: "Group identifier does not exist: fhqwhgadshgnsdhjsdbkhsdabkfabkveyb",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//<#END_FILE: test-process-setgroups.js
|
||||
110
test/js/node/test/parallel/process-uid-gid.test.js
Normal file
110
test/js/node/test/parallel/process-uid-gid.test.js
Normal file
@@ -0,0 +1,110 @@
|
||||
//#FILE: test-process-uid-gid.js
|
||||
//#SHA1: fdd637ef2fcf3bcada2c86f574494e32e5c03780
|
||||
//-----------------
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"use strict";
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
const isMainThread = !process.env.NODE_WORKER_ID;
|
||||
|
||||
if (isWindows) {
|
||||
test("uid/gid functions are POSIX only", () => {
|
||||
// uid/gid functions are POSIX only.
|
||||
expect(process.getuid).toBeUndefined();
|
||||
expect(process.getgid).toBeUndefined();
|
||||
expect(process.setuid).toBeUndefined();
|
||||
expect(process.setgid).toBeUndefined();
|
||||
});
|
||||
} else if (isMainThread) {
|
||||
test("setuid with invalid arguments", () => {
|
||||
expect(() => process.setuid({})).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
message: expect.stringContaining('The "id" argument must be of type number or string'),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => process.setuid("fhqwhgadshgnsdhjsdbkhsdabkfabkveyb")).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_UNKNOWN_CREDENTIAL",
|
||||
message: "User identifier does not exist: fhqwhgadshgnsdhjsdbkhsdabkfabkveyb",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
{
|
||||
// Passing -0 shouldn't crash the process
|
||||
// Refs: https://github.com/nodejs/node/issues/32750
|
||||
// And neither should values exceeding 2 ** 31 - 1.
|
||||
const ids = [-0, 2 ** 31, 2 ** 32 - 1];
|
||||
const fns = [process.setuid, process.setuid, process.setgid, process.setegid];
|
||||
|
||||
for (const fn of fns) {
|
||||
for (const id of ids) {
|
||||
test(`edge cases for uid/gid functions: ${fn.name}: ${id}`, () => {
|
||||
expect(() => {
|
||||
try {
|
||||
fn(id);
|
||||
} catch {
|
||||
// Continue regardless of error.
|
||||
}
|
||||
}).not.toThrow();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process.getuid() !== 0) {
|
||||
test("non-root user permissions", () => {
|
||||
// Should not throw.
|
||||
expect(() => process.getgid()).not.toThrow();
|
||||
expect(() => process.getuid()).not.toThrow();
|
||||
|
||||
expect(() => process.setgid("nobody")).toThrow(/EPERM|Group identifier does not exist/);
|
||||
|
||||
expect(() => process.setuid("nobody")).toThrow(/EPERM|User identifier does not exist/);
|
||||
});
|
||||
} else {
|
||||
test("root user permissions", async () => {
|
||||
const oldgid = process.getgid();
|
||||
try {
|
||||
process.setgid("nobody");
|
||||
} catch (err) {
|
||||
if (err.code !== "ERR_UNKNOWN_CREDENTIAL") {
|
||||
throw err;
|
||||
}
|
||||
process.setgid("nogroup");
|
||||
}
|
||||
|
||||
const newgid = process.getgid();
|
||||
expect(newgid).not.toBe(oldgid);
|
||||
|
||||
const olduid = process.getuid();
|
||||
process.setuid("nobody");
|
||||
const newuid = process.getuid();
|
||||
expect(newuid).not.toBe(olduid);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//<#END_FILE: test-process-uid-gid.js
|
||||
Reference in New Issue
Block a user