diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/node/types.zig | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index d1c92e970..bc2144095 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -1682,6 +1682,87 @@ pub const Path = struct { return JSC.ZigString.init(out).withEncoding().toValueGC(globalThis); } + + fn dirnameWindows(path: []const u8) []const u8 { + if (path.len == 0) + return "."; + + const root_slice = std.fs.path.diskDesignatorWindows(path); + if (path.len == root_slice.len) + return root_slice; + + const have_root_slash = path.len > root_slice.len and (path[root_slice.len] == '/' or path[root_slice.len] == '\\'); + + var end_index: usize = path.len - 1; + + while (path[end_index] == '/' or path[end_index] == '\\') { + // e.g. '\\' => "\\" + if (end_index == 0) { + return path[0..1]; + } + end_index -= 1; + } + + while (path[end_index] != '/' and path[end_index] != '\\') { + if (end_index == 0) { + if (root_slice.len == 0) { + return "."; + } + if (have_root_slash) { + // e.g. "c:\\" => "c:\\" + return path[0 .. root_slice.len + 1]; + } else { + // e.g. "c:foo" => "c:" + return root_slice; + } + } + end_index -= 1; + } + + if (have_root_slash and end_index == root_slice.len) { + end_index += 1; + } + + return path[0..end_index]; + } + + fn dirnamePosix(path: []const u8) []const u8 { + if (path.len == 0) + return "."; + + var end_index: usize = path.len - 1; + + while (path[end_index] == '/') { + // e.g. "////" => "/" + if (end_index == 0) { + return "/"; + } + end_index -= 1; + } + + while (path[end_index] != '/') { + if (end_index == 0) { + // e.g. "a/", "a" + return "."; + } + end_index -= 1; + } + + // e.g. "/a/" => "/" + if (end_index == 0 and path[0] == '/') { + return "/"; + } + + // "a/b" => "a" or "//b" => "//" + if (end_index <= 1) { + if (path[0] == '/' and path[1] == '/') { + end_index += 1; + } + } + + return path[0..end_index]; + } + pub fn dirname(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); if (args_len == 0) { @@ -1697,9 +1778,9 @@ pub const Path = struct { const base_slice = path.slice(); const out = if (isWindows) - std.fs.path.dirnameWindows(base_slice) orelse "." + @This().dirnameWindows(base_slice) else - std.fs.path.dirnamePosix(base_slice) orelse "."; + @This().dirnamePosix(base_slice); return JSC.ZigString.init(out).toValueGC(globalThis); } |