From c700a70872e59bba20ac35385d3cad6ceea8a4fc Mon Sep 17 00:00:00 2001 From: dave caruso Date: Tue, 24 Oct 2023 19:11:06 -0800 Subject: [PATCH] fix(runtime): remove env variable limit (#6697) * fix env limit * test --- src/bun.js/api/bun.zig | 15 ++++++++++++--- src/bun.js/bindings/JSEnvironmentVariableMap.cpp | 13 ++++++++----- test/cli/run/env.test.ts | 15 +++++++++++---- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index 21c2ecd0e1..c6250a47c2 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -4414,8 +4414,16 @@ pub const FFIObject = struct { /// Also, you can't iterate over process.env normally since it only exists at build-time otherwise // This is aliased to Bun.env pub const EnvironmentVariables = struct { - pub export fn Bun__getEnvNames(globalObject: *JSC.JSGlobalObject, names: [*]ZigString, max: usize) usize { - return getEnvNames(globalObject, names[0..max]); + pub export fn Bun__getEnvCount(globalObject: *JSC.JSGlobalObject, ptr: *[*][]const u8) usize { + const bunVM = globalObject.bunVM(); + ptr.* = bunVM.bundler.env.map.map.keys().ptr; + return bunVM.bundler.env.map.map.unmanaged.entries.len; + } + + pub export fn Bun__getEnvKey(ptr: [*][]const u8, i: usize, data_ptr: *[*]const u8) usize { + const item = ptr[i]; + data_ptr.* = item.ptr; + return item.len; } pub export fn Bun__getEnvValue(globalObject: *JSC.JSGlobalObject, name: *ZigString, value: *ZigString) bool { @@ -4453,7 +4461,8 @@ export fn Bun__reportError(globalObject: *JSGlobalObject, err: JSC.JSValue) void comptime { if (!is_bindgen) { _ = Bun__reportError; - _ = EnvironmentVariables.Bun__getEnvNames; + _ = EnvironmentVariables.Bun__getEnvCount; + _ = EnvironmentVariables.Bun__getEnvKey; _ = EnvironmentVariables.Bun__getEnvValue; } } diff --git a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp index 4989f7e96d..4942b300fa 100644 --- a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp +++ b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp @@ -8,7 +8,9 @@ #include "BunClientData.h" using namespace JSC; -extern "C" size_t Bun__getEnvNames(JSGlobalObject*, ZigString* names, size_t max); +extern "C" size_t Bun__getEnvCount(JSGlobalObject* globalObject, void** list_ptr); +extern "C" size_t Bun__getEnvKey(void* list, size_t index, unsigned char** out); + extern "C" bool Bun__getEnvValue(JSGlobalObject* globalObject, ZigString* name, ZigString* value); namespace Bun { @@ -113,9 +115,8 @@ JSValue createEnvironmentVariablesMap(Zig::GlobalObject* globalObject) VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - size_t max = 768; - ZigString names[max]; - size_t count = Bun__getEnvNames(globalObject, names, max); + void* list; + size_t count = Bun__getEnvCount(globalObject, &list); JSC::JSObject* object = nullptr; if (count < 63) { object = constructEmptyObject(globalObject, globalObject->objectPrototype(), count); @@ -126,7 +127,9 @@ JSValue createEnvironmentVariablesMap(Zig::GlobalObject* globalObject) static NeverDestroyed TZ = MAKE_STATIC_STRING_IMPL("TZ"); bool hasTZ = false; for (size_t i = 0; i < count; i++) { - auto name = Zig::toStringCopy(names[i]); + unsigned char* chars; + size_t len = Bun__getEnvKey(list, i, &chars); + auto name = String::fromUTF8(chars, len); if (name == TZ) { hasTZ = true; continue; diff --git a/test/cli/run/env.test.ts b/test/cli/run/env.test.ts index 1c2d51e8e4..6d210cb6aa 100644 --- a/test/cli/run/env.test.ts +++ b/test/cli/run/env.test.ts @@ -328,16 +328,23 @@ test(".env doesnt crash with 159 bytes", () => { ); }); -test(".env with >768 entries", () => { +test(".env with 50000 entries", () => { const dir = tempDirWithFiles("dotenv-many-entries", { - ".env": new Array(2000) + ".env": new Array(50000) .fill(null) .map((_, i) => `TEST_VAR${i}=TEST_VAL${i}`) .join("\n"), - "index.ts": "console.log(process.env.TEST_VAR47);", + "index.ts": /* ts */ ` + for (let i = 0; i < 50000; i++) { + if(process.env['TEST_VAR' + i] !== 'TEST_VAL' + i) { + throw new Error('TEST_VAR' + i + ' !== TEST_VAL' + i); + } + } + console.log('OK'); + `, }); const { stdout } = bunRun(`${dir}/index.ts`); - expect(stdout).toBe("TEST_VAL47"); + expect(stdout).toBe("OK"); }); test(".env space edgecase (issue #411)", () => {