diff --git a/patches/node/src_use_cp_utf8_for_wide_file_names_on_win32.patch b/patches/node/src_use_cp_utf8_for_wide_file_names_on_win32.patch deleted file mode 100644 index 04eb8aea3f..0000000000 --- a/patches/node/src_use_cp_utf8_for_wide_file_names_on_win32.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Fedor Indutny -Date: Tue, 11 Nov 2025 13:43:01 -0800 -Subject: src: use CP_UTF8 for wide file names on win32 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -`src/node_modules.cc` needs to be consistent with `src/node_file.cc` in -how it translates the utf8 strings to `std::wstring` otherwise we might -end up in situation where we can read the source code of imported -package from disk, but fail to recognize that it is an ESM (or CJS) and -cause runtime errors. This type of error is possible on Windows when the -path contains unicode characters and "Language for non-Unicode programs" -is set to "Chinese (Traditional, Taiwan)". - -See: #58768 -PR-URL: https://github.com/nodejs/node/pull/60575 -Reviewed-By: Anna Henningsen -Reviewed-By: Darshan Sen -Reviewed-By: Stefan Stojanovic -Reviewed-By: Juan José Arboleda -Reviewed-By: Joyee Cheung -Reviewed-By: Rafael Gonzaga - -diff --git a/src/node_file.cc b/src/node_file.cc -index 969e7d08086f8442bed476feaf15599b8c79db7c..e7459654401c275dfb86207831016ed71060bcc9 100644 ---- a/src/node_file.cc -+++ b/src/node_file.cc -@@ -3175,42 +3175,6 @@ static void GetFormatOfExtensionlessFile( - return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT); - } - --#ifdef _WIN32 --#define BufferValueToPath(str) \ -- std::filesystem::path(ConvertToWideString(str.ToString(), CP_UTF8)) -- --std::string ConvertWideToUTF8(const std::wstring& wstr) { -- if (wstr.empty()) return std::string(); -- -- int size_needed = WideCharToMultiByte(CP_UTF8, -- 0, -- &wstr[0], -- static_cast(wstr.size()), -- nullptr, -- 0, -- nullptr, -- nullptr); -- std::string strTo(size_needed, 0); -- WideCharToMultiByte(CP_UTF8, -- 0, -- &wstr[0], -- static_cast(wstr.size()), -- &strTo[0], -- size_needed, -- nullptr, -- nullptr); -- return strTo; --} -- --#define PathToString(path) ConvertWideToUTF8(path.wstring()); -- --#else // _WIN32 -- --#define BufferValueToPath(str) std::filesystem::path(str.ToStringView()); --#define PathToString(path) path.native(); -- --#endif // _WIN32 -- - static void CpSyncCheckPaths(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - Isolate* isolate = env->isolate(); -@@ -3223,7 +3187,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo& args) { - THROW_IF_INSUFFICIENT_PERMISSIONS( - env, permission::PermissionScope::kFileSystemRead, src.ToStringView()); - -- auto src_path = BufferValueToPath(src); -+ auto src_path = src.ToPath(); - - BufferValue dest(isolate, args[1]); - CHECK_NOT_NULL(*dest); -@@ -3231,7 +3195,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo& args) { - THROW_IF_INSUFFICIENT_PERMISSIONS( - env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView()); - -- auto dest_path = BufferValueToPath(dest); -+ auto dest_path = dest.ToPath(); - bool dereference = args[2]->IsTrue(); - bool recursive = args[3]->IsTrue(); - -@@ -3260,8 +3224,8 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo& args) { - (src_status.type() == std::filesystem::file_type::directory) || - (dereference && src_status.type() == std::filesystem::file_type::symlink); - -- auto src_path_str = PathToString(src_path); -- auto dest_path_str = PathToString(dest_path); -+ auto src_path_str = ConvertPathToUTF8(src_path); -+ auto dest_path_str = ConvertPathToUTF8(dest_path); - - if (!error_code) { - // Check if src and dest are identical. -@@ -3356,7 +3320,7 @@ static bool CopyUtimes(const std::filesystem::path& src, - uv_fs_t req; - auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); - -- auto src_path_str = PathToString(src); -+ auto src_path_str = ConvertPathToUTF8(src); - int result = uv_fs_stat(nullptr, &req, src_path_str.c_str(), nullptr); - if (is_uv_error(result)) { - env->ThrowUVException(result, "stat", nullptr, src_path_str.c_str()); -@@ -3367,7 +3331,7 @@ static bool CopyUtimes(const std::filesystem::path& src, - const double source_atime = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9; - const double source_mtime = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9; - -- auto dest_file_path_str = PathToString(dest); -+ auto dest_file_path_str = ConvertPathToUTF8(dest); - int utime_result = uv_fs_utime(nullptr, - &req, - dest_file_path_str.c_str(), -@@ -3502,7 +3466,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo& args) { - std::error_code error; - for (auto dir_entry : std::filesystem::directory_iterator(src)) { - auto dest_file_path = dest / dir_entry.path().filename(); -- auto dest_str = PathToString(dest); -+ auto dest_str = ConvertPathToUTF8(dest); - - if (dir_entry.is_symlink()) { - if (verbatim_symlinks) { -@@ -3565,7 +3529,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo& args) { - } - } else if (std::filesystem::is_regular_file(dest_file_path)) { - if (!dereference || (!force && error_on_exist)) { -- auto dest_file_path_str = PathToString(dest_file_path); -+ auto dest_file_path_str = ConvertPathToUTF8(dest_file_path); - env->ThrowStdErrException( - std::make_error_code(std::errc::file_exists), - "cp", -diff --git a/src/node_modules.cc b/src/node_modules.cc -index 5355f2f96e9c9f6548ae43fd38b0d89a825e6b60..15686c00524b6e9a31d6d27069605b1d9ebd5d38 100644 ---- a/src/node_modules.cc -+++ b/src/node_modules.cc -@@ -345,22 +345,24 @@ const BindingData::PackageConfig* BindingData::TraverseParent( - - // Stop the search when the process doesn't have permissions - // to walk upwards -- if (is_permissions_enabled && -- !env->permission()->is_granted( -- env, -- permission::PermissionScope::kFileSystemRead, -- current_path.generic_string())) [[unlikely]] { -- return nullptr; -+ if (is_permissions_enabled) { -+ if (!env->permission()->is_granted( -+ env, -+ permission::PermissionScope::kFileSystemRead, -+ ConvertGenericPathToUTF8(current_path))) [[unlikely]] { -+ return nullptr; -+ } - } - - // Check if the path ends with `/node_modules` -- if (current_path.generic_string().ends_with("/node_modules")) { -+ if (current_path.filename() == "node_modules") { - return nullptr; - } - - auto package_json_path = current_path / "package.json"; -+ - auto package_json = -- GetPackageJSON(realm, package_json_path.string(), nullptr); -+ GetPackageJSON(realm, ConvertPathToUTF8(package_json_path), nullptr); - if (package_json != nullptr) { - return package_json; - } -@@ -382,20 +384,12 @@ void BindingData::GetNearestParentPackageJSONType( - - ToNamespacedPath(realm->env(), &path_value); - -- std::string path_value_str = path_value.ToString(); -+ auto path = path_value.ToPath(); -+ - if (slashCheck) { -- path_value_str.push_back(kPathSeparator); -+ path /= ""; - } - -- 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) { -diff --git a/src/util-inl.h b/src/util-inl.h -index d07bceb425f00882db116975a92f4835d7c2cf3b..6898e8ea794675e903e13e2b45524d572a3f68bb 100644 ---- a/src/util-inl.h -+++ b/src/util-inl.h -@@ -718,12 +718,11 @@ inline bool IsWindowsBatchFile(const char* filename) { - return !extension.empty() && (extension == "cmd" || extension == "bat"); - } - --inline std::wstring ConvertToWideString(const std::string& str, -- UINT code_page) { -+inline std::wstring ConvertUTF8ToWideString(const std::string& str) { - int size_needed = MultiByteToWideChar( -- code_page, 0, &str[0], static_cast(str.size()), nullptr, 0); -+ CP_UTF8, 0, &str[0], static_cast(str.size()), nullptr, 0); - std::wstring wstrTo(size_needed, 0); -- MultiByteToWideChar(code_page, -+ MultiByteToWideChar(CP_UTF8, - 0, - &str[0], - static_cast(str.size()), -@@ -731,6 +730,59 @@ inline std::wstring ConvertToWideString(const std::string& str, - size_needed); - return wstrTo; - } -+ -+std::string ConvertWideStringToUTF8(const std::wstring& wstr) { -+ if (wstr.empty()) return std::string(); -+ -+ int size_needed = WideCharToMultiByte(CP_UTF8, -+ 0, -+ &wstr[0], -+ static_cast(wstr.size()), -+ nullptr, -+ 0, -+ nullptr, -+ nullptr); -+ std::string strTo(size_needed, 0); -+ WideCharToMultiByte(CP_UTF8, -+ 0, -+ &wstr[0], -+ static_cast(wstr.size()), -+ &strTo[0], -+ size_needed, -+ nullptr, -+ nullptr); -+ return strTo; -+} -+ -+template -+std::filesystem::path MaybeStackBuffer::ToPath() const { -+ std::wstring wide_path = ConvertUTF8ToWideString(ToString()); -+ return std::filesystem::path(wide_path); -+} -+ -+std::string ConvertPathToUTF8(const std::filesystem::path& path) { -+ return ConvertWideStringToUTF8(path.wstring()); -+} -+ -+std::string ConvertGenericPathToUTF8(const std::filesystem::path& path) { -+ return ConvertWideStringToUTF8(path.generic_wstring()); -+} -+ -+#else // _WIN32 -+ -+template -+std::filesystem::path MaybeStackBuffer::ToPath() const { -+ return std::filesystem::path(ToStringView()); -+} -+ -+std::string ConvertPathToUTF8(const std::filesystem::path& path) { -+ return path.native(); -+} -+ -+std::string ConvertGenericPathToUTF8(const std::filesystem::path& path) { -+ return path.generic_string(); -+} -+ - #endif // _WIN32 - - inline v8::MaybeLocal NewDictionaryInstance( -diff --git a/src/util.h b/src/util.h -index 1db426df35e4976427b578a2974041ec9e92cf4c..52e6a149d6760640d93c56ce91a759ae9207a8c7 100644 ---- a/src/util.h -+++ b/src/util.h -@@ -507,6 +507,8 @@ class MaybeStackBuffer { - inline std::basic_string_view ToStringView() const { - return {out(), length()}; - } -+ // This can only be used if the buffer contains path data in UTF8 -+ inline std::filesystem::path ToPath() const; - - private: - size_t length_; -@@ -1038,9 +1040,15 @@ class JSONOutputStream final : public v8::OutputStream { - // Returns true if OS==Windows and filename ends in .bat or .cmd, - // case insensitive. - inline bool IsWindowsBatchFile(const char* filename); --inline std::wstring ConvertToWideString(const std::string& str, UINT code_page); -+inline std::wstring ConvertUTF8ToWideString(const std::string& str); -+inline std::string ConvertWideStringToUTF8(const std::wstring& wstr); -+ - #endif // _WIN32 - -+inline std::filesystem::path ConvertUTF8ToPath(const std::string& str); -+inline std::string ConvertPathToUTF8(const std::filesystem::path& path); -+inline std::string ConvertGenericPathToUTF8(const std::filesystem::path& path); -+ - // A helper to create a new instance of the dictionary template. - // Unlike v8::DictionaryTemplate::NewInstance, this method will - // check that all properties have been set (are not empty MaybeLocals)