- A binding that a local class captures counts as written: the class's
methods may assign it while the loop runs, so the call keeps its helper.
- Copied bodies rename the labels of switch and for-of statements and the
binding of for-of loops.
- The known-union and record-temporary cleanups rewrite switch cases and
for-of bodies, where they left declarations of removed locals.
- Copied locals keep their source bindings. In programs that write
contract types, a parameter with a source binding keeps its own local,
so an Int32 parameter is checked against the elements the loop passes.
A class declared `extends Array` (or `extends Array<T>`) was refused with
"extending classes not declared in the program ('Array')", which blocked
lru-cache at module load. An instance is now an array of the class's
element type: its struct begins with the runtime's array header, whose
reference count it shares, and the class's own fields follow it. The
class's TypeScript type maps to its element array type, so every array
operation applies to an instance, and passing it where an array is
expected passes the same object. The class's own fields, methods,
accessors and statics read the array as the class object.
super() follows the Array constructor: one number argument sets the
length (a RangeError for an invalid one), other arguments become the
elements, and the implicit constructor forwards its arguments the same
way. The runtime finds the class through the array's ext (ScrArrClass:
name, destroy, the own fields, the species constructor), so instanceof
the class (or a binding that holds it) works on static, array-typed and
dyn values, util.inspect
prints `Name(length) [ ..., field: value ]`, Object.keys lists the own
fields, and a release through any array path reaches the class's
teardown. Instances whose elements or fields can form cycles carry the
collector header and are traced.
map, filter, slice, splice, concat, flat and flatMap construct their
result through the class as ArraySpeciesCreate does: `new C(length)` with
the specification's argument, then the elements, then the length where
the specification sets it. A map to another element type retypes the
new instance when its constructor added no elements. Array.of and
Array.from called on the class construct through it. Programs that
declare no Array subclass compile as before.
A generic subclass, a subclass of such a class and `static
[Symbol.species]` are refused at compile time; a species result the
class's constructor cannot construct throws a TypeError.
String() of an array with checked-dynamic elements now uses the
runtime's String() instead of being refused.
Corpus 7720-7726, diagnostics fixture array-subclass-fences.ts.
`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.
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>
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.