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.
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.
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.
A while loop over typed arrays also versioned when its only checks were
thread-owned receivers or static indices. A worker's job loop such as
`while ((job = Atomics.load(next, 0)) < count) { ...; run(job) }` then
got a second copy whose guard fails whenever the array is shared, and
the doubled call kept the job function from being inlined. A while loop
now versions only when it has an access at one of its counters. Other
while loops compile as they did before they could version.
A class instance converted to an untyped value was boxed in a capsule of
its static class. Before any member table read it,
%dyn.class.normalize tested it against each subclass and boxed it again
at the instance's own class: two capsules per crossing for every value
of a class with subclasses, and the subclass tests on every member read.
After the dispatch tables settle, each conversion of a value whose static
JavaScript class has a normalization branch now calls
%dyn.class.boxExact:<Class>, which runs the same subclass tests in the
same order once, at the conversion. The capsule is created at the exact
class, and normalization falls through for it. TypeScript hierarchies,
classes that are never boxed, and hierarchies without subclasses are
untouched.
zod 3, z.array(Order).parse over 500 orders: 178.5M -> 174.4M
instructions per round (-2.3%).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zValidator's default failure hook serializes zod 4's ZodError with
`name` after `message` natively, and with the first `name` zod's factory
assigns ("$ZodError") when the second assignment took the typed slot.
ZodError instances are views of a JavaScript class extending Error: each
view rebuilds `message` and `name` from the error slots at fixed
positions (after `stack`, and after every other property), and the
property bag that holds the dynamically added properties copied its
committed, possibly stale, values over them.
A JavaScript Error subclass with a property bag now marks its class
(errorBagOrder), and its view calls scr_error_dyn_follow_bag after the
bag is copied: `name` and `message` move to follow the property they
followed when the bag was committed, and data values come from the
slots. TypeScript classes keep their views.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zod 4's z.record rejected every plain object natively ("expected record,
received object"): its isPlainObject reads o.constructor.prototype, which
was undefined, and asks whether that prototype has its own isPrototypeOf,
which Object.prototype answered false.
- The Object, Array and Error constructors held as values have their
builtin prototype as a non-writable, non-enumerable, non-configurable
own `prototype`; reading Function's constructor value's prototype
throws SC2020 instead of answering undefined.
- hasOwnProperty / Object.hasOwn on Object.prototype answer its builtin
members, and on Array.prototype its constructor;
Object.getOwnPropertyNames lists them in Node's order.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dynMatch helper for a class target tested the capsule's class key and,
when it did not match, materialized the capsule's view and matched that.
A materialized view is a plain object, which never matches a class target,
so the answer was always false: the helper now answers false directly.
Checked casts from unknown to unions of classes no longer build a view per
non-matching arm (1,000 casts x 2,000 rounds: 255 ms -> 67 ms).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>