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

src: fix generation of path objects in Windows #56696

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3146,21 +3146,8 @@ static void GetFormatOfExtensionlessFile(
}

#ifdef _WIN32
std::wstring ConvertToWideString(const std::string& str) {
int size_needed = MultiByteToWideChar(
CP_UTF8, 0, &str[0], static_cast<int>(str.size()), nullptr, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8,
0,
&str[0],
static_cast<int>(str.size()),
&wstrTo[0],
size_needed);
return wstrTo;
}

#define BufferValueToPath(str) \
std::filesystem::path(ConvertToWideString(str.ToString()))
std::filesystem::path(ConvertToWideString(str.ToString(), CP_UTF8))

std::string ConvertWideToUTF8(const std::wstring& wstr) {
if (wstr.empty()) return std::string();
Expand Down
24 changes: 20 additions & 4 deletions src/node_modules.cc
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,16 @@ void BindingData::GetNearestParentPackageJSON(
path_value_str.push_back(kPathSeparator);
}

auto package_json =
TraverseParent(realm, std::filesystem::path(path_value_str));
std::filesystem::path path;

#ifdef _WIN32
std::wstring wide_path = ConvertToWideString(path_value_str, GetACP());
path = std::filesystem::path(wide_path);
#else
path = std::filesystem::path(path_value_str);
#endif

auto package_json = TraverseParent(realm, path);

if (package_json != nullptr) {
args.GetReturnValue().Set(package_json->Serialize(realm));
Expand All @@ -370,8 +378,16 @@ void BindingData::GetNearestParentPackageJSONType(
path_value_str.push_back(kPathSeparator);
}

auto package_json =
TraverseParent(realm, std::filesystem::path(path_value_str));
std::filesystem::path path;

#ifdef _WIN32
std::wstring wide_path = ConvertToWideString(path_value_str, GetACP());
path = std::filesystem::path(wide_path);
#else
path = std::filesystem::path(path_value_str);
#endif

auto package_json = TraverseParent(realm, path);

if (package_json == nullptr) {
return;
Expand Down
16 changes: 16 additions & 0 deletions src/util-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,22 @@ bool IsWindowsBatchFile(const char* filename) {
#endif // _WIN32
}

#ifdef _WIN32
inline std::wstring ConvertToWideString(const std::string& str,
UINT code_page) {
int size_needed = MultiByteToWideChar(
code_page, 0, &str[0], static_cast<int>(str.size()), nullptr, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(code_page,
0,
&str[0],
static_cast<int>(str.size()),
&wstrTo[0],
size_needed);
return wstrTo;
}
#endif // _WIN32

} // namespace node

#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/copy/utf/新建文件夹/experimental.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"ofLife": 42
}
24 changes: 24 additions & 0 deletions test/parallel/test-module-create-require-multibyte.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

require('../common');
const fixtures = require('../common/fixtures');
const assert = require('assert');

// This test ensures that the module can be resolved
// even if the path given to createRequire contains multibyte characters.

const { createRequire } = require('module');

{
const u = fixtures.fileURL('あ.js');

const reqToo = createRequire(u);
assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 });
}

{
const u = fixtures.fileURL('copy/utf/新建文件夹/index.js');

const reqToo = createRequire(u);
assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 });
}
Loading