diff --git a/src/node_file.cc b/src/node_file.cc index 8ab92f4e55d6e6..acf0ed2d8e83bf 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -3130,14 +3130,14 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo& args) { ToNamespacedPath(env, &src); THROW_IF_INSUFFICIENT_PERMISSIONS( env, permission::PermissionScope::kFileSystemRead, src.ToStringView()); - auto src_path = std::filesystem::path(src.ToStringView()); + auto src_path = std::filesystem::path(src.ToWString()); BufferValue dest(isolate, args[1]); CHECK_NOT_NULL(*dest); ToNamespacedPath(env, &dest); THROW_IF_INSUFFICIENT_PERMISSIONS( env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView()); - auto dest_path = std::filesystem::path(dest.ToStringView()); + auto dest_path = std::filesystem::path(dest.ToWString()); bool dereference = args[2]->IsTrue(); bool recursive = args[3]->IsTrue(); diff --git a/src/util.h b/src/util.h index a6da8720c499df..8eb97c3a9977f8 100644 --- a/src/util.h +++ b/src/util.h @@ -126,6 +126,10 @@ void DumpJavaScriptBacktrace(FILE* fp); #define ABORT_NO_BACKTRACE() abort() #endif +#ifdef _WIN32 +#include +#endif + // Caller of this macro must not be marked as [[noreturn]]. Printing of // backtraces may not work correctly in [[noreturn]] functions because // when generating code for them the compiler can choose not to @@ -562,6 +566,20 @@ class BufferValue : public MaybeStackBuffer { inline std::string_view ToStringView() const { return std::string_view(out(), length()); } + inline std::wstring ToWString() const { +#ifdef _WIN32 + auto size_needed = MultiByteToWideChar( + CP_UTF8, 0, out(), static_cast(length()), nullptr, 0); + std::wstring wstrTo(length(), 0); + MultiByteToWideChar( + CP_UTF8, 0, out(), static_cast(length()), &wstrTo[0], size_needed); +#else + auto size_needed = std::mbstowcs(nullptr, out(), 0); + std::wstring wstrTo(size_needed, L'\0'); + std::mbstowcs(&wstrTo[0], out(), length()); +#endif + return wstrTo; + } }; #define SPREAD_BUFFER_ARG(val, name) \ diff --git "a/test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266/index.js" "b/test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266/index.js" new file mode 100644 index 00000000000000..12388b0457bdda --- /dev/null +++ "b/test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266/index.js" @@ -0,0 +1,3 @@ +module.exports = { + purpose: 'testing copy' +}; diff --git a/test/parallel/test-fs-cp.mjs b/test/parallel/test-fs-cp.mjs index 63bc813ae226c7..987da4430b2659 100644 --- a/test/parallel/test-fs-cp.mjs +++ b/test/parallel/test-fs-cp.mjs @@ -30,6 +30,14 @@ function nextdir() { // Synchronous implementation of copy. +// It copies a nested folder containing UTF characters. +{ + const src = './test/fixtures/copy/utf/新建文件'; + const dest = nextdir(); + cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })); + assertDirEquivalent(src, dest); +} + // It copies a nested folder structure with files and folders. { const src = './test/fixtures/copy/kitchen-sink';