diff --git a/src/allocators/maybe_owned.zig b/src/allocators/maybe_owned.zig index efedbf39da..61f9a40678 100644 --- a/src/allocators/maybe_owned.zig +++ b/src/allocators/maybe_owned.zig @@ -2,7 +2,7 @@ /// /// ``` /// // Either owned by the default allocator, or borrowed -/// const MaybeOwnedFoo = bun.ptr.Owned(*Foo, bun.allocators.MaybeOwned(bun.DefaultAllocator)); +/// const MaybeOwnedFoo = bun.ptr.OwnedIn(*Foo, bun.allocators.MaybeOwned(bun.DefaultAllocator)); /// /// var owned_foo: MaybeOwnedFoo = .new(makeFoo()); /// var borrowed_foo: MaybeOwnedFoo = .fromRawIn(some_foo_ptr, .initBorrowed()); diff --git a/src/bun.zig b/src/bun.zig index acaa0ec66a..7a5c884ec7 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -2849,23 +2849,6 @@ pub fn reinterpretSlice(comptime T: type, slice: anytype) ReinterpretSliceType(T return new_ptr[0..@divTrunc(bytes.len, @sizeOf(T))]; } -extern "kernel32" fn GetUserNameA(username: *u8, size: *u32) callconv(std.os.windows.WINAPI) c_int; - -pub fn getUserName(output_buffer: []u8) ?[]const u8 { - if (Environment.isWindows) { - var size: u32 = @intCast(output_buffer.len); - if (GetUserNameA(@ptrCast(@constCast(output_buffer.ptr)), &size) == 0) { - return null; - } - return output_buffer[0..size]; - } - var env = std.process.getEnvMap(default_allocator) catch outOfMemory(); - const user = env.get("USER") orelse return null; - const size = @min(output_buffer.len, user.len); - copy(u8, output_buffer[0..size], user[0..size]); - return output_buffer[0..size]; -} - pub inline fn resolveSourcePath( comptime root: enum { codegen, src }, comptime sub_path: []const u8, diff --git a/src/main.zig b/src/main.zig index 1000c0134a..d07a0630c6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -40,6 +40,7 @@ pub fn main() void { &bun.mimalloc.mi_calloc, &bun.mimalloc.mi_free, ); + bun.handleOom(bun.windows.env.convertEnvToWTF8()); environ = @ptrCast(std.os.environ.ptr); _environ = @ptrCast(std.os.environ.ptr); } diff --git a/src/string/immutable/unicode.zig b/src/string/immutable/unicode.zig index 15af6e87d2..df860fe94e 100644 --- a/src/string/immutable/unicode.zig +++ b/src/string/immutable/unicode.zig @@ -303,17 +303,9 @@ pub fn convertUTF16ToUTF8Append(list: *std.ArrayList(u8), utf16: []const u16) OO } pub fn toUTF8AllocWithTypeWithoutInvalidSurrogatePairs(allocator: std.mem.Allocator, utf16: []const u16) OOM![]u8 { - if (bun.FeatureFlags.use_simdutf) { - const length = bun.simdutf.length.utf8.from.utf16.le(utf16); - // add 16 bytes of padding for SIMDUTF - var list = try std.ArrayList(u8).initCapacity(allocator, length + 16); - list = try convertUTF16ToUTF8(list, utf16); - return list.items; - } - - var list = try std.ArrayList(u8).initCapacity(allocator, utf16.len); - list = try toUTF8ListWithType(list, utf16); - return list.items; + // previously, this function was an exact copy of `toUTF8AllocWithType`. + // TODO: actually make this function behave differently? + return toUTF8AllocWithType(allocator, utf16); } pub fn toUTF8AllocWithType(allocator: std.mem.Allocator, utf16: []const u16) OOM![]u8 { @@ -322,12 +314,12 @@ pub fn toUTF8AllocWithType(allocator: std.mem.Allocator, utf16: []const u16) OOM // add 16 bytes of padding for SIMDUTF var list = try std.ArrayList(u8).initCapacity(allocator, length + 16); list = try convertUTF16ToUTF8(list, utf16); - return list.items; + return list.toOwnedSlice(); } var list = try std.ArrayList(u8).initCapacity(allocator, utf16.len); list = try toUTF8ListWithType(list, utf16); - return list.items; + return list.toOwnedSlice(); } pub fn toUTF8ListWithType(list_: std.ArrayList(u8), utf16: []const u16) OOM!std.ArrayList(u8) { diff --git a/src/windows.zig b/src/windows.zig index d3bfd16598..a788762bba 100644 --- a/src/windows.zig +++ b/src/windows.zig @@ -4144,6 +4144,8 @@ pub fn renameAtW( return moveOpenedFileAt(src_fd, new_dir_fd, new_path_w, replace_if_exists); } +pub const env = @import("./windows/env.zig"); + const builtin = @import("builtin"); const std = @import("std"); diff --git a/src/windows/env.zig b/src/windows/env.zig new file mode 100644 index 0000000000..7bf26306a4 --- /dev/null +++ b/src/windows/env.zig @@ -0,0 +1,60 @@ +/// After running `convertEnvToWTF8`, the pointers in `std.os.environ` will point into this buffer. +pub var wtf8_env_buf: ?[]const u8 = null; +/// `convertEnvToWTF8` will set this to the original value of `std.os.environ`. +pub var orig_environ: ?[][*:0]u8 = null; + +var env_converted: if (Environment.ci_assert) bool else void = if (Environment.ci_assert) false; + +/// Converts all strings in `std.os.environ` to WTF-8. +/// +/// This function should be called only once, at program startup, before any code that needs to +/// access the environment runs. +/// +/// This function is Windows-only. +pub fn convertEnvToWTF8() bun.OOM!void { + if (comptime Environment.ci_assert) { + bun.assertf(!env_converted, "convertEnvToWTF8 may only be called once", .{}); + env_converted = true; + } + errdefer if (comptime Environment.ci_assert) { + env_converted = false; + }; + + var num_vars: usize = 0; + const wtf8_buf: []u8 = blk: { + var wtf16_buf: [*:0]u16 = try std.os.windows.GetEnvironmentStringsW(); + defer std.os.windows.FreeEnvironmentStringsW(wtf16_buf); + var len: usize = 0; + while (true) { + const str_len = std.mem.len(wtf16_buf[len..]); + len += str_len + 1; // each string is null-terminated + if (str_len == 0) break; // array ends with empty null-terminated string + num_vars += 1; + } + break :blk try bun.strings.toUTF8AllocWithType(bun.default_allocator, wtf16_buf[0..len]); + }; + errdefer bun.default_allocator.free(wtf8_buf); + var len: usize = 0; + + var envp: bun.collections.ArrayListDefault(?[*:0]u8) = try .initCapacity(num_vars + 1); + errdefer envp.deinit(); + while (true) { + const str_len = std.mem.indexOfScalar(u8, wtf8_buf[len..], 0).?; + defer len += str_len + 1; // each string is null-terminated + if (str_len == 0) break; // array ends with empty null-terminated string + const str_ptr: [*:0]u8 = @ptrCast(wtf8_buf[len..].ptr); + try envp.append(str_ptr); + } + try envp.append(null); + + const envp_slice: []?[*:0]u8 = try envp.toOwnedSlice(); + const envp_nonnull_slice: [][*:0]u8 = @ptrCast(envp_slice[0 .. envp_slice.len - 1]); + wtf8_env_buf = wtf8_buf; + orig_environ = std.os.environ; + std.os.environ = envp_nonnull_slice; +} + +const std = @import("std"); + +const bun = @import("bun"); +const Environment = bun.Environment;