Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add win32 path.toNamespacedPath and align rest of node:path with Node #8469

Merged
merged 1 commit into from
Feb 12, 2024

Conversation

jdalton
Copy link
Contributor

@jdalton jdalton commented Jan 25, 2024

What does this PR do?

Add win32 path.toNamespacedPath and align rest of node:path with Node.

  • Port of Node's node:path 22+ methods to Zig 🎉
  • Added Node's node:path unit tests (80 node:path tests now) 🗒️
  • Verified on Windows (test\\js\\node\\path\\*

This is a very close port of Node's methods. I like this approach as it avoids gotchas that creep in with reworking code. Even things like how JavaScript allows -1 for String#slice plays its part in Node's implementation.

It's a biggie

After this lands I'll do a follow-up PR to move these into resolve_path.zig.

Copy link
Contributor

github-actions bot commented Jan 25, 2024

Copy link
Contributor

github-actions bot commented Jan 25, 2024

Copy link
Contributor

github-actions bot commented Jan 25, 2024

Copy link
Contributor

github-actions bot commented Jan 25, 2024

Copy link
Contributor

github-actions bot commented Jan 25, 2024

❌🪟 @jdalton, there are 11 test regressions on Windows x86_64

  • test\cli\hot\hot.test.ts
  • test\cli\run\require-cache.test.ts
  • test\cli\run\transpiler-cache.test.ts
  • test\js\bun\console\console-iterator.test.ts
  • test\js\bun\util\bun-file-windows.test.ts
  • test\js\deno\crypto\webcrypto.test.ts
  • test\js\bun\http\bun-server.test.ts
  • test\js\node\process\process-args.test.js
  • test\js\third_party\es-module-lexer\es-module-lexer.test.ts
  • test\js\web\timers\setTimeout.test.js
  • test\js\web\workers\worker.test.ts

Full Test Output

paperclover

This comment was marked as outdated.

@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch 2 times, most recently from 2a52ec0 to 529197d Compare January 26, 2024 02:56
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from 529197d to 546932d Compare February 2, 2024 08:07
@jdalton jdalton changed the title Add Windows implementation of path.toNamespacedPath Add win32 path.toNamespacedPath and align rest of node:path with Node Feb 2, 2024
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from 546932d to c30180a Compare February 2, 2024 08:17
@jdalton jdalton requested a review from paperclover February 2, 2024 08:18
@jdalton jdalton marked this pull request as ready for review February 2, 2024 08:19
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from c30180a to 394730b Compare February 2, 2024 08:32
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch 4 times, most recently from f84b876 to dd3112e Compare February 2, 2024 11:00
jdalton referenced this pull request Feb 2, 2024
* windows: fix module.paths getter causing a crash

* use the buffer that was there before
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from dd3112e to e3ca9de Compare February 2, 2024 19:57
Copy link
Member

@paperclover paperclover left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the approach of copying node 1:1 is great i think, though i did not verify all code was ported over properly. might be worth double checking if tests are failing, as i did spot one single place where something was misported.

regards to performance, i see:

  • the obvious complexity of what node:path does. this is unavoidable and i think it isn't actually going to be that huge of a deal. path normalization has to happen, and this will be a big win in accuracy (bun is not accurate in many regards)
  • the environment variable lookup in resolve is problematic i think. i really wish it didnt have to happen, see comments at that point in the review
  • the allocation stategy is alright but i think the getBufAlloc function seems very problematic. i simply think we should just not support paths longer than the max. though i may be wrong in the need for this. i am incorrect

after this pr, it would also be nice to reintroduce bun.String.map, a function did not ever commit: it lets us actually apply the generic versions of these functions to the javascript strings. some advances by dylan and georgijs in our string code make this a more useful api now (at the time i couldnt actually use the function or anything)

also, maybe we rename the Impl functions to have T as the suffix, as that was the pattern taken by the other code doing a similar pattern of generic string manipulation


pub fn create(globalObject: *JSC.JSGlobalObject, isWindows: bool) callconv(.C) JSC.JSValue {
return shim.cppFn("create", .{ globalObject, isWindows });
/// Taken from Zig 0.11.0 zig/src/resinator/rc.zig
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wish this was in the standard library

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can be with a PR to zig! It's used internally to them already.

@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch 8 times, most recently from 0bac691 to 5e4a05c Compare February 3, 2024 18:41
}

const results = await Promise.allSettled(pending);
for (let i = 0; i < iterCount; i++) {
expect(results[i].status).toBe("rejected");
expect(results[i].reason!.code).toBe("ENOENT");
expect(results[i].reason!.path).toBe(join(notfound, i));
expect(results[i].reason!.path).toBe(join(notfound, `${i}`));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ Ensure path.join gets string values.

//
// While Node's error message is:
// The "pathObject" argument must be of type object. Received nullå
message: `"pathObject" property must be of type object, got ${typeof pathObject}`,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👆 TODO for error message compliance. Node provides a bit more-helpful messages around data types.

@@ -1,900 +1,62 @@
const { file } = import.meta;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to test/js/node/path/browserify.test.js

// const spawnResult = child.spawnSync(process.argv[0], [relativeFixture, currentDriveLetter]);
// const resolvedPath = spawnResult.stdout.toString().trim();
// assert.strictEqual(resolvedPath.toLowerCase(), process.cwd().toLowerCase());
// }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ TODO for once our spawnSync().stdout result works on Windows.

@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from 8dcafa5 to 767b62b Compare February 12, 2024 17:50

inline fn MaybeSlice(comptime T: type) type {
return Maybe([]const T, Syscall.Error);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MaybeBuf and MaybeSlice use Syscall.Error for now.

};
const pathZStr = path_ptr.getZigString(globalObject);
const len = pathZStr.len;
if (len == 0) return toUTF8JSString(globalObject, CHAR_STR_DOT);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ We don't even allocate if len is0, exiting early

);
const allocator = stack_fallback.get();

const pathZSlice = pathZStr.toSlice(allocator);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming pathZSlice to distinguish between the ZigString.Slice and the standard buffer slice. Since we will be doing pathZSlice.slice() later and reading it from a glance can be a head scratcher.

else
toJSString(globalObject, normalizePosix(pathZSlice.slice(), buf));
}
var buf: PathBuffer = undefined;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ We only use the allocator when needed else we use the cheap stack var buf: PathBuffer = undefined;

@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from 767b62b to f4e4fe9 Compare February 12, 2024 18:04
if (len == 0) {
// Skip work for empty entries
paths[i] = "";
} else {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ Skip work for empty paths (defer allocator.free(paths) is still happy)

);
const allocator = stack_fallback.get();

const pathZSlice = path_ptr.toSlice(globalObject, allocator);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ The only place we jump straight to pathZSlice instead of going to pathZStr.

@@ -2431,6 +4930,9 @@ pub const Path = struct {
@export(Path.resolve, .{
.name = Export[9].symbol_name,
});
@export(Path.toNamespacedPath, .{
.name = Export[10].symbol_name,
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ toNamespacePath wiring

@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from f4e4fe9 to 769c79a Compare February 12, 2024 18:18
@paperclover paperclover self-requested a review February 12, 2024 18:46
@@ -173,7 +173,7 @@ pub const RefCount = @import("./ref_count.zig").RefCount;

pub const MAX_PATH_BYTES: usize = if (Environment.isWasm) 1024 else std.fs.MAX_PATH_BYTES;
pub const PathBuffer = [MAX_PATH_BYTES]u8;
pub const WPathBuffer = [MAX_PATH_BYTES / 2]u16;
pub const WPathBuffer = [windows.PATH_MAX_WIDE]u16;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from 769c79a to 8e272e5 Compare February 12, 2024 19:43
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch 2 times, most recently from d54f2cc to 46ec84d Compare February 12, 2024 20:13
@jdalton jdalton force-pushed the jdalton/to-namespaced-path-win branch from 46ec84d to fc31407 Compare February 12, 2024 20:21
@paperclover paperclover merged commit 96e7227 into main Feb 12, 2024
26 of 31 checks passed
@paperclover paperclover deleted the jdalton/to-namespaced-path-win branch February 12, 2024 22:27
gvilums added a commit that referenced this pull request Feb 13, 2024
* Fix some related to paths and string encoding

* Fix relative paths with glob

* Fix scan tests

* Fix glob scan test

* [autofix.ci] apply automated fixes

* Fix leak test

* clean up post merge

* [autofix.ci] apply automated fixes

* clean up glob getcwd

* remove old struct

* fix open on posix

* feat: Add win32 path.toNamespacedPath and align rest of node:path with Node (#8469)

* restore zls file change

* [autofix.ci] apply automated fixes

* switch to using fs.top_level_dir in glob

---------

Co-authored-by: Jarred Sumner <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Georgijs Vilums <[email protected]>
Co-authored-by: Georgijs Vilums <[email protected]>
Co-authored-by: John-David Dalton <[email protected]>
Co-authored-by: Georgijs <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants