Repository navigation
node v26 compat, combined: CLI flags, async_hooks ids, deep-equality fidelity, console/util/dns/path fixes and 35 upstream tests - #35391
Draft
cirospaciari wants to merge 217 commits into
Draft
cirospaciari wants to merge 217 commits into
cirospaciari wants to merge 217 commits into
Conversation
…ughtException
These callbacks are dispatched from a promise reaction, so a throw inside one
rejected the derived promise and surfaced as an unhandledRejection instead of an
uncaughtException as it does in Node, where the callback runs off the libuv
request completion. process.on('uncaughtException') and node:domain never saw
errors thrown from fs, dns, or crypto.pbkdf2 callbacks.
Add guardCallback in internal/shared and apply it at the existing callback
chokepoints (ensureCallback in fs, validateResolve in dns) plus the few sites
that bypass them. The callback keeps its exact place in the event loop; only the
throw is rerouted, through the same native path timer callbacks already use,
which is why setTimeout was never affected.
opendir and glob already hop through process.nextTick for this and are left
alone, since routing them would change their timing.
Found by sweeping every upstream test absent from both main and all 47 open pull requests, so none of these overlap work in flight. No source change is needed for any of them. sequential/test-cpu-prof-default sequential/test-cpu-prof-dir-absolute sequential/test-cpu-prof-dir-and-name sequential/test-cpu-prof-dir-relative sequential/test-cpu-prof-drained parallel/test-disable-sigusr1 parallel/test-whatwg-webstreams-adapters-to-writablestream Each was run 6 times, checked for a skip marker, and tamper-checked: mutating a mustCall count or an assertion makes every one of them exit non-zero, so none is passing vacuously. No-Verification-Needed: test-only diff, no runtime surface to drive
test-pipe-stream
test-pipe-unref
test-queue-microtask-uncaught-asynchooks
All three bind unix or UDP sockets, so an earlier sweep that ran them under a
restricted sandbox recorded them as flaky and they were wrongly discarded. With
the sandbox off they are 6/6, verbatim. CI is unaffected by that restriction.
The two pipe tests are tamper-checked: mutating an assertion exits 1. The
queue-microtask one is not, because its only assertion runs inside a
process.on('exit') handler and a failure there does not change the exit code --
but that is equally true on the node v26.3.0 binary, so there is no
bun-versus-node differential. It still exercises async_hooks, queueMicrotask and
uncaughtException together and would catch a crash or a hang.
Upstream tests run with --expose-internals import node's internal modules
directly. Bun already has the mechanism (exposedInternals in
internal-for-testing.ts); this widens it to more of Bun's REAL modules under the
names node's tests use:
internal/validators -> src/js/internal/validators.ts
internal/util/inspect -> src/js/internal/util/inspect.js
internal/util -> { normalizeEncoding } from node_util_binding
internal/errors -> bun's internal/errors.ts (aggregateTwoErrors only)
internal/event_target -> native Event/CustomEvent/EventTarget + kWeakHandler
internal/freelist, internal/fixed_queue, internal/assert/myers_diff
internal/net is recovered in the harness by probing net._normalizeArgs([]) for
the module-private normalizedArgsSymbol rather than minting a look-alike.
hasTemporal and hasLocalStorage are feature-detected in common/index.js; both
are false here.
Nothing above is a test-only construct: each name maps to the same code users
hit. Modules with no Bun counterpart were deliberately not shimmed -- the rest
of internal/errors is native C++ factory functions rather than a JS codes table,
so E/SystemError/hideStackFrames would be a second error hierarchy and the tests
would measure the shim rather than bun.
Adds test-global-customevent, test-net-normalize-args and
test-whatwg-encoding-singlebyte (57 subtests) with its fixtures, verbatim.
Found by re-sweeping the 754 upstream tests still absent from main and every open pull request, against a build carrying this branch's callback-dispatch and internal-module changes. Passes as-is, no source change. 6/6 with no skip marker, byte-identical to upstream, and tamper-checked: a mutated assertion exits 1. No-Verification-Needed: test-only diff, no runtime surface to drive
A `git add -A test/js/node/test` on an earlier commit swept in files that were never meant to land here: a scratch file, a test previously rejected as vacuous (test-gc-net-timeout), one that belongs to another branch and fails `handle instanceof UDP` on Windows (test-dgram-create-socket-handle), one that times out on every Windows shard (test-pipe-unref), and seven files that duplicate the free-wins branch (test-cpu-prof-*, test-disable-sigusr1, test-whatwg-webstreams-adapters-to-writablestream). All removed; each lives on in the branch that owns it, or nowhere, as appropriate. Also fixes CI-visible test-order dependence in the callback-throw suite: every subtest shared one tempdir, so the symlink subtests' l3/l4/lnc entries could become the first entry the Dir subtest's dir.read() returns. The Dir subtest now uses its own directory.
Node exposes formatTime from internal/util/debuglog and its test imports it from there under --expose-internals. Bun's copy was a closure inside the ConsoleObject builtin, unreachable by name. It now lives in internal/util/debuglog, required by createConsoleConstructor the same way that function already requires internal/validators, and is exposed through exposedInternals. Output is unchanged: the algorithm is line-for-line the same and the module is loaded lazily by the console.Console getter, so global console.timeEnd, which is native, is untouched. Plain prototype methods replace the captured-$call style because that is the internal-module convention, per neighboring modules. Adds test-console-formatTime from Node v26.3.0, verbatim.
Deprecations, matching node's exact text and once-per-process semantics:
_tls_common and _tls_wrap emit DEP0192 (the latter previously aliased straight
to node:tls with nowhere to warn, so it is now node's re-export shim, and plain
require("tls")/require("https") stay silent). --pending-deprecation and
NODE_PENDING_DEPRECATION gate DEP0111 on process.binding() and DEP0119 on
binding("uv").errname. Bun's own builtins call process.binding() where node's
internals use internalBinding, so internal callers neither warn nor consume the
once-latch; a later user call still warns exactly once.
cpu-prof: --cpu-prof-name/-dir/-interval without --cpu-prof exit 9 with node's
message instead of warning and continuing, with an interval equal to the
default treated as a noop as node does. ${pid} is substituted in
--cpu-prof-name. The default filename is node's
CPU.<yyyymmdd>.<hhmmss>.<pid>.<tid>.<seq>.cpuprofile in local time; the old name
used epoch microseconds, and the first cut of this exposed that
bun_core::Timespec is not wall-clock (it produced 1970), so the timestamp comes
from SystemTime with localtime_r, or GetLocalTime on Windows. A self-directed
fatal signal via process.kill with no JS listener flushes the profile before
dying, as node's Kill binding does; the process still dies by the real signal.
Not converted, deliberately: DEP0169 on url.parse was removed on purpose in
PR #16641, so re-adding it would reverse a product decision; and SIGPROF is not
reserved by JSC, so node's "reserved while debugging" warning would claim a
behavior bun does not have.
Adds six upstream Node v26.3.0 tests, verbatim.
…G_SNAPSHOT getHeapStatistics gains total_allocated_bytes so the key set matches node's exactly. getHeapSpaceStatistics and getHeapCodeStatistics report JSC's real totals in node's shape instead of throwing: JSC has one undivided heap, so its used and capacity numbers appear under old_space and the other twelve V8 space names carry zeros; the names are required by shape-dependent consumers, the numbers are real. getCppHeapStatistics validates its argument with node's message and returns the empty statistics node itself reports when cppgc holds nothing. setFlagsFromString validates and records the flags instead of throwing, and cachedDataVersionTag derives a stable uint32 from the runtime version plus the recorded flags, so the tag changes across a setFlagsFromString call as node's does. startupSnapshot callbacks throw node's ERR_NOT_BUILDING_SNAPSHOT. writeHeapSnapshot path handling is deliberately untouched: PR #34084 already fixes it. queryObjects is not implemented; it needs real heap iteration by prototype chain, which JSC does not expose. Adds test-v8-stats, test-v8-version-tag, test-v8-startup-snapshot-api and test-cppheap-stats from Node v26.3.0, verbatim.
--heap-prof-name/-dir/-interval without --heap-prof now exit 9 with node's
"<argv0>: <flag> must be used with --heap-prof" instead of warning and
continuing; --heap-prof-interval was previously not registered at all, so
`bun --heap-prof-interval 128 x.js` parsed 128 as the script. An interval
equal to node's default (512 KiB) is a noop without --heap-prof, like node.
--heap-prof now writes node's V8 sampling-heap-profile JSON
({"head": {...}, "samples": [...]}) under node's filename format
Heap.<yyyymmdd>.<hhmmss>.<pid>.<tid>.<seq>.heapprofile in local time (the old
name also hit the same non-wall-clock Timespec bug the CPU side fixed).
JavaScriptCore has no allocation-site sampler, so the profile reports the
real live-heap size on the (root) frame with no per-function attribution;
the full .heapsnapshot remains available via v8.writeHeapSnapshot() and
Bun.generateHeapSnapshot("v8"). The markdown format (--heap-prof-md) is
unchanged. Heap profiles also flush on a self-directed fatal signal via
process.kill, sharing the CPU profiler's hook.
Writing to an absolute --heap-prof-dir or --heap-prof-name (and an absolute
--cpu-prof-name) previously hit a debug assertion in AutoAbsPath::append;
both writers now use resolve-style join.
Adds two upstream Node v26.3.0 tests, verbatim. The other nine
test-heap-prof-* files assert a runAllocation call frame inside the profile
tree (or per-worker profiles), which requires allocation-stack sampling JSC
does not provide, so they are not vendored.
The vendored harness now parses node's `// Env: A=1 B=2` comment convention: parseTestMetadata mirrors upstream, and the test re-spawns itself with the merged environment when any variable differs, as node's common does. Two gaps that respawning exposed are fixed with it: the --expose-internals interceptor now installs when the flag arrives via execArgv in a re-spawned child, and the internal/options shim resolves --test-isolation from execArgv. node:url exports URLPattern, which node v26 re-exports from the global. pathToFileURL is ported from node's own JS implementation: the windows option, UNC and extended-UNC edges, node's pre-encode character set, and posix backslashes kept as %5C, which bun dropped. fileURLToPath attaches err.input, the parsed URL object, on ERR_INVALID_FILE_URL_PATH. The Bun.pathToFileURL and Bun.fileURLToPath globals are untouched. The exposed internal/util/inspect.getStringWidth now implements node's per-code-point east-asian-width-first algorithm, so a family emoji measures 8 and a skin-tone emoji 4 as in node. Bun.stringWidth and bun's own console layout are deliberately unchanged; bun measures grapheme clusters and that is a product decision, not a test's to overturn. Adds seven upstream Node v26.3.0 tests, verbatim: the three Env-comment tests, test-urlpattern, test-icu-stringwidth, and the two file-URL conversion tests.
A getcwd failure at startup aborted every entry point with a generic
ENOENT. Node falls back to the executable's directory
(Environment::GetCwd in env.cc) and lets process.cwd() surface the
error later.
- add bun_core::getcwd_or_exe_dir and use it for the synthetic entry
paths (-e/-p, stdin, cron, node-emulation eval and relative scripts,
feedback) and for the parsed startup cwd of runtime commands only;
install/test/build keep the hard error so they never act on a tree
found above the executable
- an absolute --cwd no longer needs a live cwd; a relative one still
errors; the stored cwd is the post-chdir physical path so
process.cwd(), path.resolve, and the resolver agree
- route a bare --interactive to the REPL like node's --interactive
Enables test-cwd-enoent{,-preload,-repl}.js (verbatim from Node
v26.3.0).
process.cwd() returned the resolver's cached top_level_dir, so it kept
returning a stale path after the directory was rmdir'ed. Node re-runs
uv_cwd on every cache miss and clears its cache on chdir
(lib/internal/bootstrap/switches/does_own_process_state.js).
- Bun__Process__getCwd now does a real getcwd and on failure throws
Node's uv_cwd UVException (message, code, errno, syscall verified
byte-identical against node v26.3.0)
- Process_functionChdir clears the cached cwd instead of repopulating
it, so the next process.cwd() re-queries the OS
- WriteStream's internal $fastPath no longer path.resolve()s its
discarded path, so child_process spawn keeps working from a deleted
cwd (its stdin wiring constructs WriteStream(""))
- drop the now-unused node::path get_cwd alias
The hot path is unchanged: the cached JSString still serves repeated
process.cwd() calls; only the first call after startup or chdir pays
the syscall.
Enables test-cwd-enoent-improved-message.js (verbatim from Node
v26.3.0).
A failed require or import threw ResolveMessage with bun's own message and no code, so the ubiquitous userland pattern `err.code === 'MODULE_NOT_FOUND'` never matched. ResolveMessage now extends Error via a new prototypeBase class option in codegen -- the direction NodeUtilTypesModule.cpp's FIXME already sanctions -- and its message getter returns node's exact text for runtime import kinds: MODULE_NOT_FOUND with a Require stack and a requireStack array for CJS, ERR_MODULE_NOT_FOUND with the specifier truncated to the package name for bare ESM imports. The class itself is kept: Bun.build's log API documents name and constructor as ResolveMessage, and the getter is prefix-gated so invalid-URL, data-URL and ENAMETOOLONG texts are untouched, as is the CLI stderr display text. require.resolve now validates options.paths with node's exact ERR_INVALID_ARG_TYPE and ERR_INVALID_ARG_VALUE messages. Nine assertions across three bun-owned test files are updated to the node shapes; each is listed in the pull request for sign-off. Adds test-require-resolve-invalid-paths from Node v26.3.0, verbatim.
…o stack/callback-throw-dispatch
…stack/callback-throw-dispatch # Conflicts: # src/js/node/dns.ts
…nto stack/callback-throw-dispatch
…ack/callback-throw-dispatch
…ns' into stack/callback-throw-dispatch
- CommonJS.ts: read options.paths once into a local instead of three property reads (oxlint single-read rule; also tamper-resistant against getters) - BunCPUProfiler.rs: replace open-coded mem::zeroed with the audited bun_core::ffi::zeroed wrapper and use raw-pointer borrows for the localtime_r out-params - bun_core: add Zeroable impl for libc::tm
Implements node v26's Assert class: the namespace is built from Assert.prototype, options live behind a private symbol so destructured methods fall back to defaults, calling without new throws ERR_CONSTRUCT_CALL_REQUIRED, and the diff option is threaded through assertion_error.ts, where full disables truncation and partialDeepStrictEqual appends diffs to custom messages. Deep equality gains a third checkPrototypes template flag enabled ONLY by the new node entry point: node:assert's strict variants and util.isDeepStrictEqual now compare prototypes (Buffer vs Uint8Array, subclass vs base are unequal, as in node) while Bun.deepEquals and every expect() instantiation are verified byte-identical in behavior before and after. Also fixed on the node-gated path: own-enumerable-only property walks, boxed Symbol/BigInt values, boxed-string own properties, RegExp lastIndex, invalid dates comparing equal, own properties of Dates/Maps/Sets/arrays/typed arrays, and WeakMap/WeakSet/Promise never equal. All twelve documented strictBug entries in bun's own deep-equal tests now pass and their markers are removed. Standalone fix worth its own line: the Rust inspect newline splitter emitted a trailing empty chunk for strings ending in a newline, breaking assertion diff line counts everywhere. One bun-owned behavior change, flagged for sign-off: assert !== assert.ok now, matching node 25+, as a consequence of the prototype layout; assert.spec.ts is updated accordingly. Adds test-assert-class, test-assert-class-destructuring and test-util-isDeepStrictEqual from Node v26.3.0, verbatim.
…nto stack/callback-throw-dispatch
…mordial-safe Node's deprecate() closures live in each Environment's own JS, so every worker warns once itself. The function-local statics latched process-wide and raced across JS threads; move them onto the Process object. Also restore the captured prototype methods formatTime used before it moved out of ConsoleObject.
Node's ESM loader classifies specifiers platform-independently, but the module-not-found message shaping used the host-native package-path check, whose Windows arm accepts any byte as a drive letter. A specifier like ':://x' was therefore reported as "Cannot find module" on Windows and "Cannot find package '::'" on POSIX (Node prints the latter everywhere). Classify with a host-agnostic predicate that only treats relative forms, separator-led paths, and ASCII-letter drive forms as path-like.
…soned CallSite.prototype.getFileName degrades to false instead of escaping to url.parse
…row exec_check to pub(crate)
…into claude/node-v26-combined-34660
…s name overflows the flag column
…ebuglog resolves lazily
…e now-passing looseBug markers
… was silently ignored
robobun
added a commit
that referenced
this pull request
Aug 22, 2026
…5492 Removes the copy of the permission model this integration branch carried (runtime/permission.rs, internal/permission.ts, the fs/net/child/worker/wasi/ dgram/dns/inspector gates, the --permission and --allow-* handling, the 45 vendored test-permission-* files and their fixtures). The --permission and --allow-fs-* rejection from #35391, which this branch also carries, is back in place, together with its run-eval tests.
This was referenced Oct 1, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #34660 — review that first. This branch is based on
claude/callback-throw-uncaught, notmain.This is a consolidation branch. It carries eight previously separate stacked PRs so there is one review surface instead of eight. Nothing here is new work by me: every source change and every vendored test comes from a member branch unchanged, except where a merge forced a choice — those are listed under "Conflict resolutions" below and are the parts worth a careful read.
Supersedes
claude/node-v26-cli-flags@3c39e303c8--checksyntax mode,--input-type, Node's CLI missing-argument/NODE_OPTIONSerror contract,-e/-pvalue binding, rejection of the unimplemented permission-model flagsclaude/node-v26-sweep-a@0c71dce4efutil.diff(),dnsperformance entries, proxy-awaredeepStrictEqualclaude/node-v26-sweep-b@32ec502b4fConsole#tablelayout, Map/Set iterator previews,isBufferfixclaude/node-v26-sweep-c@c3bd460ed3os.constants.signals,performance.toJSON(),styleTexthex colors, readline-after-close, plus already-passing vendorsclaude/node-v26-sweep-e@26565d2746--disallow-code-generation-from-stringsclaude/node-v26-sweep-d@eb24e27470path.normalize,node:domainanddebuglogparityclaude/node-v26-deep-equal@d1e9ec58a5Bun__deepEqualsfidelity: loose-mode relation,AggregateError.errors, set/map pairingclaude/node-async-hooks-v26@e8f90bb646init/before/after/destroydelivery for ticks, immediates, fs callbacks andAsyncResourceThe member branches are left in place; only the PRs are closed. Read the individual PR descriptions above for the rationale behind each source change — this description does not repeat them.
Tests
35 upstream Node v26.3.0 test files are added under
test/js/node/test/{parallel,sequential}, byte-identical to theirnodejs/nodev26.3.0 copies. All 35 pass. Now 35 files:parallel/test-process-raw-debug.jslanded on main separately in #31831 andparallel/test-util-styletext-hex.jswas dropped from this branch because one of its tty-gated cases fails. The diff also deletes two tests that were already on main,parallel/test-process-execve-permission-granted.jsandparallel/test-repl-permission-model.js, because both run under--permission, which this branch rejects; they only passed on main because the flag was ignored.Each file was run the way
scripts/runner.node.mjsruns it: one process per file,bun run --config=bunfig.node-test.toml <file>, withBUN_DEBUG_QUIET_LOGS=1 BUN_GARBAGE_COLLECTOR_LEVEL=1 BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING=1 NO_COLOR=1and noFORCE_COLOR, against a debug build of this branch.test/expectations.txtis untouched.One file removed:
test-compile-cache-permission-allowed.js#35380 vendored this file; it is deleted here. It was a false pass, not a regression.
The test spawns children as
node --permission --allow-fs-read=<dir> --allow-fs-read=<cache> --allow-fs-write=<cache> empty.jsand asserts the compile cache still writes and reloads under that allowlist. On #35380's branch Bun ignored--permissionand both--allow-fs-*flags, so the child ran with no sandbox at all and the compile-cache assertions were the only thing ever exercised. The file asserted "Bun passes a permission-model test" while Bun has no permission model.#35375 makes
--permissionexit 1 with--permission is not supported by Bun (the Node.js permission model is not implemented)— silently running without a requested sandbox is worse than refusing. That change did not break the test; it revealed that the test never covered anything. So the file comes out rather than the rejection being reverted.This is not permanent. A permission-model branch is in flight on this same base, building the flag surface,
process.permission, and fs/net/child enforcement. Once that lands the test becomes genuinely passable and should be re-added by whoever owns that work.One member deliberately left out
#35390 (
claude/node-v26-diagnostics, 11 tests) is not folded in. Merged, four of its tests fail that pass 3/3 on its own branch and its own build:sequential/test-heapdump.js,sequential/test-heapdump-flag.js,sequential/test-heapdump-flag-custom-dir.js— 0/3 merged, 3/3 alone.v8.writeHeapSnapshot()with no filename throwsENOENTopening the generatedHeap.<date>.<time>.<pid>.0.001.heapsnapshotname, even thoughprocess.cwd()at that point is correct and exists, and the precedingwriteHeapSnapshot('my.heapdump')in the same test succeeds. A standalone reproduction (mkdtemp, chdir, named snapshot, then unnamed) works on both builds, so the trigger is narrower than "chdir plus no-arg".parallel/test-v8-take-coverage-noop.js— 1/3 merged, 3/3 alone.Rather than hold up the other eight members or land four red tests, #35390 stays its own PR until that is understood. Nothing in this branch is a candidate cause that I could identify by inspection; it needs its author.
Two resolutions a reviewer cannot infer from the diff
A.
src/js/node/util.ts— this is the one place a member's lines are intentionally absent. The base branch and #35379 independently ported Node v26'sstyleText(hex colors,validateStream, close-code re-opening). Both ports are correct; the base's is the primordial-safe one —SafeMaprather than a bareMapwith$get/$set,RegExpPrototypeExecrather thanhexColorRegExp.test, hoistedObjectGetOwnPropertyNames, cached lazyrequires — so #35379's duplicate is dropped and the base's is kept. #35379's vendoredparallel/test-util-styletext-hex.jspasses against the kept implementation, which is the check that matters. 19 lines inutil.tsand 4 renamed locals intest/js/node/util/util.test.jsare the only member-added lines not present on this branch; everything else from all eight members is verified present line-by-line.B.
src/jsc/bindings/bindings.cpp— the WeakMap/WeakSet/Promise check is left-operand-only on purpose. Do not "fix" it back to both operands. The base and #35382 moved in opposite directions here, so this is a semantic merge, not a textual one. The base rewrote the Symbol/BigInt wrapper comparison (out ofif constexpr (checkPrototypes)into ac1Type == ObjectTypeblock) and re-added a both-operand WeakMap/WeakSet/Promise rejection insidespecialObjectsDequal. #35382 was deleting exactly that check fromspecialObjectsDequal— which is called twice with the operands swapped, so it cannot express an asymmetric rule — and adding it toBun__deepEquals, where operand order is stable, testingc1only. Resolution: keep the base's Symbol/BigInt block, delete the base's both-operand check, keep #35382's left-operand-only one.The asymmetry is deliberate Node parity, verified against the v26.3.0 binary:
Node tests the left operand only (comparisons.js#L449-L451). Both of #35382's changes are verified present: the left-operand check and the proxy class-name skip. All of it is gated on
checkPrototypes, soBun.deepEqualsandexpect()are untouched.Other conflict resolutions
test/js/node/util/util.test.js— the base's assertions are kept and node compat: styleText hex colors, os/perf_hooks/net/readline fixes, and 11 upstream v26.3.0 tests #35379's explanatory comment aboutvalidateStream: falseis carried over.src/runtime/cli/Arguments.rs— three-way. cli: add --check syntax mode and Node's CLI error contract #35375's split ofBASE_PARAMS_intoBASE_HEAD_PARAMS/BASE_TAIL_PARAMSis load-bearing, not cosmetic: it is how the runtime commands get a--configwithout the-calias, freeing-cfor--check. cli: add --disallow-code-generation-from-strings (+1 node v26 test) #35385's--disallow-code-generation-from-stringsis additive inRUNTIME_PARAMS_. Both are present and merged cleanly;parallel/test-cli-*andparallel/test-eval-disallow-code-generation-from-strings.jscover them.src/jsc/bindings/bindings.cpp— new helper functions. The base addedhasExtraOwnPropertiesand assert: node v26 deep-equality fidelity — loose mode, errors, set/map pairing (+0 tests, correctness only) #35393 addedinheritsFromErrorPrototype+errorLikeFieldsEqualin the same place. Both are kept; they are unrelated. assert: node v26 deep-equality fidelity — loose mode, errors, set/map pairing (+0 tests, correctness only) #35393's changes are all gated oncheckPrototypes, soBun.deepEqualsandexpect()are untouched.src/js/internal/async_hooks_tick.tsis deleted by async_hooks: real async ids and hook delivery for ticks, immediates, fs callbacks and AsyncResource (+8 tests) #35383, which rewires emission intointernal/async_hooks.ts. No reference toasync_hooks_tickortickInitHooksremains anywhere undersrc/.src/js/internal/util/inspect.js— console: route global console through process.stdout/stderr, native table index column, _rawDebug (+4 tests) #35380's one-linepreviewEntriesexport and the base's changes are disjoint; no resolution was needed.Tests that skip rather than run
Inherited from the members; each was declared on its own PR:
parallel/test-module-subpath-import-long-path.js,parallel/test-path-win32-normalize-device-names.js— Windows-only; these do execute on the Windows CI lane.Vendored test files added, by member
#35375 — CLI (9)
parallel/test-cli-bad-options.js,parallel/test-cli-node-options-disallowed.js,parallel/test-cli-syntax-eval.js,parallel/test-cli-syntax-piped-bad.js,parallel/test-cli-syntax-piped-good.js,sequential/test-cli-syntax-bad.js,sequential/test-cli-syntax-file-not-found.js,sequential/test-cli-syntax-good.js,sequential/test-cli-syntax-require.js#35382 — assert/util/dns (3)
parallel/test-common-must-not-mutate-object-deep.mjs,parallel/test-diff.js,parallel/test-dns-perf_hooks.js#35380 — console/compile cache (2)
parallel/test-console-count.js,parallel/test-console-table.js,parallel/test-process-raw-debug.js(
parallel/test-compile-cache-permission-allowed.jsremoved — see above)(
parallel/test-process-raw-debug.jsis no longer in this diff: it landed on main separately in #31831)#35389 — path/domain/debuglog (4)
parallel/test-path-win32-normalize-device-names.js,parallel/test-pipe-unref.js,parallel/test-stdout-close-catch.js,parallel/test-timers-reset-process-domain-on-throw.js#35393 — assert deep-equality fidelity (0)
Correctness only:
assert.deepEqualwas callingBun.deepEquals(a, b, false)— theexpect().toEqual()relation — sodeepEqual(4, '4')threw where node passes;AggregateError.errorsis own-but-non-enumerable and was never compared, soAggregateError([e1])equalledAggregateError([e1, e2]); and sets/maps were matched rather than paired, sodeepStrictEqual(new Set([{a:1},{a:1}]), new Set([{a:1},{a:2}]))returned equal.#35379 — long-tail sweep (10)
parallel/test-module-setsourcemapssupport.js,parallel/test-module-subpath-import-long-path.js,parallel/test-net-onread-static-buffer.js,parallel/test-os-constants-signals.js,parallel/test-path-win32-normalize-device-names.js,parallel/test-pipe-abstract-socket.js,parallel/test-pipe-unref.js,parallel/test-queue-microtask-uncaught-asynchooks.js,parallel/test-tojson-perf_hooks.js,parallel/test-util-styletext-hex.js,sequential/test-http2-ping-flood.js(
parallel/test-util-styletext-hex.jsis no longer in this diff: it was dropped from this branch because one of its tty-gated cases fails)#35385 — CLI (1)
parallel/test-eval-disallow-code-generation-from-strings.js#35383 — async_hooks (8)
parallel/test-async-hooks-close-during-destroy.js,parallel/test-async-hooks-destroy-on-gc.js,parallel/test-async-hooks-disable-gc-tracking.js,parallel/test-async-hooks-enable-disable.js,parallel/test-async-hooks-enable-recursive.js,parallel/test-async-hooks-prevent-double-destroy.js,parallel/test-async-hooks-top-level-clearimmediate.js,parallel/test-async-wrap-trigger-id.js