In JavaScript dependencies, a createRequire require call with a computed
specifier, and require.resolve called with a computed request or read as
a value, now compile. The new runtime unit scr_require.c resolves the
specifier with Node 24's CommonJS algorithm (builtins, relative and
absolute paths with Node's extension search, package "main", "exports"
and self-reference, node_modules and NODE_PATH lookup) when the call runs:
- require.resolve returns the id or real path Node returns, and throws
Node's MODULE_NOT_FOUND error when nothing resolves.
- require throws the same MODULE_NOT_FOUND error when nothing resolves,
so packages that probe for optional addons, such as pi-tui, take their
absent branch as in Node. When the specifier resolves to a native addon,
a builtin or another file, Node would load that module: the program
prints an SC2020 error naming it and exits with status 1, without
running the catch clause around the call.
Coverage lists these calls as deferred to runtime. TypeScript sources keep
the compile-time refusal.
Refs #1777.
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.
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.
`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.
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.
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.
`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.
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.
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>