Commit Graph
3704 Commits
Author SHA1 Message Date
Chris Tate 73778e8496 WebAssembly W3–W4: translate modules to native code at build time, implement the JavaScript API over them, and send modules to workers (#1395) 2026-10-20 11:06:25 -05:00
Chris Tate 25780d9231 Merge main 2026-10-20 11:03:09 -05:00
Chris Tate 8c40f92019 Merge main 2026-10-20 11:00:03 -05:00
Chris Tate 8eb5ad28e5 Keep WebAssembly references and memory storage alive while they are in use; merge main
Externrefs a guest holds are borrowed pointers. An import's result was
kept only until the outermost call returned, which was before the export
call converted its results to JavaScript, so a result created by an
import was freed before conversion. A table or global slot released the
reference it replaced at once, although the guest may still hold it in a
local after reading the slot. The kept references are now released after
the outermost caller has converted its results (scr_wasm_leave), and a
table or global store during a call keeps the reference it replaces until
then.

Checked memories (explicit bounds checks: sanitized builds, Windows)
grew with realloc, which can move the storage that memory.buffer and its
views alias. They now reserve the address space for their largest size
(mmap on POSIX hosts, VirtualAlloc on Windows) and commit pages as they
grow, so the base never moves. Hosts without address-space reservation
grow in place only until a buffer has been handed out; after that,
growth that would move the storage fails.

Tests: webassembly-externref-lifetimes.mjs (import results through an
export, table and global references replaced by the guest and by
JavaScript), webassembly-memory-growth.test.ts (views written after
growth from JavaScript and from the guest), and translate.test.ts cases
for memargs naming memory 0 explicitly and for local.tee operand types,
which b3bcbaaf7 made consistent with validation. Under SCRIPTC_SAN=1 the
two runtime tests report heap-use-after-free without these changes.

Merges main; internal/compatibility/generated/node-v24-backlog.json is
regenerated with pnpm node-compat.
2026-10-20 10:58:34 -05:00
Chris Tate 33354cc481 Abort the request of a redirect that fetch follows or rejects
A redirect fetch followed or rejected was marked to drain: its body was
read and dropped until the server ended it, and the abort listener was
already removed. A body that never ends kept the connection busy after
cancellation and stalled a pool of one connection. Following or
rejecting a redirect now aborts its request, so the connection closes.
undici 7 leaves that connection open with its body paused, which stalls
the same pool; the follow-up request here gets a new connection.
2026-10-20 10:50:19 -05:00
Chris Tate 8aca6d653d Abort the request of a redirect that fetch follows or rejects
A redirect fetch followed or rejected was marked to drain: its body was
read and dropped until the server ended it, and the abort listener was
already removed. A body that never ends kept the connection busy after
cancellation and stalled a pool of one connection. Following or
rejecting a redirect now aborts its request, so the connection closes.
undici 7 leaves that connection open with its body paused, which stalls
the same pool; the follow-up request here gets a new connection.
2026-10-20 10:48:36 -05:00
Malte UblandClaude Opus 5.5 d883c84752 Add corpus programs for events.once with a signal, over streams, and in races
6490 covers events.once with an AbortSignal: abort, an aborted signal, an
undefined signal, abort-listener order, 'removeListener' events, a
throwing 'newListener' listener and the settlement turns. 6491 covers
stream receivers (file streams, Readable.from, a destroyed PassThrough, a
Writable) and a NodeJS.ReadableStream part raced against its destination.
6492 covers races over events.once results with entries that only reject
and entries of different value types. 6493 covers stream subclasses whose
completion callbacks are typed `Function`. 6494 covers events.once over
checked-dynamic stream slots. The node-types fixture runs the race shapes
under @types/node, where events.once returns Promise<any[]>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:48:00 -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
Malte UblandClaude Opus 5.5 67ace26573 Unbox native streams for events.once over checked-dynamic stream slots
Under checked-dynamic NodeJS stream slots, events.once over a
NodeJS.ReadableStream or NodeJS.WritableStream slot unboxes a native
stream by identity and takes the stream path; any other value throws the
not-supported Error that for await and pipeline stages already throw for
JavaScript stream objects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:53 -07:00
Malte UblandClaude Opus 5.5 09f427c4fe Accept Function-typed completion callbacks in stream underscore methods
A stream subclass that declares `_transform(chunk, encoding, cb: Function)`
(or _write, _final, _destroy, _flush with a broad `Function` callback) was
rejected because 'Function' has no lowering, which also blocked every
construction of the class. The callback parameter now takes the
checked-dynamic callable the runtime already passes implicitly typed
callbacks, and calls through it are dynamic calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:52 -07:00
Malte UblandClaude Opus 5.5 2630e8438a Combine Promise.race entries whose combined type has no representation
When the checker's combined type has no representation (events.once's
any[] arrays, or 'void | any[]'), the race result takes the one type the
entries that can fulfill share, or 'unknown' when each of them widens into
it; Promise<never> entries do not take part. An entry whose payload widens
into the result type converts through the checked promise payload
widening, which keeps its settlement turn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:52 -07:00
Malte UblandClaude Opus 5.5 2429eaf556 Admit Promise<never> race entries (the race part of main's 465abda81)
The Promise.race portion of 465abda81 on main, applied unchanged so the
race changes that follow build on it and merge with main cleanly: a
Promise<never> entry can only reject, so it races under any result type
and its fulfillment adapter traps; a Promise<never> executor's
one-parameter resolve validates against the void inner. Includes that
commit's corpus program 6450.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:52 -07:00
Malte UblandClaude Opus 5.5 c7b2620e5c Compile events.once with an AbortSignal option and over stream receivers
events.once(emitter, name, { signal }) lowers to events.onceSignal, served
by a new runtime unit (scr_events_once_signal.c, linked only through the
eventsOnceSignal feature). It follows Node 24's lib/events.js: an
undefined signal is the plain form, a value that is not an AbortSignal
rejects with ERR_INVALID_ARG_TYPE, an aborted signal rejects with an
AbortError whose cause is signal.reason, and otherwise a once,
resist-stop-propagation 'abort' listener removes the event and 'error'
listeners and rejects. The event or the error removes the abort listener.
Options other than an object literal with one signal stay refused.

events.once now accepts stream receivers: a stream's runtime-emitted
events use their fixed tuples, and its 'data' and 'keypress' events stay
refused. A NodeJS stream interface slot that holds a stdio handle requests
the general stream representation.

Node's once is an async function that returns the executor's promise, so
its result adopts that promise through a thenable job. The plain form
settled its result two turns early; both forms now settle on Node's turn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:51 -07:00
Chris Tate d1c516a337 Implement fs-extra as a built-in package; hoist lazily defined error classes (#1504) 2026-10-20 10:41:35 -05:00
Chris Tate b5e7c23b93 Merge main 2026-10-20 10:38:47 -05: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 313a984066 Keep regular destination files when fs-extra's copy meets a symlink source
copy and copySync now follow fs-extra's onLink: only a destination that
is itself a symlink is replaced; over a regular file or directory the
symlink call fails with EEXIST and the destination is kept, whatever
overwrite says. The fs-extra corpus program covers both forms.
2026-10-20 10:36:00 -05:00
Malte UblandClaude Opus 5.5 e5b9102e0d Compile compound assignment, ++/-- and ??= through literal-union and index-signature record keys
`totals[side] += n`, where `side` is a union of string literals naming
declared fields of one type, now dispatches over those fields: the
receiver and key evaluate once, the old value is read from the field the
key names, then the right side, then the write to that same field. Every
compound operator, prefix and postfix ++/--, and ??=/||=/&&= share the
path. A single literal key (spelled at the site or carried by a const)
reads and writes the field directly. A key smuggled outside its literal
type throws the fixed-shape TypeError of a keyed write miss.

A string key into a pure index-signature record (`counts[name] += 1`,
`counts[name]++`) reads the entry, NaN for a missing one under numeric
operators, and inserts or replaces it.

Keys naming fields of different types, class instances and JavaScript
sources keep their refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:32:19 -07:00
Chris Tate 200fe8d220 Read http.request options at run time, speak HTTP over Unix sockets, and fill the boot path's net and fetch gaps (#1515) 2026-10-20 10:28:21 -05:00
Chris Tate 89f8dbe9e0 Merge main 2026-10-20 10:23:43 -05:00
Chris Tate a2a6764ce0 Merge opt/variadic-generic-wrappers 2026-10-20 10:22:57 -05:00
Chris Tate 23355baa2c Merge main 2026-10-20 10:22:00 -05:00
Chris Tate 7d35fee688 Validate flat request header arrays and drop lookup listeners when a socket closes
- http.request, https.request and get validate each name and value of a
  flat [name, value, ...] headers array, as Node's _storeHeader does: a
  name that is not an HTTP token throws ERR_INVALID_HTTP_TOKEN, a value
  with an invalid character throws ERR_INVALID_CHAR, and an odd length
  throws ERR_INVALID_ARG_VALUE with the inspected array. The
  [[name, value], ...] entry form throws the options fence.
- A closing socket drops its 'lookup' listeners with its other listeners,
  so a listener that holds the socket no longer keeps it alive.
- The options-record diagnostics snapshot no longer expects the
  socketPath refusal.
2026-10-20 10:21:03 -05:00
Chris Tate e0b131c0f9 Merge main into opt/variadic-generic-wrappers 2026-10-20 10:19:08 -05:00
Chris Tate 7dd13e4ddd Serve Temporal's absence, v8, stream/web, dns/promises, EvalError and graceful-fs (#1318) 2026-10-20 10:17:15 -05:00
Chris Tate da476df676 Merge main 2026-10-20 10:11:51 -05:00
Malte Ubl aaf1e83ad8 Merge remote-tracking branch 'origin/opt/npm-polyfill-shims' into opt/npm-fs-extra-shim 2026-10-20 08:08:36 -07:00
Chris Tate efb54c4f58 Write the byte order mark in a corpus test as an escape (#1525) 2026-10-20 10:01:12 -05:00
Malte UblandClaude Opus 5.5 4470bab308 Give the undici shim's Dispatcher an explicit constructor
The implicit constructor forwarded its arguments to EventEmitter's options-taking constructor, which compiles to a deferred runtime fence. Dispatcher takes no options, so it calls super() directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 07:58:16 -07: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 da0f6b642b Merge main 2026-10-20 09:52:32 -05:00
Chris Tate c91bfea743 Compile object literals that spread index-signature records, unknown spreads, and union-of-records results (#1505) 2026-10-20 09:51:27 -05:00
Chris Tate 2330953ebe Write the byte order mark in a corpus test as an escape 2026-10-20 09:49:10 -05:00
Chris Tate 5ea3df1244 Merge main 2026-10-20 09:47:20 -05:00
Chris Tate bec87d6ac5 Compile mixed-tuple Promise.all, Boolean callbacks, enum key lookups and nullable regex receivers (#1500) 2026-10-20 09:40:13 -05:00
Chris Tate 6a658c6ae3 Compile the remaining safe-fetch shapes: Promise<never> race entries, typed Array(n).fill, narrowed header entries, lookup option unions and CommonJS export aliases (#1521) 2026-10-20 09:38:23 -05:00
Chris Tate cb99a06fe5 Shadow the export alias only in the scope that declares it again
The export-alias rewrite skipped a whole function when a let or const
anywhere inside it declared the alias's name, so the function's other
references to the alias kept the alias name after its declaration was
removed. A function now shadows the alias only through its parameters,
its own name, its vars and the declarations directly in its body; a
block, case block, catch clause or for loop shadows it through its own
declarations, and the walk skips just that scope.
2026-10-20 09:35:14 -05:00
Chris Tate 39e3b4a5dd Adopt thenable entries and place tuple slots by position in mixed Promise.all
- A checked-dynamic entry of a tuple Promise.all goes through
  PromiseResolve (`dyn.promiseResolve`): a native promise is itself, a
  thenable adopts its settlement through its resolve job, and any other
  value fulfills. Before, a thenable fulfilled the slot with the object.
- Tuple fields read their entry by position. Shape fields are sorted by
  name, so tuples of more than ten entries paired fields with the wrong
  entries.
2026-10-20 09:34:19 -05:00
Chris Tate 90ff0af5b7 Merge main 2026-10-20 09:33:27 -05:00
Chris Tate 53f41e1a09 List an error's own name where it was created (#1482) 2026-10-20 09:31:04 -05:00
Chris Tate e6ca194308 Merge main 2026-10-20 09:26:26 -05: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
Malte UblandClaude Opus 5.5 2081aaa721 Compile readable-stream 3.x as Node's stream module too
readable-stream 3.x is a copy of Node 10's streams. Like 2.x and 4.x it
now compiles as node:stream: readable.js as stream.Readable carrying the
stream classes, Stream, finished and pipeline, and lib/_stream_*.js as the
matching builtin classes. Unlike them, this is not the package's own
READABLE_STREAM=disable mode, which throws on Node 24 (it Object.assigns
every stream export onto stream.Readable, which inherits the getter-only
`promises` accessor). The limitations and dependencies pages and the
compatibility notes say so.

The corpus program readable-stream-3 runs the vendored 3.6.2 under Node and
keeps to behavior its streams share with the builtin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 07:22:27 -07:00
Chris Tate 575f6491f4 Fix silent wrong output: object identity, Object.prototype values, Date parsing, stored builtins (#1336) 2026-10-20 09:18:37 -05:00
Chris Tate 56de47defc Check programs with tsc-ts by default (#1353) 2026-10-20 09:12:30 -05:00
Chris Tate 0ccb58943a Compile esbuild's lazily initialized ES modules; select @types-typed and untyped dependencies by default (#1422) 2026-10-20 09:06:46 -05:00
Chris Tate 68a3d8f846 Merge main 2026-10-20 09:06:21 -05:00
Chris Tate 7d555c4cf3 Merge main 2026-10-20 09:04:02 -05:00
Chris Tate 55f4eaca5b Merge main 2026-10-20 09:02:52 -05:00
Chris Tate 7cd7b483bf Merge main 2026-10-20 09:02:06 -05:00