Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions bench/snippets/process-env.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { bench, run } from "../runner.mjs";

// What a program does before the code that is measured here runs:
// a copy for a child process, which reads every variable,
globalThis.childEnv = { ...process.env };
// a feature flag that is checked often,
for (let n = 0; n < 20_000; n++) globalThis.flag = process.env.NOT_SET_FLAG;
// and dotenv-style writes.
for (const key of ["BENCH_A", "BENCH_B", "BENCH_C"]) process.env[key] = "1";
delete process.env.BENCH_C;

const keys = ["HOME", "PATH", "BENCH_A", "NOT_SET_1", "NOT_SET_2", "USER", "NOT_SET_3", "BENCH_B"];
let i = 0;

bench("process.env.HOME", () => process.env.HOME);
bench("process.env.NOT_SET", () => process.env.NOT_SET);
bench("process.env[key]", () => process.env[keys[i++ & 7]]);
bench("process.env.BENCH_A = 'value'", () => {
process.env.BENCH_A = "value";
});
bench("{ ...process.env }", () => ({ ...process.env }));
bench("Object.keys(process.env)", () => Object.keys(process.env));
bench("process.argv", () => process.argv);
bench("process.argv[1]", () => process.argv[1]);
bench("process.argv.length", () => process.argv.length);
bench("process.execArgv", () => process.execArgv);

await run();
103 changes: 19 additions & 84 deletions src/jsc/bindings/BunProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3170,105 +3170,42 @@ static JSValue constructExecPath(VM& vm, JSObject* processObject)
return JSValue::decode(Bun__Process__getExecPath(globalObject));
}

extern "C" EncodedJSValue Bun__Process__getArgv(JSGlobalObject* lexicalGlobalObject)
static JSValue constructArgv(VM& vm, JSObject* processObject)
{
auto* globalObject = defaultGlobalObject(lexicalGlobalObject);
auto* process = globalObject->processObject();
if (!process) {
return JSValue::encode(jsUndefined());
}

return JSValue::encode(process->getArgv(globalObject));
return JSValue::decode(Bun__Process__createArgv(processObject->globalObject()));
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

// get from js
JSC_DEFINE_CUSTOM_GETTER(processArgv, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName))
static JSValue constructExecArgv(VM& vm, JSObject* processObject)
{
Process* process = getProcessObject(globalObject, JSValue::decode(thisValue));
if (!process) {
return JSValue::encode(jsUndefined());
}

return JSValue::encode(process->getArgv(globalObject));
return JSValue::decode(Bun__Process__createExecArgv(processObject->globalObject()));
}

JSValue Process::getArgv(JSGlobalObject* globalObject)
{
if (auto argv = m_argv.get()) {
return argv;
}

JSValue argv = JSValue::decode(Bun__Process__createArgv(globalObject));
setArgv(globalObject, argv);
return argv;
return get(globalObject, Identifier::fromString(globalObject->vm(), "argv"_s));
}

void Process::setArgv(JSGlobalObject* globalObject, JSValue value)
JSValue Process::getExecArgv(JSGlobalObject* globalObject)
{
auto& vm = globalObject->vm();
m_argv.set(vm, this, value);
return get(globalObject, Identifier::fromString(globalObject->vm(), "execArgv"_s));
}

JSC_DEFINE_CUSTOM_SETTER(setProcessArgv, (JSGlobalObject * globalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName))
extern "C" EncodedJSValue Bun__Process__getArgv(JSGlobalObject* lexicalGlobalObject)
{
Process* process = getProcessObject(globalObject, JSValue::decode(thisValue));
if (!process) {
return true;
}

JSValue value = JSValue::decode(encodedValue);
process->setArgv(globalObject, value);
return true;
auto* globalObject = defaultGlobalObject(lexicalGlobalObject);
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
JSValue argv = globalObject->processObject()->getArgv(globalObject);
Comment thread
robobun marked this conversation as resolved.
RETURN_IF_EXCEPTION(scope, {});
return JSValue::encode(argv);
}

extern "C" EncodedJSValue Bun__Process__getExecArgv(JSGlobalObject* lexicalGlobalObject)
{
auto* globalObject = defaultGlobalObject(lexicalGlobalObject);
auto* process = globalObject->processObject();
if (!process) {
return JSValue::encode(jsUndefined());
}

return JSValue::encode(process->getExecArgv(globalObject));
}

JSC_DEFINE_CUSTOM_GETTER(processExecArgv, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName))
{
Process* process = getProcessObject(globalObject, JSValue::decode(thisValue));
if (!process) {
return JSValue::encode(jsUndefined());
}

return JSValue::encode(process->getExecArgv(globalObject));
}

JSValue Process::getExecArgv(JSGlobalObject* globalObject)
{
if (auto argv = m_execArgv.get()) {
return argv;
}

JSValue argv = JSValue::decode(Bun__Process__createExecArgv(globalObject));
setExecArgv(globalObject, argv);
return argv;
}

void Process::setExecArgv(JSGlobalObject* globalObject, JSValue value)
{
auto& vm = globalObject->vm();
m_execArgv.set(vm, this, value);
}

JSC_DEFINE_CUSTOM_SETTER(setProcessExecArgv, (JSGlobalObject * globalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName))
{
Process* process = getProcessObject(globalObject, JSValue::decode(thisValue));
if (!process) {
return true;
}

JSValue value = JSValue::decode(encodedValue);
process->setExecArgv(globalObject, value);
return true;
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
JSValue execArgv = globalObject->processObject()->getExecArgv(globalObject);
RETURN_IF_EXCEPTION(scope, {});
return JSValue::encode(execArgv);
}

JSC_DEFINE_CUSTOM_GETTER(processGetEval, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName))
Expand Down Expand Up @@ -3776,8 +3713,6 @@ void Process::visitChildrenImpl(JSCell* cell, Visitor& visitor)
visitor.append(thisObject->m_uncaughtExceptionCaptureCallback);
visitor.append(thisObject->m_nextTickFunction);
visitor.append(thisObject->m_cachedCwd);
visitor.append(thisObject->m_argv);
visitor.append(thisObject->m_execArgv);
visitor.append(thisObject->m_onWarning);

thisObject->m_cpuUsageStructure.visit(visitor);
Expand Down Expand Up @@ -5026,7 +4961,7 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
loadEnvFile constructLoadEnvFile PropertyCallback
finalization constructFinalization PropertyCallback
arch constructArch PropertyCallback
argv processArgv CustomAccessor
argv constructArgv PropertyCallback
Comment thread
robobun marked this conversation as resolved.
argv0 constructArgv0 PropertyCallback
assert Process_functionAssert Function 1
availableMemory Process_availableMemory Function 0
Expand All @@ -5045,7 +4980,7 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
dlopen Process_functionDlopen Function 1
emitWarning Process_emitWarning Function 1
env constructEnv PropertyCallback
execArgv processExecArgv CustomAccessor
execArgv constructExecArgv PropertyCallback
execPath constructExecPath PropertyCallback
execve Process_functionExecve Function 3
exit Process_functionExit Function 1
Expand Down
5 changes: 0 additions & 5 deletions src/jsc/bindings/BunProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ class Process : public WebCore::JSEventEmitter {
WriteBarrier<JSObject> m_nextTickFunction;
// https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/lib/internal/bootstrap/switches/does_own_process_state.js#L113-L116
WriteBarrier<JSString> m_cachedCwd;
WriteBarrier<Unknown> m_argv;
WriteBarrier<Unknown> m_execArgv;
// The JS warning printer (ProcessObjectInternals createOnWarning), built on the first warning.
WriteBarrier<JSObject> m_onWarning;

Expand Down Expand Up @@ -92,10 +90,7 @@ class Process : public WebCore::JSEventEmitter {
void clearCachedCwd() { m_cachedCwd.clear(); }

JSValue getArgv(JSGlobalObject* globalObject);
void setArgv(JSGlobalObject* globalObject, JSValue argv);

JSValue getExecArgv(JSGlobalObject* globalObject);
void setExecArgv(JSGlobalObject* globalObject, JSValue execArgv);

static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject,
JSC::JSValue prototype)
Expand Down
5 changes: 3 additions & 2 deletions src/jsc/bindings/InspectorLifecycleAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,10 @@ Protocol::ErrorStringOr<ModuleGraph> InspectorLifecycleAgent::getModuleGraph()
Ref<JSON::ArrayOf<String>> argv = JSON::ArrayOf<String>::create();
{

auto* array = uncheckedDowncast<JSC::JSArray>(process->getArgv(global));
JSC::JSValue argvValue = process->getArgv(global);
RETURN_IF_EXCEPTION(scope, fail("Failed to get argv"_s));
for (size_t i = 0, length = array->length(); i < length; i++) {
auto* array = dynamicDowncast<JSC::JSArray>(argvValue);
for (size_t i = 0, length = array ? array->length() : 0; i < length; i++) {
auto value = array->getIndex(global, i);
RETURN_IF_EXCEPTION(scope, fail("Failed to get value at index"_s));
auto string = value.toWTFString(global);
Expand Down
Loading
Loading