Commit Graph
6488 Commits
Author SHA1 Message Date
Chris Tate 43bafa67d1 Test262 group C: early errors, undeclared reads, async-iterator relaxation, compareArray harness (#2500) 2026-10-29 15:17:08 -05:00
Chris Tate ffa0753a82 Generic arrows: enclosing-frame captures (incl. mutable, boxed), optional-call arity, declared-arity refusal (#2506) 2026-10-29 15:14:11 -05:00
Chris Tate 145f8fcd5e fs.watch names the changed entry; fs.watchFile polls in its own gated unit (#2507) 2026-10-29 15:13:12 -05:00
Chris Tate 2de17f95df Pass every argument to emitter listeners that read arguments, and deliver the leak warning at exit (#2544) 2026-10-29 15:12:50 -05:00
Chris Tate 03b26a7e8e Stdio write hook: console lines pass (line, errorHandler), byte chunks pass a Buffer (#2511) 2026-10-29 15:12:31 -05:00
Chris Tate dfa940a82d Return freed memory sooner: chunked shared writes, a bounded string spare, idle trims (#2518) 2026-10-29 15:12:10 -05:00
Chris Tate b9587f361d Reuse lowered units across builds behind SCRIPTC_INCR_LOWERING=1 (#2521) 2026-10-29 15:11:51 -05:00
Chris Tate f2e82c68e1 Pack jammed saturating loops one copy per lane and test their exit every fourth iteration (#2522) 2026-10-29 15:11:29 -05:00
Chris Tate 4458e11a75 Read /proc/self/maps once per glibc thread heap (#2527) 2026-10-29 15:11:09 -05:00
Chris Tate 16f3c16752 Match Node's node:path behavior from Node 24's path tests (#2495) 2026-10-29 15:10:50 -05:00
Chris Tate 6b2af671e5 Weigh program profile matches by the profile's counts (#2528) 2026-10-29 15:10:28 -05:00
Chris Tate 2d2cd25d26 Count the arguments a replaced stdio write receives (#2530) 2026-10-29 15:10:03 -05:00
Chris Tate 3c9d162a99 Test the direct index once in number-key lookups, and inline the probe in loops (#2525) 2026-10-29 15:09:43 -05:00
Chris Tate 7eda6fa880 Trim the per-chunk work of compiled object-mode stream callbacks (#2523) 2026-10-29 15:09:24 -05:00
Chris Tate 59eced7a6c Lower ReadableStream tee, pipeTo and pipeThrough in TypeScript (#2513) 2026-10-29 15:09:05 -05:00
Chris Tate fe46ed63b8 Compile the functions a sparse profile never ran as cold code (#2526) 2026-10-29 15:08:45 -05:00
Chris Tate 771b9a96ba Throw Node's TypeError when a nullable destructuring source is null (#2537) 2026-10-29 15:08:26 -05:00
Chris Tate 1784445e31 Split the Linux LLVM artifacts job and take its glibc packages from native_linux (#2536) 2026-10-29 15:08:06 -05:00
Chris Tate 03e461b842 Match macOS objects and paths in the native install, loop poll and profile tests (#2541) 2026-10-29 15:07:46 -05:00
Chris Tate 4db725e622 Don't offset a null pointer when an array has no dense storage (#2559) 2026-10-29 15:07:27 -05:00
Chris Tate a9e2cb994f Deliver the lines a chunk split after a line listener closes the interface (#2533) 2026-10-29 15:07:08 -05:00
Chris Tate a391eef92a Read and write cached regular files on the loop thread in fs streams (#2540) 2026-10-29 15:06:47 -05:00
Chris Tate 08e2b4596a Run for-in over a receiver that may be null or undefined (#2534) 2026-10-29 15:06:00 -05:00
Chris Tate 7d283cbda3 Read at the exact bigint position in fs.readSync (#2535) 2026-10-29 15:05:39 -05:00
Chris Tate 5dc4bfd6d8 Read builtins into untyped TypeScript slots as Node's values (#2556) 2026-10-29 15:05:19 -05:00
Chris Tate d19fad3999 Match Node's emitWarning, kill, chdir and userInfo behavior (#2532) 2026-10-29 15:04:59 -05:00
Chris Tate 98b3277a43 Provide the libnode pack to the shape overlay npm lanes (#2542) 2026-10-29 15:04:40 -05:00
Chris Tate e6f6cd4b98 Release the web view of an abandoned fetch body while its transfer runs (#2570) 2026-10-29 15:04:15 -05:00
Chris Tate 42e57e4ef3 Deliver a line to a single line listener without the listener snapshot (#2531) 2026-10-29 15:03:53 -05:00
Chris Tate ce6d9d0f1a Skip the receiver bracket for adapters of receiver-free callbacks (#2564) 2026-10-29 15:03:34 -05:00
Chris Tate 0f6c3ae700 Count ArrayBuffer storage in process.memoryUsage() (#2569) 2026-10-29 15:03:14 -05:00
Chris Tate 5c58f3db34 Keep the runtime pack's verified artifacts in a record beside the pack (#2566) 2026-10-29 15:02:52 -05:00
Chris Tate d67f378a50 Release the web view of an abandoned fetch body while its transfer runs
A Response body's stream gets a web ReadableStream view when a member the
fetch stream lacks is read (for example `body.tee`). The view's source holds
the stream, and the stream released the view only when that source was its
last holder. While the transfer runs it holds the stream too, so a dropped
body with a view kept a reference count of 2: the unobserved-response
discard never ran, the paused socket was never resumed, and a compressed
response dropped before HTTP EOF kept the process alive.

The stream now releases the view when only the view's source and the live
transfer hold it, and then takes the unobserved-response discard, as a
body without a view does.

The static-abandon-view fixture reads `body.tee` and `body.locked` of a
4 MiB incompressible gzip response from the new /gzip-incompressible route
and drops it. It hung until the test's timeout before this change and now
exits as Node does.
2026-10-29 13:44:32 -05:00
Chris Tate f9b024dbab Count ArrayBuffer storage in process.memoryUsage()
process.memoryUsage() reported external and arrayBuffers as 0. arrayBuffers
is now the storage of the ArrayBuffers, typed arrays, Buffers, DataViews
and SharedArrayBuffers the program holds, and external the same storage
without SharedArrayBuffers, as Node splits them. A view over existing
storage adds nothing. v8.getHeapStatistics().external_memory reads the
same figure as external.

Each ScrBytes owner records the bytes it counts in the struct's padding,
so ScrBytes stays 64 bytes and the offsets compiled code reads hold; a
static assertion pins them. Owners are counted in a per-instance counter,
because their reference counts are not atomic and they are released on
their instance's thread. Shared storage moves its owner's count to a
process-wide atomic counter, since any thread may release it.
2026-10-29 13:36:41 -05:00
Chris Tate c12f2d64f3 Keep the runtime pack's verified artifacts in a record beside the pack
Each build stages the runtime artifacts it links from the runtime pack and
hashes each one with SHA-256 unless the build cache records that it was
verified with the file identity it still has. A build with an empty cache
therefore hashed every artifact again: on Linux x64, 40 objects and 4.3 MB
for a Benchmarks Game program, about 25 ms of a 300-1100 ms build.

Staging now also reads and writes runtime-pack.verified.json beside the
pack. It lists each verified artifact with its digest and file identity
(device, inode, size, mtime and ctime), as the cache's record does:

- An artifact is trusted only when one of the two records lists it with
  the manifest's digest and size and the identity its file has during the
  read. Any change to the file means hashing it again.
- A missing, unreadable or malformed record, or a malformed entry, is
  treated as absent.
- The record is written to a new file and renamed over the old one, so a
  reader sees a whole record. A write merges the record as it is then.
- When the pack directory cannot be written, the cache's record is the only
  one, as before.

The runtime pack packages do not publish the file. The native CLI build
removes the record its probe builds leave in the bundled pack, and
verify-native-cli.mjs rejects a distribution that has one.
2026-10-29 11:11:35 -05:00
Chris Tate 51c9e31533 Skip the receiver bracket for adapters of receiver-free callbacks
A signature adapter forwards the ambient receiver to its original, and
its closure carries the original's RECEIVER_FREE bit. Calls through the
closure's own pointer tested that bit, but the direct entry of a known
adapter target bracketed every call, because the adapter itself counts
as a receiver reader. The direct entry now tests the bit too.

The receiver readers analysis also admits more node kinds that run no
user code: optional chains, record presence and absent fields, dynamic
boxing, array for-of loops, typed array writes, typed array methods and
constructors over typed operands, the module binding check and region
intrinsics, performance.now, Atomics operations, string and number
library calls over primitives, and new Error(message, options) without
an options object.
2026-10-29 10:42:30 -05:00
Chris Tate 23e3577264 Compute an array's allocation start as an integer
The previous change avoided offsetting a null pointer with a branch in
scr_arr_alloc_start. The function is inlined into scr_arr_release and
scr_arr_destroy, so the branch changed their control flow, and the
functions that changed since the committed runtime profile was collected
then held 5.2% of its counts, over runtime-profile.test.ts's 5% limit.
The address is now computed as an integer, which is defined for a null
block and leaves the callers' control flow as it was.
2026-10-29 10:34:42 -05:00
Chris Tate 7aaf98b53c Check nullable destructuring sources through their unit arm
The TypeError check for a null or undefined source now reads the unit arm the value holds as a dyn null or undefined, instead of converting the whole union to dyn. A union whose data arm has no dyn form, such as a record holding a generator, compiles again instead of failing with SC9001.
2026-10-29 10:24:12 -05:00
Chris Tate 12e284aa2a Merge pull request #2560 from vercel-labs/ctate/give-intel-macos-d388b2
Give the Intel macOS release build 90 minutes
v0.4.6
2026-10-29 10:08:21 -05:00
Chris Tate 78400c316f Give a default export the name default in reuse's declaration tables
A default export without a name of its own (`export default function
(...)`, `export default class`, an `export default` expression) declared no
name, so a change to it left the units of its default imports applied. Each
default export now declares `default` beside its own names, and a change to
it reaches the names that import it.
2026-10-29 09:19:10 -05:00
Chris Tate 851d3362c2 Give the Intel macOS release build 90 minutes 2026-10-29 08:55:52 -05:00
Chris Tate ac978fc686 Don't offset a null pointer when an array has no dense storage
scr_arr_alloc_start subtracted the prefix from the dense block even when
the array had no storage, which computes NULL - 0. That is undefined in C,
and the macOS lane's UndefinedBehaviorSanitizer reports it
("applying zero offset to null pointer" at scr_array.c:60) in
scr_json.test.ts's weak-map program. Without a prefix, the function now
returns the block as it is.
2026-10-29 08:48:35 -05:00
Chris Tate 352842f020 Scope early errors to function bodies and class strictness, and match the upstream compareArray reads
- A function body or class static block treats its top-level function
  declarations as var-scoped: duplicates are legal in strict code, and a
  let/const/class of the same name is SC0006.
- Strictness is the code around a node: a function declaration's own
  "use strict" no longer makes its declaring context strict.
- Every part of a class is strict; object literal methods and accessors
  are strict only by their own prologue or their surroundings, and an
  arrow function's block body can carry "use strict".
- The bare compareArray reads b.length, then a.length, and a.length again
  before every element pair, converting it as the upstream `i < a.length`
  does, so a string length compares its elements.
- Tests that relied on the old handling of undeclared names now use
  constructs that are still refused or still compile: the installed-entry
  diagnostics fixture reports a syntax error (a read of an undeclared name
  is now Node's run-time ReferenceError), and static-objects-order's
  loops.js stores from its for-in head into `undefined` instead of an
  undeclared name (a store into an undeclared name refuses its package with
  SC1091).
2026-10-29 08:37:25 -05:00
Chris Tate dd927301fc Read builtins into untyped TypeScript slots as Node's values
In a TypeScript source, a builtin global used as an object literal member
(`const o: any = { j: JSON }`) failed to lower, and the member silently
became a closure that threw when called. Node reads the global itself, so
`typeof o.j` answered "function" instead of "object", two reads were never
equal, and `o.j.stringify(x)` threw "is not a function". There was no
diagnostic.

A builtin read into a slot the checker types as any or unknown now holds
the value a JavaScript source reads: the JSON, Math and Reflect namespace
objects, Buffer, and functions such as structuredClone, atob and
queueMicrotask. This covers object and array
literal members, arguments, initializers and return values. A member of a
literal whose own slot is any takes the literal's slot. Array, setTimeout
and setImmediate keep their refusal: their values lack Array's statics and
the timers' util.promisify.custom getter.

Object literal members of TypeScript sources no longer defer a failed
lowering to a runtime closure. A builtin with no value (Intl, Proxy,
parseInt, process, a typed slot) reports SC2020 at compile time.

util.inspect now prints a plain object's Symbol.toStringTag as Node does:
`Object [Math] {}`, `[Object [Y]]` past the depth limit, and
`[Object: null prototype] [N] {}`. The tag is read through the prototype
chain and getters, and it is skipped when it is empty, not a string, the
name "Object", listed as an own enumerable key, or its getter throws.
2026-10-29 07:57:38 -05:00
Chris Tate 9021a03133 Pass a shared view whole to a replaced stdout or stderr write
A shared view written to stdout or stderr went out in 64 KiB pieces through
scr_stdio_write, so a replaced process.stdout.write received the first
piece alone, and a false return, which only reports backpressure, ended the
loop: a view larger than 64 KiB lost the rest. With a write hook, the view
is now copied whole and passed in one call, as Node passes it; the bounded
pieces go to the stream itself through scr_stdio_write_raw, which never
stops early.

tests/corpus/shared-bytes-stdio-write.ts replaces process.stdout.write with
a function that records each chunk's length and returns false, and writes a
150,000-byte shared view through it.
2026-10-29 07:50:05 -05:00
Malte UblandClaude Opus 5.5 ad8f8daccd Keep scr_lib.c's default object byte-identical for the fs.watchFile poll
Adding scr_stats_of_path and scr_stats_zero to scr_lib.c moved every
program's executable: scr_lib.o is linked everywhere, so its new symbols
and strings shifted addresses even for programs that never watch a file.

The two entry points now live in an SCR_FS_WATCH_FILE build of scr_lib.c,
the matrix's variant for programs whose feature set has watchFile, and the
poll unit calls the renamed scr_stats_poll_path. Programs that do not poll
link the default object unchanged: compiled without the define, scr_lib.o
is byte-identical to the base (verified by comparing the two objects).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:42:49 -07:00
Malte UblandClaude Opus 5.5 f76a8202dd Record order-parity baselines for the group C fixtures
Add the TS7 preflight/order baselines for the new diagnostics and corpus
fixtures so the completeness check and the parity batches cover them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:34:49 -07:00
Malte UblandClaude Opus 5.5 b1b7aff25c Renumber the new corpus programs to 8514 and 8515
Group C adds two corpus programs whose 8423 prefix another group also
proposes; main's highest corpus number is 8513, so take the next two free
numbers and move the matching per-program cost files with them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:34:49 -07:00
Malte UblandClaude Opus 5.5 48d524a321 Lower a JavaScript read of an undeclared name to Node's ReferenceError
D-2: Node resolves a name nothing declares at run time, and the read always
throws the catchable `ReferenceError: x is not defined` at the access. A
`.js` read of such a name now compiles to exactly that throw instead of
refusing the program, with Node's message and Node's catchability.

The read's value is checked-dynamic (the checker's error-any after the
relaxation in the previous commit, narrowed by the use site where one
provides context), and every path through it unwinds before a use observes
the value, so the dynamic slot never carries a wrong value. Shorthand
position (`{ x }`) needs its own declaration test: there the checker
answers the PROPERTY symbol, so the name is bound when
`getShorthandAssignmentValueSymbol` has no value for it.

`typeof` is the one operator that never touches its operand value, and Node
answers "undefined" for an undeclared name, so `lowerDynTypeofTest` folds
the test to a literal before the read is ever lowered — `typeof x ===
"undefined"` stays true and `typeof x` alone prints "undefined".

No name that Node serves from the global object reaches this branch: the
compiler models those as declared (that is how the corpus reads `process`,
`console` and friends), so this is the name Node itself would report
missing.

The corpus program pins every shape: bare read, call, member read,
arithmetic, comparison, shorthand, destructuring default, typeof test, a
guarded read that keeps running after the throw, and a declared control.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:34:48 -07:00
Malte UblandClaude Opus 5.5 ff93a5a4de Refuse sloppy implicit-global writes by name, and relax undeclared JS names
Node resolves a name nothing declares at run time. In sloppy mode a WRITE
creates a property on the process-wide global object, which a native binary
has no object for, so those programs belong on the Node island route (plan
D-2/D-5). Until that routing exists, an undeclared write in a `.js` source
is refused at build time under a dedicated code, SC1091, whose text names
the island route instead of failing with a generic no-lowering message.

Reaching that refusal at all means the checker has to stop treating an
undeclared name in a JavaScript source as a compile error, so 2304, its
did-you-mean spelling 2552, and shorthand position's 18004 join the JS
relaxation set. The relaxation stays `isJsSourceFileName`-gated: TypeScript
input keeps the compile error, where an undeclared name is a bug rather
than a runtime path.

The refusal is a preflight walk over every JavaScript file, so it reports
once per write, before any code is emitted, at the span the checker used.
`isJsWriteTarget7` is shared with the lowerer's unresolved-reference fence,
which supplies the same refusal for a write that reaches lowering by a path
preflight does not model. An empty identifier is skipped: it is a parse
recovery artifact, never a name a program writes.

The JS-read half of D-2 (the name lowers to Node's catchable
`ReferenceError`) is the next commit; this one only changes what the build
says about a write.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:34:47 -07:00