aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Ai Hoshino <ambiguous404@gmail.com> 2023-07-25 15:41:22 +0800
committerGravatar GitHub <noreply@github.com> 2023-07-25 00:41:22 -0700
commit130079b558c87519b60109028e98feffdf984933 (patch)
treefd6c06575a930f9776a30d7c639d9c001949c0e2 /src
parent83568307274d515aca645b638879118bae2d15a9 (diff)
downloadbun-130079b558c87519b60109028e98feffdf984933.tar.gz
bun-130079b558c87519b60109028e98feffdf984933.tar.zst
bun-130079b558c87519b60109028e98feffdf984933.zip
fix some cases in the `dirname` function. (#3785)
Close: #3782
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/node/types.zig85
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);
}