Commit Graph
4650 Commits
Author SHA1 Message Date
Chris Tate 66726267fc Share untyped module bindings that combine with strings and numbers (#2087) 2026-10-24 02:35:45 -05:00
Chris Tate 0e0bedca01 Forward pointer-union wraps of call arguments to the callee's parameter proof (#2048) 2026-10-24 01:56:42 -05:00
Chris Tate 9496e42968 Keep a pointer-wrapped argument on the heap when its callee keeps the narrowed payload
A union parameter's proof covered the union, not its payload: narrowing it
and storing, returning or pushing the result, a narrowed nullish read, and a
store into a nullable-pointer field all counted as projections. That holds
for a boxed union, whose payload is a separate object. A record passed
through a nullable-pointer union is that payload, so forwarding it to such a
callee let a record in its caller's frame escape the frame.

A pointer-wrapped argument now needs a second fact from the callee's union
parameter: its payload stays in place too. The payload is in place when it
is only tested, narrowed for a field read (directly or through the checked
narrowing a field read of a `T | undefined` parameter compiles to), or passed
on to a parameter that is proved in turn. The facts that other arguments use
are unchanged.

Corpus 7663 has callees that push (directly and through a non-null
assertion), default, store in a global record field or a class field, or
pass on the narrowed record, and one that only reads it.
2026-10-24 01:27:44 -05:00
Chris Tate 1e90263517 Support Symbol.toStringTag class fields and getters (#2037) 2026-10-24 01:21:32 -05:00
Chris Tate 70c2b8246d Share untyped module bindings that combine with strings and numbers
A JavaScript module binding whose initializer joins an untyped value with
a string, number or boolean through `||`, `&&`, `??` or `?:`
(`export const APP_NAME = pkg.appConfig?.name || "app"`) stayed a local of
the module's initializer, so reads from other modules and functions
failed with "a binding form with no lowering". Such initializers now
register the binding in checked-dynamic module storage, like the untyped
initializers they combine.

pi-coding-agent's config.js declares APP_NAME, APP_TITLE and isBundledNode
this way.

Refs #1777.
2026-10-24 01:03:18 -05:00
Chris Tate 373ebd9706 Initialize import cycles that re-export a member with export \* (#2081) 2026-10-24 00:55:34 -05:00
Chris Tate 98e3ff52b3 Reuse linked executables on Linux (#2077) 2026-10-24 00:50:58 -05:00
Chris Tate 7bf50dd9cc zlib: Brotli compression and decompression over the vendored brotli 1.2.0 (#2053) 2026-10-24 00:30:21 -05:00
Chris Tate fd768cd914 Initialize import cycles that re-export a member with export *
An `export * from` declaration binds each re-exported name to the binding
of the module that declares it, like a named re-export, so it has no
initialization state of its own. Import cycles whose modules re-export
another member of the cycle this way now compile with the exact cycle
initialization: re-exported names read the same values, and throw the
same temporal dead zone errors, as in Node. `export * as ns` of a cycle
member keeps the SC1016 refusal.

pi-coding-agent's sdk.js (sdk.js → agent-session-runtime.js →
agent-session-services.js → sdk.js) has this shape.

Refs #1777.
2026-10-24 00:24:12 -05:00
Chris Tate de5557ce5a Answer Error.prototype for Object.getPrototypeOf of an Error (#2058) 2026-10-24 00:04:29 -05:00
Chris Tate 07bab259ee Read typed-array elements through non-null assertions as undefined where Node does (#2067) 2026-10-23 23:53:54 -05:00
Chris Tate cbb87e8812 Address review comments 2026-10-23 23:49:40 -05:00
Chris Tate e3fb35cc68 Cap the Linux test step's memory and move memory-heavy side files apart (#2030) 2026-10-23 23:48:45 -05:00
Chris Tate fe3fd0de44 Parse URL hosts and paths as the URL Standard does, and inspect URLs as Node does (#2071) 2026-10-23 23:38:03 -05:00
Chris Tate cdef55778a Answer Error.prototype only while an error keeps its built prototype
Object.getPrototypeOf of an Error answers Error.prototype when the error's view was built from its fields and its prototype is still the object the view was built with. After Object.setPrototypeOf(error, {}), it answers the object that was set.
2026-10-23 23:31:30 -05:00
Chris Tate 543cb5c3c2 Divide by Math.pow(2, n) as a multiply by its reciprocal (#2076) 2026-10-23 23:29:14 -05:00
Chris Tate 6722a01898 Track asserted typed-array reads that can be undefined in element state 2026-10-23 23:28:09 -05:00
Chris Tate f060cad505 Inspect dynamic classes, functions and %o arguments as Node does (#1848) 2026-10-23 23:23:51 -05:00
Chris Tate f5972b0e75 Prepare v0.4.4 release (#2065) v0.4.4 2026-10-23 23:20:41 -05:00
Chris Tate 0431240719 Reuse linked executables on Linux
The native compiler's executable cache restored a linked executable only
on darwin. On Linux every exe build linked again, even when the frontend
and object caches answered the rest of the build.

- The cache now opens on Linux when the linker is a clang driver. One link
  with `-v -Wl,-t` lists the driver's linker job and every file the linker
  loads; their identities are checked again before an entry is published
  and when it is restored.
- On Linux a key's first link only records that it was linked. A later
  link of the same key traces and publishes, so a program built once pays
  no tracing.
- The key names the runtime pack manifest by its file identity on Linux
  instead of by its text.
- The executable and object caches share one digest of the LLVM text.
- Content-addressed entries are hashed once, and identities are compared
  by field.

darwin keeps its own driver check, dry run and key.
2026-10-23 23:20:06 -05:00
Chris Tate 928697324f Reject class capsules of other classes without materializing them (#2075) 2026-10-23 23:14:24 -05:00
Chris Tate 0b4deda1d0 Print URL {} past the inspect depth limit 2026-10-23 23:05:32 -05:00
Chris Tate cc4428ad1e Keep int32 class fields beside Buffer.from over an ArrayBuffer range (#2070) 2026-10-23 23:02:51 -05:00
Chris Tate d6a6980849 Divide by Math.pow(2, n) as a multiply by its reciprocal
A quotient x / Math.pow(2, n) divided on every evaluation, and a
division's latency bounds loops that carry the quotient, such as a key
that keeps its low bits with k - Math.floor(k / Math.pow(2, n)) *
Math.pow(2, n). A divisor that is a positive power of two from 2^-1022
to 2^1022 has a reciprocal that is a power of two too, whose bits are
0x7FE0000000000000 minus the divisor's, and the product with it is the
quotient for every dividend. The quotient now multiplies by that
reciprocal when the divisor's bits are such a power, and divides
otherwise.

Corpus 8180 compares the quotient with an ordinary division for every
integer exponent from -1080 to 1030, including divisors that are
subnormal, zero or infinite, and for exponents that are not integers.
2026-10-23 22:59:39 -05:00
Chris Tate f986d76d3b Bound Brotli parameter names in error messages 2026-10-23 22:57:22 -05:00
Chris Tate 3dcd730841 Detect class cycles by class identity when inspecting static fields 2026-10-23 22:50:14 -05:00
Chris Tate 260cf6e8c0 Answer builtin prototype reflection in untyped code as Node does (#2054) 2026-10-23 22:26:47 -05:00
Chris Tate 5c131cba35 Report dictionary copies of {} views, and keep method calls direct after writes into dictionaries of dictionaries (#1855) 2026-10-23 22:18:05 -05:00
Chris Tate 52e84ad3b4 Parse URL hosts and paths as the URL Standard does, and inspect URLs as Node does 2026-10-23 21:57:53 -05:00
Chris Tate c9346c1583 Merge main 2026-10-23 21:51:54 -05:00
Chris Tate 9031ddafe0 Merge main 2026-10-23 21:50:24 -05:00
Chris Tate 9e07382bcd Merge main 2026-10-23 21:48:59 -05:00
Chris Tate 96dbc6204f Keep int32 class fields beside Buffer.from over an ArrayBuffer range
Buffer.from(arrayBuffer, byteOffset[, length]) lowers to
buffer.poolFromDynRange with its operands as checked values. The int32
slot analysis treats any runtime helper with a checked-value argument
as a possible store into a live class instance unless the helper is
listed as read-only, so one such call dropped every int32 class field
fact in the program (tsc-ts's scanner makes one).

buffer.poolFromDynRange and buffer.poolFromDynOffset read their
operands (the ArrayBuffer's view after Node's offset and length
conversions, or a copy of a string's, array-like's or typed array's
values) and store into no class instance, so they join DYN_READ_ONLY.
2026-10-23 21:48:25 -05:00
Chris Tate 1df99a8414 Convert checked-dynamic expected errors in assert.throws and assert.match (#2066) 2026-10-23 21:41:23 -05:00
Chris Tate e4079abd41 Keep swap under the test memory cap and continue past OOM kills 2026-10-23 21:39:03 -05:00
Chris Tate 43b0f29011 Guard direct calls after dot-property method writes through dictionary views 2026-10-23 21:34:14 -05:00
Chris Tate ee237c3276 Keep literal key order through self copies and conversions that build no records (#1982) 2026-10-23 21:21:37 -05:00
Chris Tate 61647a8e40 Read typed-array elements through non-null assertions as undefined where Node does
`t[i]!` on a typed array always took the numeric element read, which is NaN
for an index outside the array. Node reads undefined there, so `t[n]! ===
t[n]!` was false instead of true, `${t[n]!}` was "NaN", and `typeof t[n]!`
was "number".

`t[i]!` now takes the numeric read only where its use converts the value to
a number. Where the use tells undefined from NaN (an equality, a template
span, `+` with a string, a comparison with a string, `!`, `typeof`, an array
literal element, or an argument whose parameter admits undefined, such as
`Object.is` and `String`), it reads undefined for an invalid index, like
`t[i]`. Returns and plain bindings keep the numeric read.

Corpus 7394.
2026-10-23 21:20:57 -05:00
Malte UblandClaude Opus 5.5 995f345827 Record corpus 8115's CI cost
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:15:31 -07:00
Chris Tate 10e3476a55 Convert checked-dynamic expected errors in assert.throws and assert.match
An expected regex or string read from a JavaScript object literal's
field is a checked-dynamic value while its checker type is RegExp or
string. assert.throws chose its regex comparison from the checker type
and passed the value unconverted, an internal compiler error, and
assert.match and the expected-object form refused it. Such a value now
converts to the regex or string its type names.
2026-10-23 21:12:15 -05:00
Chris Tate a294403acd Version while loops only for accesses at their counters (#2056) 2026-10-23 21:02:55 -05:00
Chris Tate 02aa5d4184 Keep the run-time result of overloaded calls with untyped arguments (#2064) 2026-10-23 21:00:49 -05:00
Chris Tate e59fdca0f4 Search TypedArrays, read stdin through 'readable', and assign constructor-function globals (#1974) 2026-10-23 20:57:24 -05:00
Chris Tate f9e9f3cb52 Keep an error's name and message where a JavaScript factory created them (#2055) 2026-10-23 20:55:51 -05:00
Chris Tate 7784800c8e Prepare v0.4.4 release 2026-10-23 20:51:00 -05:00
Chris Tate cecab7fc0f Keep null and undefined through non-null assertions into nullable destinations (#2050) 2026-10-23 20:48:03 -05:00
Chris Tate 0392a032c5 Merge main and fix the self-copy key order 2026-10-23 20:47:40 -05:00
Chris Tate 6dfde9919c Keep checked dictionary protocols and invalidate direct calls after method writes 2026-10-23 20:45:37 -05:00
Chris Tate 0f75f5b952 Keep the run-time result of overloaded calls with untyped arguments
The checker resolves an overloaded call whose argument is `any` to the
first overload that argument satisfies, but in JavaScript the value can
select another one: generateKeyPairSync("ec", options) returns KeyObjects
or PEM strings by the options, and digest(encoding) returns a Buffer when
the encoding is undefined. The result was converted to the first
overload's return type, so such calls threw a TypeError where Node
returns the other overload's value.

When a checked-dynamic argument could take another overload whose return
type differs (trailing untyped or undefined arguments may also be
absent), the call's result in a JavaScript source is checked-dynamic. So
are the unannotated bindings it initializes, destructured or not, and
the unannotated functions that return it. fs.globSync keeps choosing its
result form from the resolved overload, since the runtime checks that
withFileTypes agrees with it.
2026-10-23 20:31:12 -05:00
Chris Tate a5db27a5a7 Merge main and fix the review comments 2026-10-23 20:24:35 -05:00