Commit Graph
248 Commits
Author SHA1 Message Date
Chris Tate 1cd06fda4c Read events.defaultMaxListeners from the ES module namespace copy
Reads of defaultMaxListeners through an ES module namespace import or a
named import answer the namespace's copy of the export, which keeps its
value from program start until module.syncBuiltinESMExports() refreshes it,
as in Node. The default import, the EventEmitter class and CommonJS module
bindings keep reading the current default. A destructured CommonJS binding
of defaultMaxListeners, which held a placeholder string in JavaScript
files, is refused.
2026-10-18 07:44:23 -05:00
Chris Tate 89b5baedd7 Add t.assert.snapshot and t.assert.fileSnapshot
node:test changes, matching Node 24.22:

- t.assert.snapshot(value[, options]) serializes the value with Node's
  default serializer, JSON.stringify(value, null, 2), or with an
  options.serializers array literal applied in order, and compares it
  with assert.strictEqual against the snapshot stored under
  "<test full name> <n>" in "<entry file>.snapshot".
- t.assert.fileSnapshot(value, path[, options]) compares the serialized
  value with the contents of path.
- Snapshot files are read in the form Node writes them, exports[`key`] =
  `value`; statements, with template escapes and CRLF line endings
  cooked as in a template literal.
- Missing snapshots, unreadable snapshot files and throwing serializers
  throw Node's ERR_INVALID_STATE errors, with Node's messages.
- Running the binary with Node's --test-update-snapshots flag as its
  first argument records the values and writes the snapshot files after
  the last test, keys sorted as Node sorts them. The flag is kept out of
  process.argv and appears in process.execArgv, which is otherwise [].
- Snapshot assertions count toward the test's plan.

The snapshot fixture compares the reporter output with Node, plain and
with SCRIPTC_SAN=1, against a snapshot file Node wrote. The update-mode
harness test runs Node and the binary with --test-update-snapshots and
compares the files they write. The node:test normalization also drops
the "... N lines matching cause stack trace ..." line Node prints for an
error cause, with the stack frames it summarizes.
2026-10-18 05:31:40 -05:00
Chris Tate ffd760bfa2 Merge main 2026-10-18 04:55:11 -05:00
Chris Tate a0b1e93dec Merge main 2026-10-18 03:52:20 -05:00
Chris Tate 51777dee63 Add markAsUncloneable and worker[Symbol.asyncDispose]
markAsUncloneable(value) marks a plain object, a record, an error or a
class instance (scr_json.c); structuredClone and postMessage then throw
DataCloneError "Cannot clone object of unsupported type." for it, also
where it is nested. As in Node, the mark has no effect on primitives,
arrays, typed arrays and ArrayBuffers. Marked values are retained until
the thread exits; with nothing marked, the clone paths add one branch.

worker[Symbol.asyncDispose]() terminates the worker and resolves with
undefined after its 'exit' event, so `await using` disposes a Worker at
the end of its block. The Worker handle's symbol_get op answers the
well-known symbol: the symbol unit registers Symbol.asyncDispose with the
dyn core when the program names it, and scr_dyn_is_async_dispose_symbol
tells the worker unit, so worker programs that never name the symbol do
not link the symbol unit.

static-support.json adds rows for markAsUncloneable, isInternalThread
(already lowered as false and declared) and worker[Symbol.asyncDispose]().

Corpus 5990-5991 match Node v24.22.0; corpus-costs.json records their
costs.
2026-10-18 03:43:06 -05:00
Chris Tate d7ac6d3165 Merge main 2026-10-18 03:17:25 -05:00
Chris Tate 9750d3994a Merge main 2026-10-18 01:21:52 -05:00
Chris Tate 58e6396a1d Merge main 2026-10-18 00:42:37 -05:00
Chris Tate 7804e62041 Merge main 2026-10-18 00:39:44 -05:00
Chris Tate d6bb761ede Merge main 2026-10-18 00:37:03 -05:00
Chris Tate f4daa00d5c Merge main 2026-10-17 21:59:33 -05:00
Chris Tate aad9b4f140 Merge main 2026-10-17 21:01:15 -05:00
Chris Tate 8d8b96fefa Merge main 2026-10-17 20:59:05 -05:00
Chris Tate a5c7c09ad3 Add mock.timers to node:test 2026-10-17 20:55:17 -05:00
Chris Tate 1ad47f1f77 Match Node 24 in util.format, util.types and util.inspect
- util.format %d and %i format bigint, symbol, null and undefined arguments
- util.format %j prints [Circular] for circular arguments
- util.types answers the remaining brand checks
- util.inspect prints WeakMap, WeakSet, Date and numeric typed array values as Node does
- util.inspect lowers the breakLength, compact and sorted options
2026-10-17 17:58:40 -05:00
Chris Tate 2ba6bfa9cd Merge main 2026-10-17 17:57:22 -05:00
Chris Tate 0580460c46 Match Node 24 in URLSearchParams, querystring, string_decoder and os
- URLSearchParams iterators compile outside a for-of head
- URLSearchParams can be built from [string, string] tuple pairs
- querystring.stringify writes bigint values
- StringDecoder accepts an encoding known only at run time
- os.setPriority is lowered
2026-10-17 17:54:52 -05:00
Chris Tate 6ae3eb5cc8 Match Node 24 in events and timers/promises
- The EventEmitter leak warning reaches process 'warning' listeners on the next tick
- The events listener-count and max-listener helpers work over EventEmitter instances
- timers/promises setTimeout, setImmediate and scheduler.wait accept an AbortSignal
- timers/promises scheduler.wait and scheduler.yield are lowered
2026-10-17 17:48:42 -05:00
Chris Tate 0db6d27c7c Support net.SocketAddress and net.BlockList
net.SocketAddress and net.BlockList were refused at compile time. They
are now native checked-dynamic handles in scr_net.c, so their getters
and methods also work on untyped values, and they match Node 24:

- new SocketAddress(options) checks the options in Node's order
  (ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE for the family,
  ERR_SOCKET_BAD_PORT, ERR_OUT_OF_RANGE for the flow label) and throws
  ERR_INVALID_ADDRESS for an address that does not parse. parse() reads
  URL.parse(`http://${input}`)'s hostname and port and answers undefined
  on failure; isSocketAddress(), toJSON() and util.inspect match.
- BlockList takes address, range, subnet and CIDR rules (addAddress,
  addAddresses, addRange, addSubnet, addCIDR, addCIDRs), removes them
  (removeAddress, removeRange, removeSubnet, removeCIDR, clear) and lists
  them in Node's order: IPv4 addresses, IPv6 addresses, subnets, then
  ranges, each newest first, with a repeated address kept once.
- check() compares across families through the IPv4-mapped IPv6 form,
  as Node's SocketAddress::compare and is_in_network do, and answers
  false for a string that does not parse in the given family.
- rules, size, toJSON(), fromJSON() (Node's rule patterns), isBlockList(),
  PRIVATE_RANGES, instanceof and util.inspect match, with the validation
  errors of lib/internal/blocklist.js.

Corpus 5659 and the node-types fixture net-blocklist.ts cover both
classes.

The compatibility registry lists the BlockList methods and
SocketAddress.parse as supported, and both classes as partial: their
structured clone and worker transfer forms are not modeled.
2026-10-17 14:32:06 -05:00
Chris Tate 8e507160c4 Add BroadcastChannel and the remaining Node 24 worker_threads surfaces 2026-10-17 11:06:47 -05:00
Chris Tate 23056949da Keep readline's terminal cursor on character boundaries, and merge main 2026-10-17 11:06:19 -05:00
Chris Tate b429d4ca6f Merge pull request #1108 from vercel-labs/ctate/add-messagechannel-receivemessageonport-5d9f36
Add MessageChannel, receiveMessageOnPort and MessagePort transfer
2026-10-17 09:35:15 -05:00
Chris Tate 4b7ff49da8 Support createHash and createHmac values as streams (#1120) 2026-10-17 08:47:55 -05:00
Chris Tate d5034758fb Merge main 2026-10-17 03:33:06 -05:00
Chris Tate 53023c615d Merge main 2026-10-17 03:30:55 -05:00
Chris Tate 0c4056fb0e Add the plan and timeout test options (#1165) 2026-10-17 03:22:28 -05:00
Chris Tate 26aeeb4c6f Lower util.promisify over the zlib callback one-shots (#1179) 2026-10-17 03:10:14 -05:00
Chris Tate 2896e94b20 Merge main 2026-10-17 02:59:21 -05:00
Chris Tate 7dcb1e6c4e Lower util.promisify over the zlib callback one-shots
promisify(zlib.deflate) and the other callback one-shots (inflate,
deflateRaw, inflateRaw, gzip, gunzip, unzip) over a named or namespace
import of node:zlib now lower. A call through the binding,
gzipAsync(data, options?), runs the callback form's work on the worker
pool and returns a promise that settles where the callback would run:
fulfilled with the Buffer, or rejected with the callback form's Error
(errno, code and message). An invalid option or input rejects the promise
instead of throwing, as the throw inside Node's promisify wrapper does.

The runtime adds scr_zlib_codec_promise and its checked-dynamic twin,
which share the callback forms' options ladder and worker-pool operation
and settle a pending promise in place of the callback. The fallback
declarations gain the matching util.promisify overload.
2026-10-17 02:46:20 -05:00
Chris Tate bc0636de7b Merge main 2026-10-17 02:35:31 -05:00
Chris Tate 0777ad7223 Merge main 2026-10-17 02:33:12 -05:00
Chris Tate 5c39821726 Merge main 2026-10-17 02:30:43 -05:00
Chris Tate f61e5dc938 Add readline's terminal mode, cursor helpers and emitKeypressEvents 2026-10-17 02:10:27 -05:00
Chris Tate 3e83b4a5c7 Lower util.promisify(stream.finished) and util.promisify(stream.pipeline)
Node's util.promisify returns the custom promisified forms of
stream.finished and stream.pipeline, which are stream/promises' functions
of the same name. A const binding of promisify over the node:stream named
imports or namespace members now registers that stream/promises member
as the projection, so calls through the binding lower as the
stream/promises call and accept the stream arguments and options it
accepts.

The fallback declarations gain the matching util.promisify overloads.
pipeline's overload comes first: its (...streams: unknown[]) => unknown
type is assignable to every other target's parameter type.
2026-10-17 01:51:57 -05:00
Chris Tate d7a5568726 Revert "Lower child_process.exec's callback forms" (#1161) 2026-10-16 22:05:36 -05:00
Chris Tate dfac9a950c Merge main 2026-10-16 21:33:56 -05:00
Chris Tate 53f22f7054 Merge main 2026-10-16 21:31:59 -05:00
Chris Tate db94b2d257 Add fs.cpSync, fs.cp and fs/promises cp
fs.cpSync, fs.cp and fs/promises cp compile with every option:
dereference, errorOnExist, filter, force, mode, preserveTimestamps,
recursive and verbatimSymlinks. They follow Node's two implementations.
cpSync follows cp-sync.js over the fs binding: copy errors are plain
Errors with a code, std::error_code failures throw an ErrnoException,
and links inside a copied directory point at their canonical targets.
fs.cp and fs/promises cp follow cp.js, whose copy errors are
SystemErrors with code, info, errno, syscall and path.

Options and paths validate in Node's order with Node's errors. filter
runs for the top-level paths and each entry in Node's order; an async
filter must return a promise that is already settled, and a pending one
throws SC2020. The callback and promise forms complete the copy before
the callback runs or the promise settles. Windows builds throw SC2020.

The copy lives in the new scr_fs_cp.c. Directory walks keep their frames
on the heap, so deep trees also copy on a fiber's stack. File contents
copy with sendfile on Linux, and COPYFILE_FICLONE uses FICLONE
where it exists. ScrError gains the SystemError context and the
ErrnoException key order, with matching fields in the compiler's Error
layout. The stored fs.cp callback uses the same implementation.

Corpus 5567-5571 cover the sync, callback and promise forms, errors,
symlinks and 1500-level trees.
2026-10-16 21:06:22 -05:00
Chris Tate d8c2b0f96d Lower child_process.exec's callback forms (#1161) 2026-10-16 20:57:36 -05:00
Chris Tate e2c34f381b Add the plan and timeout test options 2026-10-16 20:55:26 -05:00
Chris Tate 2ed22d38a4 Merge main 2026-10-16 20:32:43 -05:00
Chris Tate d53c1b8ba0 Merge main 2026-10-16 20:30:22 -05:00
Chris Tate 9681454556 Lower util.promisify(setTimeout) and util.promisify(setImmediate)
Node's util.promisify returns the custom promisified form of setTimeout
and setImmediate, which is timers/promises' function of the same name.
A const binding of promisify over the global functions, the node:timers
named imports or the node:timers namespace members now registers that
timers/promises member as the projection, so calls through the binding
lower as the timers/promises call: they fulfill with the given value
(undefined without one) after the delay or in the check phase.

The fallback declarations gain the matching util.promisify overloads.
2026-10-16 20:22:19 -05:00
Chris Tate cef618b553 Lower child_process.exec's callback forms
exec(command, callback) and exec(command, { encoding, maxBuffer },
callback) lower like execFile's callback slice. The command line runs
with /bin/sh -c, as execSync runs it, the call returns the live
ChildProcess, and the error-first callback receives the captured utf8
stdout and stderr. A non-zero exit, including the shell's 127 for a
missing command, reports Node's "Command failed: <command>\n<stderr>":
scr_exec_file takes a shell flag so the message shows the command line.

Under @types/node, child_process.ExecException maps to Error, as
ExecFileException does. Its code member is the child's numeric exit
status, which the runtime error's string code slot does not hold, so
reading it, testing it with `in`, or testing its typeof is a named
refusal.
2026-10-16 20:14:33 -05:00
Chris Tate 85439ae670 Merge main 2026-10-16 19:54:32 -05:00
Chris Tate 2e52dcd35c Add Readable.from over Sets, iterators and class iterables (#1074) 2026-10-16 19:30:21 -05:00
Chris Tate 5a091f050f Run the zlib one-shot forms on the stream engine (#1139) 2026-10-16 19:11:18 -05:00
Chris Tate d533fd7ce9 Merge main 2026-10-16 09:33:08 -05:00
Chris Tate 6f43e566a4 Merge main 2026-10-16 09:31:00 -05:00
Chris Tate ed5ab6796b Run the zlib one-shot forms on the stream engine
deflateSync, inflateSync, gzipSync, gunzipSync, deflateRawSync,
inflateRawSync and unzipSync, and their callback forms, accept Node's
options and run Node's processChunkSync over the zlib stream engine.

- Options (windowBits, level, memLevel, strategy, dictionary, chunkSize,
  finishFlush, maxOutputLength, rejectGarbageAfterEnd) are validated at
  run time with Node's ladder, shared with the stream classes; info is
  refused at run time.
- Errors carry Node's errno and code; maxOutputLength reports
  ERR_BUFFER_TOO_LARGE and rejectGarbageAfterEnd
  ERR_TRAILING_JUNK_AFTER_STREAM_END. The default-options decoders also
  read every gzip member.
- Untyped JavaScript inputs may be strings, TypedArrays, DataViews or
  ArrayBuffers; other values throw Node's ERR_INVALID_ARG_TYPE after the
  options are checked.
- Results are Buffers, as in Node: they convert to their text.

Corpus programs 5378, 5379 and 5415 cover the sync, callback and untyped
input forms.
2026-10-16 09:18:32 -05:00