Compare commits

...

1 Commits

Author SHA1 Message Date
dave caruso
b58f93e749 stop inlining process.env in the bundler 2024-01-30 10:48:03 -08:00
3 changed files with 12 additions and 178 deletions

View File

@@ -250,168 +250,6 @@ pub const Loader = struct {
return this.get(key[1..]) orelse key;
}
/// Load values from the environment into Define.
///
/// If there is a framework, values from the framework are inserted with a
/// **lower priority** so that users may override defaults. Unlike regular
/// defines, environment variables are loaded as JavaScript string literals.
///
/// Empty enivronment variables become empty strings.
pub fn copyForDefine(
this: *Loader,
comptime JSONStore: type,
to_json: *JSONStore,
comptime StringStore: type,
to_string: *StringStore,
framework_defaults: Api.StringMap,
behavior: Api.DotEnvBehavior,
prefix: string,
allocator: std.mem.Allocator,
) !void {
var iter = this.map.iter();
var key_count: usize = 0;
var string_map_hashes = try allocator.alloc(u64, framework_defaults.keys.len);
defer allocator.free(string_map_hashes);
const invalid_hash = std.math.maxInt(u64) - 1;
@memset(string_map_hashes, invalid_hash);
var key_buf: []u8 = "";
// Frameworks determine an allowlist of values
for (framework_defaults.keys, 0..) |key, i| {
if (key.len > "process.env.".len and strings.eqlComptime(key[0.."process.env.".len], "process.env.")) {
const hashable_segment = key["process.env.".len..];
string_map_hashes[i] = bun.hash(hashable_segment);
}
}
// We have to copy all the keys to prepend "process.env" :/
var key_buf_len: usize = 0;
var e_strings_to_allocate: usize = 0;
if (behavior != .disable and behavior != .load_all_without_inlining) {
if (behavior == .prefix) {
std.debug.assert(prefix.len > 0);
while (iter.next()) |entry| {
if (strings.startsWith(entry.key_ptr.*, prefix)) {
key_buf_len += entry.key_ptr.len;
key_count += 1;
e_strings_to_allocate += 1;
std.debug.assert(entry.key_ptr.len > 0);
}
}
} else {
while (iter.next()) |entry| {
if (entry.key_ptr.len > 0) {
key_buf_len += entry.key_ptr.len;
key_count += 1;
e_strings_to_allocate += 1;
std.debug.assert(entry.key_ptr.len > 0);
}
}
}
if (key_buf_len > 0) {
iter.reset();
key_buf = try allocator.alloc(u8, key_buf_len + key_count * "process.env.".len);
const js_ast = bun.JSAst;
var e_strings = try allocator.alloc(js_ast.E.String, e_strings_to_allocate * 2);
errdefer allocator.free(e_strings);
errdefer allocator.free(key_buf);
var key_fixed_allocator = std.heap.FixedBufferAllocator.init(key_buf);
const key_allocator = key_fixed_allocator.allocator();
if (behavior == .prefix) {
while (iter.next()) |entry| {
const value: string = entry.value_ptr.value;
if (strings.startsWith(entry.key_ptr.*, prefix)) {
const key_str = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable;
e_strings[0] = js_ast.E.String{
.data = if (value.len > 0)
@as([*]u8, @ptrFromInt(@intFromPtr(value.ptr)))[0..value.len]
else
&[_]u8{},
};
const expr_data = js_ast.Expr.Data{ .e_string = &e_strings[0] };
_ = try to_string.getOrPutValue(
key_str,
.{
.can_be_removed_if_unused = true,
.call_can_be_unwrapped_if_unused = true,
.value = expr_data,
},
);
e_strings = e_strings[1..];
} else {
const hash = bun.hash(entry.key_ptr.*);
std.debug.assert(hash != invalid_hash);
if (std.mem.indexOfScalar(u64, string_map_hashes, hash)) |key_i| {
e_strings[0] = js_ast.E.String{
.data = if (value.len > 0)
@as([*]u8, @ptrFromInt(@intFromPtr(value.ptr)))[0..value.len]
else
&[_]u8{},
};
const expr_data = js_ast.Expr.Data{ .e_string = &e_strings[0] };
_ = try to_string.getOrPutValue(
framework_defaults.keys[key_i],
.{
.can_be_removed_if_unused = true,
.call_can_be_unwrapped_if_unused = true,
.value = expr_data,
},
);
e_strings = e_strings[1..];
}
}
}
} else {
while (iter.next()) |entry| {
const value: string = entry.value_ptr.value;
const key = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable;
e_strings[0] = js_ast.E.String{
.data = if (entry.value_ptr.value.len > 0)
@as([*]u8, @ptrFromInt(@intFromPtr(entry.value_ptr.value.ptr)))[0..value.len]
else
&[_]u8{},
};
const expr_data = js_ast.Expr.Data{ .e_string = &e_strings[0] };
_ = try to_string.getOrPutValue(
key,
.{
.can_be_removed_if_unused = true,
.call_can_be_unwrapped_if_unused = true,
.value = expr_data,
},
);
e_strings = e_strings[1..];
}
}
}
}
for (framework_defaults.keys, 0..) |key, i| {
const value = framework_defaults.values[i];
if (!to_string.contains(key) and !to_json.contains(key)) {
_ = try to_json.getOrPutValue(key, value);
}
}
}
pub fn init(map: *Map, allocator: std.mem.Allocator) Loader {
return Loader{
.map = map,

View File

@@ -1145,7 +1145,6 @@ pub fn definesFromTransformOptions(
log: *logger.Log,
maybe_input_define: ?Api.StringMap,
target: Target,
env_loader: ?*DotEnv.Loader,
framework_env: ?*const Env,
NODE_ENV: ?string,
) !*defines.Define {
@@ -1164,7 +1163,6 @@ pub fn definesFromTransformOptions(
var behavior: Api.DotEnvBehavior = .disable;
load_env: {
const env = env_loader orelse break :load_env;
const framework = framework_env orelse break :load_env;
if (Environment.allow_assert) {
@@ -1172,19 +1170,6 @@ pub fn definesFromTransformOptions(
}
behavior = framework.behavior;
if (behavior == .load_all_without_inlining or behavior == .disable)
break :load_env;
try env.copyForDefine(
defines.RawDefines,
&user_defines,
defines.UserDefinesArray,
&environment_defines,
framework.toAPI().defaults,
framework.behavior,
framework.prefix,
allocator,
);
}
if (behavior != .load_all_without_inlining) {
@@ -1535,7 +1520,6 @@ pub const BundleOptions = struct {
this.log,
this.transform_options.define,
this.target,
loader_,
env,
node_env: {
if (loader_) |e|

View File

@@ -199,6 +199,18 @@ describe("bundler", () => {
ARBITRARY: "secret environment stuff!",
},
});
itBundled("edgecase/ProcessEnvArbitraryBun", {
files: {
"/entry.js": /* js */ `
capture(process.env.ARBITRARY);
`,
},
target: "bun",
capture: ["process.env.ARBITRARY"],
env: {
ARBITRARY: "secret environment stuff!",
},
});
itBundled("edgecase/StarExternal", {
files: {
"/entry.js": /* js */ `