Commit Graph
3146 Commits
Author SHA1 Message Date
Chris Tate 5ea3df1244 Merge main 2026-10-20 09:47:20 -05:00
Chris Tate 56de47defc Check programs with tsc-ts by default (#1353) 2026-10-20 09:12:30 -05:00
Chris Tate 0ccb58943a Compile esbuild's lazily initialized ES modules; select @types-typed and untyped dependencies by default (#1422) 2026-10-20 09:06:46 -05:00
Chris Tate 55f4eaca5b Merge main 2026-10-20 09:02:52 -05:00
Chris Tate ee33951924 Refuse returns a generic callback's inferred result would drop members of (#1507) 2026-10-20 09:01:42 -05:00
Chris Tate 58c858338a Iterate class instances whose Symbol.iterator is a generator method (#1405) 2026-10-20 09:01:06 -05:00
Chris Tate f1d78a48b5 Merge main 2026-10-20 08:59:06 -05:00
Chris Tate d850e14d50 Refuse dropped members through conditional and satisfies returns
The refusal of callback returns that the inferred result type would cut
down found the return by walking up through parentheses and await only,
so a return inside a conditional's branch or a `satisfies` expression
converted silently and lost the extended members. It now walks through
every parent whose value can be the expression's own: parentheses,
await, satisfies, non-null assertions, conditional branches, the
operands of ??, || and &&, and the right operand of a comma.
2026-10-20 08:58:50 -05:00
Chris Tate f31f856783 Convert object literals with accessors to unknown again (#1506) 2026-10-20 08:55:35 -05:00
Chris Tate e44f6ccbf2 Decode an AST list's position only when it is read (#1509) 2026-10-20 08:54:40 -05:00
Chris Tate fe589fdddf Run SHA-384 and SHA-512 with AVX2, AVX-512VL or the arm64 SHA-512 instructions (#1464) 2026-10-20 08:53:46 -05:00
Chris Tate 5e0ad5bbaa Compare checker panics without their text in the checker identity check
A statement whose lowering meets a checker panic keeps the panic's text in its SC0004 fence. tsgo and tsc-ts reach the same panic for `s.match(re) || []` (6187-js-match-or-empty-array.js) and describe it in their own words, so the check now replaces the text after `panic:` before it compares the IR and the diagnostics.
2026-10-20 08:51:47 -05:00
Chris Tate ce5e4294ad Merge main 2026-10-20 08:49:25 -05:00
Chris Tate 6b708392d7 Merge main 2026-10-20 08:48:08 -05:00
Chris Tate 1ef2004c9b Compare only the 48 bytes SHA-384 writes in the cross-kernel check 2026-10-20 08:46:56 -05:00
Chris Tate f2f667fffb Use classes that extend EventEmitter or a stream class as values (#1479) 2026-10-20 08:46:00 -05:00
Chris Tate c475aabc2a Refuse arguments to inherited stream constructors from untyped code
Construction from checked-dynamic code (`new F(options)` with F an
untyped value holding a ctor-less subclass of a stream class or
EventEmitter) dispatched to the class's constructor and completed the
arguments against the inherited signature, which takes none here, so the
options were dropped. The checked construction dispatch now reports
those arguments at run time with the message typed construction reports
at compile time, located at the class: a fixed argument count refuses at
the call, and a spread call refuses when its argument list is not empty.
2026-10-20 08:41:04 -05:00
Malte UblandClaude Opus 5.5 1092f69ea9 Split a chained Set call the self-hosted compiler cannot lower
`deadDeclarators.add(d).add(memoDecl)` stopped the self-hosting build
with "chained Set method calls ... has no scriptc lowering yet".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 05:22:55 -07:00
Chris Tate e1c27176a6 Throw checked-dynamic primitives as primitives so catch typeof tests see them (#1510) 2026-10-20 04:19:32 -05:00
Malte UblandClaude Opus 5.5 d968975f34 Build dict-spreading literals with other members as checked-dynamic objects
An object literal that spreads an index-signature record but has
members outside the scalar join (an array of labels), an unknown-valued
spread (Record<string, unknown>), or a member a later spread may
overwrite with another type now maps to the checked-dynamic value: it is
built like a JavaScript object literal, so spreads copy their own keys
in order and later keyed writes land on the same object.

'c && { k: v }' spreads contribute k exactly when c is truthy even where
the checker's union of the two does not map (an AbortSignal member), and
a conditional spread onto an 'unknown' field leaves the checked-dynamic
undefined in its empty arm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 02:01:48 -07:00
Chris Tate 1ccda45f7d Decode an AST list's position only when it is read
Every read of an AST list field built an AstNodeList whose pos and end
were decoded from the wire first, though most readers only use `nodes`.
The list now keeps the wire file and the list's index, and pos and end
decode when they are read. The allocation per read stays the same size,
and a decoded file still holds no list objects.
2026-10-20 03:59:25 -05:00
Chris Tate e1e45f12b9 Give converted object literals their accessors
An object literal with get/set accessors converted to `any` or `unknown`
listed its reserved closure slots (`%get:x`) as data keys, so a dynamic
read of the accessor answered undefined without calling the getter, and
Object.keys and JSON.stringify listed the slot instead of the property.

The checked-dynamic copy now defines each accessor as one enumerable,
configurable property whose getter and setter are the slot closures, in
declaration order: the record shape records its accessor key order
(`accessorOrder`). Live views of such records build that copy, and
checking a copy back into the record reads the closures from the
accessor's getter and setter. Reads, writes, Object.keys,
Object.entries, JSON.stringify and property descriptors answer as in
Node.
2026-10-20 03:55:43 -05:00
Chris Tate b8a955b23f Compile function export objects; name conditional export objects (#1434) 2026-10-20 03:16:27 -05:00
Chris Tate 603c6720f9 Keep function export rewrites from capturing names or keys
The pass respells `exports.x` and `module.exports.x` through the
exported function's name. A parameter, local, nested function or catch
binding of that name between a respelled read and the top level would
capture it, so the pass now applies only when the file binds the name
once, at its top-level declaration.

`{ exports }` after the rebinding respelled to `{ SemVer }`, which
renames the property; the shorthand now becomes `{ exports: SemVer }`.
2026-10-20 03:13:40 -05:00
Chris Tate 9d10ae169e Compile lazy barrels, star re-exports and npm aliases in bundled packages (#1427) 2026-10-20 03:12:25 -05:00
Chris Tate eb729399ad Merge branch 'opt/npm-lazy-loaders' into opt/npm-cjs-exports 2026-10-20 03:09:23 -05:00
Chris Tate 66d2010388 Remove lazy loaders together and keep their receiver rule
Lazy loaders that share a var statement each removed their declarators
on their own, and declarators of one statement removed separately leave
overlapping edits, of which applyEdits keeps the first. A later loader
in the statement (one using __toESM, say) stayed behind and the interop
pass refused the package. Every removed declarator of the pass (the
interop requires, the loaders and the unused export tables) now goes
into one set, removed once.

A call through a loader (`load().fn()`) respelled the callee as the
export's live read, which drops the namespace receiver. Loader calls now
take the rule namespace calls already use: the callee must be a
top-level function that never reads `this`; other calls keep the package
refused.
2026-10-20 03:08:09 -05:00
Malte UblandClaude Opus 5.5 c70d9d7e28 Refuse returns a generic callback's inferred result would drop members of
A callback passed to a generic call without a return annotation can
return values the checker unifies into a narrower result type ('return
items' beside 'return items.map((i) => ({ ...i, extra }))' infers
Item[]). Converting the extended objects into that type copied them
and dropped the added members, which Node keeps and a later wider view
reads back. Such a return is now refused by name, pointing at the
annotation that keeps the members.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 00:53:19 -07:00
Chris Tate ea611bec02 Convert object literals with accessors to unknown again
#1490 also took records with accessor slots out of the dyn-convertible
domain, which refused passing such a literal where `unknown` is
expected. Native APIs read these values through their accessor slots:
fileURLToPath, fileURLToPathBuffer and pathToFileURL call the `windows`
getter of an options object, so tests/corpus/node24-file-url-options.ts
stopped compiling.

Records with accessor slots convert to checked-dynamic values again.
JSON.stringify of their typed values stays refused, since the typed
serializer cannot invoke the getter.
2026-10-20 02:52:38 -05:00
Malte UblandClaude Opus 5.5 b74224f31c Throw checked-dynamic primitives as primitives so catch typeof tests see them
A value thrown from `unknown` storage (`throw values[i]`) that holds a
number, string or boolean now throws as that primitive, like a statically
typed `throw 5`. Before, it threw as a checked-dynamic reference, so
`typeof e === "number"` (and "string"/"boolean") on the catch
binding answered false and the narrowed reads were unreachable. A
primitive has no identity to keep, and reading the binding as `unknown`
converts it back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 00:50:32 -07:00
Chris Tate 35e566855f Accept mock.fn() without an original (#1417) 2026-10-20 02:42:59 -05:00
Chris Tate c8b22e3435 Merge main 2026-10-20 02:40:17 -05:00
Malte UblandClaude Opus 5.5 2553818b0c Compile the round-2 index-signature and union-of-records shapes
- An object literal that spreads an index-signature record (the
  metric-tags idiom '{ ...tags, bucket, status }') maps to the pure
  index-signature record joining the spread slots and member types: the
  checker drops the signature, but the object holds every spread key.
  Declared members read and write as keys of it.
- A conditional spread into an index-signature record adds no key when
  it does not apply.
- '{ ...unknownValue }' into an index-signature record copies the
  value's own keys through the checked extraction; null, undefined,
  numbers and booleans spread nothing.
- 'return Promise.reject(e)' in an async function is typed by the
  function's own result.
- A union of record layouts flowing into one record slot converts each
  arm; fields the checker types 'undefined' alone lift into
  undefined-armed slots.
- '(x as { m: T }).m' on a union of records reads the arms that declare
  m and answers undefined for the others.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 00:19:07 -07:00
Chris Tate d5d9a1185a Compile process.send presence, process.exitCode reads, wider stream hooks, void race entries and promisify of callbacks (#1429) 2026-10-20 02:18:40 -05:00
Chris Tate 391b9ac00e Merge main 2026-10-20 02:15:13 -05:00
Chris Tate d3a567f830 Pass rest-parameter functions into slots with fixed parameters (#1480) 2026-10-20 02:13:34 -05:00
Chris Tate b6ef49d39d Promisify callback-last functions that return a value
The promisified executor typed its call of the function as void, so a
function with a non-void return type failed to compile with SC9001. The
call now has the function's return type, and its value is discarded, as
in Node.
2026-10-20 02:09:48 -05:00
Chris Tate bdf1bb9734 Pass rest-parameter functions into nullable and optional fixed-parameter slots
Structural conversion lifts a function into a union's function arm only
when cleanFuncAdaptable accepts the pair, and it refused every rest
signature. A typed-rest function assigned to `((m: string) => void) |
null`, an optional parameter of that type, or a `| undefined` binding
therefore failed with SC2003. cleanFuncAdaptable now accepts the pairs
the rest packing adapter serves, so these slots use the same adapter as
a plain fixed-parameter slot.

6445 covers the nullable, optional and undefined slots, and 6445 and
6446 get their corpus costs.
2026-10-20 02:06:21 -05:00
Chris Tate f6f4ad1b00 Give errors held as any their own stack accessor (#1450) 2026-10-20 02:05:17 -05:00
Chris Tate d45a542221 Compile esbuild's bundled CommonJS chunks and CommonJS cycles statically (#1411) 2026-10-20 02:00:58 -05:00
Chris Tate 0c3a7ae73e Keep error stacks through computed keys, clones and throwing getters
A read through a computed key now counts as a stack read when the program
contains the string "stack", so `e[key]` captures frames like `e.stack`
does. A key the program assembles from other strings or from data it
reads keeps the static answer.

structuredClone of an error held as `any` copies a stack that was already
formatted as a non-enumerable data property, as it did before the stack
became an accessor.

When a name or message getter throws while the stack is formatted, the
stack accessor propagates the exception instead of reading the missing
string.
2026-10-20 02:00:21 -05:00
Chris Tate 7551434bd7 Support freezing and redefining fields of class instances (#1385) 2026-10-20 01:57:15 -05:00
Chris Tate a16a53d33c Return parked workers' memory while the event loop waits (#1501) 2026-10-20 01:55:58 -05:00
Chris Tate 5a38f414dd Resolve parameter-list references without the function body's vars
A function's parameter initializers run in their own scope, which sees
the parameters and a function expression's own name but not the body's
`var`s. Chunk splitting resolved them against the body's names too, so a
helper that a default value reads was not copied into the chunk when the
body declared a `var` of the same name, and the chunk read an undefined
binding. A computed method name now resolves outside the method.

A named function expression whose body declares a `var` of its own name
still exposes the shared function to its parameter initializers, so those
reads must be calls for the function to travel with a chunk.
2026-10-20 01:54:30 -05:00
Chris Tate 9791aa587e Return parked workers' memory while the event loop waits, after a delay that grows
The trim helper returned parked workers' memory once no worker had run for
100 ms. A compiler in watch mode starts its workers again for each rebuild
and faulted the returned pages back in, and a rebuild that runs on the main
thread alone had the discards run alongside it.

- The delay starts at 1 s (SCR_SA_DISCARD_DELAY_MS) and doubles each time
  workers start within ten delays of a discard, up to
  SCR_SA_DISCARD_DELAY_MAX_MS (10 s by default).
- Once the event loop of the thread that is not a worker runs, the helper
  discards one arena at a time, and only while that loop has been in one
  wait with nothing ready for a step (scr_sa_loop_waiting, called by the
  event loop around its sleep). A loop that does not wait gets the
  discards SCR_SA_DISCARD_DELAY_MAX_MS after the delay.
- Programs without a running event loop discard after the delay, as before.
2026-10-20 01:50:55 -05:00
Malte Ubl b664590eca Merge commit '12d0215c4' into opt/builtin-base-class-values 2026-10-19 23:50:41 -07:00
Malte UblandClaude Opus 5.5 44f4e2e74c Refuse inline stream completion callbacks that name the error
Node passes write and end callbacks an error argument (null on success),
but the native callbacks receive none, so an inline callback that names
the parameter read undefined. It now refuses where it is written. The
stream-shims npm case compiles now that stream subclasses are values;
its remaining scenarios are deferred refusals, so it is recorded as one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:50:20 -07:00
Chris Tate b8ee250c4a Narrow unions of records by intersection refinements, and keep members an assertion attaches (#1484) 2026-10-20 01:50:19 -05:00
Chris Tate f77298ea82 Merge main 2026-10-20 01:49:45 -05:00
Chris Tate 6197a45ab0 Refuse arguments through class values of ctor-less stream subclasses
A class without a constructor that extends a stream class or
EventEmitter inherits the runtime constructor, which takes no arguments
here. Direct construction with arguments already reported that, but
construction through the class's value (`new registry.upper({ ... })`)
completed the arguments against the empty inherited signature and
dropped them. Both paths now share refuseInheritedBuiltinCtorArgs, so
the class-value path reports at the first argument with the same
message.
2026-10-20 01:48:22 -05:00