1399 Commits
Author SHA1 Message Date
Filip Skokan acbc3ff133 test,benchmark: drop OpenSSL 1.x-only coverage
Delete test-crypto-ecb.js, which can no longer run anywhere: Blowfish
is available only from OpenSSL's legacy provider and is absent from
BoringSSL.

The addon and cctest version guards become OPENSSL_IS_BORINGSSL checks.
Remove legacy digest-alias coverage and unreachable OpenSSL 1.x
branches. JavaScript test and benchmark gates, skip reasons, and TLS
error expectations that distinguished OpenSSL 1.x from provider-backed
OpenSSL now distinguish BoringSSL, including PKCS12 parsing, named DH
groups, private-key serialization, RSA-PSS parameters, consolidated
provider caches, FIPS availability, and empty KMAC output. Keep the CCM
alternate finalization error only for BoringSSL.

Provider-only test skips use version-neutral terminology or state the
actual minimum OpenSSL version.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/64777
Fixes: https://github.com/nodejs/node/issues/56733
Refs: https://github.com/nodejs/node/pull/64211
Refs: https://github.com/nodejs/node/pull/63966
Refs: https://github.com/nodejs/node/pull/53329
Refs: https://github.com/nodejs/node/pull/48950
Refs: https://github.com/nodejs/node/issues/45465
Refs: https://github.com/nodejs/node/issues/42827
Refs: https://github.com/nodejs/node/issues/47076
Refs: https://github.com/nodejs/node/pull/62862
Refs: https://github.com/nodejs/node/pull/38512
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-25 22:36:32 +01:00
Robert Nagy 6dea43a0f8 lib: speed up AbortSignal
Speed up creating and aborting signals, adding and removing abort
listeners, AbortSignal.any() and AbortSignal.timeout(), and stop the
default abort reason from retaining the aborting caller.

- Only allocate and dispatch the abort event when the signal has abort
  listeners, and only allocate the dependent signal list when there
  are dependent signals.
- Track whether an event is trusted with a private field instead of a
  WeakSet.
- Flatten addEventListener() options into locals instead of
  allocating a normalized options object, only validate the signal
  option when one is passed, and use the listener flags directly.
- Call the EventTarget kNewListener and kRemoveListener
  implementations directly. V8 does not optimize keyed super property
  access such as super[kNewListener]().
- Initialize the internal slots that AbortSignal.any() adds to its
  sources up front, and the composite-only slots for composites, so
  live signals don't change shape.
- Give every signal a single WeakRef that is shared by all the
  composites that follow it, and register each composite and each
  source once with their cleanup registries instead of registering
  every (source, composite) pair with an unregister token. Registering
  with an unregister token is several times more expensive.
- Register AbortSignal.timeout() timers through a holder that is
  emptied when the timer fires, instead of using the signal as an
  unregister token.
- Take positional arguments in AbortSignal's internal constructor
  instead of destructuring an options object that defaults to
  kEmptyObject. kEmptyObject is a null-prototype object, which V8 keeps
  in dictionary mode, so each of those reads was an uncached dictionary
  miss that cost more than the rest of the constructor.
- Create the default abort reason with Error.stackTraceLimit set to 0.
  Until a captured stack is formatted, V8 keeps the call sites, which
  retain the receivers and functions of the aborting caller's frames,
  so a retained signal kept the aborted work alive. Formatting the
  stack eagerly would fix that but costs several microseconds per
  abort(). The default AbortError no longer shows where abort() was
  called; callers that want that can pass their own reason.
- Add benchmarks for aborting, adding and removing abort listeners,
  and AbortSignal.any().

Refs: https://github.com/nodejs/node/issues/66192
Refs: https://github.com/nodejs/node/pull/66265
Assisted-by: claude:opus-5.5
Signed-off-by: Robert Nagy <ronagy@icloud.com>
PR-URL: https://github.com/nodejs/node/pull/66789
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2026-10-24 19:17:24 +00:00
Robert Nagy c7974d9982 tls: coalesce buffered records into one read
SSL_read() returns at most one TLS record, and ClearOut() emitted a
separate read for each one. Peers that use small records, such as
nginx with its default 4 KiB ssl_buffer_size or servers doing dynamic
record sizing, made every record pay for its own buffer allocation
and call into JavaScript.

While the next buffered record is application data, keep reading into
the same 16 KiB buffer before emitting it, so reads never get larger
than one full record already makes them. Batching stops before any
other record type, so that e.g. a TLS 1.2 renegotiation is still
processed after the data in front of it has been emitted. It also
stops before records short enough to be empty, because SSL_read()
skips empty records and carries on with the next one. If SSL_read()
fails in the middle of a batch, the error is captured first and
reported after the data.

test-tls-max-send-fragment relied on 'data' chunks matching records,
so it now checks the record sizes on the wire.

Signed-off-by: Robert Nagy <ronagy@icloud.com>
Assisted-by: claude:opus-5.5
PR-URL: https://github.com/nodejs/node/pull/66698
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
2026-10-21 12:58:11 +00:00
Antoine du Hamel 796a83a7ce build: do not pass vendored headers when building against shared libs
And setup `test-shared.yml` so we can detect regressions.

Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66844
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
2026-10-21 09:59:53 +02:00
Philipp Dunkel df2ea49e00 zlib: add crc32c
Add zlib.crc32c(data[, value]), which computes the CRC-32C checksum
(Castagnoli polynomial, RFC 3720 section 12.1). CRC-32C has better
error detection properties than the CRC-32 of zlib.crc32() and is the
checksum required by many current protocols, formats and services,
among them:

- iSCSI header and data digests (RFC 7143)
- SCTP packet checksums (RFC 9260)
- iWARP MPA framing (RFC 5044)
- NVMe/TCP header and data digests
- ext4, Btrfs and XFS metadata checksums
- the Snappy framing format
- Apache Kafka record batches
- LevelDB and RocksDB block checksums
- TensorFlow TFRecord files
- Google Cloud Storage and Amazon S3 object checksums

Implementing any of these in JavaScript currently needs a userland
CRC-32C, which is far slower than native code.

The function mirrors zlib.crc32(): it accepts a string (encoded as
UTF-8) or an ArrayBufferView, takes an optional 32-bit unsigned
starting value so a checksum can be continued across chunks, and has a
V8 fast API path.

The checksum is computed by absl::ExtendCrc32c() from the bundled
Abseil, which is already built and linked into node, so this adds no
new dependency and no new checksum implementation. absl_crc32c is
added to the libraries linked with --shared-abseil.

Abseil selects its hardware-accelerated CRC-32C path (SSE4.2 and
PCLMULQDQ on x64, the CRC32 and PMULL extensions on arm64) at compile
time, so with node's default compiler flags the portable table-driven
implementation is used. It runs at about the same speed as zlib.crc32()
(about 6.5 GB/s on a recent x64 machine), while the hardware path
reaches about 38 GB/s. Builds whose target CPU baseline already
includes those instructions get the hardware path without changes.
Enabling it for generic builds is left out on purpose: on x64, Abseil
uses the accelerated code for unrecognized CPUs without a runtime
feature check, so compiling it in unconditionally would fault on CPUs
without SSE4.2.

Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
PR-URL: https://github.com/nodejs/node/pull/66828
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
2026-10-20 12:33:08 +00:00
Donghoon Kang 4c14b9f58a ffi: add getFunction cache-miss benchmark
The existing get-function benchmark reuses the callable cached during
warmup, so it no longer measures trampoline creation.

Add a cache-miss benchmark that resolves a function once per library
instance. Construct the instances before timing to exclude library
loading while including symbol resolution, signature preparation,
and callable creation.

Update the existing benchmark comments to describe cache-hit lookups.

Signed-off-by: HoonDongKang <d159123@naver.com>
Assisted-by: Codex:Astra-medium
PR-URL: https://github.com/nodejs/node/pull/66456
Refs: https://github.com/nodejs/node/pull/64969
Refs: https://github.com/nodejs/node/pull/64971
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-20 02:50:14 +00:00
Murat Kirazkaya 8175dc3c05 tools: add lint rule for unread benchmark n
If a benchmark declares `n` in its configs, main() must read it.
nodejs/node#59872 renamed a config key from `num` to `n` but left
`{ num: n }` in main(), so `n` resolved to undefined and the
benchmark silently reported near-zero results until #62084 fixed
it.

The rule also found `async_hooks/async-resource-vs-destroy.js`,
which has declared `n: [1e6]` since it was added but never read
it. Remove the unused key.

Refs: https://github.com/nodejs/node/pull/59872
Refs: https://github.com/nodejs/node/pull/62084
Signed-off-by: Murat Kirazkaya <groophylifefor@gmail.com>
Assisted-by: Claude Code
PR-URL: https://github.com/nodejs/node/pull/66807
Refs: https://github.com/nodejs/performance/issues/187
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2026-10-19 15:51:08 +00:00
Roberto Bianchi bb3f9176ca fs: reduce glob section allocations
Store prefix counts in section records to avoid a separate vector
and its allocations during multi-globstar matching.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: https://github.com/nodejs/node/pull/66716
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-19 14:53:43 +00:00
Rafael Gonzaga a4231cfc6b benchmark: honor n in perf_hooks usertiming
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66746
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-10-17 00:53:36 +00:00
Roberto Bianchi f59539b514 url: skip plain prefixes in percent-escape checks
decodeFormComponent() already finds the first percent character, but
hasPercentHex() scans the plain prefix again. Start the check at the
known position to avoid repeating that work.

Replacing plus signs with spaces preserves character positions, so
escape validation and decoding behavior remain unchanged.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: https://github.com/nodejs/node/pull/66696
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-16 16:59:40 +00:00
Rafael Gonzaga 77609be7c0 benchmark: use process.execPath when pinning CPUs in run.js
The taskset path used the node from PATH, not the running binary.

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66724
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-10-16 13:24:14 +00:00
Rafael Gonzaga 2d908f48d9 benchmark: fix hideStackFrames error benchmarks
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66723
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-10-16 12:44:22 +00:00
Sebastian Beltran 12ce81920a lib: deprecate _http_*
Signed-off-by: Sebastian Beltran <bjohansebas@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/58535
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
2026-10-15 00:52:34 +00:00
Guilherme Araújo 68df1db7b0 sqlite: use shared-shape objects for result rows
`all()`, `get()` and `iterate()` built each row with the
`Object::New()` overload that takes names and values. That overload
always returns a dictionary-mode object, so no two rows shared a map
and every property read was a hash lookup.

Build rows from a `DictionaryTemplate` cached on the statement in place
of the column names, invalidated on re-prepare. Rows keep their null
prototype. Statements whose column names a template cannot express
(array indices, duplicates, non-ASCII names, which the template
interns as Latin-1) or with more than 64 columns keep the previous
path.

Add a benchmark that reads every column of each row, since the
existing ones only measure building rows.

Fixes: https://github.com/nodejs/node/issues/65799
Assisted-by: Claude
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66385
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-10-14 18:50:29 +00:00
Roberto Bianchi dd7235cb6a url: reduce search params sort buffering
URLSearchParams.sort() copies both merge runs into temporary arrays.
Buffer only the left run and read the right run from the output array,
removing one scratch-array allocation and the right-run copying.

While left-side elements remain, the output cursor stays behind unread
right-side elements. Once the left run is exhausted, the right remainder
is already in place. Taking the left key on equality preserves
stability. The insertion-sort path below 50 pairs is unchanged.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: https://github.com/nodejs/node/pull/66665
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-14 08:51:58 +00:00
Nigro Simone a0ce8f152b src: keep ALS store in AsyncResource::MakeCallback
AsyncResource saves the async context frame when it is created, and
MakeCallback() enters it with async_context_frame::Scope. Then
node::MakeCallback() opens the callback scope with an undefined frame,
so the callback never runs in the saved one. Since AsyncContextFrame is
the default, AsyncLocalStorage loses its store in these callbacks.

Pass the saved frame to InternalMakeCallback(), as the Node-API
AsyncContext already does. This also removes the Scope from every call,
with its two Environment lookups and its global handle.

Refs: https://github.com/nodejs/node/pull/66316
Refs: https://github.com/nodejs/node/issues/43038
Refs: https://github.com/nodejs/performance/issues/24
Signed-off-by: Nigro Simone <nigro.simone@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66326
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
2026-10-14 01:57:03 +00:00
Roberto Bianchi e2bc15692e http: reduce raw header name allocations
Reuse the values array instead of allocating a second result array.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: https://github.com/nodejs/node/pull/66488
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Tim Perry <pimterry@gmail.com>
2026-10-12 09:13:52 +00:00
Nigro Simone 6f71b9ba66 benchmark,tools: fix napi benchmarks on GHA
The GHA benchmark never built the addons of benchmark/napi, and its
--debug-node build made benchmark/common.js look for them in
build/Debug. Build them when the napi category runs, and pick the
build type as test/common does.

Refs: https://github.com/nodejs/node/pull/66395
Signed-off-by: Nigro Simone <nigro.simone@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66423
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
2026-10-11 09:45:36 +02:00
Rafael Gonzaga daed8a3b7f benchmark: fix input passed to subtle.digest in webcrypto-digest
The data is already a random Buffer, so passing it through
TextEncoder decoded it as UTF-8 and re-encoded it, making
subtle.digest hash a different and larger input than createHash.

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66608
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-10-10 16:22:11 +00:00
Rafael Gonzaga 3e6347726b benchmark: fix buffer option in buffer read/write benchmarks
main() read `buf` instead of `buffer`, so every run measured
Buffer.allocUnsafeSlow() even when labeled buffer=fast. Also benchmark
the slow variant and trim the byteLength matrix.

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66604
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
2026-10-10 14:22:00 +00:00
Roberto Bianchi b823c3a21e http2: speed up response getHeaders
Copy validated header names directly into the shallow result instead
of using ObjectAssign on the internal null-prototype map.

Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
PR-URL: https://github.com/nodejs/node/pull/66592
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-10 13:02:45 +00:00
Rafael Gonzaga 17fa5deb23 benchmark: add util.parseArgs benchmark
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66599
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-10-10 12:27:17 +00:00
RafaelGSS dd9777b284 benchmark: fix url-searchparams-sort to sort a fresh list
Copying from another URLSearchParams only slices its internal list,
so every iteration sorts a fresh, unsorted copy.

Refs: https://github.com/nodejs/node/issues/50566
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/66535
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
2026-10-08 18:47:11 -03:00
Geoffrey Booth c89ec290f0 module: synchronously load most ES modules
Signed-off-by: Geoffrey Booth <webadmin@geoffreybooth.com>
PR-URL: https://github.com/nodejs/node/pull/62530
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Jacob Smith <jacob@frende.me>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-10-06 17:40:45 +00:00
James M Snell 3a4454151a http: add websocketMask() and websocketUnmask()
Add websocketMask(source, mask, output[, offset[, length]]) and
websocketUnmask(buffer, mask), which XOR data with a repeating 4-byte
key. This is the masking that WebSocket clients apply to every frame
they send (RFC 6455, Section 5.3), and that servers undo on every frame
they receive.

Userland WebSocket implementations do this either with a byte-by-byte
JS loop (undici, and ws without optional dependencies) or with the
bufferutil native addon. bufferutil is installed for only about 3% of
ws downloads and has no linux-arm64 prebuild, so almost all users run
the JS loop. The signature matches bufferutil, so existing users can
switch with a feature check, as ws did for buffer.isUtf8().

The implementation uses a V8 fast API call and processes 8-byte words,
which the compiler vectorizes. It handles overlapping source and output
views, and treats every view type as raw bytes. It is about 20x faster
than the JS loop at 1 KiB and 40x faster at 64 KiB, and faster than
bufferutil at every size from 32 bytes up.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66335
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
2026-10-06 11:36:02 +00:00
Matteo Collina c56cb0947f stream: share webstreams async iterator methods
ReadableStream.prototype.values() built each iterator from an object
literal with a computed symbol-key method plus five closures. Such a
literal is rebuilt through the runtime on every evaluation, costing
close to a microsecond per iterator, which dominates iterating a
short-lived stream.

Move next() and return() to a shared ReadableStreamAsyncIterator
prototype, as for any WebIDL async iterator, and keep the per-iterator
state in its read request. The prototype chain and property shape are
the ones WPT checks; the placeholder AsyncIterator object in util.js is
no longer needed. As in WebIDL, next() and return() now reject when
called on something that is not a ReadableStream async iterator, and
iterators no longer carry own next/return properties.

Add an async-iterator kind to benchmark/webstreams/lifecycle.js.

webstreams/lifecycle.js kind='async-iterator'   ***  +16.22%

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66392
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
2026-10-05 07:00:09 +00:00
James M Snell 6812e92dea util: make mime parsing faster
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66369
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-10-05 05:47:29 +00:00
Matteo Collina 40933d58ae benchmark: add implicit-framing case to http/set-header
The existing `setHeader` and `setHeaderWH` cases set `Content-Length`
explicitly, and `normal` passes every header to `writeHead()`. The very
common handler shape `res.setHeader(...)` + `res.end(body)`, where
`end()` derives the framing, exercises a different path and was not
covered.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66420
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
2026-10-03 09:50:37 +00:00
James Ross 7bdd1f6363 benchmark: add zstdCompress benchmark
Signed-off-by: James Ross <james@jross.me>
PR-URL: https://github.com/nodejs/node/pull/66358
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2026-09-29 21:23:50 +00:00
Nigro Simone e77e173004 benchmark: add a node::MakeCallback benchmark
The addon calls into JS with node::MakeCallback from a libuv timer, so
every call opens a top-level callback scope, like an I/O callback does.

Signed-off-by: Nigro Simone <nigro.simone@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66316
Refs: https://github.com/nodejs/performance/issues/24
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-29 06:45:36 +00:00
James M Snell 296584b7af benchmark: add http header validator benchmark
Compare http.isValidHeaderName() and http.isValidHeaderValue() with
http.validateHeaderName() and http.validateHeaderValue() wrapped in
try/catch, for valid and invalid input, and for both 'strict' and
'relaxed' header value validation.

Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66334
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
2026-09-29 04:38:28 +00:00
Matteo Collina cff7b12df1 stream: keep webstreams nil requests in fast mode
The shared "no pending request" records in the writable stream were
`__proto__: null` literals, which V8 creates in dictionary mode. They
sit in inFlightWriteRequest, closeRequest and pendingAbortRequest
whenever nothing is pending, and their promise field is checked several
times per write, so those loads did a hash lookup on every write and
every pipe. They are now built as plain literals and get their null
prototype afterwards, which keeps them in fast mode.

The readable controllers also initialized their state slot with an
empty object that setup replaced immediately. That throwaway allocation
is gone, matching the writable and transform controllers.

Add a writable-write benchmark: nothing in benchmark/webstreams drove
WritableStreamDefaultWriter.write() directly.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66230
Reviewed-By: Mattias Buelens <mattias@buelens.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-28 07:51:16 +00:00
James M Snell 8f43e8884b buffer: add isLatin1
Implements a fast check to determine if a string is
a valid byte string (only chars <= 0xff).

Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66298
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
2026-09-28 04:22:37 +00:00
Donghoon Kang c97bbfb2e7 benchmark: remove duplicate ffi string length direct
Signed-off-by: HoonDongKang <d159123@naver.com>
PR-URL: https://github.com/nodejs/node/pull/66278
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-09-27 12:05:50 +00:00
Matteo Collina 7ff62671a5 stream: keep consumer state in fast mode
Create null-prototype share and broadcast consumer state with fast
   properties instead of V8 dictionary properties.

Assisted-by: Pi
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66266
Reviewed-By: Mattias Buelens <mattias@buelens.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-26 21:43:46 +00:00
James M Snell d1960949bb benchmark: protect against accidental fork bomb
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66132
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-26 21:18:45 +00:00
Tim Perry af13502159 benchmark: fix shadowing that broke h=20 on incoming_headers benchmark
Previously the inner 'headers' variable shadowed the outer, meaning that
headers=20 sends the same 7 headers as headers=0.

Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66257
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-26 18:27:41 +00:00
Guilherme Araújo f2b698f1cf sqlite: rename DatabaseSync and StatementSync
Rename the DatabaseSync and StatementSync classes to Database and
Statement, and the internal DatabaseSyncLimits helper to
DatabaseLimits. The old names are kept as aliases of the new classes
and are Documentation-only deprecated (DEP0210, DEP0211).

Assisted-by: Claude Code
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65988
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2026-09-26 00:03:45 +00:00
Matteo Collina 9c06dab7d0 http: pass maxHeaderPairs to parser.initialize()
The parser read the `maxHeaderPairs` property from its JS object in
C++ once per header section to enforce the header count limit. That
lookup is a runtime property load for every parsed request, and costs
up to 7% on the parser benchmark for requests with few headers.

Pass the limit to `initialize()` instead and keep it in a field. The
property is still set, as the JS side uses it to trim the header list.

Refs: https://github.com/nodejs/node/pull/64988
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66250
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
2026-09-25 21:29:33 +00:00
Noah 96ee81c708 doc,src,test: fix typos in code comments
Correct miscellaneous spelling and grammar typos in code comments and
documentation. No code identifiers or runtime logic were modified.

Signed-off-by: Noah Webber <noah.webber@pmg.com>
Assisted-by: Gemini
PR-URL: https://github.com/nodejs/node/pull/66218
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-25 18:14:48 +02:00
Filip Skokan e0748dfd9d benchmark: cover Web Crypto conversion costs
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
2026-09-25 13:23:25 +00:00
James M Snell b9e257f5cb perf_hooks: add histogram.snapshot()
Cloning a histogram with `structuredClone()` or `postMessage()` shares
the native histogram instead of copying it. Capturing the state of a
histogram at a point in time, while other code keeps recording into
it, requires serializing it with `export()` and parsing the result
with `importHistogram()`.

Add `histogram.snapshot()`, which returns a new, independent
`Histogram` containing a copy of the histogram's configuration,
recorded values, `exceeds` count, and EWMA state, without the
serialization round trip. Values cannot be recorded into the returned
histogram. The method is available on all histograms, including
`RecordableHistogram` and `ELDHistogram` instances.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: OpenCode
PR-URL: https://github.com/nodejs/node/pull/66099
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-25 03:31:51 +00:00
Soul Lee b3fc35134e benchmark: remove duplicate ffi add-64 benchmark
add-64.js measured the same add_f64 symbol with the same signature as
add-f64.js and differed only in its argument constants.

Signed-off-by: Soul Lee <alus20x@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66121
Refs: https://github.com/nodejs/node/pull/63068
Refs: https://github.com/nodejs/node/pull/62918
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-22 03:28:28 +00:00
Filip Skokan 194eb69f8b test: deflake test-benchmark-crypto
Test mode reduces bufferSize to one, giving the random buffers a 1/256
chance of matching and failing the comparison count assertion. Use 256
bytes in test mode and force the first bytes to differ before timing.
Remove the flaky designation.

Fixes: https://github.com/nodejs/node/issues/52690
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66151
Fixes: https://github.com/nodejs/node/issues/58353
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-09-21 21:06:43 +00:00
Guilherme Araújo bfb84d3eb1 lib: add primitive fast path to structuredClone
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/64190
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-20 21:03:24 +00:00
Filip Skokan 59b5ac83ba crypto: read RSA-PSS restrictions from provider
Query salt length and digest restrictions instead of serializing the key
to SPKI and parsing its algorithm identifier. A readable salt length
distinguishes restricted keys, including empty parameter sequences, from
unrestricted keys.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66108
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2026-09-20 14:21:47 +00:00
Filip Skokan 6adf7c1722 crypto: skip private RSA parameters in key details
Retrieving asymmetricKeyDetails only needs the modulus, public exponent,
and RSA-PSS restrictions. Add a public-only Rsa view so provider-backed
keys do not also extract private components or probe additional primes.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66108
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2026-09-20 14:21:46 +00:00
James M Snell 97af3d7da5 perf_hooks: add performanceNodeTiming.uvMetricsInfoBigInt
`performance.nodeTiming.uvMetricsInfo` returns the libuv event loop
metrics as numbers, which are only exact up to
`Number.MAX_SAFE_INTEGER`. Add `uvMetricsInfoBigInt`, which returns
the same metrics as bigints backed by `uint64_t` storage, carrying the
full 64-bit range reported by libuv.

A single native call fills both a `Float64Array` and a
`BigUint64Array`, so `uvMetricsInfo` does not pay for bigint
allocation and conversion. The new property is omitted from
`toJSON()`, as `JSON.stringify()` cannot serialize bigints.

Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66094
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
2026-09-19 22:02:10 +00:00
Matteo Collina 22ab7d77f1 buffer: add Buffer.stringLength()
Add `Buffer.stringLength(input[, encoding])`, the counterpart of
`Buffer.byteLength()`: it returns the number of UTF-16 code units that
`buf.toString(encoding)` would produce, without decoding.

For UTF-8 the count is computed with simdutf. Invalid input is counted
with the same maximal-subpart replacement that the decoder applies, so
the result always matches `toString().length`. The other encodings are
computed from `byteLength` alone.

This lets code that accumulates streamed input check the result against
`buffer.constants.MAX_STRING_LENGTH` and size its memory budget before
decoding.

Refs: https://github.com/nodejs/node/issues/66062
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66064
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-09-19 05:21:30 +00:00
Filip Skokan 1a3712d1f8 crypto: use names for asymmetric key algorithms
Provider-backed keys can have no numeric OpenSSL ID. Identify and
construct asymmetric keys by algorithm name, replacing the custom PQC
name-to-NID substitution with provider-aware matching in ncrypto.

Centralize known algorithm names, public key-type names, capabilities,
and backend compatibility in ncrypto. Use named key generation jobs and
remove asymmetric EVP_PKEY constants from the internal JavaScript
binding.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/65966
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-17 20:25:55 +00:00