diff --git a/src/node_process_object.cc b/src/node_process_object.cc index 5dfa59350c317f..bea2ef9ba9da69 100644 --- a/src/node_process_object.cc +++ b/src/node_process_object.cc @@ -105,18 +105,43 @@ MaybeLocal CreateProcessObject(Realm* realm) { READONLY_PROPERTY( process, "version", FIXED_ONE_BYTE_STRING(isolate, NODE_VERSION)); - // process.versions Local versions = Object::New(isolate); - READONLY_PROPERTY(process, "versions", versions); + // Node.js version is always on the top + READONLY_STRING_PROPERTY( + versions, "node", per_process::metadata.versions.node); + +#define V(key) +1 + std::pair + versions_array[NODE_VERSIONS_KEYS(V)]; +#undef V + auto* slot = &versions_array[0]; #define V(key) \ - if (!per_process::metadata.versions.key.empty()) { \ - READONLY_STRING_PROPERTY( \ - versions, #key, per_process::metadata.versions.key); \ - } + do { \ + *slot++ = std::pair( \ + #key, per_process::metadata.versions.key); \ + } while (0); NODE_VERSIONS_KEYS(V) #undef V + std::sort(&versions_array[0], + &versions_array[arraysize(versions_array)], + [](auto& a, auto& b) { return a.first < b.first; }); + + for (const auto& version : versions_array) { + versions + ->DefineOwnProperty( + context, + OneByteString(isolate, version.first.data(), version.first.size()), + OneByteString( + isolate, version.second.data(), version.second.size()), + v8::ReadOnly) + .Check(); + } + + // process.versions + READONLY_PROPERTY(process, "versions", versions); + // process.arch READONLY_STRING_PROPERTY(process, "arch", per_process::metadata.arch); diff --git a/src/node_report.cc b/src/node_report.cc index a6622b49a0e0ba..2998bd09b049fd 100644 --- a/src/node_report.cc +++ b/src/node_report.cc @@ -794,10 +794,26 @@ static void PrintComponentVersions(JSONWriter* writer) { writer->json_objectstart("componentVersions"); -#define V(key) writer->json_keyvalue(#key, per_process::metadata.versions.key); +#define V(key) +1 + std::pair versions_array[NODE_VERSIONS_KEYS(V)]; +#undef V + auto* slot = &versions_array[0]; + +#define V(key) \ + do { \ + *slot++ = std::make_pair(#key, per_process::metadata.versions.key); \ + } while (0); NODE_VERSIONS_KEYS(V) #undef V + std::sort(&versions_array[0], + &versions_array[arraysize(versions_array)], + [](auto& a, auto& b) { return a.first < b.first; }); + + for (const auto& version : versions_array) { + writer->json_keyvalue(version.first, version.second); + } + writer->json_objectend(); } diff --git a/test/parallel/test-process-versions.js b/test/parallel/test-process-versions.js index de55405e46d341..23590d58a587d9 100644 --- a/test/parallel/test-process-versions.js +++ b/test/parallel/test-process-versions.js @@ -9,7 +9,6 @@ const expected_keys = [ 'ares', 'brotli', 'modules', - 'node', 'uv', 'v8', 'zlib', @@ -45,7 +44,9 @@ if (common.hasIntl) { } expected_keys.sort(); -const actual_keys = Object.keys(process.versions).sort(); +expected_keys.unshift('node'); + +const actual_keys = Object.keys(process.versions); assert.deepStrictEqual(actual_keys, expected_keys);