aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-02-04 02:05:41 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-02-04 02:05:41 -0800
commit909e6a6bab01661c1e015658987ba6f53ee3ffd2 (patch)
tree08c49af3fa689db630093e898cb808943b844cef
parenta2f91b167d6a58c26454cd29a051084d4ea47c7c (diff)
downloadbun-909e6a6bab01661c1e015658987ba6f53ee3ffd2.tar.gz
bun-909e6a6bab01661c1e015658987ba6f53ee3ffd2.tar.zst
bun-909e6a6bab01661c1e015658987ba6f53ee3ffd2.zip
`path.resolve()` passes tests
-rw-r--r--integration/bunjs-only-snippets/path.test.js65
-rw-r--r--src/javascript/jsc/node/types.zig29
2 files changed, 81 insertions, 13 deletions
diff --git a/integration/bunjs-only-snippets/path.test.js b/integration/bunjs-only-snippets/path.test.js
index d6987bf80..997368150 100644
--- a/integration/bunjs-only-snippets/path.test.js
+++ b/integration/bunjs-only-snippets/path.test.js
@@ -390,3 +390,68 @@ it("path.normalize", () => {
);
strictEqual(path.posix.normalize("foo/bar\\baz"), "foo/bar\\baz");
});
+
+it("path.resolve", () => {
+ const failures = [];
+ const slashRE = /\//g;
+ const backslashRE = /\\/g;
+
+ const resolveTests = [
+ // [
+ // path.win32.resolve,
+ // // Arguments result
+ // [
+ // [["c:/blah\\blah", "d:/games", "c:../a"], "c:\\blah\\a"],
+ // [["c:/ignore", "d:\\a/b\\c/d", "\\e.exe"], "d:\\e.exe"],
+ // [["c:/ignore", "c:/some/file"], "c:\\some\\file"],
+ // [["d:/ignore", "d:some/dir//"], "d:\\ignore\\some\\dir"],
+ // [["."], process.cwd()],
+ // [["//server/share", "..", "relative\\"], "\\\\server\\share\\relative"],
+ // [["c:/", "//"], "c:\\"],
+ // [["c:/", "//dir"], "c:\\dir"],
+ // [["c:/", "//server/share"], "\\\\server\\share\\"],
+ // [["c:/", "//server//share"], "\\\\server\\share\\"],
+ // [["c:/", "///some//dir"], "c:\\some\\dir"],
+ // [
+ // ["C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js"],
+ // "C:\\foo\\tmp.3\\cycles\\root.js",
+ // ],
+ // ],
+ // ],
+ [
+ path.posix.resolve,
+ // Arguments result
+ [
+ [["/var/lib", "../", "file/"], "/var/file"],
+ [["/var/lib", "/../", "file/"], "/file"],
+ [["a/b/c/", "../../.."], process.cwd()],
+ [["."], process.cwd()],
+ [["/some/dir", ".", "/absolute/"], "/absolute"],
+ [
+ ["/foo/tmp.3/", "../tmp.3/cycles/root.js"],
+ "/foo/tmp.3/cycles/root.js",
+ ],
+ ],
+ ],
+ ];
+ const isWindows = false;
+ resolveTests.forEach(([resolve, tests]) => {
+ tests.forEach(([test, expected]) => {
+ const actual = resolve.apply(null, test);
+ let actualAlt;
+ const os = resolve === path.win32.resolve ? "win32" : "posix";
+ if (resolve === path.win32.resolve && !isWindows)
+ actualAlt = actual.replace(backslashRE, "/");
+ else if (resolve !== path.win32.resolve && isWindows)
+ actualAlt = actual.replace(slashRE, "\\");
+
+ const message = `path.${os}.resolve(${test
+ .map(JSON.stringify)
+ .join(",")})\n expect=${JSON.stringify(
+ expected
+ )}\n actual=${JSON.stringify(actual)}`;
+ if (actual !== expected && actualAlt !== expected) failures.push(message);
+ });
+ });
+ strictEqual(failures.length, 0, failures.join("\n"));
+});
diff --git a/src/javascript/jsc/node/types.zig b/src/javascript/jsc/node/types.zig
index 005ba6860..b02d5ef89 100644
--- a/src/javascript/jsc/node/types.zig
+++ b/src/javascript/jsc/node/types.zig
@@ -2136,17 +2136,17 @@ pub const Path = struct {
return JSC.ZigString.init(out).withEncoding().toValueGC(globalThis);
}
}
+ fn isAbsoluteString(path: JSC.ZigString, windows: bool) bool {
+ if (!windows) return path.len > 0 and path.slice()[0] == '/';
+
+ return isZigStringAbsoluteWindows(path);
+ }
pub fn isAbsolute(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) return JSC.JSValue.jsBoolean(false);
var zig_str: JSC.ZigString = args_ptr[0].getZigString(globalThis);
if (zig_str.isEmpty()) return JSC.JSValue.jsBoolean(false);
-
- if (!isWindows) {
- return JSC.JSValue.jsBoolean(zig_str.slice()[0] == '/');
- }
-
- return JSC.JSValue.jsBoolean(isZigStringAbsoluteWindows(zig_str));
+ return JSC.JSValue.jsBoolean(isAbsoluteString(zig_str, isWindows));
}
fn isZigStringAbsoluteWindows(zig_str: JSC.ZigString) bool {
if (zig_str.is16Bit()) {
@@ -2298,28 +2298,31 @@ pub const Path = struct {
pub fn resolve(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 < 2) return normalize(globalThis, isWindows, args_ptr, args_len);
var stack_fallback_allocator = std.heap.stackFallback(
(32 * @sizeOf(string)),
heap_allocator,
);
var allocator = stack_fallback_allocator.get();
- var out_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
- // TODO:
- _ = isWindows;
+ var out_buf: [std.fs.MAX_PATH_BYTES * 2]u8 = undefined;
+
var parts = allocator.alloc(string, args_len) catch unreachable;
defer allocator.free(parts);
- var i: u16 = 0;
+
var arena = std.heap.ArenaAllocator.init(heap_allocator);
var arena_allocator = arena.allocator();
defer arena.deinit();
+ var i: u16 = 0;
while (i < args_len) : (i += 1) {
- parts[i] = args_ptr[0].toSlice(globalThis, arena_allocator).slice();
+ parts[i] = args_ptr[i].toSlice(globalThis, arena_allocator).slice();
}
- var out = JSC.ZigString.init(PathHandler.joinAbsStringBuf(Fs.FileSystem.instance.top_level_dir, &out_buf, parts, .posix));
+ var out = if (!isWindows)
+ JSC.ZigString.init(PathHandler.joinAbsStringBuf(Fs.FileSystem.instance.top_level_dir, &out_buf, parts, .posix))
+ else
+ JSC.ZigString.init(PathHandler.joinAbsStringBuf(Fs.FileSystem.instance.top_level_dir, &out_buf, parts, .windows));
+
if (arena.state.buffer_list.first != null) out.setOutputEncoding();
return out.toValueGC(globalThis);
}