Skip to content

deps: V8: backport 8521e2e77535 - #65898

Open
luyahan wants to merge 279 commits into
nodejs:v26.x-stagingfrom
luyahan:v26.x-staging
Open

deps: V8: backport 8521e2e77535#65898
luyahan wants to merge 279 commits into
nodejs:v26.x-stagingfrom
luyahan:v26.x-staging

Conversation

@luyahan

@luyahan luyahan commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Original commit message:

[riscv]Fix unordered FP comparison and emit at the consumer

The lowering for kFloatLessThanOrUnordered and
kFloatLessThanOrEqualOrUnordered incorrectly mapped to (LT, true)
and (LE, true), respectively. Since ComputeBranchInfo can negate a
branch condition after emitting the comparison, complementary
conditions must use the same comparison and invert its predicate.
The incorrect mappings dropped the negation, breaking NaN semantics.
For example, optimized Wasm loops like
`do { x += 1.0; } while (!(x > 0.0));` produced wrong results.

Fix the mappings: kFloatLessThanOrUnordered now uses negated GE,
and kFloatLessThanOrEqualOrUnordered uses negated GT. To prevent
this class of bug, also convert kRiscvCmpS and kRiscvCmpD into
pseudo-instructions like the integer kRiscvCmp. The actual
comparison is now emitted at the single flags consumer (branch,
boolean materialization, or select) through the new EmitFPCompare
helper, using the consumer's final FlagsCondition. This ensures
the predicate and machine condition are resolved consistently.
Generated code remains byte-identical.

Bug: 557938134
Change-Id: I230e181753c5e9c6e7fbea651e551192a76e4005
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8360836
Reviewed-by: Ji Qiu <qiuji@iscas.ac.cn>
Auto-Submit: Yahan Lu (LuYahan) <yahan@iscas.ac.cn>
Commit-Queue: Ji Qiu <qiuji@iscas.ac.cn>
Cr-Commit-Position: refs/heads/main@{#109690}

Refs: v8/v8@8521e2e

DevJunz and others added 30 commits September 3, 2026 12:04
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: nodejs#64959
Assisted-by: claude:fable-5
Signed-off-by: JunHwan Choi <devjunsday@gmail.com>
PR-URL: nodejs#65344
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Luigi Pinca <luigipinca@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: nodejs#65434
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#65434
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@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: nodejs#65510
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@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: nodejs#51854
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65510
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Signed-off-by: jakecastelli <38635403+jakecastelli@users.noreply.github.com>
PR-URL: nodejs#65515
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#65436
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Beth Griggs <bethanyngriggs@gmail.com>
Signed-off-by: Alexander Lichter <github@lichter.io>
PR-URL: nodejs#64003
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
This removes a guard (no reads while write pending) that creates
this deadlock, which was added as a security mechanism. This guard is
redundant given then other existing mechanisms, and a test is added to
demonstrate that.

Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: nodejs#65440
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
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: nodejs#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>
Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: nodejs#65519
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Add type declarations for the `permission` internalBinding so
lib/internal/process/permission.js gets editor autocomplete and
type checking for `has()` and `drop()`.

Signed-off-by: seungmin Nam <nhjbest22@g.skku.edu>
PR-URL: nodejs#65385
Reviewed-By: James M Snell <jasnell@gmail.com>
Hmac.prototype._flush was aliased to Hash.prototype._flush, which
finalizes the native HMAC context but never sets the JavaScript-side
kFinalized flag. After an Hmac has been used as a stream, a subsequent
Hmac.prototype.digest() call therefore still believes the object has not
been finalized and calls into C++ a second time. On that second call the
native context has already been reset, so the digest buffer is never
written and Digest::MAX_SIZE bytes of uninitialized stack memory are
returned to JavaScript.

Hash is not affected because Hash::HashDigest caches its digest
(refs nodejs#28245); Hmac never received the equivalent protection.

Give Hmac its own _flush that sets kFinalized so repeat digest() calls
after stream use are handled by the existing DEP0206 guard. As defense
in depth, also set buf.len = 0 on the native side when the context has
already been reset so unwritten bytes can never be emitted.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: nodejs#65112
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
The previous fix (f67e45e) wrapped header/response event dispatch in
reqAsync.runInAsyncScope(), but missed the stream.push(null) call that
triggers the 'end' event. When END_STREAM arrives on a trailing HEADERS
frame (as gRPC does), the 'end' event fires in the session's async
context instead of the request's context.

Wrap stream.push(null) at end-of-stream in reqAsync.runInAsyncScope()
so that the 'end' event preserves the correct AsyncLocalStorage context.

Refs: nodejs#55460
Signed-off-by: Orgad Shaneh <orgad.shaneh@audiocodes.com>
PR-URL: nodejs#63814
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Other calls in initialization code often already check for null pointers
via CHECK_NOT_NULL(). Do the same here.

Signed-off-by: ndossche <7771979+ndossche@users.noreply.github.com>
PR-URL: nodejs#63457
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Signed-off-by: Huáng Jùnliàng <jlhwung@gmail.com>
PR-URL: nodejs#62352
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Measure construction and low-cost method paths for crypto classes whose
state is stored in native or private slots.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65518
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Cache constructor-known KeyObject types in the existing private slot
until a native handle is needed. Prime normal CryptoKey slot arrays
from constructor arguments while retaining the native fallback for
transferred keys.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65518
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Construct X509Certificate instances directly on the existing native
X.509 wrapper and keep lazy cached values in private state. Use a
non-throwing native brand check while preserving the existing
structured-clone behavior.

Preserve derived-constructor prototype semantics without rereading
new.target.prototype.

Add coverage for receiver validation, hidden state, prototype edge
cases, subclassing, and structured cloning through workers and message
ports.

Replace the key-only instanceof lint rule with a module-aware crypto
class guard and extend it to X509Certificate. Resolve references by
lexical binding so shadowed constructor names remain valid.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65518
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
removeEventListener(type, fn, true) never matched a listener added
the same way, because removeEventListener compared
options?.capture === true directly while addEventListener flattened
a boolean third argument via validateEventListenerOptions().

The underlying fix landed independently in nodejs#64894 (worker:
add support for Web Workers), as a side effect of an unrelated
refactor, so this PR now only adds the regression test that would
have caught it. WPT does not cover this path: the
EventTarget-removeEventListener.any.js test is skipped in
test/wpt/status/dom/events.json.

Fixes: nodejs#65244
Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com>
PR-URL: nodejs#65245
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
fs.rmSync previously embedded paths directly into
custom error messages while also passing the path
to ThrowErrnoException.

This caused duplicated paths for ASCII names and
corrupted paths for non-ASCII directory names on
Linux, and inconsistent path formatting on Windows.

Remove path concatenation from custom messages and
rely on ThrowErrnoException to attach the path safely.
Add a test to cover non-ASCII directory names.

Signed-off-by: Yeaseen <yeaseen.arafat96@gmail.com>
PR-URL: nodejs#61233
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Release QUIC stream stats and state arena slots when the stream is
destroyed instead of from the Stream destructor.
Realm cleanup destroys QUIC binding data before draining remaining
BaseObjects, so a stream that survives until process teardown must
not need BindingData from its destructor.

HTTP/3 header callbacks can synchronously destroy their stream. Check
whether the stream was destroyed after those callbacks before accessing
its arena-backed state, and make repeated native destruction safe after
the slots have been released.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#65410
Fixes: nodejs#65408
Reviewed-By: James M Snell <jasnell@gmail.com>
Currently, any runtime gated experimental feature security
vulnerability is considered a "valid" vulnerability, even if
the work is still very much work in progress. This adds friction
because it ends up requiring that things be compile time gated
which makes it more difficult if there is not a corresponding
CI job to run tests.

This relaxes the policy a bit. For anything that is 1.0 and 1.1,
a vuln report is only valid if it directly compromises a stable
feature, allows a workaround that compromises a stable feature,
etc. An example would be an obvious DOS vector that can be
exploited even if the feature is not enabled, for instance.

This gives us leeway to reject vuln reports on things that are
enabled only by `--experimental-*` runtime flag that are still
works in progress.

Given it's complexity and active development, give ourselves
coverage by specifically excluding QUIC/H3 from vuln reports.
Any vuln reports received for QUIC, unless it's something that
can compromise security of something else in Node.js when the
`--experimental-quic` runtime flag is not enabled, should be
handled as regular issues and not as security vulns

Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#65438
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Beth Griggs <bethanyngriggs@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
When node itself is not position independent (the official Linux
binaries, and any build with a toolchain that does not default to PIE),
LIEF made room for the extra program header by moving the header table
into the largest gap between two PT_LOAD segments and extending the
earlier segment across that gap. Whenever the gap it picked was the one
between the read-only data and the read-write segment, whose boundary
is not page aligned, the extended segment ended inside the first page
of the next one. Linux 4.17 to 5.3, and RHEL 8's 4.18 kernel, map an
executable's segments with MAP_FIXED_NOREPLACE and refuse the second
mapping, so the single executable was killed with SIGSEGV before it ran
a single instruction ('elf segment at ... requested but the memory is
mapped already' in the kernel log). Which gap is largest depends on
section sizes, so roughly one build in three produced such binaries.

Ask LIEF to place the table after .bss for non-PIE executables instead,
which leaves every existing segment as the linker laid it out; the
output grows by the size of .bss. A test checks that no two PT_LOAD
segments of a --build-sea executable share a page.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65564
Refs: nodejs/build#4433
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Stewart X Addison <sxa@redhat.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Bind the path, symbols, and functions getter templates to the
DynamicLibrary constructor signature. This causes V8 to reject
incompatible receivers before invoking the native callbacks,
preventing them from crashing the process.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: nodejs#65415
Fixes: nodejs#65287
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Add contribution guidance and an advisory AgentScan warning for
first-time pull request authors.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: nodejs#65533
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Mike McCready <66998419+MikeMcC399@users.noreply.github.com>
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Signed-off-by: kyungrae <kyungrae2002@gmail.com>
PR-URL: nodejs#65450
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Document the lifecycle of node:test reporter events under
Class: TestsStream, with an ASCII diagram that distinguishes
declaration-order events from their execution-order twins
(test:dequeue/test:complete), the leaf vs suite flow, and the
run-level finale.

Fixes: nodejs#51908
Signed-off-by: sangwook <rewq5991@gmail.com>
PR-URL: nodejs#63780
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Signed-off-by: StefanStojanovic <stefan.stojanovic@janeasystems.com>
PR-URL: nodejs#65535
Refs: nodejs#63114
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs#65431
Reviewed-By: James M Snell <jasnell@gmail.com>
codebytere and others added 23 commits September 7, 2026 17:22
test-external-memory-reasonable-size makes a child allocate 1.2 GB of
external memory so that V8's --external-memory-max-reasonable-size
check fires and the process aborts. The abort raises SIGABRT with all
of that memory resident, and on hosts that write core files (the
SmartOS CI machines in particular) the dump takes longer than the test
timeout, so the test has been timing out there since it was added.

Run the child under `ulimit -c 0` on POSIX, the same way
test-abort-fatal-error and common.childShouldThrowAndAbort() handle
their aborting children.

Refs: nodejs#65589
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65780
Fixes: nodejs#64226
Refs: nodejs#59146
Refs: nodejs#54534
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
test-run-watch-emit-restarted expected exactly one test:watch:restarted
event, but it starts run({ watch: true }) right after writing the
fixtures into the watched directory. Watch backends that deliver events
with some latency, FSEvents on macOS most visibly, can still report
those setup writes once the first run is under way, which restarts it
and makes the later, intentional write the second restart. The test has
been marked flaky on macOS x64 for that reason.

Wait for the first drain, then require that the write is followed by a
restart and a drain, ignoring whatever the setup produced before it, and
drop the flaky marker.

Refs: nodejs#54534
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65780
Fixes: nodejs#64226
Refs: nodejs#59146
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
test-wasi-pthread fails now and then on every platform with
"Assertion failed: r == 0 (c/pthread.c: main: 17)", i.e.
pthread_create() itself reporting an error. The fixture implements
`thread-spawn` by starting a Worker and blocking in
Atomics.wait(result, 0, 0, 1000) until the worker signals that it has
instantiated the module. Two things go wrong there: the worker signals
success by storing 0, the value the main thread is already waiting on,
so when the worker is quicker than the main thread its notify is lost
and the wait runs into the timeout; and one second is not always enough
for a Worker to start and instantiate a threads build on the slower CI
hosts (arm debug, Windows, macOS). Either way spawn() returns -6 and
wasi-libc turns that into a pthread_create() failure.

Wait on a sentinel value that neither outcome writes, and give the
worker a platform-scaled 30 seconds. Drop the flaky markers.

Fixes: nodejs#64226
Refs: nodejs#59146
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65780
Refs: nodejs#54534
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
test-dns-resolver-max-timeout times a query with `{ timeout: 500,
tries: 3 }` against one that also sets `maxTimeout: 500` and asserts
the first took longer. c-ares only expires a try when cares_wrap's
timer fires, every `timeout` ms, so each try costs one or two ticks
depending on sub-millisecond ordering, and uncapped retries also get
0.5-1x jitter. That leaves the capped run anywhere in 1500-3000 ms and
the uncapped one in 3000-4500 ms; on a busy rhel10-ppc64le host both
came out at 3005 ms. With `timeout: 100, tries: 5` the ranges (about
600-1000 ms and 5000-7500 ms measured under load) cannot meet.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65780
Fixes: nodejs#64226
Refs: nodejs#59146
Refs: nodejs#54534
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Most node:bench tests record a sample with `b.start();
process.hrtime.bigint(); b.end(1)`, counting on the extra clock read to
make end() see a later timestamp than start(). On a debian12-x64 CI
host the monotonic clock is coarse enough that all three reads returned
the same value, so end() threw ERR_INVALID_STATE ("insufficient clock
precision for benchmark sample") and test-bench-harness-errors failed;
every test using the idiom can fail the same way there.

Add test/common/bench.js with completeSample(), which spins until
process.hrtime.bigint() moves between start() and end(), and use it at
all of those sites, bench-runner fixtures included.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65780
Fixes: nodejs#64226
Refs: nodejs#59146
Refs: nodejs#54534
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Add a StreamPipeBinding declaration for internalBinding('stream_pipe')
and wire it into InternalBindingMap.

Signed-off-by: leah-1ee <selee3196@gmail.com>
PR-URL: nodejs#65664
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Add a FsEventWrapBinding declaration for
internalBinding('fs_event_wrap') and wire it into InternalBindingMap.

Signed-off-by: leah-1ee <selee3196@gmail.com>
PR-URL: nodejs#65661
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Signed-off-by: leah-1ee <selee3196@gmail.com>
PR-URL: nodejs#65661
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
ffi.getInt8() through ffi.getFloat64(), ffi.setInt8() through
ffi.setFloat64(), ffi.toBuffer() and ffi.toArrayBuffer() return
undefined instead of throwing when a required argument is omitted, so a
call that read or wrote nothing cannot be told apart from one that read
a zero byte. All 22 helpers behave this way.

GetValidatedPointerAddress() and GetValidatedSize() already reject the
same argument when it is passed explicitly as undefined. The
args.Length() test in front of them short-circuits the call and returns
Nothing without scheduling an exception. These six are the only tests in
src/ where args.Length() can skip a call that throws; the only other
Length() tests that guard a call at all guard Buffer::HasInstance(),
which cannot throw. The remaining tests in this file guard an inline
predicate and throw in the branch, which is why setUint8(ptr) reports
"Expected an offset argument" while setUint8() reports nothing at all.

Drop those tests. FunctionCallbackInfo::operator[] returns Undefined for
an out-of-range index, which is exactly the value these validators
reject, so each missing argument now produces the error its explicit
undefined counterpart produces. The documentation already describes this
behavior: the signatures are ffi.getInt8(pointer[, offset]),
ffi.setInt8(pointer, offset, value) and
ffi.toBuffer(pointer, length[, copy]), and the getters are documented to
return a number or a bigint.

ExportBytes() carried the same two tests. They are unreachable through
the public API because exportBytes is not exported and its three callers
all validate len in JavaScript first, but they are the same shape.

Signed-off-by: Soul Lee <alus20x@gmail.com>
PR-URL: nodejs#65500
Fixes: nodejs#65499
Refs: nodejs#62072
Refs: nodejs#62858
Refs: nodejs#65842
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#65788
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Signed-off-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
PR-URL: nodejs#65800
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Signed-off-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
PR-URL: nodejs#65688
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
V8 defaults `v8_enable_sandbox` to on whenever the shared pointer
compression cage and the external code space are enabled, and that is
the configuration embedders that use the sandbox build with. Now that
the sandbox builds and passes the tests, follow that default for
`--experimental-pointer-compression-shared-cage` so the configuration
is reachable from `configure`. Multi-cage pointer compression builds
stay without it: there every IsolateGroup gets its own sandbox, and
`NodeArrayBufferAllocator` always allocates from the default one.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#62237
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
The C++ fast path that fs.cpSync() takes when no filter is given created
the destination directories with default permissions, so a 0700
directory came out of the copy as 0755 (with the default umask). The
JavaScript implementation, which fs.cp(), fs.promises.cp() and
fs.cpSync() with a filter still use, chmod()s every directory it
creates to the mode of its source, and so did cpSync before the port.

Set the source directory's permissions on each directory the copy
creates (the destination root included); directories that already
exist keep theirs, as before.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65488
Refs: nodejs#58461
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
fs.cp() and fs.promises.cp() walked the tree in JavaScript with several
thread pool round trips per entry (opendir batches, two stat()s, the
copyFile(), a chmod()), all awaited in sequence: a 2 100-file tree took
~215 ms with ~110 ms of that on the main thread, against ~36 ms for
fs.cpSync(), which copies the tree in C++ when no filter is given.

Factor that C++ walk into CopyDirRecursive(), which records the error
instead of throwing so that it can run on any thread, and run it as one
ThreadPoolWork request (CpDirJob) for fs.cp()/fs.promises.cp() when
the destination directory does not exist yet and nothing has to run per
entry (no filter, no dereference, permission model off). Copying into
an existing tree keeps the JavaScript walk and its rules for what may
already be there. The same tree now takes ~30 ms with under 1 ms on the
main thread.

For that job the walk follows the JavaScript walk's rules rather than
cpSync's: it creates every directory with mkdir() and every file with
an exclusive uv_fs_copyfile() (honouring the copyFile() mode flags) and
fails with EEXIST if anything has appeared in their place since the
JavaScript check, so it never opens or follows something it did not
create; sockets, FIFOs and unknown entries are reported back to
JavaScript, which rejects them with the same SystemErrors as before;
relative link targets are made absolute lexically as path.resolve()
does. cpSync keeps merging into existing directories, skipping special
files and canonicalizing link targets.

The walk now uses the error_code overloads of std::filesystem throughout
(directory iteration included), so an unreadable directory inside the
tree is reported as EACCES by both cp() and cpSync() instead of
terminating the process, which cpSync() has done since the walk moved
to C++. Filesystem errors raised inside the walk keep their codes, with
'cp' or 'copyfile'/'mkdir' as the syscall. With preserveTimestamps the
walk stamps each directory it filled, root included, so cp() keeps
preserving directory times and cpSync() without a filter now does too.
Both file copies set the destination's mode before writing the data,
which clears setuid and setgid, so the walk puts the source mode back
after each file it copied; the JavaScript walk already chmod()s there.

Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65488
Refs: nodejs#58461
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
The GN build always compiles the bundled copies of brotli, c-ares,
HdrHistogram, llhttp, libuv, nghttp2, SQLite and zstd, so anyone
packaging a GN-built Node.js for a Linux distribution has no
counterpart to configure's --shared-* options.

Add node_shared_* args named after the GYP variables. When one is set,
that dependency's GN template defines its target as a group carrying a
pkg-config config instead of the bundled sources, so every existing
"deps/<name>" reference picks up the system library without further
changes, and config.gypi reports the choice like a GYP build does.

Refs: nodejs#55903
Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: nodejs#65797
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Build `v8_debug_helper.{so|dylib}` to enable V8 gdb/lldb postmortem
plugin support for the V8 version that Node.js built with.

Signed-off-by: Chengzhong Wu <cwu631@bloomberg.net>
PR-URL: nodejs#65786
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Original commit message:

    [objects]: Defer CallSiteInfo creation

    Store the raw data in a FixedArray and create the CallSiteInfo objects
    only on demand.

    This can be further optimized to omit CallSiteInfo creation altogether
    in some code paths, but currently those code paths are not critically important.

    Change-Id: I6480862caf6b64020737527c571e3e3eac704ed3
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7673818
    Commit-Queue: Marja Hölttä <marja@chromium.org>
    Reviewed-by: Leszek Swirski <leszeks@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#106127}

Refs: v8/v8@ebd1578
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65764
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Original commit message:

    [stack traces] Reduce stack frame summarization costs

    During stack trace capture, Summarize() is the most expensive step — it
    creates a full TranslatedState for every optimized frame even though
    most frames are never inspected. This CL reduces that cost in two ways:

    1. Lightweight Summarize() for optimized frames: instead of building a
       full TranslatedState, walk only the deopt translation frame headers
       and resolve function/receiver via ResolveTaggedValue(), falling back
       to the full TranslatedState path for wasm-inlined or unresolvable
       closures.

    2. Deferred baseline frames: during CaptureSimpleStackTrace, baseline
       frames store the raw Code + PC offset and defer bytecode offset
       resolution to ExpandDeferredFrames(), which runs lazily before the
       stack trace is formatted or inspected.

    A new Torque bitfield flag (is_deferred_baseline_frame) marks entries in
    the raw capture array that still need resolution. All consumers
    (GetSimpleStackTrace, GetDetailedStackTraceFromCallSiteInfos,
    GetFormattedStack, PrintCurrentStackTrace) call ExpandDeferredFrames()
    before processing the array.

    Change-Id: I1fe8cce918ba129d655d66f608ac6aa0ed160920
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7722138
    Commit-Queue: Leszek Swirski <leszeks@chromium.org>
    Auto-Submit: Jakob Linke <jgruber@chromium.org>
    Reviewed-by: Leszek Swirski <leszeks@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#106237}

Refs: v8/v8@74e153d
Refs: v8/v8@c9c0abf
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65764
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Original commit message:

    [stack traces] Fall back to full walk when receiver is unboxed

    The lightweight OptimizedJSFrame::Summarize path added in
    crrev.com/c/7722138 assumed that closure and receiver are always
    encoded as LITERAL or TAGGED_STACK_SLOT in the deopt translation.
    This holds for the closure (a JSFunction reference is always tagged)
    but not for the receiver: the "receiver" slot in an InterpretedFrame
    translation is just parameter 0 of the (possibly inlined) frame and
    is emitted via BuildDeoptFrameSingleValue, which encodes it according
    to the value's representation. An inlined frame whose `this` was
    typed as Float64 ends up as DOUBLE_STACK_SLOT, hitting UNREACHABLE in
    ResolveTaggedValue.

    Rename ResolveTaggedValue to TryResolveTaggedValue, return
    std::optional, and fall back to SummarizeFull when the receiver isn't
    a directly-resolvable tagged value.

    Fixed: 499260582
    Change-Id: I1f9cdd28e4b6b76a253a46e43b248d9239a4ecd8
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7748309
    Auto-Submit: Jakob Linke <jgruber@chromium.org>
    Reviewed-by: Leszek Swirski <leszeks@chromium.org>
    Commit-Queue: Leszek Swirski <leszeks@chromium.org>
    Commit-Queue: Jakob Linke <jgruber@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#106423}

Refs: v8/v8@1a00890
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65764
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65614
Reviewed-By: James M Snell <jasnell@gmail.com>
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs#65614
Reviewed-By: James M Snell <jasnell@gmail.com>
Original commit message:

    [riscv]Fix unordered FP comparison and emit at the consumer

    The lowering for kFloatLessThanOrUnordered and
    kFloatLessThanOrEqualOrUnordered incorrectly mapped to (LT, true)
    and (LE, true), respectively. Since ComputeBranchInfo can negate a
    branch condition after emitting the comparison, complementary
    conditions must use the same comparison and invert its predicate.
    The incorrect mappings dropped the negation, breaking NaN semantics.
    For example, optimized Wasm loops like
    `do { x += 1.0; } while (!(x > 0.0));` produced wrong results.

    Fix the mappings: kFloatLessThanOrUnordered now uses negated GE,
    and kFloatLessThanOrEqualOrUnordered uses negated GT. To prevent
    this class of bug, also convert kRiscvCmpS and kRiscvCmpD into
    pseudo-instructions like the integer kRiscvCmp. The actual
    comparison is now emitted at the single flags consumer (branch,
    boolean materialization, or select) through the new EmitFPCompare
    helper, using the consumer's final FlagsCondition. This ensures
    the predicate and machine condition are resolved consistently.
    Generated code remains byte-identical.

    Bug: 557938134
    Change-Id: I230e181753c5e9c6e7fbea651e551192a76e4005
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8360836
    Reviewed-by: Ji Qiu <qiuji@iscas.ac.cn>
    Auto-Submit: Yahan Lu (LuYahan) <yahan@iscas.ac.cn>
    Commit-Queue: Ji Qiu <qiuji@iscas.ac.cn>
    Cr-Commit-Position: refs/heads/main@{#109690}

Refs: v8/v8@8521e2e
Co-authored-by: LuYahan <yahan@iscas.ac.cn>
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/gyp
  • @nodejs/security-wg
  • @nodejs/v8-update

@nodejs-github-bot nodejs-github-bot added build Issues and PRs related to Node.js builds or CI infrastructure. needs-ci PRs that need a full CI run. v26.x Issues that can be reproduced on v26.x or PRs targeting the v26.x-staging branch. v8 engine Issues and PRs related to the V8 dependency. labels Sep 8, 2026
@aduh95
aduh95 requested a review from a team as a code owner September 9, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Issues and PRs related to Node.js builds or CI infrastructure. needs-ci PRs that need a full CI run. v8 engine Issues and PRs related to the V8 dependency. v26.x Issues that can be reproduced on v26.x or PRs targeting the v26.x-staging branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.