Commit Graph
438 Commits
Author SHA1 Message Date
Chris Tate 9e55835014 Compile more npm and CommonJS JavaScript dependencies statically (#2122) 2026-10-24 18:30:56 -05:00
Chris Tate 9c670e8d93 Count the arguments a function receives when it is called through a value (#1880) 2026-10-24 17:58:41 -05:00
Chris Tate 8d9705e22d Run CommonJS top-level return, untyped assert forms, and untyped instanceof Object as Node does (#2101) 2026-10-24 17:01:39 -05:00
Chris Tate 6a8ba89d9f Make Dates mutable objects with Node's setters and conversions (#2072) 2026-10-24 16:21:06 -05:00
Chris Tate 4f0975cbbe Compile more npm and CommonJS JavaScript dependencies statically 2026-10-24 12:01:26 -05:00
Chris Tate d9f1457cd5 Run CommonJS top-level return, untyped assert forms, and untyped instanceof Object as Node does 2026-10-24 08:07:52 -05:00
Chris Tate 7bf50dd9cc zlib: Brotli compression and decompression over the vendored brotli 1.2.0 (#2053) 2026-10-24 00:30:21 -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 1af3a86370 Compile unions of typed-array classes (#2011) 2026-10-23 20:00:12 -05:00
Chris Tate 37df3c4dfd Support split CommonJS require bindings (#1945) 2026-10-23 19:50:13 -05:00
Chris Tate 4206155ac9 Convert non-null asserted operands that hold undefined or null as Node does (#2049) 2026-10-23 19:25:15 -05:00
Chris Tate bf68b3860c Skip split require calls by identity and climb parentheses in early-read checks 2026-10-23 19:05:58 -05:00
Chris Tate 9adb9692cd Accept file URL paths in existsSync and fs.promises (#2042) 2026-10-23 18:47:49 -05:00
Chris Tate a9da37b82e zlib: Brotli compression and decompression over the vendored brotli 1.2.0 2026-10-23 18:11:49 -05:00
Chris Tate 4b6a6e6bc4 Convert non-null asserted operands that hold undefined or null as Node does
`x!` performs no runtime check, but the compiler extracted the asserted arm
with a checked narrow, so a value that still held undefined or null threw
"TypeError: undefined is not representable in the target union" wherever it
was used. In Node the value reaches the operator, which converts it.

When `x!` is an operand of an arithmetic, bitwise or relational operator,
`+`, a compound assignment, a unary `-`, `+` or `~`, or an argument of a
Math function, and `x` is a union of numbers, strings, booleans, null and
undefined, the operand is now converted with ToNumber: undefined is NaN and
null is 0. As an operand of an equality operator, of `!`, of a template
span, of `+` with a string, or of a comparison with a string, the union
itself reaches the operator, so `x! === 0` is false and `${x!}` is
"undefined". Array and typed-array element reads keep their handling of a
missing element, and `+` whose result TypeScript types as a string keeps
the checked narrow where Node's result is NaN.

`x == null` on a union with both null and undefined arms evaluated its
operand twice, so an operand other than a plain read was refused. It is now
evaluated once into a hidden local.

Corpus 7392.
2026-10-23 17:34:59 -05:00
Chris Tate 68eda48251 Merge main 2026-10-23 17:27:47 -05:00
Chris Tate 02597fa3e8 Merge main and give split require cycles the const form's admission 2026-10-23 17:15:33 -05:00
Chris Tate 932837ee23 Compile string-key destructuring of any values and cast-guarded Buffer aliases (#2034) 2026-10-23 16:55:29 -05:00
Chris Tateandjlucaso1 0b83599af4 Accept file URL paths in existsSync, fs.promises and order-checked fs calls
existsSync and the fs.promises functions accept a file: URL wherever
they accept a path. They convert it after their arguments are evaluated,
and a URL that does not convert gives false from existsSync and a promise
rejected with fileURLToPath's error from fs.promises, as in Node.

copyFileSync and renameSync check a string source for null bytes before
they convert a URL destination, and readFileSync checks a runtime
encoding before it converts a URL path, so the error Node reports first
is the one thrown.

Refs #1616

Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
2026-10-23 16:27:40 -05:00
Chris Tate 4fe88e0821 Keep the cast marker on copied and defaulted Buffer aliases 2026-10-23 16:23:37 -05:00
Chris Tate e7943984a5 Bind both Dates before comparing, and cache only new Date locals as time values 2026-10-23 15:50:09 -05:00
e75174aeea Compile string-key destructuring of any values and cast-guarded Buffer aliases
Co-authored-by: patlux <4481570+patlux@users.noreply.github.com>
Co-authored-by: jlucaso1 <55464917+jlucaso1@users.noreply.github.com>
2026-10-23 15:13:03 -05:00
Chris Tate c016b97acb Fix CI on typed-array unions 2026-10-23 12:54:17 -05:00
Chris Tate 1221104388 Merge main and fix CI 2026-10-23 07:50:09 -05:00
Chris Tate b6d6eb60ae Replace a scheduled _construct hook, and keep runtime option values in order
Node's constructNT reads _construct on the construction tick, so an
assignment after the constructor and before that tick replaces a scheduled
construct hook. The assignment was dropped, so the original hook ran. It
now lowers to stream.replaceConstruct, which swaps the hook while its tick
has not run and has no effect after it or on a stream without a hook.

Runtime decodeStrings and defaultEncoding values are read into locals
before the constructor evaluates the other option members, while Node
evaluates the members in order. A runtime value after a member whose value
has effects (a call or an assignment) now refuses instead of reading a
value that member could still change.
2026-10-23 01:34:19 -05:00
Chris Tate 9dbb16d7f8 Support new.target in class constructors (#1917) 2026-10-22 21:52:42 -05:00
Chris Tate df9f83bbc1 Refuse new.target over function-local subclasses lowered later
Lowering collects a function-local class with the body declaring it, so
a local subclass whose function lowers after its base's constructor was
missing from new.target's dispatch, which then answered with the base for
its instances. The refusal no longer depends on that order: the program's
function-local classes are found once, and one that extends the
constructor's class, directly or through other classes its extends
clauses name, refuses new.target as a collected one does.
2026-10-22 21:47:37 -05:00
Chris Tate 6115135d96 Dispatch new.target over generic subclasses and own static names
A constructor's new.target dispatch skipped generic class families, so a
generic subclass instantiated only in a body lowered later answered with
the base's name, and `new.target === Base` held for its instances. A
family now has its own arm, tested by its instanceof interval, which holds
every instantiation: `new.target.name` reads the family's name and
comparisons with a program class are false. Under an instantiation, the
generic subclasses of its family are candidates too. `new.target` as a
value refuses generic subclasses, which have no common class value.

`new.target.name` reads a class's own static `name` field, which replaces
its name (a subclass has its own name); a static method `name` or a
non-string field is refused.
2026-10-22 21:18:48 -05:00
Chris Tate 8c67f04062 Throw Node's TypeError for class constructors called through call/apply (#1892) 2026-10-22 20:36:01 -05:00
Chris Tate 5966f23bd3 Keep the class-value call fence when a subclass declares a static call
`C.call(...)` through a class value typed as `Base` may run a subclass's own
static `call`, which Node calls instead of the class constructor. The
constructor-call lowering now applies only when no class the receiver can
hold declares a static `call` or `apply`: the class and its bases (any
static member of that name, including accessors, fields without
initializers and computed names), and, for a receiver that may hold a
subclass, every subclass. Otherwise the call keeps its existing
diagnostic.
2026-10-22 20:33:33 -05:00
Chris Tate 8d5b3377aa Represent Dates as objects with identity
A Date is a refcounted object holding its time value, shared with the
checked-dynamic Date handle, so it keeps its identity through unknown.
Dates compile in arrays (includes, indexOf, lastIndexOf, join, default
sort by toString() text), in Date | undefined and Date | null slots, as
Map and Set keys and values, in index signatures, and in records, tuples,
class fields, closures, promises and generators. === compares identity,
relational operators compare time values, new Date(date) makes a new
Date, and JSON.stringify writes toJSON().

Closes #225
Co-authored-by: Max B <max@tfq.at>
2026-10-22 20:33:09 -05:00
Chris Tate fbaa71a66f Run the fromEntries aliasing program and drop compiled Iterable entries from the iterator fences
Since Iterable<T> values compile (#1875), two diagnostics fixtures changed:

- fromentries-aliased-entries.ts compiles and prints what Node prints:
  the entries' one array stays shared by both fields. It moves to the run
  corpus as 7440-fromentries-aliased-entries.ts.
- iterator-slot-fences.ts no longer reports its Iterable<number>
  parameter (SC2020) and the call through it (SC2004). That part leaves
  the fixture, which keeps the class-iterator fence; corpus 7380-7383
  cover Iterable values.
2026-10-22 19:54:17 -05:00
Malte UblandClaude Opus 5.5 ac940ed936 Support new.target in class constructors
Inside a class constructor new.target is the class of the instance under
construction. A compiled new allocates the instance with its concrete class
before the constructor chain runs, and the class hierarchy is closed, so
new.target lowers to a static dispatch over the constructor's class and its
descendants (deepest instanceof first). new.target.name reads the exact
class's name and new.target === C is an exact-class test, without a class
value, so subclasses may construct with other signatures. new.target as a
class value requires every subclass to share the constructor's signature.
Plain functions and function-local subclasses keep explicit refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 17:43:09 -07:00
Chris Tate f132cf5f39 Compile Iterable<T> values (#1875) 2026-10-22 18:30:45 -05:00
Chris Tate aaca1f1e2b Count the arguments a function receives when it is called through a value
`arguments.length` in a typed function folds to a constant. In a function
declaration it was the declared parameter count even when the function is
called through a value with more arguments: Node prints 4 for
`[1].map(f)` with `function f(v) { return v + arguments.length; }`, the
compiled program printed 2.

A top-level function declaration that reads `arguments` and that the
program uses as a value now gets a count slot. Its value is an adapter
that stores the parameter count of the function type the value is passed
as (3 for map, 4 for reduce, 2 for a sort comparator) and forwards; the
function reads the slot on entry and clears it, so a direct call sees the
declared count.

Function expressions and declarations passed where the expected function
type has optional or rest parameters (a replace callback) are called with
a varying count and are refused with SC1090 instead of folding to a wrong
count, as are methods, nested functions, and arrows inside a function
used as a value.
2026-10-22 18:17:48 -05:00
Chris Tate a0c207cc25 Merge main 2026-10-22 18:12:20 -05:00
Malte UblandClaude Opus 5.5 089ec6739b Compile Iterable<T> values
Iterable<T> maps to a union of the sources that keep their own
representation (T[], Set<T>, Map<K, V> for [K, V] entries, string) and a
generator over T that holds every iterator. An array stays the same
multi-pass object; a generator stays single-pass. for-of gives the array
arm its own array loop, so iterating an Iterable that holds an array runs
at array speed. Spread, Array.from, the Set/Map constructors and
Object.fromEntries consume it; optional Iterables narrow into it;
generator functions may declare an Iterable return. Class iterables and
typed arrays are refused at the conversion with a named diagnostic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 16:00:41 -07:00
Chris Tate 98712c364a Merge main 2026-10-22 17:49:58 -05:00
Chris Tate 4f6c55a8e6 Narrow filter results through written type predicates with checked conversions (#1819) 2026-10-22 17:21:41 -05:00
Chris Tate e4dc0900d7 Fence arguments.length in function expressions that call themselves by name
A function expression stored in a function type with more parameters
folds `arguments.length` to that type's parameter count, the count every
call through the slot passes. A named expression that calls itself
through its own name passes only its declared parameters there, so no
constant answers both calls. Such a read now reports SC1090 with the
reason, and expressions that do not refer to their own name keep the
fold.
2026-10-22 10:09:08 -05:00
Chris Tate 2f3e25b431 Accept Buffer-compatible chunk annotations and keep super(undefined) in byte mode 2026-10-22 08:35:56 -05:00
Chris Tate 12563f720e Compile conditional spreads of several properties and 2026-10-22 07:58:53 -05:00
Chris Tate dd3ea7c00c Narrow filter results through written type predicates with checked conversions
`.filter` with a written type predicate (`(p): p is Cat => ...`, or a
guard function passed as a value such as `filter(isDog)`) was refused with
SC1090, because TypeScript does not check the predicate. An inferred
predicate that keeps several union arms (`v => v !== undefined` over
`(string | number | undefined)[]`) was refused too.

The filter loop now keeps the receiver's element type, and the result
converts to the predicate's type element by element
(filter-predicates.ts):
- a union element to one of its arms, or to a union of some of its arms,
  by its tag;
- a checked-dynamic element by dynCheck;
- a class instance to a subclass by its class;
- a tuple or record to one with the same fields, field by field.

An element the predicate's type does not describe, kept because the
predicate returned true for it, throws a catchable TypeError: "a kept
element is not a 'Cat' (a type predicate returned true for a value of
another type)". The diagnostics fixture filter-narrow.ts, which pinned
the three refusals, compiles now; corpus 7007 covers its cases.

Fixes #1680.
2026-10-22 07:47:03 -05:00
Chris Tate 41ef12e463 Construct builtins through stored constructors and fix function-local class names and dispatch 2026-10-22 06:44:59 -05:00
Chris Tate 3edec984d5 Compile JSX with the classic runtime (#1786) 2026-10-22 06:29:40 -05:00
Chris Tate 8ff58d2810 Match Node for generic arrow bindings used before their declarations (#1773) 2026-10-22 06:19:57 -05:00
Chris Tate df6de14c94 Support new tls.TLSSocket and tls.connect({ socket }) (#1791) 2026-10-22 06:01:47 -05:00
Chris Tate 1360830149 Support new tls.TLSSocket and tls.connect({ socket }) 2026-10-22 04:52:44 -05:00
Chris Tate c47a0e90ae Compile JSX with the classic runtime
Fixes #889
Co-authored-by: papack <33105506+papack@users.noreply.github.com>
2026-10-22 04:27:35 -05:00
Chris Tate b5fb4115e1 Merge main 2026-10-22 03:33:29 -05:00