Commit Graph
6750 Commits
Author SHA1 Message Date
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 36daee3f61 Fix the CI failure 2026-10-23 23:16:58 -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 8c94f6f10c Fix Date setter edge cases and the library profile fences 2026-10-23 23:10:56 -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 5b12488842 Merge main 2026-10-23 22:56:03 -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 5d8804db38 Version string scans over the UTF-16 units of strings that are not ASCII
`for (let i = 0; i < s.length; i++) if (s.charCodeAt(i) === 32) n++`
over a text with any non-ASCII character failed the loop version's ASCII
guard and ran the checked loop. Each read tested the ASCII bit, compared
the string with the runtime's published scan receiver, tested the
bounds, loaded the units pointer, and kept the opaque fallback.

The guard now also accepts a version's one string receiver when it is
not ASCII. One runtime read publishes the string as the scan receiver
(ScrStrScan), whose UTF-16 units the runtime holds once a scan has
read it enough. The guard then tests the accesses against the published
unit count, and a third copy of the loop reads each unit with one
16-bit load from the units pointer taken in the guard.

The guard takes that path only while the runtime publishes the receiver
itself, so the length it took is the receiver's UTF-16 length on both
fast paths. Both fast copies read it for the receiver's `length`, which
a while loop's condition otherwise asks the runtime for on every
iteration.

The runtime drops a string's units when the string is released or
appended to in place, or when its index entry is evicted because
another non-ASCII string is indexed. The receiver is a binding the loop
does not write, so the first two cannot happen while the loop runs. A
units copy is emitted only for a loop that uses unit-safe operations
(string-unit-versions.ts): numbers, locals, records and class fields,
typed arrays, number arrays, Math, the receiver's charCodeAt and length,
and calls of functions made of the same operations that read no string.

Tests of `s.charAt(i)` against one-unit literals now become charCodeAt
compares in the IR pass (char-unit-locals.ts), so a version sees one
kind of read.
2026-10-23 22:40:04 -05:00
Chris Tate 3b3f7228a8 Merge main and address the review comment 2026-10-23 22:38:44 -05:00
Chris Tate d68a705975 Read a union's discriminant once in checked casts
A checked cast into a union whose discriminant has four or more string
literals reads the discriminant field once (scr_dyn_discriminant_case)
and then tests only the arms whose literal it holds and the arms without
a literal, in the union's arm order. Every other arm's literal test would
fail, so the arm chosen and the error for a value no arm matches are
unchanged. A typed capsule, an accessor or an inherited discriminant
still takes the tests arm by arm. Unions with fewer literals emit the
same code as before.
2026-10-23 22:31:08 -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 27593e366e Make Dates mutable objects with Node's setters and conversions 2026-10-23 22:08:02 -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 2a98dbfa32 Answer constructor reads on instances without a property bag
The constructor read asked dyn.hasOwn on the instance's property bag, which
is undefined until the instance has one, and on the bag's prototype, so it
threw "Cannot convert undefined or null to object" for an instance without
own properties (for example `new ParseFailure('p').constructor` for a class
that extends SyntaxError). It now goes through a lifted helper that answers
false before the instance has a bag and when the bag has no prototype, as
the dyn.hasKey read did.
2026-10-23 21:57:25 -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 01e88d0b48 Support named properties and Symbol.species on typed arrays held as untyped values 2026-10-23 21:30:21 -05:00
Chris Tate 0e733f22cf Construct an Array subclass's species result before the first callback, and merge main 2026-10-23 21:25:55 -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 c9ce961458 Restore the inspection context when a custom inspector throws 2026-10-23 20:54:08 -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 07d6cb56a3 Merge main 2026-10-23 20:41:24 -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
Malte UblandClaude Opus 5.5 15cc7310ac Keep record values that subtype reduction folds into an inferred type
TypeScript infers a function's return type as the subtype-reduced union of
the values it returns: returning `{ status }` in one branch and
`{ status, value }` (or a call returning either) in another infers just
`{ status }`. Records have fixed layouts, so that type cannot hold the
second value: the return failed its union wrap at run time ('... is not
representable in the target union'), and values that reached a binding of
the reduced type failed a checked narrowing.

- A function with an inferred return type and no contextual signature
  returns the union of the record types it actually returns, including
  through calls of other such functions. Only value types the checker's
  reduction dropped from the inferred union are added, so functions whose
  inferred type already names every returned type keep their layout.
  Declared return types keep their meaning.
- Reading such a union through the reduced type (a binding, a member read,
  JSON.stringify) uses a dedicated checked extraction that converts the wider
  record arms with the ordinary width coercion; other narrowings are
  unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:26:39 -07:00
Chris Tate a5db27a5a7 Merge main and fix the review comments 2026-10-23 20:24:35 -05:00
Chris Tate e813250813 Keep a constructor's name ahead of later properties in the runtime fallback 2026-10-23 20:22:14 -05:00
Chris Tate b2e609d73e Merge main 2026-10-23 20:20:34 -05:00
Chris Tate 01e802ff9d Box JavaScript class instances at their exact class (#2047) 2026-10-23 20:18:12 -05:00
Chris Tateandblurname 7bce848e4d Freeze class instances held in untyped values
Object.freeze, Object.seal and Object.preventExtensions of a class
instance held in an untyped value threw SC2020 at run time. Node changes
the instance itself: writes through its typed references then throw the
read-only TypeError in strict mode code, adding properties through any
reference fails, and Object.isFrozen, isSealed and isExtensible report
the state through either reference.

- In a program that freezes, seals or prevents extensions of an untyped
  value that is not a fresh literal, every class hierarchy that can be held
  there gets the integrity word that static Object.freeze already uses, and
  with it the existing write checks.
- The runtime applies the operation to the instance's checked view and
  commits the view. The commit of such a hierarchy stores the view's
  integrity state in the word (scr_dyn_class_view_integrity) and makes the
  instance's property bag not extensible with it. A hierarchy without the
  word still throws SC2020.
- These commits replace and remove the bag's field entries whatever their
  attributes, so a sealed or frozen view does not leave stale field values
  in the bag.
- The analysis behind records and arrays now starts from these calls only,
  rather than from every untyped freeze the lowering emits, such as the
  frozen strings array of a tagged template.
- Programs without such calls compile as before. The runtime ABI moves to
  v38.

Corpus 7407 covers freeze, seal and preventExtensions through unknown of
classes and subclasses, writes through typed and untyped references and
through methods, properties added before and after the operation, and the
integrity queries, and matches Node.

Refs #1374

Co-authored-by: blurname <50226652+blurname@users.noreply.github.com>
2026-10-23 20:13:09 -05:00
Chris Tate 17f1351b6f Fix the CI failures 2026-10-23 20:12:40 -05:00