Regex literals and new RegExp calls accept the v (unicode sets) flag, which
the vendored engine implements: class subtraction and intersection, nested
classes, \q{...} string literals and properties of strings. The flag uses
unicode mode for pattern decoding and string iteration, and flags read in
getter order (dgimsuvy). Regex literals now also report their flags in
getter order, as Node does for /x/yg, and the flag getters (global,
unicodeSets and the rest) compile on statically typed regexes.
In v mode the engine rejected `-` and doubled punctuation outside a
character class, and the `\-` escape inside \q{...}. It now applies the
class-only checks inside classes and \q{...} only, and parses \q{...}
contents with the class escapes, matching Node. The d flag is still
refused.
On Linux, a worker thread that exits without having made any object it
allocated reachable from another thread gives back all of its memory: the
pages it carved, including ProgramLifetime instances and other objects it
never freed, and the system blocks it still holds.
A worker carves past each slice's frontier while the arena's free lists and
returned regions are set aside, takes from those free lists only once a
slice has no bump room left, and records the system blocks it allocates.
Messages and intern tables that share published graphs by pointer, and the
process-wide key arrays of typed records, mark the thread as sharing; so
does a remote free of one of its blocks. When a worker that did not share
parks, the trim helper returns its pages, frees its system blocks, and
restores the arena to its state at the claim, with the free blocks the
worker took free again. A worker that shared keeps its memory as before.
SCR_SA_DISCARD=0 keeps every worker's memory; SCR_SA_DISCARD=poison makes
the discarded pages inaccessible instead, for tests.
A Hash or Hmac that flows into an unknown or any slot, or into untyped
JavaScript code, is now a native handle (Hash or Hmac) instead of a
compile error. The handle keeps the value's identity, so a cast back to
Hash or Hmac answers the same value. update(), digest() and Hash's
copy() dispatch through it, called directly or read as values: update
is one function for Hash and Hmac and digest is one per class, as in
Node 24.22, and update() answers the receiver. The stream and event
members throw a coded SC2020 error there, as do the methods called with
another receiver; other names read as undefined.
The to-dyn conversion boxes a Hash or Hmac through
scr_crypto_hash_to_dyn, which installs the handle ops on first use, so
programs that never box one link none of the handle code.
A native handle read through `as any` now dispatches its method calls
through the handle. Calling copy() on an Hmac throws Node's TypeError
("mac.copy is not a function") after the arguments are evaluated,
instead of the method-call fence.
Corpus 5768 and 5769 cover the TypeScript and JavaScript forms against
Node 24.22, and errors.test.ts covers the SC2020 cases. corpus-costs.json
records their plain and sanitized costs.
d.toJSON() now answers the toISOString() string for a valid date and
null for an invalid one, as a string | null value although the lib
types say string. Unannotated bindings, object and array literal
entries initialized by it keep the null, reads of such bindings stay
checked, and JSON.stringify serializes the null instead of narrowing
it to string.
Closes#935
Co-authored-by: phall <25888173+phall1@users.noreply.github.com>
Library exports and callbacks passed text only as a pointer and length.
profile_format 2 adds the cstring class, a NUL-terminated `const char *`
(an i32 pointer in Wasm reactors), for export parameters, export results
and callback parameters. Parameters are copied in and decoded as UTF-8,
with U+FFFD for malformed bytes; a NULL pointer is the SC4012
host-contract trap. Results live in the result arena like string
results. A result or callback argument containing U+0000 traps instead
of being truncated.
Closes#615
Co-authored-by: ailuoku6 <23209876+ailuoku6@users.noreply.github.com>
An async generator that fell off its end, with a return type other than
void, settled its last next() one microtask turn after Node, so for await
loops over it also ended a turn late. The appended implicit return now
marks the completion as settled, like a bare `return;`.
return() at a suspended yield ran the generator's finally blocks before
awaiting the return value. The request now awaits the value first and
resumes the body on the next turn, and the completion that follows settles
without a further turn, also when a finally block yields or awaits first.
An explicit `return x` reached during that unwind still takes its own turn
to await x.
Array.fromAsync accepts typed async generator sources: each next() result
is awaited and its value used as is, a throwing or rejecting mapping
function closes the generator, and a rejected next() rejects the result on
the turn Node rejects it.
Float16Array is a native typed-array kind with IEEE 754 binary16 storage.
Stores round the number to nearest-even in one step from the double, as
Node does, including overflow to Infinity, subnormals, -0 and NaN; reads
widen exactly. The runtime converts with integer operations, so no target
needs half-precision hardware or compiler-rt support.
Construction, element reads and writes, ArrayBuffer views, fill, set,
subarray, slice, both sort orders, constructor values and checked-dynamic
storage work as for the other typed arrays. Math.f16round,
DataView.prototype.getFloat16 and setFloat16, and util.types.isFloat16Array
compile.
new DisposableStack() compiles to a native stack handle. use, adopt, defer,
move, dispose, disposed and [Symbol.dispose] are members of its dynamic
view, and the stack works with `using`. Disposal runs the resources in
reverse order, calls use() resources' dispose methods with the resource as
`this`, and raises a SuppressedError chain when more than one disposal
throws; a single failure is rethrown as thrown. Calls on a disposed stack
throw Node's ReferenceError, and invalid receivers, resources and
callbacks throw Node's TypeErrors.
use() of a class instance registers a function that calls the class's
[Symbol.dispose] method, and returns the instance at its static type; use()
of a union that includes class instances is refused. The stack is
collected with its callbacks when a callback captures the stack.
x instanceof DisposableStack compiles. Handles can expose symbol-keyed
members through a new symbol_get hook.
- A package typed only by an @types twin was judged under the twin's name
and refused with "its import resolves to '@types/x/index.d.ts', not to
runtime JavaScript". Selection now resolves the runtime package, and the
refusal names it with the --npm-static option that compiles it anyway.
- Refusals the declaration and shipped-JS heuristics make carry the same
remedy as a diagnostic hint; a dependency of a named package suggests
the transitive form.
- `--npm-static=pkg...` (and `"pkg..."` in a library profile) selects the
package and every package its files import, nested require() calls
included, without the eligibility heuristics.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node runs TypeScript with verbatimModuleSyntax semantics: `import type` and
`export type … from` vanish, while `import { type A }` and
`export { type A } from` keep an empty clause and still load their module.
- Package selection skipped nothing: `import type { X } from "type-fest"`
selected type-fest and failed with SC2013, and type imports pulled whole
packages into the compile. Erased edges no longer select packages.
- Files reached only through erased edges are no longer program modules,
so their imports (a `node:vm` import, say) no longer fence the build.
- Inline type-only clauses are real module edges again (their modules'
side effects ran under Node but not in the binary); a cycle closed by
one binds nothing and is admitted like a side-effect import.
- Interfaces, type aliases and type literals from an installed package's
declarations map structurally, so values the program builds with a
type-only package's types compile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After socket.setEncoding("utf8"), Node passes strings to 'data'
listeners, while @types/node types the chunk as a Buffer. An inline
listener whose chunk is typed Buffer (annotated or inferred) received a
Buffer. When a program can call setEncoding on a socket, such listeners
now take the chunk as a checked dynamic value, so console.log, typeof,
string methods and concatenation behave as in Node, and Buffer-only
methods throw Node's TypeError. Programs without setEncoding on a socket
compile to the same IR as before.
A keyed or dot read of an index signature that misses now answers
undefined, as in Node, instead of aborting with "record has no key".
The read carries an explicit optional value through the same analysis
that already widens bindings, parameters, returns and fields for missing
array elements; TypeScript's static types are unchanged. Numeric reads
whose consumers treat undefined like NaN lower to plain doubles, and
nested reads and writes through a missing entry throw Node's TypeError.
Fixes#964
Co-authored-by: Quim T. <26749475+espetro@users.noreply.github.com>
- util.format %d and %i format bigint, symbol, null and undefined arguments
- util.format %j prints [Circular] for circular arguments
- util.types answers the remaining brand checks
- util.inspect prints WeakMap, WeakSet, Date and numeric typed array values as Node does
- util.inspect lowers the breakLength, compact and sorted options
- URLSearchParams iterators compile outside a for-of head
- URLSearchParams can be built from [string, string] tuple pairs
- querystring.stringify writes bigint values
- StringDecoder accepts an encoding known only at run time
- os.setPriority is lowered
- The EventEmitter leak warning reaches process 'warning' listeners on the next tick
- The events listener-count and max-listener helpers work over EventEmitter instances
- timers/promises setTimeout, setImmediate and scheduler.wait accept an AbortSignal
- timers/promises scheduler.wait and scheduler.yield are lowered
The WebAssembly and platform docs now say that wasm32-wasi builds need
zig and the @scriptc/runtime-wasm32-wasi package where the target is
introduced. A missing cross-target runtime pack still reports SC3003
with the package name and version; its hint now says that scriptc
includes the runtime pack for its own platform only, instead of
suggesting a reinstall with optional dependencies.
Fixes#717
Co-authored-by: guest271314 <4174848+guest271314@users.noreply.github.com>
The ESNext error lib is now part of the type world, and Error.isError(value)
compiles. A catch binding tests its payload against the Error class, an
unknown value tests the checked-dynamic error encoding, and a union tests its
runtime tag against the arms whose class extends Error. Other values answer
statically: true for instances of Error and its subclasses, false for
everything else, including objects that only have an error's shape. The
argument is always evaluated. Unions with unknown arms are refused.