$ the-wire · showcase
Node loads most ES modules synchronously
By RepoJournal · Filed · About Node.js · Composed from the cited sources · methodology
Node.js extends the synchronous require(esm) path to every ES module without top-level await, while two QUIC validation bugs and a SQLite abort path get tightened up.
module: synchronously load most ES modules nodejs/node
The path Joyee Cheung built for require(esm) now resolves and loads any ES module lacking top-level await synchronously, the vast majority of modules. The sync path applies only when no async loader hooks, --import flags, or --inspect-brk are active, and the async path still handles the rest; because top-level await can only be seen after the graph is instantiated, a detected TLA falls back fro...
watch: strip underscore aliases of watch flags nodejs/node
Watch mode compared flag spellings literally when stripping its own options from process.execArgv and NODE_OPTIONS, but the C++ parser treats _ and - as the same character, so --watch_path survived and each child re-entered watch mode and spawned another child, leaving the application never running. Option names are now normalized before comparison.
sqlite: throw on oversized strings instead of aborting nodejs/node
Several SQLite text-to-V8 conversions passed a length of -1 to String::NewFromUtf8(), which makes V8 skip its length check and abort the process once UTF-8 text exceeds String::kMaxLength. Error messages embedding the offending identifier or token, and the setAuthorizer() callback path, can now throw instead of taking the process down.
quic: validate session close error codes nodejs/node
session.close() and session.destroy() only checked that options.code was a bigint or number, while QUIC error codes are 62-bit varints, so invalid values went out as other codes: on x64, 1.5 as 1, -1 as 2**62 - 1, and NaN, Infinity and 2n**62n reached the peer as NO_ERROR, turning an error close into an apparently clean one.
quic: destroy stream on invalid promise body nodejs/node
stream.setBody(Promise.resolve(42)) killed the process with an unhandled rejection, where setBody(42) throws ERR_INVALID_ARG_TYPE synchronously. The rejection handler in configureOutbound() only covered the body promise itself rejecting, so an error thrown from the fulfillment handler's recursive call went unhandled; the stream is now destroyed.
chore: Vendor milo 0.9.0. nodejs/undici
undici vendors milo 0.9.0 into the tree, so the build no longer downloads it from npm.