Commit Graph
351 Commits
Author SHA1 Message Date
Malte UblandClaude Opus 5.5 0f41b7bc67 Island handle operations, native subclasses of island classes, arrays and collections by reference (NI-5b/5c/5d)
Node islands stack, part 6 of 11 (scriptc-perf/results/islands-prs/PLAN.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 18:49:54 -07:00
Chris Tate e6115f87e8 Merge main 2026-10-22 07:22:32 -05:00
Chris Tate 714dbfe2bb Merge main 2026-10-22 06:59:47 -05:00
Chris Tate 75bcf9dfa7 Merge main 2026-10-22 06:55:45 -05:00
Chris Tate df6de14c94 Support new tls.TLSSocket and tls.connect({ socket }) (#1791) 2026-10-22 06:01:47 -05:00
Chris Tate daac2a4a15 Support objectMode streams with any value as a chunk (#1785) 2026-10-22 05:55:45 -05:00
Chris Tate 01a467060b Support WebCrypto wrapKey and unwrapKey
crypto.subtle.wrapKey exports a secret key (raw, raw-secret or jwk) and
encrypts it, and unwrapKey decrypts and imports one, as Node's
webcrypto.js does: the wrap algorithm normalizes through the wrapKey
registry (AES-KW) and then the encrypt registry (AES-GCM, AES-CBC and
AES-CTR with their dictionaries), the wrapping key's algorithm and
usages are checked, and a JWK payload is its JSON text, padded with
spaces to a multiple of 8 bytes for AES-KW. A wrapped JWK that is not
UTF-8 JSON with a kty member rejects with Node's DataError.

AES-KW is RFC 3394 key wrap over the vendored mbedTLS block cipher, in
scr_webcrypto_aes.c beside the other AES modes: wrapping takes a
multiple of 8 bytes and at least 16, unwrapping a multiple of 8 and at
least 24, and the integrity check value is compared in constant time.
The cipher's failures, and unwrapKey's import errors, reject on a later
loop turn as Node's job promises do.

This completes jose's symmetric key management: 7132 runs the real
jose 6.2.12 PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW,
A128KW and A256KW paths (EncryptJWT and jwtDecrypt) against Node.
getPublicKey replaces wrapKey as the refused method in the fenced
fixture and the JavaScript refusal test.
2026-10-22 05:48:30 -05:00
Chris Tate 1360830149 Support new tls.TLSSocket and tls.connect({ socket }) 2026-10-22 04:52:44 -05:00
Chris Tate 67247dd26b Support objectMode streams with any value as a chunk
Readable, Writable, Duplex, Transform and PassThrough take the
objectMode option, and a Duplex, Transform or PassThrough the
readableObjectMode and writableObjectMode options, as true or false
literals in an options object literal or in an options value. An
object-mode side holds any value that converts to a checked-dynamic
value: push, unshift, write, end, pipe, pipeline, for await, 'data'
listeners, Readable.from and the transform callback carry values in
TypeScript and JavaScript, and constructor-function streams and options
held in variables do the same. The object-mode high-water mark counts
values and defaults to 16. A readable buffer that mixes strings, Buffers
and other values holds them all, and push(undefined) and other values on
a byte-mode stream report ERR_INVALID_ARG_TYPE through 'error', as in
Node.

In typed code a write or transform callback, or a _write or _transform
method, may declare its chunk with any such type, which converts when
the callback runs. Writes pass the encoding argument to _write and
_transform as Node does: undefined when absent, null when a callback
took its place, otherwise the value unchanged. A parameter declared
string | null | undefined receives that value and one declared string
receives "" for undefined and null. write(chunk, encoding) on a
byte-mode stream encodes a string chunk with any known encoding and
throws ERR_UNKNOWN_ENCODING for an unknown one. Readable.from takes
typed Maps and Sets of any such value, and arrays that mix strings and
Buffers.

for await over a readable-only stream that will emit 'close' now ends
after 'close', as Node's eos does. Buffered writes that complete inside
clearBuffer run their callbacks in order, and 'finish' waits for a
deferred afterWrite that carries a callback, as Node's pendingcb does,
unless a _final callback schedules it.

The 'data' listener adapters take three slots and write and transform
callbacks read their chunk and encoding through runtime accessors, so
RUNTIME_ABI_VERSION is now 26.
2026-10-22 04:21:55 -05:00
Chris Tate 6e753cd5c8 Merge main 2026-10-22 04:08:52 -05:00
Chris Tate b5fb4115e1 Merge main 2026-10-22 03:33:29 -05:00
Chris Tate 7d20212dd4 Merge main 2026-10-22 03:24:23 -05:00
Chris Tate 1773ffbef3 WebCrypto: the crypto global, node:crypto's webcrypto, and secret-key SubtleCrypto 2026-10-22 02:52:01 -05:00
Chris Tateandsaboursepideh 1a240fbf10 Support asymmetric keys, signatures and Ed25519 in node:crypto and WebCrypto
Co-authored-by: saboursepideh <25549001+saboursepideh@users.noreply.github.com>
2026-10-22 02:49:33 -05:00
Chris Tate d426960f45 Make Cipheriv and Decipheriv Transforms and accept function stages anywhere in pipeline()
Cipheriv and Decipheriv values are Transforms, as in Node: they can be
written and ended, piped into, used as pipeline() and stream/promises
pipeline stages, composed, read, iterated with for await, read by
stream/consumers, passed to finished(), and listened to, and their stream
properties read as in Node. Each chunk goes through the cipher's
update(), and the end pushes final() or reports its error through
'error'; writing after final() throws out of write(). The stream unit
builds a cipher's Transform on its first stream use from operations the
cipher's handle provides (ScrDynHandleOps.transform), so programs that
use ciphers without streams link as before. The cipher is a
collector-headered object behind a traced handle: its Transform's steps
hold it, and the pair is reclaimed as a cycle. Through untyped values, in
a program that uses streams, a cipher's stream properties and its on,
once, off, pipe, unpipe, read, pause, resume, setEncoding, write, end,
destroy, cork and uncork members run on its Transform; other stream
members throw a coded SC2020 error.

A Transform holds a write's callback while its readable side is at the
high-water mark and runs it at the next read, and runs it on a tick once
the readable side has ended, as Transform._write does. write() on a
PassThrough, a Transform, a Hash or a cipher used to return true however
much the readable side buffered. zlib streams applied the rule already
and keep their timing.

pipeline() accepts function stages anywhere among its streams, so runs of
async generator stages can sit on both sides of a stream. A stage can be
named by a function declaration, or a const bound to a function
expression, that nothing reassigns; its body lowers again at the
pipeline with its source typed by the pipeline. The source can also be
an array, a string, a synchronous generator object, or a synchronous
generator function without parameters: an async generator steps the
source's iterator and yields each element, and the next stage receives
each element on the same tick as with Node's for await over the source.
The runtime's function-stage entry points take a bitmask of the function
positions and one (next, read, return) helper triple for each generator
pumped into a stream, so RUNTIME_ABI_VERSION is now 25. In JavaScript,
the chunks a stage receives from the previous stage's generator read as
the strings or Buffers it yields, so their string and Buffer methods
compile.

Corpus 7055-7059 cover cipher streams in TypeScript and JavaScript, their
errors, close order and backpressure, the pipeline stages and sources
with their tick order, and Transform backpressure.
2026-10-22 01:55:38 -05:00
Chris Tate 283a504fe0 Support crypto.createDiffieHellman and getDiffieHellman
crypto.createDiffieHellman, crypto.getDiffieHellman and
crypto.createDiffieHellmanGroup return native DiffieHellman and
DiffieHellmanGroup handles backed by mbedTLS bignums. generateKeys,
computeSecret, getPrime, getGenerator, getPublicKey, getPrivateKey,
setPublicKey, setPrivateKey and verifyError follow Node 24.22:

- the modp1, modp2, modp5 and modp14 through modp18 groups, with the
  private key widths of Node's OpenSSL 3 path (200 to 400 bits for
  modp5 and up, [2, p - 2] for modp1 and modp2);
- explicit primes and generators in every argument form and encoding,
  with keys of bits(p) - 2 bits, or below min(2^N, q) when the
  parameters equal an OpenSSL named group (RFC 3526, RFC 7919,
  RFC 5114);
- generated safe primes with OpenSSL's congruences for the generator;
- verifyError's DH_check bits, computed when it is first read;
- Node's argument, generator, modulus, key range, state and encoding
  errors, including the OpenSSL errors' library and reason properties.

Safe-prime generation sieves candidates with the odd primes below a
bound that grows with the prime's length and tests them with
Miller-Rabin rounds over a variable-time Montgomery exponentiation that
only reads public values; key and secret exponentiations stay on
mbedTLS's constant-time path. Primes longer than 8192 bits, property
reads other than verifyError, property writes, Object.prototype methods,
and calls whose output encoding is typed any or matches no @types/node
overload are refused.

The runtime unit scr_dh.c links, with the mbedTLS archive, only into
programs that use DiffieHellman. wasm32-wasi builds refuse it. The ECDH
unit's argument and encoding helpers move to scr_crypto_args.h, which
both units include.
2026-10-21 21:55:47 -05:00
Chris Tate 029906d861 Merge main 2026-10-21 19:34:10 -05:00
Chris Tateandjlucaso1 973884eabe Support fs.promises.rm options
fs.promises.rm(path, options) accepts the { recursive, force, maxRetries,
retryDelay } literal options that rmSync accepts. It runs the same removal
and rejects with its errors.

Removing a directory without recursive now throws Node's ERR_FS_EISDIR
SystemError from rmSync and fs.promises.rm. A retryDelay outside int32 >= 0
or a maxRetries outside uint32 throws ERR_OUT_OF_RANGE. rmSync checks these
options before the path, and fs.promises.rm checks the path first, as Node
does.

Fixes #1615

Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
2026-10-21 09:13:12 -05:00
Chris Tateandjlucaso1 d858d840f9 Accept file URL paths in synchronous fs functions
readFileSync, writeFileSync, appendFileSync, statSync, lstatSync,
readdirSync, mkdirSync, rmSync, rmdirSync, mkdtempSync, accessSync,
unlinkSync, chmodSync, chownSync, lchownSync, truncateSync, copyFileSync,
renameSync, realpathSync, realpathSync.native, openSync and opendirSync
accept a file: URL wherever they accept a path. The URL converts as
fileURLToPath converts it, with Node's errors for other schemes, hosts,
encoded separators and null bytes.

Arguments after a URL path that have side effects are evaluated into
hidden locals before the conversion, so they run even when it throws. A
URL path after a string path, or with options that are not literals,
fails with SC2020, because Node checks those arguments before it converts
the URL. existsSync and the fs.promises functions also fail with SC2020
for URL paths: existsSync answers false for a URL it cannot convert, and
fs.promises reports conversion errors as rejections.

Fixes #1616

Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
2026-10-21 08:46:44 -05:00
Chris Tate 2582e46e76 Support crypto.createECDH and ECDH.convertKey
crypto.createECDH returns a native ECDH handle backed by mbedTLS for
prime192v1, secp224r1, prime256v1, secp384r1, secp521r1, secp192k1,
secp224k1, secp256k1, brainpoolP256r1, brainpoolP384r1 and
brainpoolP512r1. generateKeys, computeSecret, getPublicKey,
getPrivateKey, setPrivateKey, setPublicKey and ECDH.convertKey follow
Node 24: compressed, uncompressed and hybrid points, input and output
encodings, the private key range, key pair validation, and Node's error
codes and messages.

Curve names follow OpenSSL's short-name lookup: names of other curves
from crypto.getCurves() are refused at compile time when literal and
throw a coded SC2020 error when computed, other OpenSSL short names
throw ERR_CRYPTO_OPERATION_FAILED, and unknown names throw
ERR_CRYPTO_INVALID_CURVE. Calls whose arguments no @types/node overload
accepts, and computeSecret(view, encoding), are refused at compile time.

The runtime unit scr_ecdh.c links, with the mbedTLS archive, only into
programs that use ECDH. wasm32-wasi builds refuse it.
2026-10-20 19:17:05 -05:00
Chris Tate 7f777f36a3 Carry runtime-decided dns.lookup answers dynamically, dial Node-typed net lookups, and keep tsc enum exports undefined until assigned (#1528) 2026-10-20 18:25:22 -05:00
Chris Tate 3751afa51f Merge main 2026-10-20 13:02:01 -05:00
Chris Tate 99af5c878b Merge main and cover a block-local arguments alias that shadows an outer one
- Merge origin/main (e9fb01603); the import lines at the top of
  lowerer.ts conflicted and both are kept.
- Corpus 6385 gains a wrapper whose block-local `args` alias shadows an
  outer one in the same function; each call forwards its own arguments.
2026-10-20 11:30:11 -05:00
Chris Tate e9fb01603f Compile NodeJS.ReadableStream and NodeJS.WritableStream as general streams when a program mixes stream producers (#1518) 2026-10-20 11:24:09 -05:00
Malte UblandClaude Opus 5.5 bc6a2fc767 Merge main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 09:06:59 -07:00
Malte UblandClaude Opus 5.5 e865594089 Accept NodeJS stream interfaces in the fallback events.once and document its boundary
The fallback declaration of events.once takes NodeJS.ReadableStream and
NodeJS.WritableStream emitters like @types/node does. The diagnostics
fixture now pins the forms that stay refused (options that are not an
object literal, a computed name, a stream's 'data' event), and the
limitations page states the supported events.once forms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:59 -07:00
Chris Tate 21c6505709 Match tuple rests and positional any[] parameters in function patterns, and merge main
- matchInferSignature reads a fixed-tuple rest as its positions, so
  (...args: [string, number]) needs two arguments, and a positional
  any[] pattern parameter matches only when the function's parameter
  there accepts an array, as TypeScript's assignability does
  (corpus 6398).
- Merge origin/main (200fe8d22); node-v24-backlog.json regenerated.
2026-10-20 10:37:43 -05:00
Chris Tate 89f8dbe9e0 Merge main 2026-10-20 10:23:43 -05:00
Malte UblandClaude Opus 5.5 f669c46f0d Carry runtime-decided dns.lookup answers dynamically, dial Node-typed net lookups, and keep tsc enum exports undefined until assigned
- dns.lookup with options known only at run time (a checked-dynamic
  value, or one cast to an overload's option type) may answer a string or,
  with `all: true`, an address list, whatever the overload the checker
  picked says: an inline callback now binds its parameters as
  checked-dynamic values. Array.isArray tests a checker-narrowed dyn read's
  dyn value instead of folding on the extracted type, so it never answers
  false for an address list the declared type omits.
- net.connect({ lookup }) accepts a lookup of Node's own type
  (net.LookupFunction: options plus a callback taking an address string
  or list), called as Node's autoSelectFamily dial does ({ hints, all:
  true }); the fallback declarations spell net.LookupFunction that way.
  dns.lookup accepts Node's hints flags (ADDRCONFIG, V4MAPPED, ALL) and
  passes them to getaddrinfo.
- A CommonJS export typed as the empty object literal (tsc's enum output
  `exports.E || (exports.E = {})` after `exports.E = void 0`) rides
  checked-dynamic storage, so the preamble's undefined no longer traps at
  module load: @opentelemetry/api loads and its no-op metrics and trace
  APIs run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 07:58:15 -07:00
Chris Tate c4ce357a9e Merge main and answer false for fixed-parameter function patterns that need more arguments
- Merge origin/main (e1c27176a).
- matchInferSignature answers false when a function needs more arguments
  than a fixed-parameter pattern passes, as TypeScript's assignability
  does (corpus 6398).
- Record corpus costs for the programs this change adds.
2026-10-20 09:24:29 -05:00
Chris Tate 7d555c4cf3 Merge main 2026-10-20 09:04:02 -05:00
Chris Tate 02fc8ab13c Keep one process-stream Writable per descriptor and never end it from a pipe
Under the general stream representation, every conversion of
process.stdout or process.stderr into a Writable slot made a new stream,
so two NodeJS.WritableStream slots holding process.stdout compared
unequal and kept separate listeners and writable state. A pipe into such
a slot also ended the converted Writable at the source's end, so later
writes through the slot failed; Node never ends process.stdout or
process.stderr from a pipe.

scr_stream_stdio_writable now keeps one Writable per descriptor and
thread, released at exit. Under the general representation, a pipe into
a Writable slot lowers to readable.pipeGeneral (scr_stream_pipe_general,
last in the stream unit), which keeps end off when the destination is
one of those Writables; programs without the general representation
lower pipes as before.

The fallback stream.Writable's on() and once() overloads for drain,
finish, close and error return the stream again, so listener chains such
as out.on("finish", listener).end(data) type-check.

Adds corpus 6468.
2026-10-20 08:54:18 -05:00
Malte UblandClaude Opus 5.5 40b80116e4 Merge origin/main into opt/http-socket-path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 03:22:28 -07:00
Malte UblandClaude Opus 5.5 1e96179f3a Carry untyped streams, casts, for await and pipeline stages into the general stream representation
An 'unknown' value flowing or cast into a NodeJS.ReadableStream slot and
'for await' over one now select the general representation, where the
checked cast to Readable applies. pipeline() stages that arrive untyped
unwrap boxed native streams at run time. @types/node's zlib interface
declarations map to the runtime Transform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 03:13:15 -07:00
Malte UblandClaude Opus 5.5 cb26c95f61 Read http.request options at run time, speak HTTP over Unix sockets, and fill the boot path's net and fetch gaps
http.request, https.request and get now accept options the compiler
cannot see as an object literal: a RequestOptions variable, a literal
that spreads one, or a literal that sets socketPath. The runtime reads
the record in the ClientRequest constructor's order with Node's errors;
documented options it does not implement throw the runtime fence when
they carry a value. https adds rejectUnauthorized, ca and servername.

socketPath dials a Unix domain socket in the net unit; the agent keys
its sockets by the path as Node's getName does, and the Host header
defaults to localhost. server.listen(path[, cb]) binds a Unix socket and
removes the socket file when the server closes; a numeric string is
still a port. Errors name the path ("connect ENOENT /path", "listen
EADDRINUSE: address already in use /path"). Windows reports ENOTSUP.

A TypeScript object literal with no contextual type that spreads a
checked-dynamic value maps to the checked dynamic, so
`const options = { ...location, path, timeout }` compiles.

A socket's 'lookup' event reaches its listeners with (err, address,
family, host) for each address a host name resolves to, or once with
the lookup error, before 'connect'. Only programs that listen for
'lookup' install the lookup records; elsewhere the hook sites are a NULL
check.

server.close((err) => ...) runs the callback with undefined at 'close',
or with ERR_SERVER_NOT_RUNNING when the server was not listening; a
server that never listened now emits 'close'. IncomingMessage 'data'
listeners may take string chunks after setEncoding, and res.end()
accepts a string-or-undefined chunk.

fetch's BodyInit and HeadersInit unions, as RequestInit-derived option
types spell them under @types/node, map to the checked dynamic, and a
URLSearchParams body is sent form-encoded, as by Node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 02:57:13 -07:00
Malte UblandClaude Opus 5.5 7cc8179a22 Close a bridged child stdin on destroy and keep stream listener typing untyped
The fallback NodeJS stream interfaces declare Node's EventEmitter listener
signature for events beyond data/end, so checked JavaScript keeps its
contextual typing for process stream listeners. The child stdin fence
fixture becomes a differential test of the forms that now compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 02:31:27 -07:00
Malte UblandClaude Opus 5.5 915c0f63c5 Request the general stream representation where a stdio handle meets the stream surface
child.stdout.pipe(), stream events and writes beyond write(string) on a
NodeJS stream interface slot, and pipes into a child's stdin now lower
the program with the general representation instead of fencing. The
fallback ChildStdin is a NodeJS.WritableStream, and the coverage
remainder relowers its unreached code the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 01:40:28 -07:00
Malte UblandClaude Opus 5.5 08fb421628 Compile NodeJS stream interfaces as general streams when other streams flow into them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 01:27:17 -07:00
Malte UblandClaude Opus 5.5 f4c6441cee Merge main (through opt/variadic-generic-wrappers) into opt/trace-reachable-blockers
Main replaced the runtime-feature scan with a rule table, the executable
unit list with a unit table and the module emission with emit-module.ts:
perfLoop becomes a rule (perf.idleTime, perf.loop*, perf.eld*), a unit
(scr_perf_loop.c) and emit-module's loop-start mark (readsLoopMetrics is
now public). The feature lists take both perfLoop and main's webcrypto.
This branch's lower-exprs.ts hunks move to expressions/property-access.ts
(histogram readings), expressions/binary.ts (`??` with a function
default) and expressions/relational.ts (`in` over class members); the
caughtRead fallback stays in lower-exprs.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 00:10:52 -07:00
Malte Ubl 25e40afa83 Merge remote-tracking branch 'origin/main' into opt/bc-node-surface 2026-10-19 23:16:41 -07:00
Chris Tate 98a7d3b33d Merge main 2026-10-20 00:08:29 -05:00
Malte UblandClaude Opus 5.5 762718a254 Compile TLSSocket.isSessionReused, keyed short-circuit assignment and Object.assign into class instances
- TLSSocket.isSessionReused() is declared in the fallback types and lowers
  to false: the TLS client never offers a cached session (no session
  resumption is a documented divergence), so no handshake resumes one.
- `o[k] ??= v`, `||=` and `&&=` through a pure index-signature record with
  a string key use the keyed read and write `o[k]` and `o[k] = v` lower to.
- Object.assign(instance, record) writes the record's fields into the
  class instance's declared fields (same or width-compatible types;
  optional source fields only when present) and answers the instance.
- Object.assign({}, instance) whose result the checker types as the class
  is refused at compile time: the copy is a plain object, so the checked
  cast into the class threw at run time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:26:47 -07:00
Malte UblandClaude Opus 5.5 c17eec0261 Compile event-loop metrics, predicate-narrowed catch bindings and other wrapper-reachable gaps
Once generic wrappers compile (#1413), the code behind them is reachable.
This closes the general gaps found there:

- performance.eventLoopUtilization() and monitorEventLoopDelay()'s
  IntervalHistogram (enable, disable, reset, percentile and the min, max,
  mean, stddev, count and exceeds readings), under the fallback
  declarations and @types/node. A new runtime unit, scr_perf_loop.c, links
  only for programs that read them (the perfLoop feature): an unref'd
  sampling interval records into HdrHistogram-shaped buckets, and
  utilization measures active time as the main thread's CPU time since
  the loop started.
- Catch bindings narrowed by a user type predicate or an assertion read
  their members through the checked-dynamic value.
- `??` with a function default of a different signature takes the
  optional callback's own function type and adapts the default.
- Optional calls on interface-typed receivers dispatch like the plain
  protocol call.
- `any` parameters of function declarations and spelled function types
  are checked-dynamic slots, and a generic instantiated at `any` takes
  `unknown` there.
- `'key' in err` on Error receivers answers from the declaring subclasses.
- Object.entries over a generic record resolves
  `keyof T extends never ? unknown : T[keyof T]` through the binding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:04:07 -07:00
Malte UblandClaude Opus 5.5 20ab1c0531 Merge main into opt/bc-node-surface
Resolve the conflicts with main's process.features value, the WebCrypto dynamic types, the NODE_COMPAT_VERSION import and the symbol.declarations API. Renumber this branch's corpus programs to 6420-6429, write the new limitations partial one sentence per line, and regenerate the compatibility outputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:02:41 -07:00
Malte UblandClaude Opus 5.5 503154e387 Compile the boot-path Node surface: process.send presence, process.exitCode reads, wider stream hooks, void race entries, RequestOptions and promisify of callbacks
- `if (process.send)`, `Boolean(process.send)`, `!process.send` and `typeof process.send` answer whether the process has an IPC channel (a fork channel this binary opened, or NODE_CHANNEL_FD from a Node.js parent). The same holds for process.disconnect.
- In a program without fork targets, `process.send?.(...)` answers undefined, and a direct call throws Node's TypeError when there is no channel. A Node.js parent's channel has no lowering, so a call fences when it runs. `process.send!(...)` lowers like the direct call.
- process.exitCode reads answer the assigned code, or undefined. Only programs that read it record assignments, including process.exit(code) before the 'exit' listeners run. Other programs keep the untracked write.
- A stream subclass hook may declare a supertype of Node's argument (`_write(chunk: Buffer | string, ...)`): the wrapper takes Node's Buffer and widens it.
- Promise.race accepts a Promise<void> entry when the result holds undefined.
- http.RequestOptions and https.RequestOptions as declared types ride checked-dynamic storage, like SpawnOptions.
- util.promisify over a typed callback-last function value (a bound method, a declaration, an arrow) builds a native promisified function. A truthy error rejects, the value fulfills, and a synchronous throw rejects.
- The bundled Node declarations gain the callback-only generic promisify overloads. Before this, `promisify(obj.close.bind(obj))` matched crypto.randomFill's overload and reported "Expected 1-3 arguments".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:46:46 -07:00
Chris Tate 37f54ff157 Merge main 2026-10-19 17:14:32 -05:00
Chris Tate c82b6d8188 Merge main 2026-10-19 17:06:58 -05:00
Chris Tate 1f07166fbf Merge main 2026-10-19 08:56:48 -05:00
Chris Tate 178646baf0 Merge main 2026-10-19 08:31:43 -05:00
Chris Tate a57089aebf Accept readline's dispose, instanceof, dynamic streams and non-string prompts
rl[Symbol.dispose]() closes the interface, as Node's dispose method
calls close(). rl instanceof readline.Interface and
readlinePromises.Interface answer which module created the interface:
rl.create's mode marks readline/promises interfaces, and the fallback
declarations declare both Interface classes as values.

In JavaScript, createInterface's input and output can be checked-dynamic
values (a function's result, an object's member, an element that may be
undefined): rl.inputFromDyn and rl.outputFromDyn unbox the stream they
hold, an output of null or undefined means no output, and other values
are refused.

In JavaScript, question() and setPrompt() accept a value that is not a
string. When such a prompt is written, an interface that is not a
terminal throws ERR_INVALID_ARG_TYPE as Node's kWriteToOutput does, and
the readline/promises question rejects with it; the question stays
pending and the previous prompt returns when it is answered. A terminal
interface writes String(value) of a primitive.

Corpus 5876-5878 match Node v24.22.0.
2026-10-19 07:51:54 -05:00