diff --git a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp index f8e469c511..bb099602fe 100644 --- a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp +++ b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp @@ -305,7 +305,7 @@ JSValue createEnvironmentVariablesMap(Zig::GlobalObject* globalObject) bool hasNodeTLSRejectUnauthorized = false; bool hasBunConfigVerboseFetch = false; - auto* cached_getter_setter = JSC::CustomGetterSetter::create(vm, jsGetterEnvironmentVariable, nullptr); + auto* cached_getter_setter = JSC::CustomGetterSetter::create(vm, jsGetterEnvironmentVariable, jsSetterEnvironmentVariable); for (size_t i = 0; i < count; i++) { unsigned char* chars; diff --git a/src/js/builtins/ProcessObjectInternals.ts b/src/js/builtins/ProcessObjectInternals.ts index 67156abc56..ce24d17d73 100644 --- a/src/js/builtins/ProcessObjectInternals.ts +++ b/src/js/builtins/ProcessObjectInternals.ts @@ -393,7 +393,7 @@ export function windowsEnv( set(_, p, value) { const k = String(p).toUpperCase(); $assert(typeof p === "string"); // proxy is only string and symbol. the symbol would have thrown by now - value = String(value); // If toString() throws, we want to avoid it existing in the envMapList + value = "" + value; // If toString() throws, we want to avoid it existing in the envMapList if (!(k in internalEnv) && !envMapList.includes(p)) { envMapList.push(p); } diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index 7ca6e85338..39632813dc 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -158,6 +158,18 @@ it("process.env", () => { expect(process.env["LOL SMILE latin1 "]).toBe(""); delete process.env["LOL SMILE latin1 "]; expect(process.env["LOL SMILE latin1 "]).toBe(undefined); + + // Node.js coerces non-string values to strings + process.env.BUN_TEST_ENV_COERCE = undefined; + expect(process.env.BUN_TEST_ENV_COERCE).toBe("undefined"); + process.env.BUN_TEST_ENV_COERCE = null; + expect(process.env.BUN_TEST_ENV_COERCE).toBe("null"); + process.env.BUN_TEST_ENV_COERCE = 123; + expect(process.env.BUN_TEST_ENV_COERCE).toBe("123"); + delete process.env.BUN_TEST_ENV_COERCE; + + // Symbol assignment should throw TypeError, matching Node.js + expect(() => { process.env.BUN_TEST_ENV_COERCE = Symbol("test"); }).toThrow(TypeError); }); it("process.env is spreadable and editable", () => {