Commit Graph
2626 Commits
Author SHA1 Message Date
Malte UblandClaude Opus 5.5 dde27c7e21 Merge branch 'opt/npm-lazy-loaders' into opt/npm-cjs-exports
Renumbers this branch's npm cases 2567-2568 to 2583-2584: #1422 now uses
2567.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:43:36 -07:00
Malte UblandClaude Opus 5.5 6fc85e848d Merge branch 'opt/npm-esm-wrappers' into opt/npm-lazy-loaders
Renumbers this branch's npm cases 2564-2566 to 2580-2582: #1411 now uses
2564-2566.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:42:59 -07:00
Chris Tate 9fc483b5c6 Box asserted class bindings into class-backed views (#1469) 2026-10-19 23:42:07 -05:00
Chris Tate 9548ab3663 Give the undici npm cases a 600 s timeout
The undici cases compile the built-in undici implementation's module
graph; a sanitized build of it on a CI runner outlasted the default
120 s per case.
2026-10-19 23:38:15 -05:00
Chris Tate cdd78b4502 Answer in on typed arrays held as any
`in` on a typed array, Buffer or DataView held as `any` or `unknown`
answered false for every key: indices, `length`, prototype methods and
Object.prototype names.

On a typed array, a canonical numeric key (one that ToString(ToNumber(key))
reproduces, or "-0") now answers by bounds: an integral index, not -0,
below the length, so "1.5", "-0", "NaN" and "Infinity" answer false. Other
keys answer true for members of %TypedArray%.prototype, Buffer.prototype on
a Buffer, the constructors' BYTES_PER_ELEMENT and Object.prototype. A
DataView has no indexed elements and answers DataView.prototype's members
and Object.prototype's.
2026-10-19 23:36:14 -05:00
Chris Tate 135e36ba7a Merge main 2026-10-19 23:35:07 -05:00
Malte UblandClaude Opus 5.5 1a65f234c9 Narrow unions of records by intersection refinements, and keep members an assertion attaches
'k' in u answers per value on arms that declare k as an optional slot.
A predicate or 'in' narrowing that intersects record arms views the
value through the stored arms that can hold it. An assertion
'r as R & { m: T }' gives R's arms m as an optional member, keeps the
object, and a binding initialized by it keeps the stored type, so
writes through it reach the original. Late writes through a union
receiver count as writes through the binding it was read from.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:32:43 -07:00
Chris Tate 2259da3cf7 Give interfaces extending class-backed protocols checked identity (#1461) 2026-10-19 23:29:44 -05:00
Chris Tate 0b98a8c713 Read an Error subclass's own code through NodeJS.ErrnoException
`(err as NodeJS.ErrnoException).code` read the runtime error's errno
slot, which only runtime errors set, so an Error subclass with its own
`code` field answered undefined where Node reads the own property. When
a class in the program under the receiver's class has its own `code`
field or a dynamic property bag, the read goes through the error's
dynamic view, which answers the own property and the errno code alike.
2026-10-19 23:28:36 -05:00
Chris Tate bc9ef21b90 Keep DataView's own behavior through unknown
A DataView reached as a checked-dynamic value behaved like a Uint8Array
over its bytes: it printed as `Uint8Array(2) [ 0, 0 ]`, its string and
tag were the typed array's, `.length` and index reads answered from the
bytes, and typed array methods ran on it. It now inspects as Node's
`DataView { [byteLength], [byteOffset], [buffer] }`, answers
"[object DataView]", has no length or indexed elements, and throws
"is not a function" for typed array methods.
2026-10-19 23:28:21 -05:00
Chris Tate c0048af88b Box asserted class bindings into class-backed views
`const node = stack.pop()!` keeps the value's undefined at run time, so
the binding holds `Base | undefined`. Asserting it to a class-backed
protocol view (`node as unknown as View`) reported SC1090, while the same
cast of a plain instance boxed the instance. A union of class instances
and undefined or null now boxes the same way: class arms give the live
instance, and undefined stays undefined until a property read throws
Node's TypeError.
2026-10-19 23:26:01 -05:00
Malte UblandClaude Opus 5.5 73bd0b53c3 Pass rest-parameter functions into slots with fixed parameters
A typed rest-parameter function passed where a function with fixed parameters is expected (`log(...m: string[])` into `(m: string) => void`) was refused. The function adapter now packs the slot's remaining arguments into the rest array, and the value check admits the function wherever that adapter fits. A nested function declaration with a typed rest parameter becomes a value with its own typed-rest signature, converted at each use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:23:54 -07:00
Malte UblandClaude Opus 5.5 d02c85a611 Use classes that extend EventEmitter or a stream class as values
Naming a class that extends EventEmitter, Readable, Writable, Duplex or Transform as a value was refused ("classes extending builtin bases as values"), and so was a class expression of that kind. The refusal also showed up as a deferred runtime fence at the class declaration, because the checked-dynamic tier reflects every class as a value. A user subclass always constructs through its own or synthesized constructor, whose super call runs the runtime initializer, so the class object's construct thunk serves it like any program class. EventTarget subclasses keep the refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:23:53 -07:00
Chris Tate 95bdd7305c Unroll the MD5 block function
scr_md5_block ran its 64 steps as one loop that chose the round
function, message index and rotation per step, and the update path
called it once per block. scr_md5_blocks unrolls the steps with the
message word, constant and rotation inlined, processes every whole block
of an update in one call, and keeps each step's critical path to the
round function of b, an add, the rotate and the add of b: a + m + K is
summed first, G is written as (b & d) + (c & ~d) so that its c & ~d half
joins that sum, and an empty asm statement keeps the compiler from moving
the constant's add after the round function. MD5, HMAC-MD5 and md5-sha1
use it.

Corpus 5775 compares MD5, md5-sha1 and HMAC-MD5 digests over every
length from 0 to 520 bytes in five update sizes and over 1 MiB with
Node; tests/harness/corpus-costs/ records its plain and sanitized costs.
2026-10-19 23:22:51 -05:00
Chris Tate 72e22ed0ed Run SHA-384 and SHA-512 blocks with AVX2, AVX-512VL or the arm64 SHA-512 instructions
SHA-384, SHA-512, SHA-512/224 and SHA-512/256 (createHash, createHmac,
crypto.hash, pbkdf2, hkdf) process their blocks with the fastest kernel
the CPU supports:

- x86-64 with AVX2 and BMI2: the message schedule is computed two words
  at a time in vector registers, interleaved with the scalar rounds,
  which rotate with RORX.
- x86-64 with AVX-512VL: the same, with vector rotates and three-input
  XOR in the schedule.
- arm64 with the SHA-512 extension: SHA512H, SHA512H2, SHA512SU0 and
  SHA512SU1.
- Otherwise the portable blocks, now unrolled over a 16-word schedule
  ring.

The CPU and OS checks run once and are cached. The update and final
paths pass all their whole blocks to the kernel in one call.

test_sha_kernels.c checks the FIPS 180-4 SHA-384 and SHA-512 vectors
through every kernel the CPU supports and compares each kernel with the
portable blocks over every length from 0 to 1100 bytes and 1 MiB, whole
and in 1-, 7-, 64- and 100-byte updates. Corpus 5779 compares SHA-384,
SHA-512 and HMAC-SHA512 digests over many lengths and update sizes with
Node; tests/harness/corpus-costs/ records its plain and sanitized costs.
2026-10-19 23:22:23 -05:00
Chris Tate bbefa36394 Bound loop counters compared as i + c with a bound
The range analysis narrowed a counter only when the comparison read the
counter itself (`i < n`). A comparison of the counter plus or minus an
integer literal (`i + 1 < xs.length`, `1 + i < n`, `i - 1 >= 0`) now
narrows it as `i < n - c` does. Against a bound within 2^52, a sum that
rounds has a magnitude of at least 2^53, so every such comparison answers
as the exact sum would.

The counter of `for (let i = 0; i + 1 < xs.length; i++)` then lands in
an i32 slot like the one of `i < xs.length - 1`, and helper calls that
index arrays with it read the elements without the double index checks.
2026-10-19 23:19:46 -05:00
Malte UblandClaude Opus 5.5 fe322ae901 Keep the JSON-shape diagnostics fixture refused now that null fields bake
A null-valued JSON field bakes as null, so the fixture's document now
compiles. It keeps its purpose with a value no literal spells (1e400 parses
to Infinity), and the mixed-table corpus program covers null elements.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:16:25 -07:00
Chris Tate 783870dec3 Compile TLSSocket.isSessionReused, keyed short-circuit assignment and Object.assign into class instances (#1460) 2026-10-19 23:10:10 -05:00
Chris Tate 751d22ae6e Pass this on to module exports only where every function that gets it ignores it
The exemption for `f.apply(this, ...)` and `f.call(this, ...)` dropped
SC1090 for every module export that passes `this` on. When the function
it reaches reads `this`, Node gives it the module object, and the direct
module call has none, so the result differed from Node.

A `this` that is passed on now counts as unread only when the function
it goes to provably ignores its `this`: an arrow, a function that uses
`this` only to pass it on to such functions, or what a known function
returns, with its parameters bound to the call's arguments and never
assigned. The analysis follows at most six calls and functions, and
refuses otherwise. Effect 4's provideService still compiles: it passes
`this` to what dual(3, body) returns, which passes it on only to the
arrow it was given.

Passing `this` on to a function that reads it now refuses, directly,
through such a factory, or when the factory reassigns its parameter.
2026-10-19 23:09:08 -05:00
Chris Tate ae83a53dad Give interfaces extending class-backed protocols checked identity
An interface that extends a class-backed protocol, such as
`interface TupleTypeReference extends TypeReference { getTarget():
TupleType }` over a `Type` that class instances flow into, mapped as a
record when no class declared itself assignable to it. Asserting a base
value to it copied the instance into that record, which has no methods:
the next method call threw "expected function at $.getTarget, got
undefined", or the assertion reported a conversion diagnostic.

Such an interface holds values of its base protocol, so it now keeps the
same checked identity: the assertion keeps the instance, and its methods
and fields read as on the base type.
2026-10-19 23:06:52 -05:00
Malte UblandClaude Opus 5.5 c208973d75 Read T[keyof T] as unknown for T bound to an unknown-valued record
Inside a generic body Object.entries(t) over T extends Record<string,
unknown> types its values 'keyof T extends never ? unknown : T[keyof T]'.
An instance whose T maps to the checked-dynamic value now reads both
branches as unknown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:01:37 -07:00
Malte UblandClaude Opus 5.5 5ffc20450e Compile SDK-declared data types, any-valued members and Pick views of classes
Message types from SDK declarations often use shapes scriptc refused:

- `{ [key: string]: any }` and `Dictionary<any>` (also a bare
  `Dictionary<T = any>`): the overflow values are checked-dynamic, like
  `Record<string, unknown>`'s.
- `any[]` members an interface, type literal or class declares, also
  optional or nullable: the checked-dynamic array, as `unknown[]` maps.
  An object literal's inferred `any[]` member keeps its existing story.
- A class a types-only package declares with public fields only (aws-sdk's
  `declare class PresignedPost { url: string; fields: Fields }`, with a
  merged namespace of types): it describes JSON data and is never
  constructed, so it maps structurally like an interface.
- `Pick<C, K>` and `Omit<C, K>` over a program class, when the view exposes
  a method: like an interface the class matches, it keeps a live receiver,
  so calls through the view run on the instance.

A record blocked by a member deep inside it now names that member's path
(`member 'poll().jobs[].handle' has type ...`) instead of the outermost
member only; a member holding `any` is named itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:55:04 -07:00
Chris Tate 6c742a7264 Compile class hierarchies across the CommonJS modules of npm packages (#1412) 2026-10-19 22:53:32 -05:00
Chris Tate 13cdc77ad0 Match class capsules in union fields of checked unions (#1456) 2026-10-19 22:48:20 -05:00
Chris Tate a1b077e16f Check private fields of function-local classes per class evaluation
Each evaluation of a function-local class creates its own private names,
while one compiled class serves every evaluation. A JavaScript class's
prototype methods are closures per evaluation whose `this` is the
call-site value, so a method taken from one evaluation could be called
with another evaluation's instance (`a.next.call(b)`, a prototype read,
Reflect.get with a receiver). Those calls read and wrote the other
instance's fields, and `#x in this` answered true. Reads and writes of
`this.#x` inside the closures also went through the property bag under
the key "#x" instead of the native field.

Private fields on a checked `this` now go through a brand check: the
receiver must be an instance of the class or a subclass whose class
environment is the closure's own evaluation, which the class's own
binding names. A matching receiver reads and writes the native field;
any other receiver throws Node's TypeError for the read or the write
(after the assigned value evaluates), and `#x in this` answers false.
Method values and accessors taken from typed instances of these classes
resolve to the instance's own evaluation's prototype functions instead of
a native thunk shared by every evaluation.

The classes this applies to are narrowed to the shapes the check covers:
JavaScript class declarations whose private members are instance fields
used only on `this`. Private methods and accessors, class expressions,
and TypeScript classes keep the "function-local classes with private
brands" refusal.
2026-10-19 22:45:03 -05:00
Chris Tate 064b072f94 Match class capsules in union fields of checked unions
A checked conversion to a union of object types tests each member's
fields with the members' matchers. For a field of type `C | undefined`
holding a class instance, the union's matcher found the instance's
capsule, which is not a capsule of the union itself, and answered no
(or matched the instance's plain-object view, which no class arm
accepts), so no member matched and the conversion threw a TypeError.
workerData read as such a union failed this way in every worker. A union
now matches capsules of other types through its arms, where the class
arm accepts the instance.
2026-10-19 22:44:28 -05:00
Malte UblandClaude Opus 5.5 52f9bf284f Destructure a match-or-empty-string union by code point
`const [hit] = re.exec(s) || ""` destructures `RegExpExecArray | string`:
the string arm answers its code point at each position, or undefined past
its end, as the string iterator does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:40:56 -07:00
Chris Tate 27017ef0af Map classes reached only through import type as their structural types
A class whose module the program reaches only through `import type`
never registers, and its instance type stayed unmapped: a field such as
`items: Emitted | undefined` reported SC2009, and the class holding it
SC1090. The program holds no instance of such a class, so its instance
type now maps as the structural type it describes, like an interface:
fields of the type hold undefined, object literals and arrays of them.
A JavaScript class outside the program keeps the unmapped type, so its
JSDoc-annotated slots still take the dynamic value.
2026-10-19 22:37:25 -05:00
Malte UblandClaude Opus 5.5 3d8c7259a0 Hoist lazily initialized ES module classes and follow on-demand workspace imports
A class a bundled ES module's __esm initializer stores into a module
binding (`Multi = class extends import_stream.Readable { … }`) becomes a
class declaration at the same text position: the initializer's body splits
around it into run-once pieces, so a class over a runtime-provided base no
longer has to exist as a stored class value. Only definitions whose
evaluation runs no code (no static fields, static blocks or computed names;
heritage absent, a builtin module member, or a hoisted class), declared
once, assigned only there and read only inside functions after the
assignment move.

npm selection now also scans the program modules a literal import()
reaches, with their static graphs: a workspace package loaded on demand
had its npm dependencies refused as "not part of the compiled module
graph".

`new import_x.C()` respelled `new require("x").C()`, which constructs the
require call; the interop binding now becomes `(require("x"))` there.

util.inherits onto a runtime-provided class (stream.Readable, the from2
and multistream shape) fences where it is written instead of failing in
Node's argument validation at run time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:33:19 -07:00
Chris Tate 60f5c852e0 Print holes in arrays reached through unknown as Node does
A holey array converted to a checked-dynamic value keeps its holes (the
conversion records them in the array's presence map), but the runtime
inspector printed every element: `const u: unknown = a` for
`a[2] = 1` printed `[ undefined, undefined, 1 ]`, where Node prints
`[ <2 empty items>, 1 ]`, and `new Array(3)` through `unknown` printed
`[ undefined, undefined, undefined ]`.

The inspector now prints each run of holes as one `<n empty items>`
entry that counts toward the 100-entry limit, as Node's
formatSpecialArray does and as the typed array inspector already does.
2026-10-19 22:31:09 -05:00
Malte UblandClaude Opus 5.5 762718a254 Compile TLSSocket.isSessionReused, keyed short-circuit assignment and Object.assign into class instances
- TLSSocket.isSessionReused() is declared in the fallback types and lowers
  to false: the TLS client never offers a cached session (no session
  resumption is a documented divergence), so no handshake resumes one.
- `o[k] ??= v`, `||=` and `&&=` through a pure index-signature record with
  a string key use the keyed read and write `o[k]` and `o[k] = v` lower to.
- Object.assign(instance, record) writes the record's fields into the
  class instance's declared fields (same or width-compatible types;
  optional source fields only when present) and answers the instance.
- Object.assign({}, instance) whose result the checker types as the class
  is refused at compile time: the copy is a plain object, so the checked
  cast into the class threw at run time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:26:47 -07:00
Chris Tate 80355af8ea Give errors held as any their own stack accessor
In Node every Error has an own, non-enumerable `stack` accessor, shared by
all errors, that formats the stack on first access. Errors that reached
checked-dynamic code read `stack` as undefined: the error encoding carried
a stack only when a typed read had already formatted one. Reads on
instances of Error subclasses found no class arm for it, and assigning
`stack` on a subclass instance, typed or through `any`, did not change
what a typed read answered.

The encoding now lists `stack` first among its own properties as a
non-enumerable accessor. Its getter formats the native error's stack on
first access, so the heading is the name and message at that point, and
its setter stores a string in the native error, which typed reads share.
Any other value replaces the accessor with a data property. Objects that
inherit from an error read the error's stack, and a getter called on any
other receiver answers undefined.

A `stack` read on a checked-dynamic value counts as a stack observation,
so such programs capture frames as they do for typed reads. Dynamic reads
and writes of `stack` on Error subclass instances use the native stack;
non-string values are kept with the instance's own properties.
2026-10-19 22:26:32 -05:00
Chris Tate 62fb17bf8c Keep thrown Maps, Sets, typed arrays and functions as the thrown objects (#1448) 2026-10-19 22:17:41 -05:00
Chris Tate d23942ecfa Keep thrown Maps, Sets, typed arrays and functions as the thrown objects
A thrown Map, Set, typed array, Buffer, function or RegExp reached its
catch binding as a type-erased reference, so inspection printed `{}`,
String() gave "[object Object]", instanceof was false and typeof of a
thrown function was "object". These values now take the checked-dynamic
conversion that thrown records and arrays use, so the catch binding is
the thrown object, as in Node.
2026-10-19 22:11:54 -05:00
Chris Tate 87895c340e Test the undici shims against a peer that sends malformed responses
The undici5 and undici7 npm cases now also run peers.ts against Node with
the vendored undici: header values with CR or LF, chunk-size lines that
are valid, malformed, overflowing or 1 MiB long, and fetch bodies that
are endless (read once, then cancelled), gzipped, truncated, empty,
corrupt, cut off, aborted after the headers, redirected while endless,
or carry six content codings. The undici5 case leaves out the Host
values, which undici 5.12 writes into the request head, and the two
fetch cases where undici 5.12 differs (six codings, and an endless
redirect, which fails with a TypeError in 5.12).

package-shims.test.ts compiles two programs in copies of the cases: one
reads 64 MiB chunk-size lines and 64 MiB plain and gzipped fetch bodies
from a separate Node peer and checks that RSS stays under 48 MiB (plain
lane), the other checks that the 5.x profile rejects a Host value with
CR or LF with undici 5.29.0's error.
2026-10-19 22:08:08 -05:00
Chris Tate 1af7a862ce Keep stored cycle functions and self-referencing helper copies refused
Two fixes for the CommonJS cycle check and the bundled-chunk splitter:
- During a cycle's initialization, a read of a partner's exported
  function is safe only where the value neither runs nor stays: an
  expression statement, typeof, void, !, an equality operand, or the test
  of if, while, do and ?:. A const alias (`const f = binding.fn`), an
  object or array literal, a return, or an argument can be called before
  the cycle settles, so these keep SC1016 (Node throws when the function
  reads a binding in its temporal dead zone). A top-level const that only
  publishes the function in an export statement, as the static rewrite
  spells an export-table re-export, stays a read.
- A copied helper whose initializer is a named function expression
  reaches itself through its own name. Each chunk gets its own copy, so
  that name must also be used only as a callee; otherwise the chunk keeps
  the package refused with the existing reason.
2026-10-19 22:05:25 -05:00
Chris Tate 2c6744e97d Merge main 2026-10-19 22:02:31 -05:00
Chris Tate d07188d250 Merge base 2026-10-19 22:00:59 -05:00
Chris Tate 6dd82db8ff Compile module exports that pass this on with apply or call 2026-10-19 21:59:58 -05:00
Malte UblandClaude Opus 5.5 33588981ae Bake mixed JSON tables and destructure unions of arrays and tuples
JSON documents whose rows mix strings and numbers (`(string | number)[][]`,
`(string | number[])[][]`, the character-set and code-point tables of
iconv-lite and tr46) now bake: comptime literals take union-typed elements
and pick each value's arm from its JSON kind and contents.

Array destructuring of a union of array and tuple types
(`const [m, a, b] = re.exec(s) || ["", "", ""]`) reads each position from
the arm the value holds: a tuple arm answers its field or undefined past
its end, an array arm its element or undefined past its end.

Unions of tuple types no longer pick the checker's `length` literal as a
discriminant: tuple shapes have no such slot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:59:40 -07:00
Chris Tate d04b7a5cf2 Read ThreadSlots values with the layout they are stored with 2026-10-19 21:59:15 -05:00
Malte UblandClaude Opus 5.5 f176de2124 Construct CommonJS constructor functions imported through a member alias
A package that exports a constructor function whole and also as a named member (`exports = module.exports = Client; exports.StatsD = Client`, the statsd-client shape) could not be constructed from TypeScript: `new StatsD(...)` was refused as "constructing values other than classes declared in the program", and a bare reference had "no lowering".

- `exports = module.exports = value` is now the module's whole export, and it rebinds `exports` too, so members attached through `exports` afterwards are exported. The fresh-table reset `exports = module.exports = {}` keeps its own handling.
- An `import { name }` or a top-level `const { name } = require(...)` of a member written once as `exports.<name> = <binding or primitive literal>` on such a module reads that value, following `module.exports = require("./x")` re-exports. The checker gives these bindings a synthesized property symbol, so the module's statements answer.
- Construction then takes the existing checked path for JavaScript functions: prototype methods, `util.inherits` between two constructor functions, and `Parent.call(this, ...)` behave as in Node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:58:56 -07:00
Malte UblandClaude Opus 5.5 4e0e7fc1af Box URL into checked-dynamic unions beside fetch handles
fetch's input under @types/node is string | URL | Request. A union with a
checked-dynamic arm collapses to the checked-dynamic representation only
when every sibling survives the collapse; URL did not qualify, so the type
(and anything typed as typeof globalThis.fetch, such as a custom fetch cast
through unknown) did not compile. URL's handle boxes by reference, keeps its
accessors and setters, answers instanceof URL and checks back out to the
typed value, so URL arms now join the collapse. A fetch() input typed
string | URL also converts through the checked-dynamic input path instead
of being narrowed to a string, which threw on the URL arm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:55:18 -07:00
Malte UblandClaude Opus 5.5 297ec38f07 Promisify functions whose callback is optional
`util.promisify(client.close.bind(client))` over `close(callback?: (error?: Error) => void)` was refused because the callback parameter is `callback | undefined`. The promisified function now takes the union's function arm and passes the callback into the union.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:53:12 -07:00
Malte Ubl 6a61eced36 Merge remote-tracking branch 'origin/opt/npm-cjs-exports' into opt/npm-polyfill-shims 2026-10-19 19:52:09 -07:00
Malte UblandClaude Opus 5.5 2efa5d9411 Fold global detection typeof tests and follow var builtin aliases
A condition built from typeof tests whose answers are static (an
undeclared global is "undefined", the global object and process are
"object") folds, so the untaken arm of `typeof window < "u" ? window : …`
never lowers, and a detection chain used as a receiver resolves to the
global object it selects. JavaScript files no longer report a name the
file feature-tests with typeof as undeclared. `typeof global.setTimeout`
answers "function" instead of the identity token's "string".

`var pna = process` (process-nextick-args once it compiles as process)
and `var Transform = require("stream").Transform` alias like their const
spellings when nothing reassigns them; before, the first silently lost
process's members.

Also reads symbol declarations directly in the CommonJS accessor
snapshot path, after the checker helper's removal on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:52:05 -07:00
Malte UblandClaude Opus 5.5 f80e4c1a09 Compile polyfill packages that are Node builtins as the builtins
isarray, safe-buffer, process-nextick-args, inherits and util-deprecate
evaluate to a Node builtin on Node 24 at their checked major versions, so
a require of one compiles as that builtin expression at the require's
position: from an opted-in package's files (the installed version where
Node's resolution finds it), from the program's own CommonJS files, and
through an esbuild __commonJS chunk whose pnpm path key names the package
and its version. The package's files never join the program.

readable-stream 2.x and 4.x compile as node:stream, the package's own
READABLE_STREAM=disable behavior (a documented divergence). A use of the
entry's export picks the builtin module (member reads of the carried
classes) or stream.Readable (value uses); a mixture keeps the package.
3.x stays as is: its disable branch throws on Node 24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:52:05 -07:00
Malte UblandClaude Opus 5.5 c1a9341739 Name the module truthiness corpus program instead of numbering it
Its number collided with another open change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:51:39 -07:00
Malte Ubl 28dc1b25a6 Merge branch 'opt/npm-lazy-loaders' into opt/npm-cjs-exports 2026-10-19 19:51:39 -07:00
Malte UblandClaude Opus 5.5 fa012f5da3 Name the corpus programs instead of numbering them
The numbers collided with other open changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:51:31 -07:00