Commit Graph
6750 Commits
Author SHA1 Message Date
Chris Tate 02597fa3e8 Merge main and give split require cycles the const form's admission 2026-10-23 17:15:33 -05:00
Chris Tate 0687bc4c0e Bound each epoll timer's deadline by clock reads around its arm call
The epoll timer heap test recorded a key's deadline from a clock read taken
before scrp_timer_arm, but the poller reads the clock again inside the call.
A loaded runner that paused the test between the two reads for more than a
millisecond made the poller's deadline later than the recorded one, and the
test's deadline-order check failed although the heap delivered every timer
in order.

The test now records the clock before and after each arm call and checks
order against those bounds, which hold however long the test is paused and
need no slack. A mutated heap that skips sifting down still fails the check.
2026-10-23 17:06:16 -05:00
Chris Tate 978059ac72 Lower borrowed typed array set calls and keep method calls direct after dictionary stores (#2035) 2026-10-23 17:01:50 -05:00
Chris Tate 37b409897c Merge main 2026-10-23 17:01:10 -05:00
Chris Tate 932837ee23 Compile string-key destructuring of any values and cast-guarded Buffer aliases (#2034) 2026-10-23 16:55:29 -05:00
Chris Tate f629e0d25a Keep a generator's record return channel dyn beside a dyn yield (#2041) 2026-10-23 16:52:20 -05:00
Chris Tate 7230b14f9d Represent Dates as objects with identity (#1915) 2026-10-23 16:49:26 -05:00
Chris Tate bc6359443a Divide mid-size executables into at least eight partitions
An executable's LLVM text was divided into one partition per 4 MiB, so a
program under 4 MiB was optimized and compiled on one thread, and one of
up to 32 MiB used fewer than eight cores. A module over 1 MiB now gets at
least eight partitions of 512 KiB or more: four up to 2 MiB, and eight up
to 32 MiB. Larger modules keep one partition per 4 MiB. The count still
depends only on the module's size.
2026-10-23 16:33:38 -05:00
Chris Tate 6b3297e3a6 Run TypedArray methods on typed arrays held as untyped values 2026-10-23 16:33:09 -05:00
Chris Tate a9cedb9839 Throw for DataView targets of borrowed typed array set calls 2026-10-23 16:28:38 -05:00
Chris Tateandjlucaso1 0b83599af4 Accept file URL paths in existsSync, fs.promises and order-checked fs calls
existsSync and the fs.promises functions accept a file: URL wherever
they accept a path. They convert it after their arguments are evaluated,
and a URL that does not convert gives false from existsSync and a promise
rejected with fileURLToPath's error from fs.promises, as in Node.

copyFileSync and renameSync check a string source for null bytes before
they convert a URL destination, and readFileSync checks a runtime
encoding before it converts a URL path, so the error Node reports first
is the one thrown.

Refs #1616

Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
2026-10-23 16:27:40 -05:00
Chris Tate 25de239076 Revert "Cache untyped property access in programs that declare classes (reland)" (#2038) 2026-10-23 16:24:32 -05:00
Chris Tate 4fe88e0821 Keep the cast marker on copied and defaulted Buffer aliases 2026-10-23 16:23:37 -05:00
Chris Tate fd3155fc39 Keep a generator's record return channel dyn beside a dyn yield
#1999 let a record channel keep its own type beside a dyn one, for the
yields of an IterableIterator<Row>. It applied to the return channel too,
so a generator typed with a dyn yield and a record return converted its
return value into that record. Effect.gen's generators are typed that way:
`yield* RpcTest.makeClient(group)` answered the client converted to a
record without its methods, and `client.double(...)` threw. Only a record
yield channel now keeps its type beside a dyn return.
2026-10-23 16:22:08 -05:00
Chris Tate 7610edcfa0 Compare and index with the integer beside a sum's double
A sum or product of exact integers whose result range is not proven, such
as `child + 1` of a speculated loop counter, computes its double and, beside
it, an i64 wide view (`wideArithmetic`). Array indexes already used that
view, but number compares and typed-array indexes did not:
`child + 1 < end` compared doubles, and `a[child + 1]` converted the double
back to an integer and tested the round trip before its bounds compare.

`alwaysExactInteger` gives a value's exact integer, or its wide view when
the view's magnitude bound is within the magnitude below which the view
equals the double. A number compare whose two operands both have one
compares the i64s, and a typed-array index uses it directly. Views that
may differ from their double, such as `2 * root + 1` of a counter that may
reach 2^53, keep the double compare.
2026-10-23 16:16:43 -05:00
Chris Tate 4e87f45817 Follow values through array properties, unknown keys, JSON callbacks, reflection and tagged templates
Five gaps in the shape analysis let values escape or change unnoticed:

- A store to a named property of an array was dropped, so a value read
  back from it and leaked did not escape.
- Named loads on instances, classes and functions ignored values written
  under unknown keys. They now read that field once it exists, without
  creating it for atoms that have none.
- JSON.parse never ran its reviver, and JSON.stringify never ran its
  replacer or the toJSON methods of the values it serializes. The reviver
  now runs with untracked values, the replacer with every serialized value
  (the holder as `this`), and toJSON on each value that has one. Their
  results are serialized in turn.
- `new Proxy` and `Proxy.revocable` record a proxy operation on the target,
  and Reflect.deleteProperty records a delete, so those literals are G.
- A tagged template now calls its tag with the strings array (with its
  `raw` array) and the substitutions, which were not evaluated before.
2026-10-23 16:16:09 -05:00
Malte UblandClaude Opus 5.5 dddcbed335 Project zod 4 and @hono/zod-validator values at the declaration boundary
The declaration-typed boundary already reaches zod 4 schemas and hono's
c.req.valid(): zod 4's z.infer and hono's validator Input generics resolve
to plain object types in the declaration world. Three gaps remained:

- Boolean literal types printed as `false` (the TS7 facade leaves
  intrinsicName unset), so `{ ok: true } | { ok: false }` lost its true
  arm and `boolean | undefined` became `undefined | false`. The printer
  reads the literal's value.
- `r.data` after `const r = S.safeParse(x); if (r.success)` never
  crossed: zod 4's result union is not data (its error arm is a class),
  and reads on projectable receivers were skipped on the assumption that
  something else types the receiver. Such reads now cross when the
  receiver is a package call whose type does not project, or a const
  bound to one.
- Reads through bindings annotated with a projected type no longer get a
  redundant cast, and aliases are named only for casts that survive.

New npm cases zod4-boundary and hono-zod-validator run real zod 4.6.7,
hono 4.13.13 and @hono/zod-validator 0.9.1 (vendored file closures) under
Node and natively; decl-boundary.test.ts checks that c.req.valid() is a
checked cast with a path TypeError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 14:09:39 -07:00
Chris Tate eb8fd9d17b Merge main 2026-10-23 16:02:44 -05:00
Chris Tate fc229822e7 Support X25519 keys and crypto.diffieHellman
X25519 KeyObjects come from generateKeyPair(Sync)("x25519"), which keeps
the private key clamped as OpenSSL does, and from createPrivateKey and
createPublicKey of PKCS#8, SubjectPublicKeyInfo, JWK (OKP, X25519) and
raw keys. They export in the same forms. sign, verify, createSign and
createVerify throw OpenSSL's "operation not supported for this keytype",
with its library, reason and code properties. X25519 uses mbedTLS's
Curve25519 group.

crypto.diffieHellman({ privateKey, publicKey }[, callback]) computes the
X25519 and ECDH secrets of two keys of one type, given as KeyObjects or
in any form createPrivateKey and createPublicKey read. The checks run in
Node's order: the options, the callback, both keys present, the key types
when both are KeyObjects ("Incompatible key types for Diffie-Hellman"),
then the public and private key inputs. Mismatched curves, a small-order
X25519 point and key types other than EC and X25519 throw OpenSSL's
errors. The callback form passes the secret, or the error without the
OpenSSL properties, in a later macrotask, as Node's DHBitsJob does.

createPublicKey also reads a private key's DER encodings (pkcs8 and
sec1), which Node accepts there.
2026-10-23 15:56:08 -05:00
Chris Tate 9eb14207a6 Revert "Cache untyped property access in programs that declare classes (reland)"
This reverts #2017 (adb8690f1), which made main CI fail.
2026-10-23 15:53:36 -05:00
Chris Tate 4acf7f047d Keep the key order of records spread from values JavaScript built (#2024) 2026-10-23 15:52:49 -05:00
Chris Tate e7943984a5 Bind both Dates before comparing, and cache only new Date locals as time values 2026-10-23 15:50:09 -05:00
Chris Tate e0d0e03eed Support Symbol.toStringTag class fields and getters 2026-10-23 15:47:49 -05:00
Chris Tate 24a89488f9 Give glibc's per-thread heaps huge pages (#2032) 2026-10-23 15:41:30 -05:00
Malte UblandClaude Opus 5.5 b630efd450 Report inferred shapes for untyped npm JavaScript (shape inference, stage 1)
SCRIPTC_DEBUG_SHAPES=1 runs a whole-program allocation-site points-to
analysis over opted-in npm packages' JavaScript and the user files that
call into them, and prints which object and array literals a native
record would represent exactly, the inferred class field types, the
census of writes and reflection on untracked receivers, and the hot
functions' parameter and return types. Report only: nothing reaches the
lowering, and the analysis runs only when the variable is set.

Design: results/design-shape-inference/DESIGN.md (scriptc-perf).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:41:29 -07:00
Chris Tate 45a6f9d9a7 Import and list exports whose names start with "__" (#2033) 2026-10-23 15:35:46 -05:00
Chris Tate 4a48f466ee Merge the Node island runtime branch and stamp the node packs with 0.4.3 2026-10-23 15:32:55 -05:00
Chris Tate 9a2d378fba Run completion callbacks in their call's AsyncLocalStorage context (#1804) 2026-10-23 15:29:35 -05:00
Chris Tate b6a3756e8f Merge main into the Node island runtime 2026-10-23 15:25:48 -05:00
fa80286f9b Lower borrowed typed array set calls and keep method calls direct after dictionary stores
Co-authored-by: ainslec <201870+ainslec@users.noreply.github.com>
Co-authored-by: MathurAditya724 <57684218+MathurAditya724@users.noreply.github.com>
2026-10-23 15:21:21 -05:00
Chris Tate 59e5c0cf8a Merge main and keep declared keys in ordered spreads 2026-10-23 15:20:26 -05:00
Chris Tate 97b64fae1c Turn the thread-heap huge-page policy off under memory tagging 2026-10-23 15:13:36 -05:00
e75174aeea Compile string-key destructuring of any values and cast-guarded Buffer aliases
Co-authored-by: patlux <4481570+patlux@users.noreply.github.com>
Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
2026-10-23 15:13:03 -05:00
Chris Tate c70652d081 Keep record key order through typed iterators and generator resumes (#1999) v0.4.3 2026-10-23 15:12:48 -05:00
Chris Tateandthekevinbrown 19d6736b01 Look up exports whose names start with "__" by their escaped key
TypeScript keys a symbol table entry whose name starts with `__` with an
extra `_` (`__x` is stored as `___x`; `symbolName` removes it). Native ESM
link checking looked an import up by its own spelling, so a program that
imports such an export compiled to Node's startup SyntaxError:

    // dep.ts
    export const __x = 1;
    // main.ts
    import { __x } from "./dep.ts"; // The requested module './dep.ts'
                                    // does not provide an export named '__x'

`escapedSymbolName`, the inverse of `symbolName`, gives a name's table key.
Link checking, external type lookups, CommonJS export lookups and the
`this` check of ES module exports now look names up through it. `Object.keys`
over a module namespace skipped every key starting with `__` to drop
TypeScript's internal names, so it also dropped these exports; it now
skips only internal names and lists exports by their own names.

Closes #1582.

Co-authored-by: thekevinbrown <1531750+thekevinbrown@users.noreply.github.com>
2026-10-23 15:04:56 -05:00
Chris Tate 850710fbea Box TextEncoder and TextDecoder records as checked-dynamic handles (#2022) 2026-10-23 15:03:43 -05:00
Chris Tate 5bb9fc556d Run Test262 tests that include testTypedArray.js (#2031) 2026-10-23 14:59:25 -05:00
Chris Tate adb8690f11 Cache untyped property access in programs that declare classes (reland) (#2017) 2026-10-23 14:47:10 -05:00
Chris Tate 807d281baf Support raw key formats, X25519 keys and crypto.diffieHellman (#2029) 2026-10-23 14:40:52 -05:00
Chris Tate 0ec4fb6de6 Merge main 2026-10-23 14:35:27 -05:00
Chris Tate 46b00f69c9 Give glibc's per-thread heaps huge pages
Blocks above 512 bytes come from glibc, which serves each worker thread
from a 64 MiB heap of its own and makes it accessible with mprotect a
page-rounded step at a time. Every 2 MiB range of a heap is first touched
while part of it is still inaccessible, so the heaps never get transparent
huge pages: on a 16-checker type check of VS Code they hold about 0.9 GB on
small pages, close to half of the process's page faults.

Once a worker thread has allocated 16 MiB of large blocks, the heap of each
large block it gets is made accessible whole and advised MADV_HUGEPAGE,
once per heap. glibc's calloc still clears only what lies below its own
high-water mark, so no page is touched early. glibc's mmap and trim
thresholds are set to 4 MiB and 8 MiB, so that the largest blocks get
mappings of their own and a heap's free top goes back to the system: with
huge pages, a heap otherwise keeps resident memory it never writes. The brk
heap policy's own thresholds take precedence once it switches on.

The policy is off unless THP is in madvise mode and malloc is glibc's, and
when the glibc.malloc.hugetlb tunable is set or the system forbids
overcommit. A heap is advised only when /proc/self/maps shows anonymous
mappings covering exactly its range. Library archives leave their
embedder's heaps alone.
2026-10-23 14:30:29 -05:00
Chris Tate 89d122574f Run Test262 tests that include testTypedArray.js 2026-10-23 14:27:20 -05:00
Chris Tate e7c2462e7a Rule out global constructor names by their first byte (#2028) 2026-10-23 14:27:01 -05:00
Chris Tate 7cdfe16c9b Cap the Linux test step's memory and spread memory-heavy side files
The Linux test shards run their suites in a transient systemd scope with
MemoryMax=13G and no swap, below the runner's 16 GB. A process tree that
grows past the cap loses its largest process to the kernel, and the job
log names the failing test, where the runner itself ran out of memory
and left no log. Hosts without systemd run the suites directly.

The side-queue balancer also takes a table of memory-heavy files, with
their measured peak. They run whole in the cost-balanced task, and each
goes to the shard with the least memory-heavy work so far, after the
time-balanced files. decl-boundary.test.ts, which peaks at about 1.8 GB
alone and had no time measurement, so vitest's file sharding put it in
shard 11, is the first entry. It now runs in shard 1 (plain) and 6 (san).
2026-10-23 14:24:38 -05:00
Chris Tate c296362834 Park typed collection iterators on the entry they read
An early exit from a loop over an iterator-typed Map or Set method parks
the iterator with a second yield of the current entry. That yield read the
entry again by its index, which aborted with a map iteration error when
the loop had deleted the entry. Each step now reads the entry once into a
local that both yields answer.

`entries()` takes the typed walk only for a slot whose yield type is the
key and value pair record. Other yield types, such as
`IterableIterator<any>` or `<unknown>`, keep the checked adapter instead of
failing to compile.
2026-10-23 14:21:21 -05:00
Chris Tate cd48b2b926 Prepare v0.4.3 release (#2019) 2026-10-23 14:18:34 -05:00
Chris Tate 3a5f563e70 Iterate untyped arrays without the generic iterator protocol (#2027) 2026-10-23 14:18:14 -05:00
Chris Tate c24ae2d7e9 Keep caches for property helpers that answer plain values first
Property helpers now start with an exit for values no class table
matches: if the receiver is neither a class capsule nor a function, they
run the generic read or write on it directly. The inline-cache
recognizer accepted only capsule branches and the subclass normalization
before a helper's generic tail, so these helpers stopped being cache
sites. It now also accepts that exit when its operation is the one the
site caches: a read or write of the same key on the receiver.
2026-10-23 14:11:21 -05:00
Chris Tate 96a5954940 Merge main 2026-10-23 14:09:13 -05:00
Chris Tate f0448238f1 Keep libnode pack manifest paths inside the bundle 2026-10-23 14:06:42 -05:00