A pipeline whose first stage is a checked-dynamic value now checks it at
run time, as Node's stage ladder does: a stream is piped as before, and a
string or a value with a Symbol.asyncIterator or Symbol.iterator method is
pumped into the next stage through an async generator over its iterator.
A typed Set, Map, generator or async generator object as the first stage
takes the same path. This covers the callback and stream/promises forms,
with or without function stages and pipeline options.
A write whose callback fails synchronously no longer sets needDrain, so no
'drain' follows the error and a pumped source stops at the failed write,
as in Node.
RUNTIME_ABI_VERSION goes from 37 to 42 for scr_stream_dyn_iterable_source.
Partitions were filled by a hash of each function's name, so most calls
crossed partitions and the thin link imported their small callees into
nearly every partition. The emitter now writes a "; scriptc-group" line
before the functions of each source file, and the text partitioner places
a group's functions together: a group larger than the mean partition, or
than 1 MiB, is divided into a power of two of chunks by name, and chunks
go, largest first, to the lighter of two partitions chosen by hash. The
1 MiB bound keeps the code a partition optimizes together, and the
inlining within it, from growing when a program has fewer partitions.
Modules with fewer than 32 partitions, and functions without a group,
keep their name-hash placement: with few partitions per core, the balance
of the largest partitions decides the build time more than the imports.
The placement still depends only on the module text and the partition
count.
The checker resolves an overloaded call whose argument is `any` to the
first overload that argument satisfies, but in JavaScript the value can
select another one: generateKeyPairSync("ec", options) returns KeyObjects
or PEM strings by the options, and digest(encoding) returns a Buffer when
the encoding is undefined. The result was converted to the first
overload's return type, so such calls threw a TypeError where Node
returns the other overload's value.
When a checked-dynamic argument could take another overload whose return
type differs (trailing untyped or undefined arguments may also be
absent), the call's result in a JavaScript source is checked-dynamic. So
are the unannotated bindings it initializes, destructured or not, and
the unannotated functions that return it. fs.globSync keeps choosing its
result form from the resolved overload, since the runtime checks that
withFileTypes agrees with it.
An executable's LLVM text was divided into one partition per 4 MiB, so a
program under 4 MiB was optimized and compiled on one thread, and one of
up to 32 MiB used fewer than eight cores. A module over 1 MiB now gets at
least eight partitions of 512 KiB or more: four up to 2 MiB, and eight up
to 32 MiB. Larger modules keep one partition per 4 MiB. The count still
depends only on the module's size.
existsSync and the fs.promises functions accept a file: URL wherever
they accept a path. They convert it after their arguments are evaluated,
and a URL that does not convert gives false from existsSync and a promise
rejected with fileURLToPath's error from fs.promises, as in Node.
copyFileSync and renameSync check a string source for null bytes before
they convert a URL destination, and readFileSync checks a runtime
encoding before it converts a URL path, so the error Node reports first
is the one thrown.
Refs #1616
Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
X25519 KeyObjects come from generateKeyPair(Sync)("x25519"), which keeps
the private key clamped as OpenSSL does, and from createPrivateKey and
createPublicKey of PKCS#8, SubjectPublicKeyInfo, JWK (OKP, X25519) and
raw keys. They export in the same forms. sign, verify, createSign and
createVerify throw OpenSSL's "operation not supported for this keytype",
with its library, reason and code properties. X25519 uses mbedTLS's
Curve25519 group.
crypto.diffieHellman({ privateKey, publicKey }[, callback]) computes the
X25519 and ECDH secrets of two keys of one type, given as KeyObjects or
in any form createPrivateKey and createPublicKey read. The checks run in
Node's order: the options, the callback, both keys present, the key types
when both are KeyObjects ("Incompatible key types for Diffie-Hellman"),
then the public and private key inputs. Mismatched curves, a small-order
X25519 point and key types other than EC and X25519 throw OpenSSL's
errors. The callback form passes the secret, or the error without the
OpenSSL properties, in a later macrotask, as Node's DHBitsJob does.
createPublicKey also reads a private key's DER encodings (pkcs8 and
sec1), which Node accepts there.
EC and Ed25519 keys read and write Node 24's raw formats:
- generateKeyPair(Sync) encodings: raw-public gives the EC point,
uncompressed or, with type "compressed", compressed, or the Ed25519
public key; raw-private gives the EC scalar at the curve's size or the
Ed25519 seed.
- KeyObject.export({ format: "raw-public" | "raw-private" | "raw-seed" }),
with Node's check of the point type, and Node's error for a passphrase
with any format other than PEM and DER, which now also covers JWK.
- createPublicKey and createPrivateKey of { key, format,
asymmetricKeyType, namedCurve }, in Node's argument order, with
compressed EC points, and createPublicKey of a raw private key.
As in Node, raw-seed and every raw format of an RSA, RSA-PSS, DSA or DH
key throw ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS, which generateKeyPair
passes to its callback. Invalid key data throws ERR_INVALID_ARG_VALUE.
Raw X25519, X448, Ed448 and post-quantum keys, EC scalars of 0 or at
least the curve order, and the EC point at infinity, which Node accepts,
throw a coded SC2020 error.
Release builds compile for the x86-64 baseline, so LLVM vectorizes with
SSE2 only. `--target-cpu=<baseline|x86-64-v2|x86-64-v3|x86-64-v4|native>`
compiles the program's code for a higher level: every emitted function
carries the level as its `target-cpu`, so LLVM can use AVX2, BMI2, FMA or
AVX-512. The executable then runs only on CPUs of that level.
- `native` resolves to the highest level the build machine supports, read
from /proc/cpuinfo on Linux and `sysctl machdep.cpu` on macOS.
- The level is part of the executable cache key; `baseline` and builds
without the option produce the same output and keys as before.
- The runtime pack keeps its baseline code.
- Targets other than x86-64 refuse a level (SC3002). The CLI's cached
bootstrap route leaves builds with the option to the full compiler.
- `bench:runtime` takes `--baseline-target-cpu` and `--candidate-target-cpu`.
A codec stored in untyped storage (hono's StreamingApi keeps
`this.encoder = new TextEncoder()` in a JavaScript class field) had no
dynamic representation and threw SC1101 at run time. The codec records
now cross 'unknown' slots as handles of two new tags that hold the record
itself, so identity and a decoder's streaming state survive the round
trip, and checked casts unbox the same record.
The handles answer encode, encodeInto and decode (with options objects),
the encoding, fatal and ignoreBOM properties, method values with Node's
ERR_INVALID_THIS, instanceof, String() tags and JSON's {}. The unit
scr_text_codec_dyn.c links only into programs that convert a codec to or
from an untyped value (the textCodecDyn runtime feature, found with the
dgram carrier walk, now shared).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hover and keyboard focus now open the tooltip separately, as the
CSS-only tooltip's hover and focus-visible rules did, so moving the
pointer off a focused badge no longer unmounts its tooltip or drops
aria-describedby. Escape still dismisses it.
The matrix mounted every badge's tooltip up front, hidden by CSS, and
re-rendered every row on each keystroke. Tooltips now mount while their
badge is hovered or has keyboard focus, are named by aria-describedby
and close on Escape. Badges and rows are memoized, each row's search
text is built once, the filter makes one pass for its rows and its
count, and the table follows deferred search and status values, with
expand all and collapse all as transitions, so input stays responsive.
The tree and filter passes move to src/lib/compatibility-tree.ts, with
unit tests that also render the badges on the server (pnpm test:unit,
part of pnpm check).
Closes#601
Co-authored-by: jonbaldie <8376953+jonbaldie@users.noreply.github.com>
'new TransformStream()' had no lowering, so hono's stream() and
streamSSE() helpers failed to compile their checked-dynamic paths. The
constructor without arguments now builds a native handle: its readable
side is a native ReadableStream with a zero high-water mark, and its
writable side runs the streams spec's WritableStream state machine
(getWriter, abort, close, locked; the writer's write, close, abort,
releaseLock, ready, closed and desiredSize). A write completes when the
readable side reads its chunk, close/abort/cancel propagate across the
pair, and deferred reactions take as many microtask turns as in Node.
Web ReadableStreams can also be weak collection keys (hono keys a
WeakMap by the response stream). A transformer, queuing strategies and
the WritableStream constructor keep the SC2020 refusal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #1777
An identifier-minified esbuild bundle renames the __commonJS helper
(var j=(u,t)=>()=>(t||u((t={exports:{}}).exports,t),t.exports)). The
recognizer already compared the helper's shape independently of its
parameter names, but only used a renamed match to refuse the package.
A stable top-level declaration with the helper's shape now splits the
bundle's chunks like the named helper, so lru-cache's CommonJS build is
no longer refused.
Refs #1777
npm packages are no longer refused up front for minified JavaScript. A
bundle whose interop helpers lost their names is still refused by the
bundle recognizers, and a package whose attempt fails is still refused on
its own.
A `var` read in a later declarator of the statement that stores it
(`var a = {...}, b = {...a}`) runs after the store. A read in a function
body is now located at the body's own statement instead of the body, so
JavaScript `var` bindings read after their store in a function keep their
type instead of gaining undefined.
`replace` and `replaceAll` with an untyped search value and a callback
call the regex callback replacement for a RegExp and the string-search
helper otherwise. That helper now accepts untyped callback parameters,
passes undefined to parameters after the subject, and converts number,
boolean and untyped results with ToString.
In JavaScript, `||` and `&&` over primitives of different types whose
result tsc types `any` evaluate in the checked domain.
child_process and http2 events ran with no store, or with the context of
whichever socket dispatch delivered them. Node runs them in the context
of the handle or request that produces them.
child_process: a child, its piped stdout, stderr and stdin, and its IPC
channel keep the context of the spawn() or fork() call. 'spawn',
'error', 'exit', 'close', stdout's and stderr's 'data' and 'end', and the
channel's 'message' and 'disconnect' run in it, in the POSIX and the
Windows implementations. stdin's 'drain' and 'error' run in the context
of the latest write() call, its 'finish' in the context of its end()
call, and a send() callback in the context of its send() call.
http2: a session keeps the context it was created in, the
http2.connect() call for a client and the server's listen() context for
a server session, and the session's socket callbacks and deferred emits
run in it. A client stream keeps the context of its request() call, and
the frames that drive a stream's events (DATA, WINDOW_UPDATE, RST_STREAM,
and a client's HEADERS) and its deferred emits run in the stream's
context. A session remembers the stream its last lookup by id found, so
the context lookup and the frame's own handling share one search.
A server stream and its compatibility request and response run with no
store, as Node's do. An accepted h2c socket's own events run with no
store, as an accepted net socket's do, so a server.close() that waits for
its sessions calls back with no store; a TLS server's sockets keep the
listen() context, as before.
Corpus 7385 to 7389.