From 840f95226876f86ed04ce2963e6d3dc6492c7d1c Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Sat, 18 Jan 2025 13:01:54 -0500 Subject: [PATCH 01/11] punycode: limit deprecation warning DEP0040 is an extremely annoying warning. Most of the people seeing it cannot do anything about it. This commit updates the warning logic to only emit outside of node_modules. This is similar to other warnings such as the Buffer() constructor warning. Ideally, this should be backported to Node 22. Refs: https://github.com/nodejs/node/pull/47202 PR-URL: https://github.com/nodejs/node/pull/56632 Reviewed-By: Jordan Harband Reviewed-By: Richard Lau Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca Reviewed-By: Matteo Collina Reviewed-By: Antoine du Hamel Reviewed-By: Joyee Cheung --- lib/punycode.js | 19 ++++++++++++------- .../errors/core_line_numbers.snapshot | 6 +++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/punycode.js b/lib/punycode.js index 7dfe552a5c9efa..e303a5373b8839 100644 --- a/lib/punycode.js +++ b/lib/punycode.js @@ -1,11 +1,16 @@ 'use strict'; - -process.emitWarning( - 'The `punycode` module is deprecated. Please use a userland ' + - 'alternative instead.', - 'DeprecationWarning', - 'DEP0040', -); +const { + isInsideNodeModules, +} = internalBinding('util'); + +if (!isInsideNodeModules(100, true)) { + process.emitWarning( + 'The `punycode` module is deprecated. Please use a userland ' + + 'alternative instead.', + 'DeprecationWarning', + 'DEP0040', + ); +} /** Highest positive signed 32-bit float value */ const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 diff --git a/test/fixtures/errors/core_line_numbers.snapshot b/test/fixtures/errors/core_line_numbers.snapshot index 54cdb52744b29e..9ef06c33af8e28 100644 --- a/test/fixtures/errors/core_line_numbers.snapshot +++ b/test/fixtures/errors/core_line_numbers.snapshot @@ -1,10 +1,10 @@ -node:punycode:49 +node:punycode:54 throw new RangeError(errors[type]); ^ RangeError: Invalid input - at error (node:punycode:49:8) - at Object.decode (node:punycode:242:5) + at error (node:punycode:54:8) + at Object.decode (node:punycode:247:5) at Object. (*core_line_numbers.js:13:10) Node.js * From 009d53ec3c3a411e9ad28eaae419c95b300cb62a Mon Sep 17 00:00:00 2001 From: Maksim Gorkov <33923276+MGorkov@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:39:56 +0300 Subject: [PATCH 02/11] child_process: fix parsing messages with splitted length field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/55834 PR-URL: https://github.com/nodejs/node/pull/56106 Reviewed-By: Luigi Pinca Reviewed-By: Juan José Arboleda Reviewed-By: James M Snell --- lib/internal/child_process/serialization.js | 7 +++++- ...ced-serialization-splitted-length-field.js | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-child-process-advanced-serialization-splitted-length-field.js diff --git a/lib/internal/child_process/serialization.js b/lib/internal/child_process/serialization.js index 7be39f0d48c3c2..46bb1faaf9fc21 100644 --- a/lib/internal/child_process/serialization.js +++ b/lib/internal/child_process/serialization.js @@ -61,7 +61,12 @@ const advanced = { *parseChannelMessages(channel, readData) { if (readData.length === 0) return; - ArrayPrototypePush(channel[kMessageBuffer], readData); + if (channel[kMessageBufferSize] && channel[kMessageBuffer][0].length < 4) { + // Message length split into two buffers, so let's concatenate it. + channel[kMessageBuffer][0] = Buffer.concat([channel[kMessageBuffer][0], readData]); + } else { + ArrayPrototypePush(channel[kMessageBuffer], readData); + } channel[kMessageBufferSize] += readData.length; // Index 0 should always be present because we just pushed data into it. diff --git a/test/parallel/test-child-process-advanced-serialization-splitted-length-field.js b/test/parallel/test-child-process-advanced-serialization-splitted-length-field.js new file mode 100644 index 00000000000000..5407a56f495c8f --- /dev/null +++ b/test/parallel/test-child-process-advanced-serialization-splitted-length-field.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const child_process = require('child_process'); + +// Regression test for https://github.com/nodejs/node/issues/55834 +const msgLen = 65521; +let cnt = 10; + +if (process.argv[2] === 'child') { + const msg = Buffer.allocUnsafe(msgLen); + (function send() { + if (cnt--) { + process.send(msg, send); + } else { + process.disconnect(); + } + })(); +} else { + const child = child_process.spawn(process.execPath, [__filename, 'child'], { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + serialization: 'advanced' + }); + child.on('message', common.mustCall(cnt)); +} From ceec5cc145220db170ed6c75d60d2e918fc7f59f Mon Sep 17 00:00:00 2001 From: yamachu Date: Sun, 19 Jan 2025 16:05:47 +0900 Subject: [PATCH 03/11] src: use std::u8string instead of std::string to pass path constructor Enforce that it is u8 because it was crashing when loading files containing Japanese in Windows, cp392 environment. Fixes: https://github.com/nodejs/node/issues/56650 --- src/node_modules.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/node_modules.cc b/src/node_modules.cc index 4b522a91323c9f..8c5de164f8622b 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -340,12 +340,14 @@ void BindingData::GetNearestParentPackageJSON( ToNamespacedPath(realm->env(), &path_value); std::string path_value_str = path_value.ToString(); + auto path_value_u8str = + std::u8string(path_value_str.begin(), path_value_str.end()); if (slashCheck) { - path_value_str.push_back(kPathSeparator); + path_value_u8str.push_back(kPathSeparator); } auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_str)); + TraverseParent(realm, std::filesystem::path(path_value_u8str)); if (package_json != nullptr) { args.GetReturnValue().Set(package_json->Serialize(realm)); @@ -366,12 +368,14 @@ void BindingData::GetNearestParentPackageJSONType( ToNamespacedPath(realm->env(), &path_value); std::string path_value_str = path_value.ToString(); + auto path_value_u8str = + std::u8string(path_value_str.begin(), path_value_str.end()); if (slashCheck) { - path_value_str.push_back(kPathSeparator); + path_value_u8str.push_back(kPathSeparator); } auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_str)); + TraverseParent(realm, std::filesystem::path(path_value_u8str)); if (package_json == nullptr) { return; From bc1a91e8dc3b96be097afbda643512857cdce04d Mon Sep 17 00:00:00 2001 From: yamachu Date: Mon, 20 Jan 2025 22:31:27 +0900 Subject: [PATCH 04/11] fixup! Format changed cpp file --- src/node_modules.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_modules.cc b/src/node_modules.cc index 8c5de164f8622b..7c1ef73c9445cc 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -369,7 +369,7 @@ void BindingData::GetNearestParentPackageJSONType( std::string path_value_str = path_value.ToString(); auto path_value_u8str = - std::u8string(path_value_str.begin(), path_value_str.end()); + std::u8string(path_value_str.begin(), path_value_str.end()); if (slashCheck) { path_value_u8str.push_back(kPathSeparator); } From 0489fc0192564522641344e6859571c1c7694855 Mon Sep 17 00:00:00 2001 From: yamachu Date: Tue, 21 Jan 2025 22:27:50 +0900 Subject: [PATCH 05/11] ci: run test on windows sjis environment --- .github/workflows/coverage-windows.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/coverage-windows.yml b/.github/workflows/coverage-windows.yml index fada006e321520..650d0f0b9266da 100644 --- a/.github/workflows/coverage-windows.yml +++ b/.github/workflows/coverage-windows.yml @@ -74,3 +74,9 @@ jobs: uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7 with: directory: ./coverage + - name: Change locale ja-JP for testing on SJIS environment + run: Set-WinSystemLocale -SystemLocale "ja-JP" + - name: Test on SJIS environment + run: ./vcbuild.bat nobuild noprojgen test-ci-js; node -e 'process.exit(0)' + env: + NODE_V8_COVERAGE: ./coverage/tmp From 83fe515340c5c4e51776310edef36b622b481eee Mon Sep 17 00:00:00 2001 From: yamachu Date: Tue, 21 Jan 2025 22:43:08 +0900 Subject: [PATCH 06/11] test: add path containing createRequire test case --- .../test-module-create-require-multibyte.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/parallel/test-module-create-require-multibyte.js diff --git a/test/parallel/test-module-create-require-multibyte.js b/test/parallel/test-module-create-require-multibyte.js new file mode 100644 index 00000000000000..0c495c70c50dbb --- /dev/null +++ b/test/parallel/test-module-create-require-multibyte.js @@ -0,0 +1,15 @@ +'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 }); From 87610e3f2f16187e5725b7897a161d0a39bcfacc Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 00:20:19 +0900 Subject: [PATCH 07/11] I don't want to wait for a CI anymore --- .github/workflows/coverage-windows.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/coverage-windows.yml b/.github/workflows/coverage-windows.yml index 650d0f0b9266da..dd33f3957b15b5 100644 --- a/.github/workflows/coverage-windows.yml +++ b/.github/workflows/coverage-windows.yml @@ -29,9 +29,9 @@ on: - codecov.yml - .nycrc -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true +# concurrency: +# group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} +# cancel-in-progress: true env: PYTHON_VERSION: '3.12' From fb7ef6a0bd091dbad7e42fadc093a49742110ede Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 00:26:01 +0900 Subject: [PATCH 08/11] revert: for checking CI is working --- src/node_modules.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/node_modules.cc b/src/node_modules.cc index 7c1ef73c9445cc..4b522a91323c9f 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -340,14 +340,12 @@ void BindingData::GetNearestParentPackageJSON( ToNamespacedPath(realm->env(), &path_value); std::string path_value_str = path_value.ToString(); - auto path_value_u8str = - std::u8string(path_value_str.begin(), path_value_str.end()); if (slashCheck) { - path_value_u8str.push_back(kPathSeparator); + path_value_str.push_back(kPathSeparator); } auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_u8str)); + TraverseParent(realm, std::filesystem::path(path_value_str)); if (package_json != nullptr) { args.GetReturnValue().Set(package_json->Serialize(realm)); @@ -368,14 +366,12 @@ void BindingData::GetNearestParentPackageJSONType( ToNamespacedPath(realm->env(), &path_value); std::string path_value_str = path_value.ToString(); - auto path_value_u8str = - std::u8string(path_value_str.begin(), path_value_str.end()); if (slashCheck) { - path_value_u8str.push_back(kPathSeparator); + path_value_str.push_back(kPathSeparator); } auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_u8str)); + TraverseParent(realm, std::filesystem::path(path_value_str)); if (package_json == nullptr) { return; From a5b736c46efbcef4f056e22b432bf6d2d81e26c7 Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 04:04:46 +0900 Subject: [PATCH 09/11] src: use u8path instead of path, u8string --- src/node_modules.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node_modules.cc b/src/node_modules.cc index 4b522a91323c9f..c331ea2708b5a8 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -345,7 +345,7 @@ void BindingData::GetNearestParentPackageJSON( } auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_str)); + TraverseParent(realm, std::filesystem::u8path(path_value_str)); if (package_json != nullptr) { args.GetReturnValue().Set(package_json->Serialize(realm)); @@ -371,7 +371,7 @@ void BindingData::GetNearestParentPackageJSONType( } auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_str)); + TraverseParent(realm, std::filesystem::u8path(path_value_str)); if (package_json == nullptr) { return; From c25be112432f1fc81d01e72cf8c46b458c7e5dfc Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 04:09:15 +0900 Subject: [PATCH 10/11] Run CI From ee09128df20b06c67a2a9101ee2a3fe8bacc30ed Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 15:39:29 +0900 Subject: [PATCH 11/11] src: fix to generate path from wchar_t via wstring. --- src/node_modules.cc | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/node_modules.cc b/src/node_modules.cc index c331ea2708b5a8..77a783e3e8ac88 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -16,6 +16,10 @@ #include "simdjson.h" +#ifdef _WIN32 +#include +#endif + namespace node { namespace modules { @@ -326,6 +330,18 @@ const BindingData::PackageConfig* BindingData::TraverseParent( return nullptr; } +#ifdef _WIN32 +std::wstring MaybeWCharTToWSTring(const std::string& input) { + bool is_unicode = IsTextUnicode(input.c_str(), input.size(), nullptr); + auto code_page = is_unicode ? CP_UTF8 : GetACP(); + int length = MultiByteToWideChar(code_page, 0, input.c_str(), -1, nullptr, 0); + + std::wstring wide_str(length, 0); + MultiByteToWideChar(code_page, 0, input.c_str(), -1, &wide_str[0], length); + return wide_str; +} +#endif + void BindingData::GetNearestParentPackageJSON( const v8::FunctionCallbackInfo& args) { CHECK_GE(args.Length(), 1); @@ -344,8 +360,16 @@ void BindingData::GetNearestParentPackageJSON( path_value_str.push_back(kPathSeparator); } - auto package_json = - TraverseParent(realm, std::filesystem::u8path(path_value_str)); + std::filesystem::path path; + +#ifdef _WIN32 + std::wstring wide_path = MaybeWCharTToWSTring(path_value_str); + 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)); @@ -370,8 +394,16 @@ void BindingData::GetNearestParentPackageJSONType( path_value_str.push_back(kPathSeparator); } - auto package_json = - TraverseParent(realm, std::filesystem::u8path(path_value_str)); + std::filesystem::path path; + +#ifdef _WIN32 + std::wstring wide_path = MaybeWCharTToWSTring(path_value_str); + 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;