Commit Graph
6750 Commits
Author SHA1 Message Date
Chris Tate 40ed0e3aff Merge main 2026-10-20 18:16:00 -05:00
Chris Tate 7bf257128c Format the ProcessVersions check (#1573) 2026-10-20 18:15:25 -05:00
Chris Tate 6bb2711c4b Continue a failed checked cast with its value in a dynamic tail (#1561) 2026-10-20 18:15:01 -05:00
Chris Tate 7cbc9c38c7 Merge main 2026-10-20 18:14:12 -05:00
Chris Tate cd833e68a4 Keep the class id of hierarchy instances in the rc word (#1486) 2026-10-20 18:12:51 -05:00
Chris Tate 826776a7e3 Format the ProcessVersions check 2026-10-20 18:12:21 -05:00
Chris Tate 3195f98401 Convert a const array spread only when it runs once per initializer
A const initialized by an array literal and spread once can still run
that spread more than once: in a loop body, loop test or update, a
function, or a class field initializer. Each run inserts the same
elements in JavaScript, so copying them into the destination's layout
would break identity. Those spreads keep the element-layout refusal.
2026-10-20 18:11:57 -05:00
Chris Tate 0635805927 Delete the docs compatibility metadata file again (#1566) 2026-10-20 18:11:28 -05:00
Chris Tate 691ee9841f Answer promises from thunked and dispatched untyped async methods (#1534) 2026-10-20 18:11:10 -05:00
Chris Tate 8441f452d7 Bound the tail copies of sequential checked casts
Each armed site lowers the code after it twice, and a cast inside another
site's tail is lowered in both copies, so n sequential casts produced 2^n
copies of the code after the last one. A site now arms only while fewer
than two splits enclose its tail or share its split point; later casts
keep the throwing cast.
2026-10-20 18:10:51 -05:00
Chris Tate da0b70bc8d Leave an Error's code to the generic store, and allow test units to include scr_js.h
The generic store keeps a native Error's code slot in step with writes
through its checked view, as it does for name, message, stack and cause,
so the store cache leaves `code` to it. The header invariant accepts
scr_js_*.test.c units, which link the dynamic tier.
2026-10-20 18:10:27 -05:00
Chris Tate 3f1cded4c3 Convert booleans with ToNumber in bitwise operators (#1547) 2026-10-20 18:10:03 -05:00
Chris Tate fa098689f1 Check for a class id before reading a stream's vtable word
The stream probes for untyped values (pipe destinations, pipeline
stages, readline input and output, and the checks against the stream
classes) read the vtable word of any boxed object. Instances with a
class id in the rc word have no vtable word, so a hierarchy instance
whose first field is a number crashed those probes. scr_stream_vt_of
answers NULL for them, and each probe treats that as no stream.
2026-10-20 18:09:22 -05:00
Chris Tate 25a11d9864 Check that the limitations partials keep one sentence per line
The Limitations page partials keep one sentence per line so edits to
different sentences merge, but AGENTS.md's general Markdown rule asks
for paragraphs on one line, and changes that followed it conflicted with
the split text. AGENTS.md now names the partials as the exception, and
limitations-partials.mjs gains a check, run by pnpm lint, that fails on a
partial line holding two sentences, and a fix mode that splits such lines.
The one partial that held several sentences per line is split; Markdown
joins the lines, so the page renders the same.
2026-10-20 18:08:33 -05:00
Chris Tate fd34d72e00 Keep each runtime benchmark workload in its own file
workloads.json listed every workload in one array, and its README table
listed them in one hand order, so changes that each added a workload
appended at the same place and conflicted. Each workload is now a JSON
file in benchmarks/runtime/workloads/ named after it, read through
benchmarks/runtime/workloads.mjs by the bench runner, the zero-cost
gate, the strace script and the dynamic-tier test, ordered by category
and then name. The loader still reads workloads.json in a checkout from
before this change, so the gate can compare against one. The README
table follows the same order.
2026-10-20 18:08:10 -05:00
Chris Tate 14ee145399 Merge main and keep inferred method returns for object literals under satisfies 2026-10-20 18:07:48 -05:00
Chris Tate d9df51594c Sort the runtime feature lists
The lib-fn sets and prefix lists in runtime-features.ts grew by
appending, so changes that added different entries to one list touched
the same last lines and conflicted. Each list's entries are now sorted
within its commented groups, and the all-off feature literal follows the
rules table's name order. Entry order is unobservable: the lists feed
membership maps and prefix tests that each set their own flag.
2026-10-20 18:06:49 -05:00
Chris Tate 762632b6b1 Give require declarators beside other declarators no storage (#1537) 2026-10-20 18:06:37 -05:00
Chris Tate be6ee5cb23 Merge main 2026-10-20 18:06:16 -05:00
Chris Tate f45a37f307 Merge main 2026-10-20 18:05:28 -05:00
Chris Tate c85f2380fc Merge main 2026-10-20 18:04:46 -05:00
Chris Tate b8fc0444ac Format the retired-file check 2026-10-20 18:04:24 -05:00
Chris Tate bb78ea2ce7 Run buffer-crc32's and yazl's capability probes as Node does (#1549) 2026-10-20 18:02:43 -05:00
Malte Ubl 73ae23a5eb Merge remote-tracking branch 'origin/main' into opt/emitter-mixed-events 2026-10-20 16:01:47 -07:00
Chris Tate 450c8ac2a5 Gate thenable adoption on then fields, keep Promise.prototype bindings checked, and cache the gate on the lowerer 2026-10-20 17:59:43 -05:00
Chris Tate c635475877 Read non-ASCII strings' units inline in worker executables and for longer texts (#1541) 2026-10-20 17:58:47 -05:00
Chris Tate 37834ed189 Merge main 2026-10-20 17:57:40 -05:00
Malte UblandClaude Opus 5.5 2f50141c0c Compile the hot-shots StatsD client over UDP
hot-shots, a StatsD client compiled from its JavaScript, failed when a
program constructed a client. Each gap on its UDP path is closed
generically:

- Sloppy-mode functions with named parameters may read `arguments`
  where the aliasing of their parameters cannot show: only
  `arguments.length`, or element reads without parameter or element
  writes.
- An `any` slot admits any boxable function value, including functions
  with optional parameters (`C.prototype.m = function (...)` through an
  untyped receiver).
- In a JavaScript file TypeScript does not check, a prototype method
  takes its documented parameters as checked-dynamic values, as
  constructors already did.
- JavaScript dgram sends run completion callbacks, buffer lists,
  connected sends and the six-argument offset/length form.
- A dgram socket crosses into the checked-dynamic tree as a handle
  (SCR_DYNH_DGRAM_SOCKET) whose methods are function values, with
  untyped listeners that survive 'close'. The handle lives in its own
  runtime unit (scr_dgram_dyn.c, the dgramDyn feature), linked only
  when a program converts a socket to or from an untyped value.
- `String.prototype.concat` on strings, and `parseInt` over a possibly
  missing or untyped value in JavaScript.

Corpus programs 6590-6596 and the hot-shots-udp npm
case (hot-shots 8.5.0 vendored) match Node in both lanes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:56:59 -07:00
Chris Tate b70cadb402 Merge main 2026-10-20 17:56:44 -05:00
Chris Tate 1c8349333a Read the ProcessVersions symbol's name with symbolName (#1565) 2026-10-20 17:55:43 -05:00
Chris Tate a1ef7950d0 Delete the docs compatibility metadata file again
#1360 moved the content hash and row count into next.config.mjs and
deleted node-v24-compatibility-meta.json, but a later merge kept a
branch's copy. Nothing reads it, and its hash line conflicts on every
compatibility change. The local compatibility check now fails while the
file exists, so a merge can't bring it back unnoticed.
2026-10-20 17:53:33 -05:00
Chris Tate b6fd72e47f Name the deepest failing path when a checked cast fails inside an optional record (#1548) 2026-10-20 17:52:53 -05:00
Chris Tate 05c6322519 Read the ProcessVersions symbol's name with symbolName 2026-10-20 17:48:25 -05:00
Chris Tate 6bbf1123dc Give the left bitwise operand a temporary when the right one takes one
When an operand of a bitwise operator is a hoisted optional boolean, the
operands evaluate into temporaries before the operation. A left operand
that is safe to repeat, such as a variable read, kept its place in the
operation while the right operand's temporary ran first, so a right
operand that assigns that variable changed the value the left operand
read: `seen ^ (seen = !seen)` gave 0 where Node gives 1.

The left operand now takes a temporary whenever the right one does, so
both evaluate in source order. The corpus program covers an assignment
in the right operand of ^ and <<.
2026-10-20 17:47:40 -05:00
Chris Tate dc5e0cb5bb Merge main 2026-10-20 17:46:26 -05:00
Chris Tate f446620ae5 Read absent process.versions entries as undefined under @types/node (#1550) 2026-10-20 17:46:00 -05:00
Chris Tate 85936f9035 Merge main 2026-10-20 17:44:58 -05:00
Chris Tate 8dd2b95e16 Merge main 2026-10-20 17:44:17 -05:00
Chris Tate f0fcf6e30c Fence fs.realpathSync's function value with realpathSync
fs.realpathSync and fs.realpathSync.native read as function values
lower to the fs.realpathValue libCall. The library sidecar's determinism
attestation demotes on every fs.* spelling, so a fence on realpathSync
has to witness that one too. It is now an alias of both members, and
the surface-manifest attestation parity test passes again.
2026-10-20 17:43:47 -05:00
Chris Tate 1abce1868c Build JavaScript default-export objects that hold class values (#1551) 2026-10-20 17:42:08 -05:00
Malte UblandClaude Opus 5.5 1ef31a1b74 Continue a failed checked cast with its value in a dynamic tail
`JSON.parse(text) as T`, `const x: T = anyValue` and `await res.json()
as T` threw `TypeError: expected X at $.path, got Y` when the value did
not fit `T`. Node never checks an assertion and continues with the value
it has, so the build-container listener rejected an order Node accepts
and a JWT with a string `exp` became a 500.

A failed cast now keeps its value when it initializes a `const`/`let`
binding declared in a function or block and only the code after the cast
reads the binding. That code (the statements after the cast in each
enclosing statement list, up to the declaration) lowers twice: the
static copy, unchanged, runs while the value fits; a dynamic copy, in
which the binding and everything derived from it is typed `any`, runs
after a failure, so missing members read undefined, wrong-typed members
keep their values, extra members stay visible in source order, and
objects keep their identity. The cast sets the flag that selects the
copy: the fused JSON.parse helper's slow path and the plain check call
scr_dyn_check_recover, which takes back the TypeError and parks the
value for checkedCast.fallbackTaken/fallbackTake.

A failed value that flows into a typed slot outside the region is
checked there, as any `any` value is: it continues when it fits and
throws at that use when it does not. A statement of the dynamic copy
with no `any` lowering becomes a runtime fence that throws only when a
failed value reaches it. Module-level bindings, regions with hoisted
declarations or super() calls, union targets and targets holding class instances, and
--tier=static-only (and library mode) keep the throwing cast.

`a?.b.c` on an `any` value now short-circuits only on `a`, so `.c`
throws when `a.b` is undefined, as in Node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:25:33 -07:00
Malte UblandClaude Opus 5.5 e060eeae25 Iterate untyped values with for await, and delegate with yield* in async generators
- A JavaScript generator whose inferred return is `any` (it delegates to
  itself) is a generator with checked-dynamic channels.
- for await over a checked-dynamic value: a compiled async generator, the
  value's Symbol.asyncIterator result, or its synchronous iterator with
  awaited values; break and throws close it through an awaited return().
  A value that is not iterable throws V8's TypeError.
- yield* in async generators delegates through the same protocol and
  completes with the delegate's return value.

The runtime part is a new unit, scr_dyn_for_await.c, linked only by
programs that use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:17:52 -07:00
Malte UblandClaude Opus 5.5 a0e850a9f1 Share one listener list between typed and untyped uses of an EventEmitter
An emitter used both through its static type and through an untyped
reference aborted: a typed `on` followed by an untyped `emit` (or a typed
`emit` from a class body reaching a listener added through `any`) hit
"computed event collided with a fixed event", and an untyped
`emit('error', ...)` trapped outright. Listener entries held either a
typed adapter or a checked-dynamic thunk, and the emit core trapped when
an entry lacked the form the emit carried.

Entries may now carry both forms. Listeners registered through
scr_emitter_on_dyn keep their thunk beside the typed adapter; typed
emits call the adapter and untyped emits call the thunk with the
arguments as given. The class dispatch of compiled emitters registers
untyped listeners under an event typed code fixes with a typed adapter
for its tuple, and converts the arguments of an untyped emit of such an
event to the tuple for listeners with typed parameters
(scr_emitter_emit_mixed; a mismatch throws the checked conversion's
TypeError). Registrations and emits through untyped values otherwise go
through scr_emitter_on_any/emit_any: runtime adapters under 'error' and
the meta events, and Node's unhandled-'error' contract. The emit core
throws instead of trapping when an entry has no usable form. The
dynamic half of the registry sits behind a hook only on_any installs,
and on_flex/emit_flex keep their plain behavior, so programs without
untyped emitter calls link none of it.

listenerCount, eventNames, removeAllListeners, listeners, rawListeners,
setMaxListeners and getMaxListeners through an untyped value on a
compiled emitter answered "is not a function"; they now dispatch to the
native registry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:13:04 -07:00
Malte UblandClaude Opus 5.5 23db1f70fd Adopt thenables in await of untyped values, and read Promise.prototype as a value
- await of a checked-dynamic value is PromiseResolve then await, so an
  object with a callable then is adopted. The rewrite applies only when a
  program source can define a thenable; other programs keep the plain
  checked await.
- promise.constructor answers the Promise constructor; its prototype and
  Promise.prototype answer an object holding the runtime's then, catch
  and finally as non-enumerable own properties.
- Reflect.getOwnPropertyDescriptor and Reflect.defineProperty over checked
  objects.

Together these run execa 5's Promise mixin over checked objects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:02:02 -07:00
Chris Tate 445b5a2ced Merge main 2026-10-20 17:01:18 -05:00
Chris Tate 4bc8a4711c Jump out of WebAssembly traps without __builtin_setjmp on AArch64 sanitized builds (#1560) v0.4.0 2026-10-20 16:57:11 -05:00
Chris Tate a95973b02a Install tsc-ts's platform packages for every release target (#1559) 2026-10-20 16:55:55 -05:00
Chris Tate 5b964e244c Jump out of WebAssembly traps without __builtin_setjmp on AArch64 sanitized builds
Clang has no __builtin_setjmp lowering for AArch64, so scr_wasm.c did not
compile under AddressSanitizer on macOS arm64. Sanitized AArch64 builds
now use an uninstrumented setjmp/longjmp pair that saves the
callee-preserved registers, sp and the frame and link registers; like the
builtin pair, no runtime intercepts it, and scr_wasm_trap still unpoisons
the abandoned frames.
2026-10-20 16:51:09 -05:00
Chris Tate faf3ced3f7 Install tsc-ts's platform packages for every release target
The darwin-arm64, linux-x64-musl and linux-arm64-musl CLI builds failed with
"tsc-ts checker: ... has no @tsc-ts/<platform> executable":

- The lockfile had no entry for @tsc-ts/darwin-arm64@0.0.5, so the
  darwin-arm64 install skipped it. The lockfile now lists all seven
  platform packages.
- A CLI ships the tsc-ts executable of its target. The musl builds run on
  glibc runners, where pnpm installs only the glibc packages. Those jobs now
  add musl to pnpm's supported libc before installing.
2026-10-20 16:50:41 -05:00
Chris Tate b2b7d33e6c Re-record the readable-stream order-parity baselines for main's module hint
Main's supported-module hint now lists dns/promises, stream/web and v8,
so the SC0001 hints recorded for readable-stream-3 and
readable-stream-disable no longer matched.
2026-10-20 16:30:34 -05:00