src: add GetBuildId helper function#355
src: add GetBuildId helper function#355santigimeno wants to merge 4717 commits intonode-v22.x-nsolid-v6.xfrom
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughAdds Linux-only ELF build-id utilities (source and header), updates build configs to include them and adjust Linux/OpenHarmony linker flags, and introduces a Linux-specific test addon and test script that validates build-id retrieval from the Node executable using libelf. Changes
Sequence Diagram(s)sequenceDiagram
participant TestJS as Test (nsolid-elf-utils.js)
participant Addon as Native Addon (binding.cc)
participant Utils as elf_utils::GetBuildId
participant LibELF as libelf
TestJS->>Addon: getBuildId(process.execPath)
Addon->>Utils: GetBuildId(path, &build_id)
Utils->>LibELF: elf_version/elf_begin/iterate sections
LibELF-->>Utils: .note.gnu.build-id data
Utils-->>Addon: build_id (hex) or error
Addon-->>TestJS: build_id string (on success)
TestJS->>TestJS: assert equals readelf-derived ID
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/nsolid/nsolid_elf_utils.h (1)
12-12: Consider documenting the return value semantics.The function returns an
intstatus code, but the expected values (0 for success, non-zero for failure) should be documented for API clarity.Add a brief comment documenting the return value:
namespace elf_utils { + // Returns 0 on success, non-zero on failure. int GetBuildId(const std::string& path, std::string* build_id); } // namespace elf_utilstest/addons/nsolid-elf-utils/binding.cc (1)
14-29: Consider returning an error instead of undefined when GetBuildId fails.When
GetBuildIdreturns a non-zero error code, the function currently returnsundefinedby not setting any return value. This makes it difficult for JavaScript code to distinguish between different error conditions (file not found, invalid ELF, no build-id, etc.).Consider throwing a JavaScript exception with the error code to provide better error context:
static void GetBuildId(const FunctionCallbackInfo<Value>& args) { #if defined(__linux__) Isolate* isolate = args.GetIsolate(); assert(args[0]->IsString()); v8::String::Utf8Value path_utf8(isolate, args[0]); std::string path(*path_utf8, path_utf8.length()); std::string build_id; int res = node::nsolid::elf_utils::GetBuildId(path, &build_id); if (res != 0) { - return; + std::string error_msg = "Failed to get build-id: error code " + std::to_string(res); + isolate->ThrowException(v8::Exception::Error( + String::NewFromUtf8(isolate, error_msg.c_str()).ToLocalChecked())); + return; } args.GetReturnValue().Set( String::NewFromUtf8(isolate, build_id.c_str()).ToLocalChecked()); #endif }src/nsolid/nsolid_elf_utils.cc (1)
29-35: Consider returning more specific error codes.The function returns
elf_errno()whenelf_version(EV_CURRENT)fails. While this is technically correct,elf_errno()might return 0 if no error was previously set, which could be confusing.Consider returning a more specific error code or ensuring elf_errno() is non-zero:
ret = 0; if (elf_version(EV_CURRENT) == EV_NONE) { - return elf_errno(); + int err = elf_errno(); + return err ? err : ELF_E_VERSION; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
node.gyp(1 hunks)node.gypi(1 hunks)src/nsolid/nsolid_elf_utils.cc(1 hunks)src/nsolid/nsolid_elf_utils.h(1 hunks)test/addons/nsolid-elf-utils/binding.cc(1 hunks)test/addons/nsolid-elf-utils/binding.gyp(1 hunks)test/addons/nsolid-elf-utils/nsolid-elf-utils.js(1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: src/nsolid/nsolid_elf_utils.cc:18-18
Timestamp: 2025-07-08T16:05:45.341Z
Learning: In the NSolid project, the `GetBuildId` function in `src/nsolid/nsolid_elf_utils.cc` is designed to be called only from the NSolid thread, so the static cache doesn't require thread safety mechanisms like mutex protection.
📚 Learning: 2025-07-08T16:05:45.341Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: src/nsolid/nsolid_elf_utils.cc:18-18
Timestamp: 2025-07-08T16:05:45.341Z
Learning: In the NSolid project, the `GetBuildId` function in `src/nsolid/nsolid_elf_utils.cc` is designed to be called only from the NSolid thread, so the static cache doesn't require thread safety mechanisms like mutex protection.
Applied to files:
src/nsolid/nsolid_elf_utils.htest/addons/nsolid-elf-utils/nsolid-elf-utils.jssrc/nsolid/nsolid_elf_utils.cctest/addons/nsolid-elf-utils/binding.cc
📚 Learning: 2025-07-08T14:48:04.827Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/binding.cc:13-28
Timestamp: 2025-07-08T14:48:04.827Z
Learning: In nsolid test native addons (e.g., `test/addons/*/binding.cc`), additional JavaScript-facing argument validation is typically omitted because the tests supply well-formed inputs.
Applied to files:
test/addons/nsolid-elf-utils/binding.gyptest/addons/nsolid-elf-utils/nsolid-elf-utils.jstest/addons/nsolid-elf-utils/binding.cc
📚 Learning: 2025-07-08T14:46:47.806Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:13-14
Timestamp: 2025-07-08T14:46:47.806Z
Learning: In the nsolid test suite, native addon bindings are expected to be built beforehand; tests do not add fs.existsSync guards to skip when bindings are missing.
Applied to files:
test/addons/nsolid-elf-utils/binding.gyptest/addons/nsolid-elf-utils/nsolid-elf-utils.jstest/addons/nsolid-elf-utils/binding.cc
📚 Learning: 2025-07-08T14:47:34.724Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:16-18
Timestamp: 2025-07-08T14:47:34.724Z
Learning: In the nsolid test suite, external tool invocations (e.g., execSync to run `readelf`) are intentionally left uncaught so that any failure causes the test to fail rather than being skipped.
Applied to files:
test/addons/nsolid-elf-utils/nsolid-elf-utils.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: build-tarball
- GitHub Check: lint-js-and-md
- GitHub Check: coverage-windows
- GitHub Check: test-macOS
- GitHub Check: build-docs
- GitHub Check: test-linux (ubuntu-24.04-arm)
- GitHub Check: test-linux (ubuntu-24.04)
🔇 Additional comments (13)
node.gypi (1)
553-565: LGTM! Cleaner separation of linker rules for OpenHarmony and Linux.The refactoring properly splits the combined condition into two OS-specific blocks, making the linker configuration more maintainable and explicit for each platform. The Linux block now unconditionally links
-lelf(required for the new ELF utilities) and conditionally handles-lrtbased onnsolid_use_librt.test/addons/nsolid-elf-utils/binding.gyp (1)
1-10: LGTM! Properly configured test addon target.The binding target is correctly configured with the necessary
NODE_WANT_INTERNALS=1define to access the internal ELF utilities API, and properly includes the common build settings.node.gyp (1)
581-586: LGTM! Correct Linux-specific inclusion of ELF utilities.The conditional addition of ELF utility sources to
nsolid_sourceson Linux is properly implemented, aligning with the platform-specific nature of the Build-Id functionality.test/addons/nsolid-elf-utils/nsolid-elf-utils.js (4)
1-11: LGTM! Proper platform check and early exit.The platform check correctly skips the test on non-Linux systems with an informative message.
13-14: LGTM! Consistent with nsolid test suite conventions.The binding loading follows the established pattern without fs.existsSync guards, as per the team's conventions documented in the learnings.
20-23: LGTM! Clear test assertion with helpful error message.The test correctly validates the Build ID and provides a descriptive error message on mismatch, which aids in debugging.
16-18: Add a clear fallback whenreadelfis missingTo prevent cryptic ENOENT failures in CI environments where
readelfisn’t installed, wrap theexecSyncinvocation in a try/catch and emit a descriptive error (or provide alternate logic) ifreadelfisn’t found:• File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js
• Lines: 16–18Suggested update:
let expected; try { expected = execSync( `readelf -n ${process.execPath} | awk '/Build ID/ { print $3 }'`, { encoding: 'utf8' } ).trim(); } catch (err) { if (err.code === 'ENOENT') { throw new Error( 'The `readelf` tool is required to run this test but was not found in your PATH.' ); } throw err; }This ensures that missing dependencies produce a clear, actionable error.
⛔ Skipped due to learnings
Learnt from: santigimeno PR: nodesource/nsolid#339 File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:16-18 Timestamp: 2025-07-08T14:47:34.724Z Learning: In the nsolid test suite, external tool invocations (e.g., execSync to run `readelf`) are intentionally left uncaught so that any failure causes the test to fail rather than being skipped.Learnt from: santigimeno PR: nodesource/nsolid#339 File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:13-14 Timestamp: 2025-07-08T14:46:47.806Z Learning: In the nsolid test suite, native addon bindings are expected to be built beforehand; tests do not add fs.existsSync guards to skip when bindings are missing.src/nsolid/nsolid_elf_utils.h (1)
1-19: LGTM! Well-structured header with proper guards.The header is properly organized with:
- Standard include guards
- NODE_WANT_INTERNALS conditional compilation
- Clear namespace hierarchy
- Clean API declaration
test/addons/nsolid-elf-utils/binding.cc (2)
1-7: LGTM!The header includes and platform-specific guard are properly structured.
31-33: LGTM!Module initialization correctly exports the function.
src/nsolid/nsolid_elf_utils.cc (3)
1-15: LGTM!Headers are properly included and namespaces are correctly structured.
17-28: Thread safety consideration for the static cache.Based on the retrieved learnings, the
GetBuildIdfunction is designed to be called only from the NSolid thread, so the static cache doesn't require thread safety mechanisms. This design constraint is valid for the current implementation.
85-90: Resource cleanup order looks correct.The cleanup sequence properly handles both the ELF object and file descriptor in the correct order, ensuring resources are freed even on error paths.
| *build_id = std::string(""); | ||
| while ((scn = elf_nextscn(e, scn)) != nullptr) { | ||
| if (gelf_getshdr(scn, &shdr) != &shdr) { | ||
| ret = elf_errno(); | ||
| goto end_error; | ||
| } | ||
|
|
||
| char* name = elf_strptr(e, shstrndx, shdr.sh_name); | ||
| if (name && strcmp(name, ".note.gnu.build-id") == 0) { | ||
| Elf_Data* data = elf_getdata(scn, nullptr); | ||
| if (data && data->d_size >= 16) { | ||
| // ELF Note header: namesz(4), descsz(4), type(4) + name padding | ||
| // Compute offset to build-id properly | ||
| uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf); | ||
| uint32_t namesz = note[0]; | ||
| uint32_t descsz = note[1]; | ||
| // Name starts at offset 12 | ||
| // Descriptor (build-id) starts at next aligned offset | ||
| size_t name_end = 12 + ((namesz + 3) & ~3); | ||
| uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end; | ||
| *build_id = utils::buffer_to_hex(id, descsz); | ||
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Potential buffer overflow risk in ELF note parsing.
The code assumes the ELF note structure without validating that the computed offsets don't exceed the buffer bounds. While data->d_size >= 16 checks for minimum size, it doesn't ensure that name_end + descsz doesn't exceed data->d_size.
Add bounds checking before accessing the build-id data:
*build_id = std::string("");
while ((scn = elf_nextscn(e, scn)) != nullptr) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
ret = elf_errno();
goto end_error;
}
char* name = elf_strptr(e, shstrndx, shdr.sh_name);
if (name && strcmp(name, ".note.gnu.build-id") == 0) {
Elf_Data* data = elf_getdata(scn, nullptr);
if (data && data->d_size >= 16) {
// ELF Note header: namesz(4), descsz(4), type(4) + name padding
// Compute offset to build-id properly
uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf);
uint32_t namesz = note[0];
uint32_t descsz = note[1];
// Name starts at offset 12
// Descriptor (build-id) starts at next aligned offset
size_t name_end = 12 + ((namesz + 3) & ~3);
+ // Ensure we don't read beyond the buffer
+ if (name_end + descsz > data->d_size) {
+ ret = ELF_E_DATA;
+ goto end_error;
+ }
uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end;
*build_id = utils::buffer_to_hex(id, descsz);
break;
}
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| *build_id = std::string(""); | |
| while ((scn = elf_nextscn(e, scn)) != nullptr) { | |
| if (gelf_getshdr(scn, &shdr) != &shdr) { | |
| ret = elf_errno(); | |
| goto end_error; | |
| } | |
| char* name = elf_strptr(e, shstrndx, shdr.sh_name); | |
| if (name && strcmp(name, ".note.gnu.build-id") == 0) { | |
| Elf_Data* data = elf_getdata(scn, nullptr); | |
| if (data && data->d_size >= 16) { | |
| // ELF Note header: namesz(4), descsz(4), type(4) + name padding | |
| // Compute offset to build-id properly | |
| uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf); | |
| uint32_t namesz = note[0]; | |
| uint32_t descsz = note[1]; | |
| // Name starts at offset 12 | |
| // Descriptor (build-id) starts at next aligned offset | |
| size_t name_end = 12 + ((namesz + 3) & ~3); | |
| uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end; | |
| *build_id = utils::buffer_to_hex(id, descsz); | |
| break; | |
| } | |
| } | |
| } | |
| *build_id = std::string(""); | |
| while ((scn = elf_nextscn(e, scn)) != nullptr) { | |
| if (gelf_getshdr(scn, &shdr) != &shdr) { | |
| ret = elf_errno(); | |
| goto end_error; | |
| } | |
| char* name = elf_strptr(e, shstrndx, shdr.sh_name); | |
| if (name && strcmp(name, ".note.gnu.build-id") == 0) { | |
| Elf_Data* data = elf_getdata(scn, nullptr); | |
| if (data && data->d_size >= 16) { | |
| // ELF Note header: namesz(4), descsz(4), type(4) + name padding | |
| // Compute offset to build-id properly | |
| uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf); | |
| uint32_t namesz = note[0]; | |
| uint32_t descsz = note[1]; | |
| // Name starts at offset 12 | |
| // Descriptor (build-id) starts at next aligned offset | |
| size_t name_end = 12 + ((namesz + 3) & ~3); | |
| // Ensure we don't read beyond the buffer | |
| if (name_end + descsz > data->d_size) { | |
| ret = ELF_E_DATA; | |
| goto end_error; | |
| } | |
| uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end; | |
| *build_id = utils::buffer_to_hex(id, descsz); | |
| break; | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/nsolid/nsolid_elf_utils.cc around lines 53 to 77, the ELF note parsing
computes name_end and then reads descsz bytes without verifying the computed
offsets fit inside data->d_size; add explicit bounds checks before accessing the
build-id: validate data and data->d_buf are non-null, cast namesz and descsz to
size_t and check namesz/descsz are reasonable (e.g. not absurdly large), compute
name_end = 12 + ((namesz + 3) & ~3) using size_t and ensure name_end <=
data->d_size and name_end + descsz <= data->d_size (also guard against overflow
when adding), and only then set *build_id from the id pointer; on failure, skip
this note or set an error/continue instead of reading out-of-bounds.
a6d9f60 to
82582a7
Compare
This requires setting BUILDING_V8_PLATFORM_SHARED to expose the public symbols since we build with hidden visibility by default. PR-URL: nodejs/node#61144 Fixes: nodejs/node#61102 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com>
PR-URL: nodejs/node#61260 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: nodejs/node#58264 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs/node#61255 Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ruy Adorno <ruy@vlt.sh> Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
PR-URL: nodejs/node#61270 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: nodejs/node#61271 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: nodejs/node#61267 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: nodejs/node#61297 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
PR-URL: nodejs/node#61273 Refs: nodejs/node#58378 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
resolves #53514 PR-URL: nodejs/node#53641 Reviewed-By: Aviv Keller <me@aviv.sh>
PR-URL: nodejs/node#61090 Refs: nodejs/node#60862 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
PR-URL: nodejs/node#60825 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Jordan Harband <ljharb@gmail.com> Reviewed-By: LiviaMedeiros <livia@cirno.name>
b9b23be to
649ccda
Compare
PR-URL: #408 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: #407 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: nodejs/node#60726 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
PR-URL: nodejs/node#60759 Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#60761 Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#60834 Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#61004 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
PR-URL: nodejs/node#60906 Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#61062 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#61135 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
PR-URL: nodejs/node#61321 Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#61315 Reviewed-By: Matthew Aitken <maitken033380023@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
When binding UTF-8 strings to prepared statements, transfer ownership of malloc-backed Utf8Value buffers to SQLite to avoid an extra copy for large strings. Use sqlite3_bind_blob64() when binding BLOB parameters. PR-URL: nodejs/node#61580 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com>
PR-URL: nodejs/node#61696 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Daniel Lemire <daniel@lemire.me> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br> Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
PR-URL: nodejs/node#61659 Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Tierney Cyren <hello@bnb.im> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
`require(mod)` does not keep the mod in require cache if mod throws synchronously. This fixes the tests to print the stack immediately in case that source map cache could be cleaned up when the CJS module is reclaimed by GC in the next event loop tick. PR-URL: nodejs/node#61699 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Add documentation explaining that applications are expected to attach 'error' event handlers to EventEmitters that can emit errors, including HTTP streams. Crashes resulting from missing error handlers are not considered denial-of-service vulnerabilities in Node.js. PR-URL: nodejs/node#61701 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Small perf improvement:
$ node benchmark/compare.js --runs 100 \
> --old ./node-0da120f879 --new ./node \
> --filter structured-clone misc > comparison.csv && \
> npx node-benchmark-compare comparison.csv
[00:02:15|% 100| 1/1 files | 200/200 runs | 3/3 configs]: Done
confidence improvement accuracy (*) (**) (***)
misc/structured-clone.js n=10000 type='arraybuffer' ** 1.81 % ±1.28% ±1.68% ±2.16%
misc/structured-clone.js n=10000 type='object' * 0.62 % ±0.55% ±0.73% ±0.93%
misc/structured-clone.js n=10000 type='string' *** 8.30 % ±1.46% ±1.92% ±2.47%
Be aware that when doing many comparisons the risk of a false-positive result increases.
In this case, there are 3 comparisons, you can thus expect the following amount of false-positive results:
0.15 false positives, when considering a 5% risk acceptance (*, **, ***),
0.03 false positives, when considering a 1% risk acceptance (**, ***),
0.00 false positives, when considering a 0.1% risk acceptance (***)
PR-URL: nodejs/node#61703
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
PR-URL: nodejs/node#61732 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
PR-URL: nodejs/node#61730 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#61685 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
PR-URL: nodejs/node#61748 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs/node#61279 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
PR-URL: nodejs/node#61280 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
PR-URL: nodejs/node#61341 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#61456 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Daniel Lemire <daniel@lemire.me> Reviewed-By: Richard Lau <richard.lau@ibm.com>
To reduce cache thrashing. PR-URL: nodejs/node#61790 Refs: nodejs/node#61436 Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Tierney Cyren <hello@bnb.im> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs/node#61742 Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com>
PR-URL: nodejs/node#61734 Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: nodejs/node#61759 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#61899 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#61903 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
PR-URL: nodejs/node#60727 Backport-PR-URL: nodejs/node#61840 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
PR-URL: nodejs/node#61530 Backport-PR-URL: nodejs/node#61840 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com>
Notable changes: async_hooks: * (SEMVER-MINOR) add `trackPromises` option to `createHook()` (Joyee Cheung) nodejs/node#61415 build,deps: * replace cjs-module-lexer with merve (Yagiz Nizipli) nodejs/node#61456 deps: * (SEMVER-MINOR) add LIEF as a dependency (Joyee Cheung) nodejs/node#61167 events: * (SEMVER-MINOR) repurpose `events.listenerCount()` to accept `EventTarget`s (René) nodejs/node#60214 fs: * (SEMVER-MINOR) add `ignore` option to `fs.watch` (Matteo Collina) nodejs/node#61433 http: * (SEMVER-MINOR) add `http.setGlobalProxyFromEnv()` (Joyee Cheung) nodejs/node#60953 module: * (SEMVER-MINOR) allow subpath imports that start with `#/` (Jan Martin) nodejs/node#60864 process: * (SEMVER-MINOR) preserve `AsyncLocalStorage` in `queueMicrotask` only when needed (Gürgün Dayıoğlu) nodejs/node#60913 sea: * (SEMVER-MINOR) split sea binary manipulation code (Joyee Cheung) nodejs/node#61167 sqlite: * (SEMVER-MINOR) enable defensive mode by default (Bart Louwers) nodejs/node#61266 * (SEMVER-MINOR) add sqlite prepare options args (Guilherme Araújo) nodejs/node#61311 src: * (SEMVER-MINOR) add initial support for ESM in embedder API (Joyee Cheung) nodejs/node#61548 stream: * (SEMVER-MINOR) add `bytes()` method to `node:stream/consumers` (wantaek) nodejs/node#60426 * (SEMVER-MINOR) do not pass `readable.compose()` output via `Readable.from()` (René) nodejs/node#60907 test: * (SEMVER-MINOR) use fixture directories for sea tests (Joyee Cheung) nodejs/node#61167 test_runner: * (SEMVER-MINOR) add `env` option to `run` function (Ethan Arrowood) nodejs/node#61367 * (SEMVER-MINOR) support expecting a test-case to fail (Jacob Smith) nodejs/node#60669 util: * (SEMVER-MINOR) add `convertProcessSignalToExitCode` utility (Erick Wendel) nodejs/node#60963 PR-URL: nodejs/node#61924
When trying to reset a CommandStream because of reasons: for example, we change `grpc` endpoint dynamically, we can enter an infinite recursion calling `GrpcAgent::reset_command_stream()` because when calling `~CommandStream()` the `OnDone()` callback may call the observer (GrpcAgent instance) which in turn would call `GrpcAgent::reset_command_stream()`. Avoid this recursion by adding a new `cancelling_for_destruction_` member variable to `CommandStream` which allows avoiding calling the observer if triggered by the destructor. PR-URL: #412 Reviewed-By: EHortua <55801532+EHortua@users.noreply.github.com>
2026-02-24 Node.js v24.14.0 Krypton (LTS) Release Git-EVTag-v0-SHA512: f02aae3385cab64e189bcb6307365e4b519b0d1142e42a4ab968e0240356a8ccbca01a8e59600e06d3a6f92369be5b93d6c233b05ad843db548fba05ef7eb68e
To allow us to read the Build-Id from ELF headers in a specific binary.
82582a7 to
75c8a88
Compare
To allow us to read the Build-Id from ELF headers in a specific binary.
Summary by CodeRabbit
Chores
Tests