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

module,win: fix long path resolve #53294

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

huseyinacacak-janea
Copy link
Contributor

Several issues were encountered with module loading due to extended path lengths on Windows. These have been addressed with corrections implemented across four distinct code locations, accompanied by the addition of a corresponding test case for each to ensure functionality.
Additionally, I've moved es-module/test-GH-50753.js to es-module/test-esm-long-path-win.js as the tests cover more cases than specified in that issue.

Fixes: #50753

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. labels Jun 3, 2024
@targos
Copy link
Member

targos commented Jun 3, 2024

@nodejs/platform-windows

H4ad
H4ad previously approved these changes Jun 3, 2024
@H4ad H4ad dismissed their stale review June 3, 2024 12:53

I actually need more time to take a look, I think the implementation will solve the problem but I want to test in which cases we should include the UNC path, since we didn't do this in all paths in the toNamespacedPath.

@H4ad
Copy link
Member

H4ad commented Jun 3, 2024

There are some conditions to include the UNC that you are not following:

node/lib/path.js

Lines 632 to 645 in 58711c2

if (StringPrototypeCharCodeAt(resolvedPath, 0) === CHAR_BACKWARD_SLASH) {
// Possible UNC root
if (StringPrototypeCharCodeAt(resolvedPath, 1) === CHAR_BACKWARD_SLASH) {
const code = StringPrototypeCharCodeAt(resolvedPath, 2);
if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) {
// Matched non-long UNC root, convert the path to a long UNC path
return `\\\\?\\UNC\\${StringPrototypeSlice(resolvedPath, 2)}`;
}
}
} else if (
isWindowsDeviceRoot(StringPrototypeCharCodeAt(resolvedPath, 0)) &&
StringPrototypeCharCodeAt(resolvedPath, 1) === CHAR_COLON &&
StringPrototypeCharCodeAt(resolvedPath, 2) === CHAR_BACKWARD_SLASH
) {

Although the condition could be matched, I think it would be better to wait for the migration of toNamespacedPath to C++.

Maybe we could include the ToNamespacePath port in this PR, and then leave that other PR just to remove the JS version and rewrite the places they are used.

@anonrig What do you think?

@StefanStojanovic StefanStojanovic added the request-ci Add this label to start a Jenkins CI on a PR. label Jun 3, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jun 3, 2024
Copy link
Member

@anonrig anonrig left a comment

Choose a reason for hiding this comment

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

I prefer to land this after the toNamespacedPath migration to C++. Unfortunately, I don't have the time to pursue this at the moment (afaict, there is only one failing test). I appreciate if you could took over that PR and apply these changes in a follow up PR.

@MoLow
Copy link
Member

MoLow commented Jun 3, 2024

I prefer to land this after the toNamespacedPath migration to C++. Unfortunately, I don't have the time to pursue this at the moment (afaict, there is only one failing test). I appreciate if you could took over that PR and apply these changes in a follow up PR.

in that case, can you convert the blocking "request changes" into a simple suggestion/friendly ask? I don't think this PR should be blocked on a PR that is not being currently worked on

@huseyinacacak-janea
Copy link
Contributor Author

I prefer to land this after the toNamespacedPath migration to C++. Unfortunately, I don't have the time to pursue this at the moment (afaict, there is only one failing test). I appreciate if you could took over that PR and apply these changes in a follow up PR.

Sure, no problem, I'll take over your PR and start working on it.

@StefanStojanovic StefanStojanovic added the request-ci Add this label to start a Jenkins CI on a PR. label Jul 2, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jul 3, 2024
@huseyinacacak-janea
Copy link
Contributor Author

I prefer to land this after the toNamespacedPath migration to C++. Unfortunately, I don't have the time to pursue this at the moment (afaict, there is only one failing test). I appreciate if you could took over that PR and apply these changes in a follow up PR.

@anonrig I've rebased this PR to use toNamespacedPath. Could you please review it?

@huseyinacacak-janea
Copy link
Contributor Author

Is there anything else I can do to help this PR move forward?

@H4ad H4ad requested a review from anonrig July 15, 2024 12:01
src/node_file.cc Outdated
switch (FilePathIsFile(env, file_path)) {
Local<Value> local_file_path =
Buffer::Copy(
env->isolate(), file_path.c_str(), strlen(file_path.c_str()))
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
env->isolate(), file_path.c_str(), strlen(file_path.c_str()))
env->isolate(), file_path.c_str(), file_path.size())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Thanks.

src/node_file.cc Outdated
switch (FilePathIsFile(env, file_path)) {
Local<Value> local_file_path =
Buffer::Copy(
env->isolate(), file_path.c_str(), strlen(file_path.c_str()))
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

// Check if the path has a trailing slash. If so, add it after
// ToNamespacedPath() as it will be deleted by ToNamespacedPath()
bool slashCheck = !path_value.ToString().empty() &&
path_value.ToString().back() ==
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
path_value.ToString().back() ==
path_value.ToStringView().ends_with
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

// Check if the path has a trailing slash. If so, add it after
// ToNamespacedPath() as it will be deleted by ToNamespacedPath()
bool slashCheck = !path_value.ToString().empty() &&
path_value.ToString().back() ==
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@@ -323,8 +323,8 @@ void BindingData::GetNearestParentPackageJSON(
// Check if the path has a trailing slash. If so, add it after
// ToNamespacedPath() as it will be deleted by ToNamespacedPath()
bool slashCheck = !path_value.ToString().empty() &&
path_value.ToString().back() ==
std::filesystem::path::preferred_separator;
path_value.ToStringView().ends_with(
Copy link
Member

Choose a reason for hiding this comment

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

The previous line is not needed path_value.ToString() creates an unnecessary string.

Can you also remove this in other places?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@@ -3096,8 +3096,14 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {

for (int i = 0; i < legacy_main_extensions_with_main_end; i++) {
file_path = *initial_file_path + std::string(legacy_main_extensions[i]);

switch (FilePathIsFile(env, file_path)) {
Local<Value> local_file_path =
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a TODO here?

// TODO: Remove this when ToNamespacedPath supports std::string as a value
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run.
7 participants