node: errors/whatwg/promise v26 compat fixes (+11 tests) - #35487
node: errors/whatwg/promise v26 compat fixes (+11 tests)#35487cirospaciari wants to merge 5 commits into
Conversation
The --expose-gc and --expose-externalize-string branches ended the flag scan with break, so a later flag on the same line was never processed. For '// Flags: --expose-gc --expose-internals' the expose-internals require interceptor was silently skipped and the test failed with "Cannot find module 'internal/...'". Continue like the other handled flags (the --no-warnings comment already promises this).
… tests)
Vendor node v26.3.0 lib/internal/errors.js byte-verbatim under
common/nodeinternals/ and register it, so tests that require
E/SystemError/codes/AbortError from 'internal/errors' run against
node's real implementation. Adds the AggregateError primordial to the
emulator and gives internalBinding('util') the privateSymbols object
(arrow_message_private_symbol) the module destructures at load.
Passing: test-errors-aborterror, test-errors-systemerror-frozen-intrinsics,
and the five test-errors-systemerror-stackTraceLimit-* variants.
…test) URL.prototype[util.inspect.custom] (and the other prototypes wired through installInspectCustom) exposed an anonymous function; node names the method '[nodejs.util.inspect.custom]' and user code can read fn.name. Create the JSFunction with that explicit name instead of relying on the symbol property key. Passing: test-whatwg-url-properties.
…1 test)
Vendor node v26.3.0 lib/internal/encoding.js (plus its
internal/encoding/single-byte and internal/encoding/util submodules)
byte-verbatim under common/nodeinternals/, so
test-whatwg-encoding-custom-internals exercises node's real
getEncodingFromLabel table.
Support pieces: internalBinding('config') ({ hasIntl }) and
internalBinding('encoding_binding') (encodeInto/encodeUtf8String/
decodeUTF8 backed by TextEncoder/TextDecoder) in the test binding shim;
uncurried %TypedArray% static primordials, a FastBuffer shim, and
customInspectSymbol in the nodeinternals emulator.
…+2 tests) Three node-parity fixes in the promise rejection plumbing: - 'unhandledRejection' listeners were called straight from native code with no JS frames on the stack, so Error.captureStackTrace(err, listener) inside a listener yielded an empty CallSite array (node's own common.mustNotCall crashes on stack[0]). Dispatch now goes through a JS trampoline that forwards to process.emit, so listeners see caller frames like node's processPromiseRejections path. Listener-exception handling is unchanged (same emitter underneath). - Warnings created while no JS is executing had stack === undefined; node always produces at least the '<name>: <message>' header. The string branch of Process::emitWarning now writes that header when no stack was captured. - PromiseRejectionHandledWarning was emitted even when a 'rejectionHandled' listener existed; node only warns when nothing handled the event. Reordered to match. Passing: test-promise-unhandled-error-with-reading-file, test-promise-unhandled-warn; the rest of the vendored test-promise-unhandled-* / test-promises-* family still passes.
|
🤖 Repro for the const http = require('http');
const server = http.createServer((req, res) => {
req.on('end', () => { console.log('rawTrailers:', JSON.stringify(req.rawTrailers)); server.close(); });
req.resume();
res.end('x f o o'); // respond immediately, before the request body finishes
});
server.listen(0, () => {
const req = http.request({ port: server.address().port, path: '/' });
req.addTrailers([['x-bAr', 'yOyOyOy']]);
req.setHeader('transfer-ENCODING', 'CHUNKED');
req.end('y b a r');
req.on('response', r => r.resume());
});Moving |
|
This PR may be a duplicate of:
🤖 Generated with Claude Code |
|
🤖 Coalesced into #35483 (same base, per review-load consolidation) — all 5 commits merged with a verified strict-superset check; closing. |
Vendors 11 previously-failing Node v26.3.0 upstream tests (byte-verbatim) and fixes the runtime/harness gaps they found. Stacked on
claude/callback-throw-uncaught.Runtime fixes
processpromise-rejection plumbing (BunProcess.cpp,ProcessObjectInternals.ts)'unhandledRejection'listeners were invoked straight from native code with zero JS frames on the stack, soError.captureStackTrace(err, listener)inside a listener produced an empty CallSite array (stack[0]undefined — this crashes node's owncommon.mustNotCallwhen used as a listener). Dispatch now goes through a tiny JS trampoline that forwards toprocess.emit, so listeners see caller frames like node'sprocessPromiseRejectionspath. The fixing line is theprocessObjectInternalsEmitUnhandledRejectionFromNativeCodeGeneratorcall inBun__handleUnhandledRejection; listener-exception handling is unchanged (same emitter).warning.stack === undefined; node always produces at least the"<name>: <message>"header.Process::emitWarningnow writes that header when no stack was captured.PromiseRejectionHandledWarningwas emitted even when a'rejectionHandled'listener existed; node only warns when nothing handled the event (if (!process.emit('rejectionHandled', ...)) emitWarning(...)). Reordered to match.[nodejs.util.inspect.custom]function name (WebStreamsInspectCustom.cpp)[nodejs.util.inspect.custom]andtest-whatwg-url-propertiesreadsfn.name. The function is now created with that explicit name; property attributes unchanged.internalBindingtest shim (src/js/internal/test/binding.ts)config(hasIntl),encoding_binding(encodeInto/encodeUtf8String/decodeUTF8 backed by the runtime's own encoders) andutil.privateSymbols(arrow_message_private_symbol) entries, needed at module-evaluation time by the vendored internals below. New switch cases only — no overlap with the http2 (http2: implement internalBinding('http2') for the vendored node test shim (+2 upstream tests) #34499) or cares_wrap (tls: close_notify on end(), injected-socket upgrades, reject-handshake wire fix, duplex data-loss, SNI, ALPN (+14 tests, tls 81%→86%) #34598) cases pending in other PRs.Test-harness fixes (test/js/node/test/common)
--expose-gc/--expose-externalize-stringbranches ended the scan withbreak, so// Flags: --expose-gc --expose-internalsnever installed the expose-internals require interceptor ("Cannot find module 'internal/...'"). They nowcontinuelike every other handled flag. The five base tests whose Flags lines are affected (test-fs-filehandle,test-performance-eventloopdelay,test-crypto-dh-leak,test-trace-events-api,test-v8-flag-pool-size-0) still pass.lib/internal/errors.js,lib/internal/encoding.js,lib/internal/encoding/{single-byte,util}.jsundercommon/nodeinternals/, plus the emulator entries they need (AggregateError primordial, uncurried%TypedArray%statics, a faithfulFastBuffershim,customInspectSymbol). The errors-family tests now run against node's realE/SystemError/AbortError/codesimplementation.Vendored tests (all byte-verbatim, all passing)
Each fails on the unfixed build (module-resolution error,
fn.name === 'anonymous', or thestack[0].getFileNamecrash respectively) and passes with this branch.Investigated and deliberately not vendored (root causes)
test-http-raw-headers: request trailers are lost when the handler callsres.end()before the request body finishes — Bun emits req'end'at dump time, before the parser has consumed the trailer section (repro in PR thread; overlaps http/http2: node v26.3.0 compat — HTTP/1 fallback + upgrade handoff, http2 session errors, perf_hooks and frame framing (+11 upstream tests) #34432's parser-spill rework, so not fixed here).test-errors-systemerror: asserts V8's exact TypeError text ("Cannot read properties of undefined"); JSC's differs.test-errors-hide-stack-frames: needs Bun's native validators to hide their own frame frome.stack(node'shideStackFramescontract) — wide-blast-radius change, tracked separately.test-abort-controller-any-timeout: only blocker is theTimeoutErrormessage text ("The operation timed out." — WebKit — vs node's "The operation was aborted due to timeout"); an existing Bun test pins the WebKit wording, so changing it needs a maintainer call.test-whatwg-url-custom-searchparams-constructor: node deviates from WebIDL (init == nulltreated as absent); Bun follows WebKit/spec ('null=').*-errorsfamily,-binding,-ping,-debug,-padding-aligned,-socket-proxy, util tests: require node's native-handle architecture (mockableHttp2Session/Http2Streamprototypes the JS layer routes through), async_hooks HTTP2PING resources, or node timer internals. (test-http2-binding/test-http2-respond-errorsare already covered by http2: implement internalBinding('http2') for the vendored node test shim (+2 upstream tests) #34499.)kTransferworker-transfer protocol orinternal/webstreams/*implementation internals;-adapters-to-streamreadableconflicts with Bun's deliberate lazy-lock design (documented in node:webstreams: +17 tests from Node v26.3.0 (30% → 76% of the suite), fix the gaps they found #32627).