Skip to content

buffer: improve performance of multiple Buffer operations#61871

Merged
nodejs-github-bot merged 11 commits intonodejs:mainfrom
thisalihassan:buffer-perf-improvements
Mar 27, 2026
Merged

buffer: improve performance of multiple Buffer operations#61871
nodejs-github-bot merged 11 commits intonodejs:mainfrom
thisalihassan:buffer-perf-improvements

Conversation

@thisalihassan
Copy link
Copy Markdown
Contributor

@thisalihassan thisalihassan commented Feb 17, 2026

Multiple performance improvements to Buffer operations, verified with benchmarks (15-30 runs, comparing old vs new binaries built from same tree).

Buffer.copyBytesFrom() (+100-210%)
Avoid intermediate TypedArrayPrototypeSlice allocation by calculating byte offsets directly into the source TypedArray's underlying ArrayBuffer.

Buffer.prototype.fill("t", "ascii") (+26-37%)

ASCII indexOf (+14-46%)
Call indexOfString directly for ASCII encoding instead of first converting the search value to a Buffer via fromStringFast and then calling indexOfBuffer. ASCII and Latin-1 share the same byte values for characters 0-127.

swap16/32/64 (+3-38%)
Add V8 Fast API C++ functions (FastSwap16/32/64) alongside the existing slow path. Largest gains at len=256 (+35%).

Benchmark results

Key results (15-30 runs, *** = p < 0.001):

Benchmark Improvement
copyBytesFrom (offset, Uint8Array, len=256) +210% ***
copyBytesFrom (offset+length, Uint8Array, len=256) +206% ***
swap16 len=256 +38% ***
fill("t", "ascii") size=8192 +37% ***
indexOf ASCII 'Alice' +46% ***
indexOf ASCII '@' +31% ***
fill("t", "ascii") size=65536 +26% ***
swap64 len=768 aligned +12% ***

Attaching Details below:
detail.pdf -- visual breakdown
buffer-benchmark-all-rebased.csv -- raw benchmark CSV
compare-R-output.txt-- full output

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/performance

@nodejs-github-bot nodejs-github-bot added buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Feb 17, 2026
@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch from d2ba38f to 495feb5 Compare February 17, 2026 21:41
Comment on lines +1210 to +1217
void FastSwap16(Local<Value> receiver,
Local<Value> buffer_obj,
// NOLINTNEXTLINE(runtime/references)
FastApiCallbackOptions& options) {
HandleScope scope(options.isolate);
ArrayBufferViewContents<char> buffer(buffer_obj);
CHECK(nbytes::SwapBytes16(const_cast<char*>(buffer.data()), buffer.length()));
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These fast callbacks are non-identical to the conventional callbacks they shadow.

  • The existing callbacks validate their argument and throws to JS if invalid, whereas your fast callbacks hard-crash the process. It might be better to validate in the JS layer, then use the same unwrapping logic on both sides.
  • Your fast callback cannot have a different return convention to the conventional callback. You will need to remove the return value from the conventional callback.

Copy link
Copy Markdown
Member

@ChALkeR ChALkeR Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was removing the validation instead of moving it to js intentional?

Also fast paths can keep the validation and fall back to slow i think, so we can still validate on the src side?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fast paths can keep the validation and fall back to slow i think, so we can still validate on the src side?

This is outdated, the fast API doesn't use fallback any more (since Node.js v23.x).

However, any validation in a JS wrapper should be shadowed by a CHECK or DCHECK in the C++ binding.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPREAD_BUFFER_ARG already contains CHECK((val)->IsArrayBufferView()) on all Slow & Fast swap methods

Comment on lines +1210 to +1217
void FastSwap16(Local<Value> receiver,
Local<Value> buffer_obj,
// NOLINTNEXTLINE(runtime/references)
FastApiCallbackOptions& options) {
HandleScope scope(options.isolate);
ArrayBufferViewContents<char> buffer(buffer_obj);
CHECK(nbytes::SwapBytes16(const_cast<char*>(buffer.data()), buffer.length()));
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fast callbacks should include debug tracking and call tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sharing these I will update the code

@Renegade334 Renegade334 added performance Issues and PRs related to the performance of Node.js. needs-benchmark-ci PR that need a benchmark CI run. labels Feb 17, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 92.39130% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.69%. Comparing base (7547e79) to head (85fb7f1).
⚠️ Report is 36 commits behind head on main.

Files with missing lines Patch % Lines
src/node_buffer.cc 72.00% 0 Missing and 7 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61871      +/-   ##
==========================================
- Coverage   91.60%   89.69%   -1.91%     
==========================================
  Files         337      676     +339     
  Lines      140745   206763   +66018     
  Branches    21802    39605   +17803     
==========================================
+ Hits       128925   185452   +56527     
- Misses      11595    13444    +1849     
- Partials      225     7867    +7642     
Files with missing lines Coverage Δ
lib/buffer.js 99.16% <100.00%> (+12.78%) ⬆️
src/node_buffer.cc 68.19% <72.00%> (ø)

... and 459 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch 4 times, most recently from 1395d2f to 01ba74f Compare February 17, 2026 23:42
FastApiCallbackOptions& options) {
TRACK_V8_FAST_API_CALL("buffer.swap16");
HandleScope scope(options.isolate);
ArrayBufferViewContents<char> buffer(buffer_obj);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArrayBufferViewContents is wrong here, as buffer.data() may be a stack-allocated copy of the byte data rather than the data itself. SPREAD_BUFFER_ARG is the correct macro to use here, as per the conventional callback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Renegade334 replaced ArrayBufferViewContents with SPREAD_BUFFER_ARG in all three fast swap callbacks

Copy link
Copy Markdown
Member

@ChALkeR ChALkeR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For toHex, wait until #61609, which improves native perf significantly (more than Uint8Array.prototype.toHex)

See also #60249 (comment)

} else if (value.length === 1) {
// Fast path: If `value` fits into a single byte, use that numeric value.
if (normalizedEncoding === 'utf8') {
if (normalizedEncoding === 'utf8' || normalizedEncoding === 'ascii') {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, ascii behaves exactly like latin1
Unsure if by design or accidentally

Copy link
Copy Markdown
Contributor Author

@thisalihassan thisalihassan Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is safe by design I am just extending the existing single byte numeric optimization to cover ASCII, since the guard already constrains it to the valid ASCII range.

@thisalihassan
Copy link
Copy Markdown
Contributor Author

Note on toBase64 / toBase64url:

I also tried replacing the C++ base64Slice/base64urlSlice bindings with V8's Uint8Array.prototype.toBase64() (similar to the toHex change) but it caused a 35-54% regression across all buffer sizes so I reverted base64/base64url and kept only the toHex optimization which showed a clear +26-37% win.

@ChALkeR
Copy link
Copy Markdown
Member

ChALkeR commented Feb 18, 2026

@thisalihassan toHex doesn't show a win anymore with nbytes update which should soon land (as it landed in nbytes)

Instead, it's ~3x slower.

See nodejs/nbytes#12

@thisalihassan
Copy link
Copy Markdown
Contributor Author

thisalihassan commented Feb 18, 2026

Hi @ChALkeR thanks for flagging I was not aware. I benchmarked the nibble approach locally and it's indeed a much bigger win (~3x vs my ~30% with toHex). Reverted the toHex path entirely the other changes in this PR are unaffected.

Should I include the nbytes nibble HexEncode optimization in this PR or keep them as separate PRs?

PS: One test is failing /test/parallel/test-debugger-restart-message.js I believe it's known mac issue and unrelated to my changes

@thisalihassan
Copy link
Copy Markdown
Contributor Author

For toHex, wait until #61609, which improves native perf significantly (more than Uint8Array.prototype.toHex)

See also #60249 (comment)

Hi @ChALkeR I see that your changes landed, congratualtions on that huge win. Is there benchmark-ci that we can run on this PR? I can rebase it

@thisalihassan
Copy link
Copy Markdown
Contributor Author

thisalihassan commented Feb 24, 2026

I re-ran the benchmark against the latest main (which contains the nibble improvement) and found out there are few regressions caused by my code:

buffers/buffer-indexof.js n=50000 type='buffer' encoding='undefined' search='aaaaaaaaaaaaaaaaa' *** -9.41 %
buffers/buffer-indexof.js n=50000 type='string' encoding='ascii' search='aaaaaaaaaaaaaaaaa' *** -10.93
buffers/buffer-indexof.js n=50000 type='string' encoding='latin1' search='aaaaaaaaaaaaaaaaa' *** -9.44 %
buffers/buffer-indexof.js n=50000 type='string' encoding='utf8' search='aaaaaaaaaaaaaaaaa' *** -9.18 %

I tried fixing this regression but unavoidable

Attaching Details below:
detail.pdf -- visual breakdown

buffer-benchmark-all-rebased.csv -- raw benchmark CSV

@thisalihassan
Copy link
Copy Markdown
Contributor Author

thisalihassan commented Feb 24, 2026

compare-R-output.txt-- full output from Rscript benchmark/compare.R (shared as a file to avoid cluttering the PR comment).

@thisalihassan thisalihassan force-pushed the buffer-perf-improvements branch from 59f5d09 to 48abfc5 Compare February 27, 2026 23:09
@thisalihassan
Copy link
Copy Markdown
Contributor Author

Hi @ChALkeR @anonrig @Renegade334 is this PR ready to land? can you also please check the latest benchmarks i have posted, I have compiled PDF for this benchmark in one my comments above for more detail

Screenshot 2026-03-01 at 2 29 23 AM Screenshot 2026-03-01 at 2 29 40 AM Screenshot 2026-03-01 at 2 29 54 AM Screenshot 2026-03-01 at 2 28 57 AM

Copy link
Copy Markdown
Member

@Qard Qard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM, but one small nit.

@aduh95
Copy link
Copy Markdown
Contributor

aduh95 commented Mar 4, 2026

Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1807/

@aduh95
Copy link
Copy Markdown
Contributor

aduh95 commented Mar 25, 2026

Can you rename the other const len = this.length / const len = TypedArrayPrototypeGetLength(this) to bufferLength please?

@thisalihassan
Copy link
Copy Markdown
Contributor Author

thisalihassan commented Mar 25, 2026

Can you rename the other const len = this.length / const len = TypedArrayPrototypeGetLength(this) to bufferLength please?

Done! Hoping this would be the last of the changes :')

Another reference spotted @aduh95

Buffer.prototype.subarray = function subarray(start, end) {
  const srcLength = this.length;

should also be?

Buffer.prototype.subarray = function subarray(start, end) {
  const srcLength = TypedArrayPrototypeGetLength(this);

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@thisalihassan
Copy link
Copy Markdown
Contributor Author

this test-runner.test-run-watch-run-duration is the only one failing on the CI

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@aduh95 aduh95 added commit-queue Add this label to land a pull request using GitHub Actions. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels Mar 27, 2026
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Mar 27, 2026
@nodejs-github-bot nodejs-github-bot merged commit 9e0dc8b into nodejs:main Mar 27, 2026
70 of 71 checks passed
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Landed in 9e0dc8b

aduh95 pushed a commit that referenced this pull request Mar 28, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: #61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
aduh95 pushed a commit that referenced this pull request Mar 28, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: #61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
aduh95 pushed a commit that referenced this pull request Mar 28, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: #61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Qard pushed a commit to Qard/node that referenced this pull request Mar 29, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: nodejs#61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
aduh95 pushed a commit to Flarna/node that referenced this pull request Mar 30, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: nodejs#61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
RafaelGSS pushed a commit to RafaelGSS/node that referenced this pull request Mar 30, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: nodejs#61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Apr 2, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [node](https://nodejs.org) ([source](https://github.com/nodejs/node)) | minor | `25.8.2` → `25.9.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>nodejs/node (node)</summary>

### [`v25.9.0`](https://github.com/nodejs/node/releases/tag/v25.9.0): 2026-04-01, Version 25.9.0 (Current), @&#8203;aduh95

[Compare Source](nodejs/node@v25.8.2...v25.9.0)

##### Notable Changes

##### Test runner module mocking improvements

`MockModuleOptions.defaultExport` and `MockModuleOptions.namedExports` have been
consolidated into a single option `MockModuleOptions.exports` to align with user
expectations and other test runners.

A `default` property on `MockModuleOptions.exports`  represents the default
export, and own enumerable properties are treated as named exports.

An automated migration is available to update user code:
<https://github.com/nodejs/userland-migrations/tree/main/recipes/mock-module-exports>

```bash
npx codemod @&#8203;nodejs/mock-module-exports
```

Contributed by sangwook in [#&#8203;61727](nodejs/node#61727).

##### Other notable changes

- \[[`312476cb84`](nodejs/node@312476cb84)] - **(SEMVER-MINOR)** **async\_hooks**: add using scopes to `AsyncLocalStorage` (Stephen Belanger) [#&#8203;61674](nodejs/node#61674)
- \[[`62d2cd473b`](nodejs/node@62d2cd473b)] - **(SEMVER-MINOR)** **cli**: add `--max-heap-size` option (tannal) [#&#8203;58708](nodejs/node#58708)
- \[[`d0ebf0e44b`](nodejs/node@d0ebf0e44b)] - **(SEMVER-MINOR)** **crypto**: add `TurboSHAKE` and `KangarooTwelve` Web Cryptography algorithms (Filip Skokan) [#&#8203;62183](nodejs/node#62183)
- \[[`f85b9d9fa8`](nodejs/node@f85b9d9fa8)] - **(SEMVER-MINOR)** **repl**: add customizable error handling (Anna Henningsen) [#&#8203;62188](nodejs/node#62188)
- \[[`67b854d407`](nodejs/node@67b854d407)] - **(SEMVER-MINOR)** **repl**: remove dependency on `node:domain` (Matteo Collina) [#&#8203;61227](nodejs/node#61227)
- \[[`966b700623`](nodejs/node@966b700623)] - **(SEMVER-MINOR)** **sea**: support code cache for ESM entrypoint in SEA (Joyee Cheung) [#&#8203;62158](nodejs/node#62158)
- \[[`e1f0d2a014`](nodejs/node@e1f0d2a014)] - **(SEMVER-MINOR)** **stream**: add stream/iter Implementation (James M Snell) [#&#8203;62066](nodejs/node#62066)

##### Commits

- \[[`312476cb84`](nodejs/node@312476cb84)] - **(SEMVER-MINOR)** **async\_hooks**: add using scopes to AsyncLocalStorage (Stephen Belanger) [#&#8203;61674](nodejs/node#61674)
- \[[`bfff8cb2ab`](nodejs/node@bfff8cb2ab)] - **(SEMVER-MINOR)** **benchmark**: add benchmarks for experimental stream/iter (James M Snell) [#&#8203;62066](nodejs/node#62066)
- \[[`c721d68502`](nodejs/node@c721d68502)] - **benchmark**: fix destructuring in dgram/single-buffer (Ali Hassan) [#&#8203;62084](nodejs/node#62084)
- \[[`e2f03c8e92`](nodejs/node@e2f03c8e92)] - **buffer**: improve performance of multiple Buffer operations (Ali Hassan) [#&#8203;61871](nodejs/node#61871)
- \[[`2fcd07f1ba`](nodejs/node@2fcd07f1ba)] - **build**: support empty libname flags in `configure.py` (Antoine du Hamel) [#&#8203;62477](nodejs/node#62477)
- \[[`b800c57fce`](nodejs/node@b800c57fce)] - **build**: fix timezone-update path references (Chengzhong Wu) [#&#8203;62280](nodejs/node#62280)
- \[[`7dc5a1e9b4`](nodejs/node@7dc5a1e9b4)] - **build**: skip dockit on IBMi (SRAVANI GUNDEPALLI) [#&#8203;62189](nodejs/node#62189)
- \[[`f0eea0f905`](nodejs/node@f0eea0f905)] - **build**: fix --node-builtin-modules-path (Filip Skokan) [#&#8203;62115](nodejs/node#62115)
- \[[`62d2cd473b`](nodejs/node@62d2cd473b)] - **(SEMVER-MINOR)** **cli**: add --max-heap-size option (tannal) [#&#8203;58708](nodejs/node#58708)
- \[[`ac4b485698`](nodejs/node@ac4b485698)] - **crypto**: update root certificates to NSS 3.121 (Node.js GitHub Bot) [#&#8203;62485](nodejs/node#62485)
- \[[`d0ebf0e44b`](nodejs/node@d0ebf0e44b)] - **(SEMVER-MINOR)** **crypto**: add TurboSHAKE and KangarooTwelve Web Cryptography algorithms (Filip Skokan) [#&#8203;62183](nodejs/node#62183)
- \[[`3009980d9d`](nodejs/node@3009980d9d)] - **crypto**: add crypto::GetSSLCtx API for addon access to OpenSSL contexts (Tim Perry) [#&#8203;62254](nodejs/node#62254)
- \[[`f5725ca81d`](nodejs/node@f5725ca81d)] - **crypto**: reject ML-KEM/ML-DSA [PKCS#8](https://github.com/PKCS/node/issues/8) import without seed in SubtleCrypto (Filip Skokan) [#&#8203;62218](nodejs/node#62218)
- \[[`f69ed4bc3f`](nodejs/node@f69ed4bc3f)] - **crypto**: rename CShakeParams and KmacParams length to outputLength (Filip Skokan) [#&#8203;61875](nodejs/node#61875)
- \[[`4d96e53570`](nodejs/node@4d96e53570)] - **crypto**: refactor WebCrypto AEAD algorithms auth tag handling (Filip Skokan) [#&#8203;62169](nodejs/node#62169)
- \[[`93d77719e8`](nodejs/node@93d77719e8)] - **crypto**: read algorithm name property only once in normalizeAlgorithm (Filip Skokan) [#&#8203;62170](nodejs/node#62170)
- \[[`3d2e23a981`](nodejs/node@3d2e23a981)] - **deps**: update ada to 3.4.4 (Node.js GitHub Bot) [#&#8203;62414](nodejs/node#62414)
- \[[`176d6d2205`](nodejs/node@176d6d2205)] - **deps**: update timezone to 2026a (Node.js GitHub Bot) [#&#8203;62164](nodejs/node#62164)
- \[[`95c7fc67ba`](nodejs/node@95c7fc67ba)] - **deps**: update googletest to [`2461743`](nodejs/node@2461743) (Node.js GitHub Bot) [#&#8203;62484](nodejs/node#62484)
- \[[`e5e9f2044a`](nodejs/node@e5e9f2044a)] - **deps**: update simdjson to 4.5.0 (Node.js GitHub Bot) [#&#8203;62382](nodejs/node#62382)
- \[[`905b94266a`](nodejs/node@905b94266a)] - **deps**: update ngtcp2 to 1.21.0 (Node.js GitHub Bot) [#&#8203;62051](nodejs/node#62051)
- \[[`180c150122`](nodejs/node@180c150122)] - **deps**: V8: cherry-pick [`cf1bce4`](nodejs/node@cf1bce40a5ef) (Richard Lau) [#&#8203;62449](nodejs/node#62449)
- \[[`bc265aa003`](nodejs/node@bc265aa003)] - **deps**: upgrade npm to 11.12.1 (npm team) [#&#8203;62448](nodejs/node#62448)
- \[[`f1b28612c4`](nodejs/node@f1b28612c4)] - **deps**: V8: cherry-pick [`b25cd62`](nodejs/node@b25cd62c7ba2) (Yagiz Nizipli) [#&#8203;62354](nodejs/node#62354)
- \[[`757719d2af`](nodejs/node@757719d2af)] - **deps**: disable rust icu compiled\_data features (Chengzhong Wu) [#&#8203;62284](nodejs/node#62284)
- \[[`3bdc955b63`](nodejs/node@3bdc955b63)] - **deps**: update sqlite to 3.51.3 (Node.js GitHub Bot) [#&#8203;62256](nodejs/node#62256)
- \[[`a9703d194a`](nodejs/node@a9703d194a)] - **deps**: update googletest to [`73a63ea`](nodejs/node@73a63ea) (Node.js GitHub Bot) [#&#8203;61927](nodejs/node#61927)
- \[[`85138935cb`](nodejs/node@85138935cb)] - **deps**: update merve to 1.2.2 (Node.js GitHub Bot) [#&#8203;62213](nodejs/node#62213)
- \[[`231521e75e`](nodejs/node@231521e75e)] - **diagnostics\_channel**: add diagnostics channels for web locks (Ilyas Shabi) [#&#8203;62123](nodejs/node#62123)
- \[[`0093863664`](nodejs/node@0093863664)] - **doc**: deprecate `module.register()` (DEP0205) (Geoffrey Booth) [#&#8203;62395](nodejs/node#62395)
- \[[`0b96ece6be`](nodejs/node@0b96ece6be)] - **doc**: clarify that features cannot be both experimental and deprecated (Antoine du Hamel) [#&#8203;62456](nodejs/node#62456)
- \[[`8d3ea975f5`](nodejs/node@8d3ea975f5)] - **doc**: fix 'transfered' typo in quic.md (lilianakatrina684-a11y) [#&#8203;62492](nodejs/node#62492)
- \[[`08ff16e0ba`](nodejs/node@08ff16e0ba)] - **doc**: move sqlite type conversion section to correct level (René) [#&#8203;62482](nodejs/node#62482)
- \[[`61cc747dd8`](nodejs/node@61cc747dd8)] - **doc**: add Rafael to last security release steward (Rafael Gonzaga) [#&#8203;62423](nodejs/node#62423)
- \[[`64cfa5a6fa`](nodejs/node@64cfa5a6fa)] - **doc**: use npm-published version of doc-kit (Aviv Keller) [#&#8203;62139](nodejs/node#62139)
- \[[`1020321fb0`](nodejs/node@1020321fb0)] - **doc**: fix overstated Date header requirement in response.sendDate (Kit Dallege) [#&#8203;62206](nodejs/node#62206)
- \[[`9caa7855b2`](nodejs/node@9caa7855b2)] - **doc**: fix guaranteed typo (lilianakatrina684-a11y) [#&#8203;62374](nodejs/node#62374)
- \[[`e254f65306`](nodejs/node@e254f65306)] - **doc**: enhance clarification about the main field (Mowafak Almahaini) [#&#8203;62302](nodejs/node#62302)
- \[[`9e724b53f8`](nodejs/node@9e724b53f8)] - **doc**: remove spawn with shell example from bat/cmd section (Kit Dallege) [#&#8203;62243](nodejs/node#62243)
- \[[`7f37c17516`](nodejs/node@7f37c17516)] - **doc**: minor typo fix (Jeff Matson) [#&#8203;62358](nodejs/node#62358)
- \[[`eb0ca98f01`](nodejs/node@eb0ca98f01)] - **doc**: add path to vulnerabilities.json mention (Rafael Gonzaga) [#&#8203;62355](nodejs/node#62355)
- \[[`198b6e0932`](nodejs/node@198b6e0932)] - **doc**: deprecate CryptoKey use in node:crypto (Filip Skokan) [#&#8203;62321](nodejs/node#62321)
- \[[`17e5aee6c5`](nodejs/node@17e5aee6c5)] - **doc**: fix small environment\_variables typo (chris) [#&#8203;62279](nodejs/node#62279)
- \[[`193d629895`](nodejs/node@193d629895)] - **doc**: test and test-only targets do not run linter (Xavier Stouder) [#&#8203;62120](nodejs/node#62120)
- \[[`4a1f20ec4a`](nodejs/node@4a1f20ec4a)] - **doc**: clarify fs.ReadStream and fs.WriteStream are not constructable (Kit Dallege) [#&#8203;62208](nodejs/node#62208)
- \[[`f976c9214d`](nodejs/node@f976c9214d)] - **doc**: clarify that any truthy value of `shell` is part of DEP0190 (Antoine du Hamel) [#&#8203;62249](nodejs/node#62249)
- \[[`4d83972681`](nodejs/node@4d83972681)] - **doc**: remove outdated Chrome 66 and ndb references from debugger (Kit Dallege) [#&#8203;62202](nodejs/node#62202)
- \[[`71f2eada5b`](nodejs/node@71f2eada5b)] - **doc**: add throwIfNoEntry version history to fs.stat (kovan) [#&#8203;62204](nodejs/node#62204)
- \[[`670c80893b`](nodejs/node@670c80893b)] - **doc**: add note (and caveat) for `mock.module` about customization hooks (Jacob Smith) [#&#8203;62075](nodejs/node#62075)
- \[[`2ff5cb13f5`](nodejs/node@2ff5cb13f5)] - **doc,test**: clarify --eval syntax for leading '-' scripts (kovan) [#&#8203;62244](nodejs/node#62244)
- \[[`6c6c9004c4`](nodejs/node@6c6c9004c4)] - **esm**: fix typo in worker loader hook comment (jakecastelli) [#&#8203;62475](nodejs/node#62475)
- \[[`1cdd23c9f3`](nodejs/node@1cdd23c9f3)] - **esm**: fix source phase identity bug in loadCache eviction (Guy Bedford) [#&#8203;62415](nodejs/node#62415)
- \[[`4f4ff15794`](nodejs/node@4f4ff15794)] - **esm**: fix path normalization in `finalizeResolution` (Antoine du Hamel) [#&#8203;62080](nodejs/node#62080)
- \[[`088167d102`](nodejs/node@088167d102)] - **events**: avoid cloning listeners array on every emit (Gürgün Dayıoğlu) [#&#8203;62261](nodejs/node#62261)
- \[[`0250b436ee`](nodejs/node@0250b436ee)] - **fs**: fix cpSync to handle non-ASCII characters (Stefan Stojanovic) [#&#8203;61950](nodejs/node#61950)
- \[[`b67a8fb171`](nodejs/node@b67a8fb171)] - **inspector**: add Target.getTargets and extract TargetManager (Kohei) [#&#8203;62487](nodejs/node#62487)
- \[[`ffcc5a5722`](nodejs/node@ffcc5a5722)] - **lib**: make SubtleCrypto.supports enumerable (Filip Skokan) [#&#8203;62307](nodejs/node#62307)
- \[[`92ef2ad8fa`](nodejs/node@92ef2ad8fa)] - **lib**: prefer primordials in SubtleCrypto (Filip Skokan) [#&#8203;62226](nodejs/node#62226)
- \[[`40a43ac4d0`](nodejs/node@40a43ac4d0)] - **module**: fix coverage of mocked CJS modules imported from ESM (Marco) [#&#8203;62133](nodejs/node#62133)
- \[[`3ef0a5b90e`](nodejs/node@3ef0a5b90e)] - **quic**: remove CryptoKey support from session keys option (Filip Skokan) [#&#8203;62335](nodejs/node#62335)
- \[[`3c8dd8eb8e`](nodejs/node@3c8dd8eb8e)] - **repl**: use vm DONT\_CONTEXTIFY context (Chengzhong Wu) [#&#8203;62371](nodejs/node#62371)
- \[[`f85b9d9fa8`](nodejs/node@f85b9d9fa8)] - **(SEMVER-MINOR)** **repl**: add customizable error handling (Anna Henningsen) [#&#8203;62188](nodejs/node#62188)
- \[[`e4c164e045`](nodejs/node@e4c164e045)] - **repl**: handle exceptions from async context after close (Anna Henningsen) [#&#8203;62165](nodejs/node#62165)
- \[[`67b854d407`](nodejs/node@67b854d407)] - **(SEMVER-MINOR)** **repl**: remove dependency on domain module (Matteo Collina) [#&#8203;61227](nodejs/node#61227)
- \[[`966b700623`](nodejs/node@966b700623)] - **(SEMVER-MINOR)** **sea**: support code cache for ESM entrypoint in SEA (Joyee Cheung) [#&#8203;62158](nodejs/node#62158)
- \[[`fe82baf970`](nodejs/node@fe82baf970)] - **src**: improve EC JWK import performance (Filip Skokan) [#&#8203;62396](nodejs/node#62396)
- \[[`d490b171e0`](nodejs/node@d490b171e0)] - **src**: handle null backing store in ArrayBufferViewContents::Read (Mert Can Altin) [#&#8203;62343](nodejs/node#62343)
- \[[`0e4af848bc`](nodejs/node@0e4af848bc)] - **src**: convert context\_frame field in AsyncWrap to internal field (Anna Henningsen) [#&#8203;62103](nodejs/node#62103)
- \[[`02980b8c8f`](nodejs/node@02980b8c8f)] - **src**: enable compilation/linking with OpenSSL 4.0 (Filip Skokan) [#&#8203;62410](nodejs/node#62410)
- \[[`064f7c2fa6`](nodejs/node@064f7c2fa6)] - **src**: use stack allocation in indexOf latin1 path (Mert Can Altin) [#&#8203;62268](nodejs/node#62268)
- \[[`ede52bc2dc`](nodejs/node@ede52bc2dc)] - **src,sqlite**: fix filterFunc dangling reference (Edy Silva) [#&#8203;62281](nodejs/node#62281)
- \[[`e1f0d2a014`](nodejs/node@e1f0d2a014)] - **(SEMVER-MINOR)** **stream**: add stream/iter Implementation (James M Snell) [#&#8203;62066](nodejs/node#62066)
- \[[`03839fb087`](nodejs/node@03839fb087)] - **stream**: preserve error over AbortError in pipeline (Marco) [#&#8203;62113](nodejs/node#62113)
- \[[`0000d2f011`](nodejs/node@0000d2f011)] - **stream**: replace bind with arrow function for onwrite callback (Ali Hassan) [#&#8203;62087](nodejs/node#62087)
- \[[`3796a73719`](nodejs/node@3796a73719)] - **test**: update WPT for WebCryptoAPI to [`2cb332d`](nodejs/node@2cb332d710) (Node.js GitHub Bot) [#&#8203;62483](nodejs/node#62483)
- \[[`ad8309415b`](nodejs/node@ad8309415b)] - **test**: update WPT for url to [`fc3e651`](nodejs/node@fc3e651593) (Node.js GitHub Bot) [#&#8203;62379](nodejs/node#62379)
- \[[`bed89b037e`](nodejs/node@bed89b037e)] - **test**: wait for reattach before initial break on restart (Yuya Inoue) [#&#8203;62471](nodejs/node#62471)
- \[[`c9ffffcc55`](nodejs/node@c9ffffcc55)] - **test**: disable flaky WPT Blob test on AIX (James M Snell) [#&#8203;62470](nodejs/node#62470)
- \[[`fd41ef31f6`](nodejs/node@fd41ef31f6)] - **(SEMVER-MINOR)** **test**: add tests for experimental stream/iter implementation (James M Snell) [#&#8203;62066](nodejs/node#62066)
- \[[`1b9d8d3eec`](nodejs/node@1b9d8d3eec)] - **test**: avoid flaky run wait in debugger restart test (Yuya Inoue) [#&#8203;62112](nodejs/node#62112)
- \[[`cb08a29d51`](nodejs/node@cb08a29d51)] - **test**: skip test-cluster-dgram-reuse on AIX 7.3 (Stewart X Addison) [#&#8203;62238](nodejs/node#62238)
- \[[`abea0af8a9`](nodejs/node@abea0af8a9)] - **test**: add WebCrypto Promise.prototype.then pollution regression tests (Filip Skokan) [#&#8203;62226](nodejs/node#62226)
- \[[`47a2132269`](nodejs/node@47a2132269)] - **test**: update WPT for WebCryptoAPI to [`6a1c545`](nodejs/node@6a1c545d77) (Node.js GitHub Bot) [#&#8203;62187](nodejs/node#62187)
- \[[`2c63d3006c`](nodejs/node@2c63d3006c)] - **test\_runner**: add exports option for module mocks (sangwook) [#&#8203;61727](nodejs/node#61727)
- \[[`44ac0e1302`](nodejs/node@44ac0e1302)] - **test\_runner**: make it compatible with fake timers (Matteo Collina) [#&#8203;59272](nodejs/node#59272)
- \[[`1865691275`](nodejs/node@1865691275)] - **test\_runner**: set non-zero exit code when suite errors occur (Edy Silva) [#&#8203;62282](nodejs/node#62282)
- \[[`0252b2bab8`](nodejs/node@0252b2bab8)] - **tools**: bump picomatch from 4.0.3 to 4.0.4 in /tools/eslint (dependabot\[bot]) [#&#8203;62439](nodejs/node#62439)
- \[[`3368155267`](nodejs/node@3368155267)] - **tools**: bump yaml from 2.8.2 to 2.8.3 in /tools/doc (dependabot\[bot]) [#&#8203;62437](nodejs/node#62437)
- \[[`5e47c359f5`](nodejs/node@5e47c359f5)] - **tools**: adopt the `--check-for-duplicates` NCU flag (Antoine du Hamel) [#&#8203;62478](nodejs/node#62478)
- \[[`4a604e82d0`](nodejs/node@4a604e82d0)] - **tools**: bump picomatch in /tools/doc (dependabot\[bot]) [#&#8203;62438](nodejs/node#62438)
- \[[`d1a98b4ddb`](nodejs/node@d1a98b4ddb)] - **tools**: bump flatted from 3.4.1 to 3.4.2 in /tools/eslint (dependabot\[bot]) [#&#8203;62375](nodejs/node#62375)
- \[[`c32daa1ab4`](nodejs/node@c32daa1ab4)] - **tools**: bump eslint deps (Huáng Jùnliàng) [#&#8203;62356](nodejs/node#62356)
- \[[`7a2fcc6d41`](nodejs/node@7a2fcc6d41)] - **tools**: do not swallow error in `lint-nix` workflow (Antoine du Hamel) [#&#8203;62292](nodejs/node#62292)
- \[[`c41a2871b5`](nodejs/node@c41a2871b5)] - **tools**: add eslint-plugin-regexp (Huáng Jùnliàng) [#&#8203;62093](nodejs/node#62093)
- \[[`56dfeb06df`](nodejs/node@56dfeb06df)] - **tools**: fix timeout errors in `lint-nix` job (Antoine du Hamel) [#&#8203;62265](nodejs/node#62265)
- \[[`22fc8078e8`](nodejs/node@22fc8078e8)] - **tools**: bump flatted from 3.3.3 to 3.4.1 in /tools/eslint (dependabot\[bot]) [#&#8203;62255](nodejs/node#62255)
- \[[`409b0663bd`](nodejs/node@409b0663bd)] - **tools**: bump undici from 6.23.0 to 6.24.1 in /tools/doc (dependabot\[bot]) [#&#8203;62250](nodejs/node#62250)
- \[[`67c69750f4`](nodejs/node@67c69750f4)] - **tools**: validate all commits that are pushed to `main` (Antoine du Hamel) [#&#8203;62246](nodejs/node#62246)
- \[[`7d9db8cd21`](nodejs/node@7d9db8cd21)] - **tools**: keep GN files when updating Merve (Antoine du Hamel) [#&#8203;62167](nodejs/node#62167)
- \[[`6c8fa42ba2`](nodejs/node@6c8fa42ba2)] - **typings**: rationalise TypedArray types (René) [#&#8203;62174](nodejs/node#62174)
- \[[`531c64d04e`](nodejs/node@531c64d04e)] - **url**: enable simdutf for ada (Yagiz Nizipli) [#&#8203;61477](nodejs/node#61477)
- \[[`2000caccde`](nodejs/node@2000caccde)] - **util**: allow color aliases in styleText (sangwook) [#&#8203;62180](nodejs/node#62180)
- \[[`0aed332ab4`](nodejs/node@0aed332ab4)] - **wasm**: support js string constant esm import (Guy Bedford) [#&#8203;62198](nodejs/node#62198)
- \[[`d3fd4a978b`](nodejs/node@d3fd4a978b)] - **worker**: heap profile optimizations (Ilyas Shabi) [#&#8203;62201](nodejs/node#62201)
- \[[`e992a34a18`](nodejs/node@e992a34a18)] - **zlib**: fix use-after-free when reset() is called during write (Matteo Collina) [#&#8203;62325](nodejs/node#62325)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDIuMTAiLCJ1cGRhdGVkSW5WZXIiOiI0My4xMDIuMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbIlJlbm92YXRlIEJvdCIsImF1dG9tYXRpb246Ym90LWF1dGhvcmVkIiwiZGVwZW5kZW5jeS10eXBlOjptaW5vciJdfQ==-->
karan-lrn pushed a commit to karan-lrn/node that referenced this pull request Apr 2, 2026
- copyBytesFrom: calculate byte offsets directly instead of
  slicing into an intermediate typed array
- toString('hex'): use V8 Uint8Array.prototype.toHex() builtin
- fill: add single-char ASCII fast path
- indexOf: use indexOfString directly for ASCII encoding
- swap16/32/64: add V8 Fast API functions

PR-URL: nodejs#61871
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs that have at least one approval, no pending requests for changes, and a CI started. buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. needs-benchmark-ci PR that need a benchmark CI run. needs-ci PRs that need a full CI run. performance Issues and PRs related to the performance of Node.js.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants