Both tests read the destination file with no ordering guarantee against
the fs.write() that Utf8Stream still has in flight, so under load the
read can observe an empty file.
In test-fastutf8stream-destroy the read is issued right after destroy().
In test-fastutf8stream-reopen it is ordered on 'drain', documented as
emitted when the buffer has drained enough to allow continued writing,
which says nothing about the bytes being observable in the file. The
reopen path also emits a 'drain' of its own from a nextTick before the
write has landed.
Order both reads on 'write' instead, documented as emitted when a write
operation has completed and emitted from #release() once the underlying
write returned. In sync mode it is emitted from within write(), so the
listener is attached before the write call.
No data is lost by Utf8Stream here: re-reading the file after a failed
assertion shows the expected content. This corrects an expectation of
the tests, not the runtime.
Signed-off-by: Christian Aurich <christian.aurichzm@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65554
Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-08-20.md
Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-08-26.md
Reviewed-By: Shelley Vohr <shelley.vohr@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Add WPT_INSPECT to launch one generated main-thread test with
--inspect-brk on an available port. Forward debugger stderr so an
inspector client can attach while the child is paused.
Require an exact generated test path and reject worker variants, whose
test code runs in a nested Worker. Cover backend precedence, selector
errors, inspector attachment, and clean shutdown.
Refs: https://github.com/nodejs/node/issues/51854
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65510
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Describe how to run WPT modules, select source files or generated
tests, and choose the existing thread or process backend. Document the
WPTRunner options and remove duplicated run instructions.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65510
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Provide a binary export/import mechanism for histograms.
Since there is no standard interchange format for histograms,
using CBOR is meant to make the format as platform/runtime
agnostic as possible while producing a compact/efficient
result. No new dependency is introduced, we just encode
the CBOR directly.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus
PR-URL: https://github.com/nodejs/node/pull/65434
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Three call sites still duplicated the ArrayIsArray check that
validateArray already performs. Both files were already importing other
validators next to these checks. The error code, argument name and
expected type are unchanged, so the thrown error stays identical.
The ArrayIsArray primordial is no longer used in histogram.js and is
dropped from its destructuring; blocklist.js still uses it elsewhere.
The existing tests only asserted the error code, so assertions covering
the full error message are added for all three call sites. They pass
both before and after this change.
Refs: https://github.com/nodejs/node/pull/64959
Assisted-by: claude:fable-5
Signed-off-by: JunHwan Choi <devjunsday@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65344
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Enumerate usable ciphers and aliases from activated OpenSSL 3 providers
instead of maintaining lists of provider-only algorithms. Skip numeric
OID aliases and filter NULL, TLS composite, multiblock, and
encrypt-then-MAC implementations that the Cipher APIs cannot use.
Preserve the OpenSSL 1.1.1 and BoringSSL paths.
Expose CBC-CTS, SM4-GCM, SM4-CCM, SM4-XTS, and additional AES key wrap
implementations. Add `ctsMode` (CS1/CS2/CS3) and `xtsStandard`
(GB/IEEE) options for selecting provider CTS and SM4-XTS variants.
Keep ordinary cipher construction on the original binding and legacy
lookup paths.
Lazily cache successful provider fetches per Environment for
string initialization and `getCipherInfo()`.
Index entries by case-insensitive query, canonical, and alias names.
Deduplicate owners by provider and canonical identity. Return borrowed
pointers on warm hits.
Use the shared process-wide FIPS-state generation to invalidate
per-Environment cipher caches and refresh `getCiphers()` snapshots in
the main thread and workers. Existing cipher contexts retain their
implementation and can finish across a transition. Release provider
owners before unloading worker addon DSOs.
Enforce one-shot updates for CBC-CTS, AES key wrap, SIV/GCM-SIV, and
CCM decryption. Reject finalization without required input or CCM tags,
and defer authentication failures to `final()`. Document streaming and
XTS data-unit constraints.
Add known-answer vectors, option validation, provider round trips,
cache, worker, snapshot, FIPS transition, and construction benchmark
coverage.
Fixes: https://github.com/nodejs/node/issues/43040
Fixes: https://github.com/nodejs/node/issues/64866
Refs: https://github.com/nodejs/node/issues/62982
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65484
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Enumerate usable digests and aliases from activated OpenSSL 3 providers
rather than relying only on the legacy digest registry. Normalize
provider aliases, omit numeric OIDs and NULL, and validate them against
the active default property query. Preserve legacy names and the OpenSSL
1.1.1 and BoringSSL paths.
Expose KECCAK-KMAC-128, KECCAK-256, SHA256-192, and other provider
digests. Add `functionName` and `customization` options for cSHAKE
digests in `createHash()` and `crypto.hash()` with OpenSSL 4.0 or later.
Resolve provider-only digest names across hashing, HMAC, KDF, signing,
verification, and RSA digest options. Keep ordinary hash construction
and one-shot hashing on the original binding arities and direct
initialization paths. Use parameterized setup only when cSHAKE options
are supplied.
Lazily cache successful provider fetches per Environment.
Index entries by case-insensitive query, canonical, and alias names.
Deduplicate owners by provider and canonical identity. Return borrowed
pointers on warm hits.
Introduce a process-wide FIPS-state generation that advances only after
successful, state-changing `setFips()` calls. Use it to invalidate
per-Environment digest caches and refresh `getHashes()` snapshots in the
main thread and workers. Keep cache IDs monotonic across invalidation
because JavaScript Realms can retain them. Existing hash contexts can
finish across a transition.
Release provider owners before unloading worker addon DSOs. Document
provider-dependent availability and operation-specific restrictions.
Add known-answer vectors, option validation, provider resolution,
property-query, FIPS transition, worker, snapshot, and cross-API
coverage.
Refs: https://github.com/nodejs/node/issues/62982
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65484
Fixes: https://github.com/nodejs/node/issues/43040
Fixes: https://github.com/nodejs/node/issues/64866
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Use the native CryptoKey FunctionTemplate brand check instead of
probing slot access and catching ERR_INVALID_THIS. Keep a private-field
fast path for ordinary same-realm CryptoKeys.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65503
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Use the native KeyObject FunctionTemplate brand check instead of
probing slot access and catching ERR_INVALID_THIS. Keep a private-field
fast path for ordinary same-realm KeyObjects.
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65503
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
CommonEnvironmentSetup::CreateForSnapshotting() always created the
SnapshotCreator without a startup blob, so V8 set up its heap from
scratch. That is impossible when the V8 that Node.js is linked against
only carries the deserializer (external startup data, as Chromium builds
it), and it puts the resulting snapshot on a different read-only heap
lineage than isolates the embedder creates from its own blob. Embedders
in that situation cannot use the snapshot support at all today.
Add SnapshotConfig::base_blob, an optional caller-owned v8::StartupData
that is handed to the SnapshotCreator so that V8 deserializes its heap
from that blob and Node.js adds its isolate data and contexts on top,
the way Blink's context snapshot is built. node_mksnapshot accepts
--v8-snapshot-blob=<file> for hosts that build Node.js with such a V8;
Node.js's own build never passes it and is unchanged. Consuming the
result needs no changes.
embedtest can create a plain V8 startup blob and build the embedder
snapshot on top of one, and a test round-trips argv through a snapshot
built that way.
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65374
Reviewed-By: James M Snell <jasnell@gmail.com>
For the sync methods spawnSync(), execSync() and execFileSync(), when
the stdio option is set to anything other than 'pipe', the stdout and
stderr returned from the C++ code will be null, and not a string or
Buffer as currently documented.
PR-URL: https://github.com/nodejs/node/pull/58575
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: James M Snell <jasnell@gmail.com>
readdir({ recursive: true }) asked the binding for names only and then
called internalModuleStat() on every entry to find the directories to
descend into; with withFileTypes it built the Dirents and still stat()ed
every entry that was not already a directory. Both variants also ran
path.join() and path.relative() per entry to build the relative result.
Ask the binding for file types in all cases, descend into directories
directly, and only stat() symbolic links and entries of unknown type
(which is what could point to a directory). The relative name is the
parent's prefix plus the entry name. Results, their order and the
symlink-following behavior are unchanged for fs.readdirSync, fs.readdir
and fs.promises.readdir.
The known_issues test for Buffer paths (#58892) called back without
checking the error; the error now reaches the callback instead of being
thrown from the completion handler, so the test asserts success to keep
expressing the issue.
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65487
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
The encode-and-enqueue transform walked the chunk code unit by code
unit, materializing a single-character string per index and building
the output with string concatenation. The only state that crosses
chunks is a trailing high (leading) surrogate, and TextEncoder.encode's
USVString conversion already replaces every interior lone surrogate
with U+FFFD, which is exactly what the spec loop produces. Join a
pending high surrogate with the incoming chunk, hold back a new
trailing high surrogate, and encode the rest in a single native call.
The streaming decode path also reuses a single options object instead
of allocating { stream: true } per chunk.
An encoding-streams benchmark is added since the suite had no
TextEncoderStream/TextDecoderStream row. Encoding improves by ~546%
with 1KB string chunks and ~20% with 16-character chunks; decode is
unchanged.
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/65414
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Mattias Buelens <mattias@buelens.com>
tls.connect() with malformed ALPNProtocols hit
CHECK_EQ(0, SSL_set_alpn_protos(...)) in the C++ layer and aborted
the process with SIGABRT.
Validate in JS instead, in convertALPNProtocols, so both client and
server fail early with a recoverable ERR_INVALID_ARG_VALUE:
- zero-length string protocols now throw from convertProtocols
- wire-format buffers are checked for zero-length and truncated
entries
- an empty buffer or array is still accepted and means skip ALPN,
matching the historical behavior for []
The C++ CHECK_EQ is left unchanged: once JS has validated the input,
a non-zero SSL_set_alpn_protos return is an internal invariant
failure rather than user-facing input.
Fixes: https://github.com/nodejs/node/issues/65069
Signed-off-by: Sankalp Thakur <sankalphimself@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65076
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
fs.readFileSync(path, 'utf8') read the whole file in 8 KiB read() calls
appended to a std::string, i.e. one syscall and a potential
reallocation per 8 KiB (an 8 MiB file took ~1400 read() calls).
Keep the exact old sequence for small files (one read into the 8 KiB
stack buffer, one read reporting EOF). Once a read fills the stack
buffer, read the rest directly into one heap buffer sized from fstat()
(plus one byte so that the EOF read does not force growth), growing
geometrically only when the size is unavailable or wrong. The size is
only an allocation hint: reading continues until read() reports EOF,
so procfs/sysfs files, FIFOs, files that change while being read and
file descriptors positioned mid-file behave as before, and the bytes
handed to StringBytes::Encode() are exactly the ones read.
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65328
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Add an --analyze flag that performs statistical analysis directly
after benchmarks complete, eliminating the need for R and compare.R.
When --analyze is specified, compare.js collects the rate data during
the run and prints a statistical summary table instead of CSV output.
The table matches the format of compare.R: improvement percentage,
significance stars (* p<0.05, ** p<0.01, *** p<0.001), and confidence
intervals at three risk levels.
Also adds a --max-regression N option that causes the compare.js to
exit with 1 (error) when the `--new` is N% slower. Useful for CI
use to detect regressions.
Uses the histogram API's welchTest() and cohensD() methods introduced
in the previous commit. Benchmark rates are scaled to integers for
HdrHistogram recording; the --scale option (default 1000) controls
the multiplier for precision.
Usage:
node benchmark/compare.js --old ./node-old --new ./node-new \
--analyze url
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus
PR-URL: https://github.com/nodejs/node/pull/65416
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Welch's t-test, Mann-Whitney U test, Cohen's d, and Cliff's delta,
and and handful of others
These methods enable in-process benchmark comparison and regression
detection without external dependencies.
No new dependencies.
Tests and docs created by the AI agent.
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus
PR-URL: https://github.com/nodejs/node/pull/65416
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>